xref: /inferno-os/libtk/ttags.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "draw.h"
3*37da2899SCharles.Forsyth #include "tk.h"
4*37da2899SCharles.Forsyth #include "textw.h"
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth #define istring u.string
7*37da2899SCharles.Forsyth #define iwin u.win
8*37da2899SCharles.Forsyth #define imark u.mark
9*37da2899SCharles.Forsyth #define iline u.line
10*37da2899SCharles.Forsyth 
11*37da2899SCharles.Forsyth static char* tkttagadd(Tk*, char*, char**);
12*37da2899SCharles.Forsyth static char* tkttagbind(Tk*, char*, char**);
13*37da2899SCharles.Forsyth static char* tkttagcget(Tk*, char*, char**);
14*37da2899SCharles.Forsyth static char* tkttagconfigure(Tk*, char*, char**);
15*37da2899SCharles.Forsyth static char* tkttagdelete(Tk*, char*, char**);
16*37da2899SCharles.Forsyth static char* tkttaglower(Tk*, char*, char**);
17*37da2899SCharles.Forsyth static char* tkttagnames(Tk*, char*, char**);
18*37da2899SCharles.Forsyth static char* tkttagnextrange(Tk*, char*, char**);
19*37da2899SCharles.Forsyth static char* tkttagprevrange(Tk*, char*, char**);
20*37da2899SCharles.Forsyth static char* tkttagraise(Tk*, char*, char**);
21*37da2899SCharles.Forsyth static char* tkttagranges(Tk*, char*, char**);
22*37da2899SCharles.Forsyth static char* tkttagremove(Tk*, char*, char**);
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #define TKTEO		(O(TkTtaginfo, env))
27*37da2899SCharles.Forsyth static
28*37da2899SCharles.Forsyth TkOption tagopts[] =
29*37da2899SCharles.Forsyth {
30*37da2899SCharles.Forsyth 	"borderwidth",
31*37da2899SCharles.Forsyth 		OPTnndist, O(TkTtaginfo, opts[TkTborderwidth]),	nil,
32*37da2899SCharles.Forsyth 	"justify",
33*37da2899SCharles.Forsyth 		OPTstab, O(TkTtaginfo, opts[TkTjustify]),	tkjustify,
34*37da2899SCharles.Forsyth 	"lineheight",
35*37da2899SCharles.Forsyth 		OPTnndist, O(TkTtaginfo, opts[TkTlineheight]),	IAUX(TKTEO),
36*37da2899SCharles.Forsyth 	"lmargin1",
37*37da2899SCharles.Forsyth 		OPTdist, O(TkTtaginfo, opts[TkTlmargin1]),	IAUX(TKTEO),
38*37da2899SCharles.Forsyth 	"lmargin2",
39*37da2899SCharles.Forsyth 		OPTdist, O(TkTtaginfo, opts[TkTlmargin2]),	IAUX(TKTEO),
40*37da2899SCharles.Forsyth 	"lmargin3",
41*37da2899SCharles.Forsyth 		OPTdist, O(TkTtaginfo, opts[TkTlmargin3]),	IAUX(TKTEO),
42*37da2899SCharles.Forsyth 	"rmargin",
43*37da2899SCharles.Forsyth 		OPTdist, O(TkTtaginfo, opts[TkTrmargin]),	IAUX(TKTEO),
44*37da2899SCharles.Forsyth 	"spacing1",
45*37da2899SCharles.Forsyth 		OPTnndist, O(TkTtaginfo, opts[TkTspacing1]),	IAUX(TKTEO),
46*37da2899SCharles.Forsyth 	"spacing2",
47*37da2899SCharles.Forsyth 		OPTnndist, O(TkTtaginfo, opts[TkTspacing2]),	IAUX(TKTEO),
48*37da2899SCharles.Forsyth 	"spacing3",
49*37da2899SCharles.Forsyth 		OPTnndist, O(TkTtaginfo, opts[TkTspacing3]),	IAUX(TKTEO),
50*37da2899SCharles.Forsyth 	"offset",
51*37da2899SCharles.Forsyth 		OPTdist, O(TkTtaginfo, opts[TkToffset]),	IAUX(TKTEO),
52*37da2899SCharles.Forsyth 	"underline",
53*37da2899SCharles.Forsyth 		OPTstab, O(TkTtaginfo, opts[TkTunderline]),	tkbool,
54*37da2899SCharles.Forsyth 	"overstrike",
55*37da2899SCharles.Forsyth 		OPTstab, O(TkTtaginfo, opts[TkToverstrike]),	tkbool,
56*37da2899SCharles.Forsyth 	"relief",
57*37da2899SCharles.Forsyth 		OPTstab, O(TkTtaginfo, opts[TkTrelief]),	tkrelief,
58*37da2899SCharles.Forsyth 	"tabs",
59*37da2899SCharles.Forsyth 		OPTtabs, O(TkTtaginfo, tabs),			IAUX(TKTEO),
60*37da2899SCharles.Forsyth 	"wrap",
61*37da2899SCharles.Forsyth 		OPTstab, O(TkTtaginfo, opts[TkTwrap]),		tkwrap,
62*37da2899SCharles.Forsyth 	nil,
63*37da2899SCharles.Forsyth };
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth static
66*37da2899SCharles.Forsyth TkOption tagenvopts[] =
67*37da2899SCharles.Forsyth {
68*37da2899SCharles.Forsyth 	"foreground",	OPTcolr,	O(TkTtaginfo, env),	IAUX(TkCforegnd),
69*37da2899SCharles.Forsyth 	"background",	OPTcolr,	O(TkTtaginfo, env),	IAUX(TkCbackgnd),
70*37da2899SCharles.Forsyth 	"fg",		OPTcolr,	O(TkTtaginfo, env),	IAUX(TkCforegnd),
71*37da2899SCharles.Forsyth 	"bg",		OPTcolr,	O(TkTtaginfo, env),	IAUX(TkCbackgnd),
72*37da2899SCharles.Forsyth 	"font",		OPTfont,	O(TkTtaginfo, env),	nil,
73*37da2899SCharles.Forsyth 	nil
74*37da2899SCharles.Forsyth };
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth TkCmdtab
77*37da2899SCharles.Forsyth tkttagcmd[] =
78*37da2899SCharles.Forsyth {
79*37da2899SCharles.Forsyth 	"add",		tkttagadd,
80*37da2899SCharles.Forsyth 	"bind",		tkttagbind,
81*37da2899SCharles.Forsyth 	"cget",		tkttagcget,
82*37da2899SCharles.Forsyth 	"configure",	tkttagconfigure,
83*37da2899SCharles.Forsyth 	"delete",	tkttagdelete,
84*37da2899SCharles.Forsyth 	"lower",	tkttaglower,
85*37da2899SCharles.Forsyth 	"names",	tkttagnames,
86*37da2899SCharles.Forsyth 	"nextrange",	tkttagnextrange,
87*37da2899SCharles.Forsyth 	"prevrange",	tkttagprevrange,
88*37da2899SCharles.Forsyth 	"raise",	tkttagraise,
89*37da2899SCharles.Forsyth 	"ranges",	tkttagranges,
90*37da2899SCharles.Forsyth 	"remove",	tkttagremove,
91*37da2899SCharles.Forsyth 	nil
92*37da2899SCharles.Forsyth };
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth int
tktanytags(TkTitem * it)95*37da2899SCharles.Forsyth tktanytags(TkTitem *it)
96*37da2899SCharles.Forsyth {
97*37da2899SCharles.Forsyth 	int i;
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth 	if(it->tagextra == 0)
100*37da2899SCharles.Forsyth 		return (it->tags[0] != 0);
101*37da2899SCharles.Forsyth 	for(i = 0; i <= it->tagextra; i++)
102*37da2899SCharles.Forsyth 		if(it->tags[i] != 0)
103*37da2899SCharles.Forsyth 			return 1;
104*37da2899SCharles.Forsyth 	return 0;
105*37da2899SCharles.Forsyth }
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth int
tktsametags(TkTitem * i1,TkTitem * i2)108*37da2899SCharles.Forsyth tktsametags(TkTitem *i1, TkTitem *i2)
109*37da2899SCharles.Forsyth {
110*37da2899SCharles.Forsyth 	int i, j;
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth 	for(i = 0; i <= i1->tagextra && i <= i2->tagextra; i++)
113*37da2899SCharles.Forsyth 		if(i1->tags[i] != i2->tags[i])
114*37da2899SCharles.Forsyth 			return 0;
115*37da2899SCharles.Forsyth 	for(j = i; j <= i1->tagextra; j++)
116*37da2899SCharles.Forsyth 		if(i1->tags[j] != 0)
117*37da2899SCharles.Forsyth 			return 0;
118*37da2899SCharles.Forsyth 	for(j = i; j <= i2->tagextra; j++)
119*37da2899SCharles.Forsyth 		if(i2->tags[j] != 0)
120*37da2899SCharles.Forsyth 			return 0;
121*37da2899SCharles.Forsyth 	return 1;
122*37da2899SCharles.Forsyth }
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth int
tkttagset(TkTitem * it,int id)125*37da2899SCharles.Forsyth tkttagset(TkTitem *it, int id)
126*37da2899SCharles.Forsyth {
127*37da2899SCharles.Forsyth 	int i;
128*37da2899SCharles.Forsyth 
129*37da2899SCharles.Forsyth 	if(it->tagextra == 0 && it->tags[0] == 0)
130*37da2899SCharles.Forsyth 		return 0;
131*37da2899SCharles.Forsyth 	for(i = 0; i <= it->tagextra; i++) {
132*37da2899SCharles.Forsyth 		if(id < 32)
133*37da2899SCharles.Forsyth 			return ((it->tags[i] & (1<<id)) != 0);
134*37da2899SCharles.Forsyth 		id -= 32;
135*37da2899SCharles.Forsyth 	}
136*37da2899SCharles.Forsyth 	return 0;
137*37da2899SCharles.Forsyth }
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth char *
tkttagname(TkText * tkt,int id)140*37da2899SCharles.Forsyth tkttagname(TkText *tkt, int id)
141*37da2899SCharles.Forsyth {
142*37da2899SCharles.Forsyth 	TkTtaginfo *t;
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth 	for(t = tkt->tags; t != nil; t = t->next) {
145*37da2899SCharles.Forsyth 		if(t->id == id)
146*37da2899SCharles.Forsyth 			return t->name;
147*37da2899SCharles.Forsyth 	}
148*37da2899SCharles.Forsyth 	return "";
149*37da2899SCharles.Forsyth }
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth /* return 1 if this actually changes the value */
152*37da2899SCharles.Forsyth int
tkttagbit(TkTitem * it,int id,int val)153*37da2899SCharles.Forsyth tkttagbit(TkTitem *it, int id, int val)
154*37da2899SCharles.Forsyth {
155*37da2899SCharles.Forsyth 	int i, changed;
156*37da2899SCharles.Forsyth 	ulong z, b;
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth 	changed = 0;
159*37da2899SCharles.Forsyth 	for(i = 0; i <= it->tagextra; i++) {
160*37da2899SCharles.Forsyth 		if(id < 32) {
161*37da2899SCharles.Forsyth 			b = (1<<id);
162*37da2899SCharles.Forsyth 			z = it->tags[i];
163*37da2899SCharles.Forsyth 			if(val == 0) {
164*37da2899SCharles.Forsyth 				if(z & b) {
165*37da2899SCharles.Forsyth 					changed = 1;
166*37da2899SCharles.Forsyth 					it->tags[i] = z & (~b);
167*37da2899SCharles.Forsyth 				}
168*37da2899SCharles.Forsyth 			}
169*37da2899SCharles.Forsyth 			else {
170*37da2899SCharles.Forsyth 				if((z & b) == 0) {
171*37da2899SCharles.Forsyth 					changed = 1;
172*37da2899SCharles.Forsyth 					it->tags[i] = z | b;
173*37da2899SCharles.Forsyth 				}
174*37da2899SCharles.Forsyth 			}
175*37da2899SCharles.Forsyth 			break;
176*37da2899SCharles.Forsyth 		}
177*37da2899SCharles.Forsyth 		id -= 32;
178*37da2899SCharles.Forsyth 	}
179*37da2899SCharles.Forsyth 	return changed;
180*37da2899SCharles.Forsyth }
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth void
tkttagcomb(TkTitem * i1,TkTitem * i2,int add)183*37da2899SCharles.Forsyth tkttagcomb(TkTitem *i1, TkTitem *i2, int add)
184*37da2899SCharles.Forsyth {
185*37da2899SCharles.Forsyth 	int i;
186*37da2899SCharles.Forsyth 
187*37da2899SCharles.Forsyth 	for(i = 0; i <= i1->tagextra && i <= i2->tagextra; i++) {
188*37da2899SCharles.Forsyth 		if(add == 1)
189*37da2899SCharles.Forsyth 			i1->tags[i] |= i2->tags[i];
190*37da2899SCharles.Forsyth 		else if(add == 0)
191*37da2899SCharles.Forsyth 			/* intersect */
192*37da2899SCharles.Forsyth 			i1->tags[i] &= i2->tags[i];
193*37da2899SCharles.Forsyth 		else
194*37da2899SCharles.Forsyth 			/* subtract */
195*37da2899SCharles.Forsyth 			i1->tags[i] &= ~i2->tags[i];
196*37da2899SCharles.Forsyth 	}
197*37da2899SCharles.Forsyth }
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth char*
tktaddtaginfo(Tk * tk,char * name,TkTtaginfo ** ret)200*37da2899SCharles.Forsyth tktaddtaginfo(Tk *tk, char *name, TkTtaginfo **ret)
201*37da2899SCharles.Forsyth {
202*37da2899SCharles.Forsyth 	int i, *ntagp;
203*37da2899SCharles.Forsyth 	TkTtaginfo *ti;
204*37da2899SCharles.Forsyth 	TkText *tkt, *tktshare;
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
207*37da2899SCharles.Forsyth 	ti = malloc(sizeof(TkTtaginfo));
208*37da2899SCharles.Forsyth 	if(ti == nil)
209*37da2899SCharles.Forsyth 		return TkNomem;
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth 	ntagp = &tkt->nexttag;
212*37da2899SCharles.Forsyth 	if(tkt->tagshare != nil) {
213*37da2899SCharles.Forsyth 		tktshare = TKobj(TkText, tkt->tagshare);
214*37da2899SCharles.Forsyth 		ntagp = &tktshare->nexttag;
215*37da2899SCharles.Forsyth 	}
216*37da2899SCharles.Forsyth 	ti->id = *ntagp;
217*37da2899SCharles.Forsyth 	ti->name = strdup(name);
218*37da2899SCharles.Forsyth 	if(ti->name == nil) {
219*37da2899SCharles.Forsyth 		free(ti);
220*37da2899SCharles.Forsyth 		return TkNomem;
221*37da2899SCharles.Forsyth 	}
222*37da2899SCharles.Forsyth 	ti->env = tknewenv(tk->env->top);
223*37da2899SCharles.Forsyth 	if(ti->env == nil) {
224*37da2899SCharles.Forsyth 		free(ti->name);
225*37da2899SCharles.Forsyth 		free(ti);
226*37da2899SCharles.Forsyth 		return TkNomem;
227*37da2899SCharles.Forsyth 	}
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth 	ti->tabs = nil;
230*37da2899SCharles.Forsyth 	for(i = 0; i < TkTnumopts; i++)
231*37da2899SCharles.Forsyth 		ti->opts[i] = TkTunset;
232*37da2899SCharles.Forsyth 	ti->next = tkt->tags;
233*37da2899SCharles.Forsyth 	tkt->tags = ti;
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 	(*ntagp)++;
236*37da2899SCharles.Forsyth 	if(tkt->tagshare)
237*37da2899SCharles.Forsyth 		tkt->nexttag = *ntagp;
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth 	*ret = ti;
240*37da2899SCharles.Forsyth 	return nil;
241*37da2899SCharles.Forsyth }
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth TkTtaginfo *
tktfindtag(TkTtaginfo * t,char * name)244*37da2899SCharles.Forsyth tktfindtag(TkTtaginfo *t, char *name)
245*37da2899SCharles.Forsyth {
246*37da2899SCharles.Forsyth 	while(t != nil) {
247*37da2899SCharles.Forsyth 		if(strcmp(t->name, name) == 0)
248*37da2899SCharles.Forsyth 			return t;
249*37da2899SCharles.Forsyth 		t = t->next;
250*37da2899SCharles.Forsyth 	}
251*37da2899SCharles.Forsyth 	return nil;
252*37da2899SCharles.Forsyth }
253*37da2899SCharles.Forsyth 
254*37da2899SCharles.Forsyth void
tktfreetags(TkTtaginfo * t)255*37da2899SCharles.Forsyth tktfreetags(TkTtaginfo *t)
256*37da2899SCharles.Forsyth {
257*37da2899SCharles.Forsyth 	TkTtaginfo *n;
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth 	while(t != nil) {
260*37da2899SCharles.Forsyth 		n = t->next;
261*37da2899SCharles.Forsyth 		free(t->name);
262*37da2899SCharles.Forsyth 		tktfreetabs(t->tabs);
263*37da2899SCharles.Forsyth 		tkputenv(t->env);
264*37da2899SCharles.Forsyth 		tkfreebind(t->binds);
265*37da2899SCharles.Forsyth 		free(t);
266*37da2899SCharles.Forsyth 		t = n;
267*37da2899SCharles.Forsyth 	}
268*37da2899SCharles.Forsyth }
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth int
tkttagind(Tk * tk,char * name,int first,TkTindex * ans)271*37da2899SCharles.Forsyth tkttagind(Tk *tk, char *name, int first, TkTindex *ans)
272*37da2899SCharles.Forsyth {
273*37da2899SCharles.Forsyth 	int id;
274*37da2899SCharles.Forsyth 	TkTtaginfo *t;
275*37da2899SCharles.Forsyth 	TkText *tkt;
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth 	if(strcmp(name, "sel") == 0) {
280*37da2899SCharles.Forsyth 		if(tkt->selfirst == nil)
281*37da2899SCharles.Forsyth 			return 0;
282*37da2899SCharles.Forsyth 		if(first)
283*37da2899SCharles.Forsyth 			tktitemind(tkt->selfirst, ans);
284*37da2899SCharles.Forsyth 		else
285*37da2899SCharles.Forsyth 			tktitemind(tkt->sellast, ans);
286*37da2899SCharles.Forsyth 		return 1;
287*37da2899SCharles.Forsyth 	}
288*37da2899SCharles.Forsyth 
289*37da2899SCharles.Forsyth 	t = tktfindtag(tkt->tags, name);
290*37da2899SCharles.Forsyth 	if(t == nil)
291*37da2899SCharles.Forsyth 		return 0;
292*37da2899SCharles.Forsyth 	id = t->id;
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth 	if(first) {
295*37da2899SCharles.Forsyth 		tktstartind(tkt, ans);
296*37da2899SCharles.Forsyth 		while(!tkttagset(ans->item, id))
297*37da2899SCharles.Forsyth 			if(!tktadjustind(tkt, TkTbyitem, ans))
298*37da2899SCharles.Forsyth 				return 0;
299*37da2899SCharles.Forsyth 	}
300*37da2899SCharles.Forsyth 	else {
301*37da2899SCharles.Forsyth 		tktendind(tkt, ans);
302*37da2899SCharles.Forsyth 		while(!tkttagset(ans->item, id))
303*37da2899SCharles.Forsyth 			if(!tktadjustind(tkt, TkTbyitemback, ans))
304*37da2899SCharles.Forsyth 				return 0;
305*37da2899SCharles.Forsyth 		tktadjustind(tkt, TkTbyitem, ans);
306*37da2899SCharles.Forsyth 	}
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth 	return 1;
309*37da2899SCharles.Forsyth }
310*37da2899SCharles.Forsyth 
311*37da2899SCharles.Forsyth /*
312*37da2899SCharles.Forsyth  * Fill in opts and e, based on info from tags set in it,
313*37da2899SCharles.Forsyth  * using tags order for priority.
314*37da2899SCharles.Forsyth  * If dflt != 0, options not set are filled from tk,
315*37da2899SCharles.Forsyth  * otherwise iInteger options not set by any tag are left 'TkTunset'
316*37da2899SCharles.Forsyth  * and environment values not set are left nil.
317*37da2899SCharles.Forsyth  */
318*37da2899SCharles.Forsyth void
tkttagopts(Tk * tk,TkTitem * it,int * opts,TkEnv * e,TkTtabstop ** tb,int dflt)319*37da2899SCharles.Forsyth tkttagopts(Tk *tk, TkTitem *it, int *opts, TkEnv *e, TkTtabstop **tb, int dflt)
320*37da2899SCharles.Forsyth {
321*37da2899SCharles.Forsyth 	int i;
322*37da2899SCharles.Forsyth 	int colset;
323*37da2899SCharles.Forsyth 	TkEnv *te;
324*37da2899SCharles.Forsyth 	TkTtaginfo *tags;
325*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth 	if (tb != nil)
328*37da2899SCharles.Forsyth 		*tb = tkt->tabs;
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 	tags = tkt->tags;
331*37da2899SCharles.Forsyth 
332*37da2899SCharles.Forsyth 	if(opts != nil)
333*37da2899SCharles.Forsyth 		for(i = 0; i < TkTnumopts; i++)
334*37da2899SCharles.Forsyth 			opts[i] = TkTunset;
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth 	memset(e, 0, sizeof(TkEnv));
337*37da2899SCharles.Forsyth 	e->top = tk->env->top;
338*37da2899SCharles.Forsyth 	colset = 0;
339*37da2899SCharles.Forsyth 	while(tags != nil) {
340*37da2899SCharles.Forsyth 		if(tkttagset(it, tags->id)) {
341*37da2899SCharles.Forsyth 			if(opts != nil) {
342*37da2899SCharles.Forsyth 				for(i = 0; i < TkTnumopts; i++) {
343*37da2899SCharles.Forsyth 					if(opts[i] == TkTunset && tags->opts[i] != TkTunset)
344*37da2899SCharles.Forsyth 						opts[i] = tags->opts[i];
345*37da2899SCharles.Forsyth 				}
346*37da2899SCharles.Forsyth 			}
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth 			te = tags->env;
349*37da2899SCharles.Forsyth 			for(i = 0; i < TkNcolor; i++)
350*37da2899SCharles.Forsyth 				if(!(colset & (1<<i)) && te->set & (1<<i)) {
351*37da2899SCharles.Forsyth 					e->colors[i] = te->colors[i];
352*37da2899SCharles.Forsyth 					colset |= 1<<i;
353*37da2899SCharles.Forsyth 				}
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth 			if(e->font == nil && te->font != nil)
356*37da2899SCharles.Forsyth 				e->font = te->font;
357*37da2899SCharles.Forsyth 
358*37da2899SCharles.Forsyth 			if (tb != nil && tags->tabs != nil)
359*37da2899SCharles.Forsyth 				*tb = tags->tabs;
360*37da2899SCharles.Forsyth 		}
361*37da2899SCharles.Forsyth 		tags = tags->next;
362*37da2899SCharles.Forsyth 	}
363*37da2899SCharles.Forsyth 	e->set |= colset;
364*37da2899SCharles.Forsyth 	if(dflt) {
365*37da2899SCharles.Forsyth 		if(opts != nil) {
366*37da2899SCharles.Forsyth 			for(i = 0; i < TkTnumopts; i++)
367*37da2899SCharles.Forsyth 				if(opts[i] == TkTunset)
368*37da2899SCharles.Forsyth 					opts[i] = tkt->opts[i];
369*37da2899SCharles.Forsyth 		}
370*37da2899SCharles.Forsyth 		te = tk->env;
371*37da2899SCharles.Forsyth 		for(i = 0; i < TkNcolor; i++)
372*37da2899SCharles.Forsyth 			if(!(e->set & (1<<i))) {
373*37da2899SCharles.Forsyth 				e->colors[i] = te->colors[i];
374*37da2899SCharles.Forsyth 				e->set |= 1<<i;
375*37da2899SCharles.Forsyth 			}
376*37da2899SCharles.Forsyth 		if(e->font == nil)
377*37da2899SCharles.Forsyth 			e->font = te->font;
378*37da2899SCharles.Forsyth 	}
379*37da2899SCharles.Forsyth }
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth char*
tkttagparse(Tk * tk,char ** parg,TkTtaginfo ** ret)382*37da2899SCharles.Forsyth tkttagparse(Tk *tk, char **parg, TkTtaginfo **ret)
383*37da2899SCharles.Forsyth {
384*37da2899SCharles.Forsyth 	char *e, *buf;
385*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
386*37da2899SCharles.Forsyth 
387*37da2899SCharles.Forsyth 	buf = mallocz(Tkmaxitem, 0);
388*37da2899SCharles.Forsyth 	if(buf == nil)
389*37da2899SCharles.Forsyth 		return TkNomem;
390*37da2899SCharles.Forsyth 	*parg = tkword(tk->env->top, *parg, buf, buf+Tkmaxitem, nil);
391*37da2899SCharles.Forsyth 	if(*buf == '\0') {
392*37da2899SCharles.Forsyth 		free(buf);
393*37da2899SCharles.Forsyth 		return TkOparg;
394*37da2899SCharles.Forsyth 	}
395*37da2899SCharles.Forsyth 	if(buf[0] >= '0' && buf[0] <= '9'){
396*37da2899SCharles.Forsyth 		free(buf);
397*37da2899SCharles.Forsyth 		return TkBadtg;
398*37da2899SCharles.Forsyth 	}
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth 	*ret = tktfindtag(tkt->tags, buf);
401*37da2899SCharles.Forsyth 	if(*ret == nil) {
402*37da2899SCharles.Forsyth 		e = tktaddtaginfo(tk, buf, ret);
403*37da2899SCharles.Forsyth 		if(e != nil) {
404*37da2899SCharles.Forsyth 			free(buf);
405*37da2899SCharles.Forsyth 			return e;
406*37da2899SCharles.Forsyth 		}
407*37da2899SCharles.Forsyth 	}
408*37da2899SCharles.Forsyth 	free(buf);
409*37da2899SCharles.Forsyth 
410*37da2899SCharles.Forsyth 	return nil;
411*37da2899SCharles.Forsyth }
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth int
tkttagnrange(TkText * tkt,int tid,TkTindex * i1,TkTindex * i2,TkTindex * istart,TkTindex * iend)414*37da2899SCharles.Forsyth tkttagnrange(TkText *tkt, int tid, TkTindex *i1, TkTindex *i2,
415*37da2899SCharles.Forsyth 			TkTindex *istart, TkTindex *iend)
416*37da2899SCharles.Forsyth {
417*37da2899SCharles.Forsyth 	int found;
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth 	found = 0;
420*37da2899SCharles.Forsyth 	while(i1->line != &tkt->end) {
421*37da2899SCharles.Forsyth 		if(i1->item == i2->item && i2->pos == 0)
422*37da2899SCharles.Forsyth 			break;
423*37da2899SCharles.Forsyth 		if(tkttagset(i1->item, tid)) {
424*37da2899SCharles.Forsyth 			if(!found) {
425*37da2899SCharles.Forsyth 				found = 1;
426*37da2899SCharles.Forsyth 				*istart = *i1;
427*37da2899SCharles.Forsyth 			}
428*37da2899SCharles.Forsyth 			if(i1->item == i2->item) {
429*37da2899SCharles.Forsyth 				/* i2->pos > 0 */
430*37da2899SCharles.Forsyth 				*iend = *i2;
431*37da2899SCharles.Forsyth 				return 1;
432*37da2899SCharles.Forsyth 			}
433*37da2899SCharles.Forsyth 		}
434*37da2899SCharles.Forsyth 		else
435*37da2899SCharles.Forsyth 		if(i1->item == i2->item || (found && i1->item->kind != TkTmark && i1->item->kind != TkTcontline))
436*37da2899SCharles.Forsyth 			break;
437*37da2899SCharles.Forsyth 		tktadjustind(tkt, TkTbyitem, i1);
438*37da2899SCharles.Forsyth 	}
439*37da2899SCharles.Forsyth 	if(found)
440*37da2899SCharles.Forsyth 		*iend = *i1;
441*37da2899SCharles.Forsyth 
442*37da2899SCharles.Forsyth 	return found;
443*37da2899SCharles.Forsyth }
444*37da2899SCharles.Forsyth 
445*37da2899SCharles.Forsyth static int
tkttagprange(TkText * tkt,int tid,TkTindex * i1,TkTindex * i2,TkTindex * istart,TkTindex * iend)446*37da2899SCharles.Forsyth tkttagprange(TkText *tkt, int tid, TkTindex *i1, TkTindex *i2,
447*37da2899SCharles.Forsyth 			TkTindex *istart, TkTindex *iend)
448*37da2899SCharles.Forsyth {
449*37da2899SCharles.Forsyth 	int found;
450*37da2899SCharles.Forsyth 
451*37da2899SCharles.Forsyth 	found = 0;
452*37da2899SCharles.Forsyth 	while(i1->line != &tkt->start && i1->item != i2->item) {
453*37da2899SCharles.Forsyth 		tktadjustind(tkt, TkTbyitemback, i1);
454*37da2899SCharles.Forsyth 		if(tkttagset(i1->item, tid)) {
455*37da2899SCharles.Forsyth 			if(!found) {
456*37da2899SCharles.Forsyth 				found = 1;
457*37da2899SCharles.Forsyth 				*iend = *i1;
458*37da2899SCharles.Forsyth 			}
459*37da2899SCharles.Forsyth 		}
460*37da2899SCharles.Forsyth 		else
461*37da2899SCharles.Forsyth 		if(found && i1->item->kind != TkTmark && i1->item->kind != TkTcontline)
462*37da2899SCharles.Forsyth 			break;
463*37da2899SCharles.Forsyth 	}
464*37da2899SCharles.Forsyth 	if(found) {
465*37da2899SCharles.Forsyth 		tktadjustind(tkt, TkTbyitem, i1);
466*37da2899SCharles.Forsyth 		*istart = *i1;
467*37da2899SCharles.Forsyth 		if(i1->item == i2->item)
468*37da2899SCharles.Forsyth 			istart->pos = i2->pos;
469*37da2899SCharles.Forsyth 	}
470*37da2899SCharles.Forsyth 
471*37da2899SCharles.Forsyth 	return found;
472*37da2899SCharles.Forsyth }
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth /* XXX - Tad: potential memory leak on memory allocation failure */
475*37da2899SCharles.Forsyth char *
tkttagchange(Tk * tk,int tid,TkTindex * i1,TkTindex * i2,int add)476*37da2899SCharles.Forsyth tkttagchange(Tk *tk, int tid, TkTindex *i1, TkTindex *i2, int add)
477*37da2899SCharles.Forsyth {
478*37da2899SCharles.Forsyth 	char *e;
479*37da2899SCharles.Forsyth 	int samei, nextra, j, changed;
480*37da2899SCharles.Forsyth 	TkTline *lmin, *lmax;
481*37da2899SCharles.Forsyth 	TkTindex ixprev;
482*37da2899SCharles.Forsyth 	TkTitem *nit;
483*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
484*37da2899SCharles.Forsyth 
485*37da2899SCharles.Forsyth 	if(!tktindbefore(i1, i2))
486*37da2899SCharles.Forsyth 		return nil;
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth 	nextra = tid/32;
489*37da2899SCharles.Forsyth 	lmin = nil;
490*37da2899SCharles.Forsyth 	lmax = nil;
491*37da2899SCharles.Forsyth 	tktadjustind(tkt, TkTbycharstart, i1);
492*37da2899SCharles.Forsyth 	tktadjustind(tkt, TkTbycharstart, i2);
493*37da2899SCharles.Forsyth 	samei = (i1->item == i2->item);
494*37da2899SCharles.Forsyth 	if(i2->pos != 0) {
495*37da2899SCharles.Forsyth 		e = tktsplititem(i2);
496*37da2899SCharles.Forsyth 		if(e != nil)
497*37da2899SCharles.Forsyth 			return e;
498*37da2899SCharles.Forsyth 		if(samei) {
499*37da2899SCharles.Forsyth 			/* split means i1 should now point to previous item */
500*37da2899SCharles.Forsyth 			ixprev = *i2;
501*37da2899SCharles.Forsyth 			tktadjustind(tkt, TkTbyitemback, &ixprev);
502*37da2899SCharles.Forsyth 			i1->item = ixprev.item;
503*37da2899SCharles.Forsyth 		}
504*37da2899SCharles.Forsyth 	}
505*37da2899SCharles.Forsyth 	if(i1->pos != 0) {
506*37da2899SCharles.Forsyth 		e = tktsplititem(i1);
507*37da2899SCharles.Forsyth 		if(e != nil)
508*37da2899SCharles.Forsyth 			return e;
509*37da2899SCharles.Forsyth 	}
510*37da2899SCharles.Forsyth 	/* now i1 and i2 both point to beginning of non-mark/contline items */
511*37da2899SCharles.Forsyth 	if(tid == TkTselid) {
512*37da2899SCharles.Forsyth 		/*
513*37da2899SCharles.Forsyth 		 * Cache location of selection.
514*37da2899SCharles.Forsyth 		 * Note: there can be only one selection range in widget
515*37da2899SCharles.Forsyth 		 */
516*37da2899SCharles.Forsyth 		if(add) {
517*37da2899SCharles.Forsyth 			if(tkt->selfirst != nil)
518*37da2899SCharles.Forsyth 				return TkBadsl;
519*37da2899SCharles.Forsyth 			tkt->selfirst = i1->item;
520*37da2899SCharles.Forsyth 			tkt->sellast = i2->item;
521*37da2899SCharles.Forsyth 		}
522*37da2899SCharles.Forsyth 		else {
523*37da2899SCharles.Forsyth 			tkt->selfirst = nil;
524*37da2899SCharles.Forsyth 			tkt->sellast = nil;
525*37da2899SCharles.Forsyth 		}
526*37da2899SCharles.Forsyth 	}
527*37da2899SCharles.Forsyth 	while(i1->item != i2->item) {
528*37da2899SCharles.Forsyth 		if(i1->item->kind != TkTmark && i1->item->kind != TkTcontline) {
529*37da2899SCharles.Forsyth 			if(tid >= 32 && i1->item->tagextra < nextra) {
530*37da2899SCharles.Forsyth 				nit = realloc(i1->item, sizeof(TkTitem) + nextra * sizeof(long));
531*37da2899SCharles.Forsyth 				if(nit == nil)
532*37da2899SCharles.Forsyth 					return TkNomem;
533*37da2899SCharles.Forsyth 				for(j = nit->tagextra+1; j <= nextra; j++)
534*37da2899SCharles.Forsyth 					nit->tags[j] = 0;
535*37da2899SCharles.Forsyth 				nit->tagextra = nextra;
536*37da2899SCharles.Forsyth 				if(i1->line->items == i1->item)
537*37da2899SCharles.Forsyth 					i1->line->items = nit;
538*37da2899SCharles.Forsyth 				else {
539*37da2899SCharles.Forsyth 					ixprev = *i1;
540*37da2899SCharles.Forsyth 					tktadjustind(tkt, TkTbyitemback, &ixprev);
541*37da2899SCharles.Forsyth 					ixprev.item->next = nit;
542*37da2899SCharles.Forsyth 				}
543*37da2899SCharles.Forsyth 				/* check nit against cached items */
544*37da2899SCharles.Forsyth 				if(tkt->selfirst == i1->item)
545*37da2899SCharles.Forsyth 					tkt->selfirst = nit;
546*37da2899SCharles.Forsyth 				if(tkt->sellast == i1->item)
547*37da2899SCharles.Forsyth 					tkt->sellast = nit;
548*37da2899SCharles.Forsyth 				i1->item = nit;
549*37da2899SCharles.Forsyth 			}
550*37da2899SCharles.Forsyth 			changed = tkttagbit(i1->item, tid, add);
551*37da2899SCharles.Forsyth 			if(lmin == nil) {
552*37da2899SCharles.Forsyth 				if(changed) {
553*37da2899SCharles.Forsyth 					lmin = i1->line;
554*37da2899SCharles.Forsyth 					lmax = lmin;
555*37da2899SCharles.Forsyth 				}
556*37da2899SCharles.Forsyth 			}
557*37da2899SCharles.Forsyth 			else {
558*37da2899SCharles.Forsyth 				if(changed)
559*37da2899SCharles.Forsyth 					lmax = i1->line;
560*37da2899SCharles.Forsyth 			}
561*37da2899SCharles.Forsyth 		}
562*37da2899SCharles.Forsyth 		if(!tktadjustind(tkt, TkTbyitem, i1))
563*37da2899SCharles.Forsyth 			break;
564*37da2899SCharles.Forsyth 	}
565*37da2899SCharles.Forsyth 	if(lmin != nil) {
566*37da2899SCharles.Forsyth 		tktfixgeom(tk, tktprevwrapline(tk, lmin), lmax, 0);
567*37da2899SCharles.Forsyth 		tktextsize(tk, 1);
568*37da2899SCharles.Forsyth 	}
569*37da2899SCharles.Forsyth 	return nil;
570*37da2899SCharles.Forsyth }
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth static char*
tkttagaddrem(Tk * tk,char * arg,int add)573*37da2899SCharles.Forsyth tkttagaddrem(Tk *tk, char *arg, int add)
574*37da2899SCharles.Forsyth {
575*37da2899SCharles.Forsyth 	char *e;
576*37da2899SCharles.Forsyth 	TkText *tkt;
577*37da2899SCharles.Forsyth 	TkTtaginfo *ti;
578*37da2899SCharles.Forsyth 	TkTindex ix1, ix2;
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
581*37da2899SCharles.Forsyth 
582*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &ti);
583*37da2899SCharles.Forsyth 	if(e != nil)
584*37da2899SCharles.Forsyth 		return e;
585*37da2899SCharles.Forsyth 
586*37da2899SCharles.Forsyth 	while(*arg != '\0') {
587*37da2899SCharles.Forsyth 		e = tktindparse(tk, &arg, &ix1);
588*37da2899SCharles.Forsyth 		if(e != nil)
589*37da2899SCharles.Forsyth 			return e;
590*37da2899SCharles.Forsyth 		if(*arg != '\0') {
591*37da2899SCharles.Forsyth 			e = tktindparse(tk, &arg, &ix2);
592*37da2899SCharles.Forsyth 			if(e != nil)
593*37da2899SCharles.Forsyth 				return e;
594*37da2899SCharles.Forsyth 		}
595*37da2899SCharles.Forsyth 		else {
596*37da2899SCharles.Forsyth 			ix2 = ix1;
597*37da2899SCharles.Forsyth 			tktadjustind(tkt, TkTbychar, &ix2);
598*37da2899SCharles.Forsyth 		}
599*37da2899SCharles.Forsyth 		if(!tktindbefore(&ix1, &ix2))
600*37da2899SCharles.Forsyth 			continue;
601*37da2899SCharles.Forsyth 
602*37da2899SCharles.Forsyth 		e = tkttagchange(tk, ti->id, &ix1, &ix2, add);
603*37da2899SCharles.Forsyth 		if(e != nil)
604*37da2899SCharles.Forsyth 			return e;
605*37da2899SCharles.Forsyth 	}
606*37da2899SCharles.Forsyth 
607*37da2899SCharles.Forsyth 	return nil;
608*37da2899SCharles.Forsyth }
609*37da2899SCharles.Forsyth 
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth /* Text Tag Command (+ means implemented)
612*37da2899SCharles.Forsyth 	+add
613*37da2899SCharles.Forsyth 	+bind
614*37da2899SCharles.Forsyth 	+cget
615*37da2899SCharles.Forsyth 	+configure
616*37da2899SCharles.Forsyth 	+delete
617*37da2899SCharles.Forsyth 	+lower
618*37da2899SCharles.Forsyth 	+names
619*37da2899SCharles.Forsyth 	+nextrange
620*37da2899SCharles.Forsyth 	+prevrange
621*37da2899SCharles.Forsyth 	+raise
622*37da2899SCharles.Forsyth 	+ranges
623*37da2899SCharles.Forsyth 	+remove
624*37da2899SCharles.Forsyth */
625*37da2899SCharles.Forsyth 
626*37da2899SCharles.Forsyth static char*
tkttagadd(Tk * tk,char * arg,char ** val)627*37da2899SCharles.Forsyth tkttagadd(Tk *tk, char *arg, char **val)
628*37da2899SCharles.Forsyth {
629*37da2899SCharles.Forsyth 	USED(val);
630*37da2899SCharles.Forsyth 
631*37da2899SCharles.Forsyth 	return tkttagaddrem(tk, arg, 1);
632*37da2899SCharles.Forsyth }
633*37da2899SCharles.Forsyth 
634*37da2899SCharles.Forsyth static char*
tkttagbind(Tk * tk,char * arg,char ** val)635*37da2899SCharles.Forsyth tkttagbind(Tk *tk, char *arg, char **val)
636*37da2899SCharles.Forsyth {
637*37da2899SCharles.Forsyth 	char *e;
638*37da2899SCharles.Forsyth 	Rune r;
639*37da2899SCharles.Forsyth 	TkTtaginfo *ti;
640*37da2899SCharles.Forsyth 	TkAction *a;
641*37da2899SCharles.Forsyth 	int event, mode;
642*37da2899SCharles.Forsyth 	char *cmd, buf[Tkmaxitem];
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth 
645*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &ti);
646*37da2899SCharles.Forsyth 	if(e != nil)
647*37da2899SCharles.Forsyth 		return e;
648*37da2899SCharles.Forsyth 
649*37da2899SCharles.Forsyth 	arg = tkskip(arg, " \t");
650*37da2899SCharles.Forsyth 	if (arg[0] == '\0')
651*37da2899SCharles.Forsyth 		return TkBadsq;
652*37da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
653*37da2899SCharles.Forsyth 	if(buf[0] == '<') {
654*37da2899SCharles.Forsyth 		event = tkseqparse(buf+1);
655*37da2899SCharles.Forsyth 		if(event == -1)
656*37da2899SCharles.Forsyth 			return TkBadsq;
657*37da2899SCharles.Forsyth 	}
658*37da2899SCharles.Forsyth 	else {
659*37da2899SCharles.Forsyth 		chartorune(&r, buf);
660*37da2899SCharles.Forsyth 		event = TkKey | r;
661*37da2899SCharles.Forsyth 	}
662*37da2899SCharles.Forsyth 	if(event == 0)
663*37da2899SCharles.Forsyth 		return TkBadsq;
664*37da2899SCharles.Forsyth 
665*37da2899SCharles.Forsyth 	arg = tkskip(arg, " \t");
666*37da2899SCharles.Forsyth 	if(*arg == '\0') {
667*37da2899SCharles.Forsyth 		for(a = ti->binds; a; a = a->link)
668*37da2899SCharles.Forsyth 				if(event == a->event)
669*37da2899SCharles.Forsyth 					return tkvalue(val, "%s", a->arg);
670*37da2899SCharles.Forsyth 		return nil;
671*37da2899SCharles.Forsyth 	}
672*37da2899SCharles.Forsyth 
673*37da2899SCharles.Forsyth 	mode = TkArepl;
674*37da2899SCharles.Forsyth 	if(*arg == '+') {
675*37da2899SCharles.Forsyth 		mode = TkAadd;
676*37da2899SCharles.Forsyth 		arg++;
677*37da2899SCharles.Forsyth 	}
678*37da2899SCharles.Forsyth 	else if(*arg == '-'){
679*37da2899SCharles.Forsyth 		mode = TkAsub;
680*37da2899SCharles.Forsyth 		arg++;
681*37da2899SCharles.Forsyth 	}
682*37da2899SCharles.Forsyth 
683*37da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
684*37da2899SCharles.Forsyth 	cmd = strdup(buf);
685*37da2899SCharles.Forsyth 	if(cmd == nil)
686*37da2899SCharles.Forsyth 		return TkNomem;
687*37da2899SCharles.Forsyth 	return tkaction(&ti->binds, event, TkDynamic, cmd, mode);
688*37da2899SCharles.Forsyth }
689*37da2899SCharles.Forsyth 
690*37da2899SCharles.Forsyth static char*
tkttagcget(Tk * tk,char * arg,char ** val)691*37da2899SCharles.Forsyth tkttagcget(Tk *tk, char *arg, char **val)
692*37da2899SCharles.Forsyth {
693*37da2899SCharles.Forsyth 	char *e;
694*37da2899SCharles.Forsyth 	TkTtaginfo *ti;
695*37da2899SCharles.Forsyth 	TkOptab tko[3];
696*37da2899SCharles.Forsyth 
697*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &ti);
698*37da2899SCharles.Forsyth 	if(e != nil)
699*37da2899SCharles.Forsyth 		return e;
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth 	tko[0].ptr = ti;
702*37da2899SCharles.Forsyth 	tko[0].optab = tagopts;
703*37da2899SCharles.Forsyth 	tko[1].ptr = ti;
704*37da2899SCharles.Forsyth 	tko[1].optab = tagenvopts;
705*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
706*37da2899SCharles.Forsyth 
707*37da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, tk->env->top);
708*37da2899SCharles.Forsyth }
709*37da2899SCharles.Forsyth 
710*37da2899SCharles.Forsyth static char*
tkttagconfigure(Tk * tk,char * arg,char ** val)711*37da2899SCharles.Forsyth tkttagconfigure(Tk *tk, char *arg, char **val)
712*37da2899SCharles.Forsyth {
713*37da2899SCharles.Forsyth 	char *e;
714*37da2899SCharles.Forsyth 	TkOptab tko[3];
715*37da2899SCharles.Forsyth 	TkTtaginfo *ti;
716*37da2899SCharles.Forsyth 	TkTindex ix;
717*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
718*37da2899SCharles.Forsyth 
719*37da2899SCharles.Forsyth 	USED(val);
720*37da2899SCharles.Forsyth 
721*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &ti);
722*37da2899SCharles.Forsyth 	if(e != nil)
723*37da2899SCharles.Forsyth 		return e;
724*37da2899SCharles.Forsyth 
725*37da2899SCharles.Forsyth 	tko[0].ptr = ti;
726*37da2899SCharles.Forsyth 	tko[0].optab = tagopts;
727*37da2899SCharles.Forsyth 	tko[1].ptr = ti;
728*37da2899SCharles.Forsyth 	tko[1].optab = tagenvopts;
729*37da2899SCharles.Forsyth 	tko[2].ptr = nil;
730*37da2899SCharles.Forsyth 
731*37da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
732*37da2899SCharles.Forsyth 	if(e != nil)
733*37da2899SCharles.Forsyth 		return e;
734*37da2899SCharles.Forsyth 
735*37da2899SCharles.Forsyth 	if(tkttagind(tk, ti->name, 1, &ix)) {
736*37da2899SCharles.Forsyth 		tktfixgeom(tk, tktprevwrapline(tk, ix.line), tkt->end.prev, 0);
737*37da2899SCharles.Forsyth 		tktextsize(tk, 1);
738*37da2899SCharles.Forsyth 	}
739*37da2899SCharles.Forsyth 
740*37da2899SCharles.Forsyth 	return nil;
741*37da2899SCharles.Forsyth }
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth static void
tktunlinktag(TkText * tkt,TkTtaginfo * t)744*37da2899SCharles.Forsyth tktunlinktag(TkText *tkt, TkTtaginfo *t)
745*37da2899SCharles.Forsyth {
746*37da2899SCharles.Forsyth 	TkTtaginfo *f, **l;
747*37da2899SCharles.Forsyth 
748*37da2899SCharles.Forsyth 	l = &tkt->tags;
749*37da2899SCharles.Forsyth 	for(f = *l; f != nil; f = f->next) {
750*37da2899SCharles.Forsyth 		if(f == t) {
751*37da2899SCharles.Forsyth 			*l = t->next;
752*37da2899SCharles.Forsyth 			return;
753*37da2899SCharles.Forsyth 		}
754*37da2899SCharles.Forsyth 		l = &f->next;
755*37da2899SCharles.Forsyth 	}
756*37da2899SCharles.Forsyth }
757*37da2899SCharles.Forsyth 
758*37da2899SCharles.Forsyth static char*
tkttagdelete(Tk * tk,char * arg,char ** val)759*37da2899SCharles.Forsyth tkttagdelete(Tk *tk, char *arg, char **val)
760*37da2899SCharles.Forsyth {
761*37da2899SCharles.Forsyth 	TkText *tkt;
762*37da2899SCharles.Forsyth 	TkTtaginfo *t;
763*37da2899SCharles.Forsyth 	TkTindex ix;
764*37da2899SCharles.Forsyth 	char *e;
765*37da2899SCharles.Forsyth 	int found;
766*37da2899SCharles.Forsyth 
767*37da2899SCharles.Forsyth 	USED(val);
768*37da2899SCharles.Forsyth 
769*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
770*37da2899SCharles.Forsyth 
771*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
772*37da2899SCharles.Forsyth 	if(e != nil)
773*37da2899SCharles.Forsyth 		return e;
774*37da2899SCharles.Forsyth 
775*37da2899SCharles.Forsyth 	found = 0;
776*37da2899SCharles.Forsyth 	while(t != nil) {
777*37da2899SCharles.Forsyth 		if(t->id == TkTselid)
778*37da2899SCharles.Forsyth 			return TkBadvl;
779*37da2899SCharles.Forsyth 
780*37da2899SCharles.Forsyth 		while(tkttagind(tk, t->name, 1, &ix)) {
781*37da2899SCharles.Forsyth 			found = 1;
782*37da2899SCharles.Forsyth 			tkttagbit(ix.item, t->id, 0);
783*37da2899SCharles.Forsyth 		}
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth 		tktunlinktag(tkt, t);
786*37da2899SCharles.Forsyth 		t->next = nil;
787*37da2899SCharles.Forsyth 		tktfreetags(t);
788*37da2899SCharles.Forsyth 
789*37da2899SCharles.Forsyth 		if(*arg != '\0') {
790*37da2899SCharles.Forsyth 			e = tkttagparse(tk, &arg, &t);
791*37da2899SCharles.Forsyth 			if(e != nil)
792*37da2899SCharles.Forsyth 				return e;
793*37da2899SCharles.Forsyth 		}
794*37da2899SCharles.Forsyth 		else
795*37da2899SCharles.Forsyth 			t = nil;
796*37da2899SCharles.Forsyth 	}
797*37da2899SCharles.Forsyth 	if (found) {
798*37da2899SCharles.Forsyth 		tktfixgeom(tk, &tkt->start, tkt->end.prev, 0);
799*37da2899SCharles.Forsyth 		tktextsize(tk, 1);
800*37da2899SCharles.Forsyth 	}
801*37da2899SCharles.Forsyth 
802*37da2899SCharles.Forsyth 	return nil;
803*37da2899SCharles.Forsyth }
804*37da2899SCharles.Forsyth 
805*37da2899SCharles.Forsyth static char*
tkttaglower(Tk * tk,char * arg,char ** val)806*37da2899SCharles.Forsyth tkttaglower(Tk *tk, char *arg, char **val)
807*37da2899SCharles.Forsyth {
808*37da2899SCharles.Forsyth 	TkText *tkt;
809*37da2899SCharles.Forsyth 	TkTindex ix;
810*37da2899SCharles.Forsyth 	TkTtaginfo *t, *tbelow, *f, **l;
811*37da2899SCharles.Forsyth 	char *e;
812*37da2899SCharles.Forsyth 
813*37da2899SCharles.Forsyth 	USED(val);
814*37da2899SCharles.Forsyth 
815*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
816*37da2899SCharles.Forsyth 
817*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
818*37da2899SCharles.Forsyth 	if(e != nil)
819*37da2899SCharles.Forsyth 		return e;
820*37da2899SCharles.Forsyth 
821*37da2899SCharles.Forsyth 	if(*arg != '\0') {
822*37da2899SCharles.Forsyth 		e = tkttagparse(tk, &arg, &tbelow);
823*37da2899SCharles.Forsyth 		if(e != nil)
824*37da2899SCharles.Forsyth 			return e;
825*37da2899SCharles.Forsyth 	}
826*37da2899SCharles.Forsyth 	else
827*37da2899SCharles.Forsyth 		tbelow = nil;
828*37da2899SCharles.Forsyth 
829*37da2899SCharles.Forsyth 	tktunlinktag(tkt, t);
830*37da2899SCharles.Forsyth 
831*37da2899SCharles.Forsyth 	if(tbelow != nil) {
832*37da2899SCharles.Forsyth 		t->next = tbelow->next;
833*37da2899SCharles.Forsyth 		tbelow->next = t;
834*37da2899SCharles.Forsyth 	}
835*37da2899SCharles.Forsyth 	else {
836*37da2899SCharles.Forsyth 		l = &tkt->tags;
837*37da2899SCharles.Forsyth 		for(f = *l; f != nil; f = f->next)
838*37da2899SCharles.Forsyth 			l = &f->next;
839*37da2899SCharles.Forsyth 		*l = t;
840*37da2899SCharles.Forsyth 		t->next = nil;
841*37da2899SCharles.Forsyth 	}
842*37da2899SCharles.Forsyth 	if(tkttagind(tk, t->name, 1, &ix)) {
843*37da2899SCharles.Forsyth 		tktfixgeom(tk, tktprevwrapline(tk, ix.line), tkt->end.prev, 0);
844*37da2899SCharles.Forsyth 		tktextsize(tk, 1);
845*37da2899SCharles.Forsyth 	}
846*37da2899SCharles.Forsyth 
847*37da2899SCharles.Forsyth 	return nil;
848*37da2899SCharles.Forsyth }
849*37da2899SCharles.Forsyth 
850*37da2899SCharles.Forsyth 
851*37da2899SCharles.Forsyth static char*
tkttagnames(Tk * tk,char * arg,char ** val)852*37da2899SCharles.Forsyth tkttagnames(Tk *tk, char *arg, char **val)
853*37da2899SCharles.Forsyth {
854*37da2899SCharles.Forsyth 	char *e, *r, *fmt;
855*37da2899SCharles.Forsyth 	TkTtaginfo *t;
856*37da2899SCharles.Forsyth 	TkTindex i;
857*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
858*37da2899SCharles.Forsyth 	TkTitem *tagit;
859*37da2899SCharles.Forsyth 
860*37da2899SCharles.Forsyth 	if(*arg != '\0') {
861*37da2899SCharles.Forsyth 		e = tktindparse(tk, &arg, &i);
862*37da2899SCharles.Forsyth 		if(e != nil)
863*37da2899SCharles.Forsyth 			return e;
864*37da2899SCharles.Forsyth 		/* make sure we're actually on a character */
865*37da2899SCharles.Forsyth 		tktadjustind(tkt, TkTbycharstart, &i);
866*37da2899SCharles.Forsyth 		tagit = i.item;
867*37da2899SCharles.Forsyth 	}
868*37da2899SCharles.Forsyth 	else
869*37da2899SCharles.Forsyth 		tagit = nil;
870*37da2899SCharles.Forsyth 
871*37da2899SCharles.Forsyth 	/* generate in order highest-to-lowest priority (contrary to spec) */
872*37da2899SCharles.Forsyth 	fmt = "%s";
873*37da2899SCharles.Forsyth 	for(t = tkt->tags; t != nil; t = t->next) {
874*37da2899SCharles.Forsyth 		if(tagit == nil || tkttagset(tagit, t->id)) {
875*37da2899SCharles.Forsyth 			r = tkvalue(val, fmt, t->name);
876*37da2899SCharles.Forsyth 			if(r != nil)
877*37da2899SCharles.Forsyth 				return r;
878*37da2899SCharles.Forsyth 			fmt = " %s";
879*37da2899SCharles.Forsyth 		}
880*37da2899SCharles.Forsyth 	}
881*37da2899SCharles.Forsyth 	return nil;
882*37da2899SCharles.Forsyth }
883*37da2899SCharles.Forsyth 
884*37da2899SCharles.Forsyth static char*
tkttagnextrange(Tk * tk,char * arg,char ** val)885*37da2899SCharles.Forsyth tkttagnextrange(Tk *tk, char *arg, char **val)
886*37da2899SCharles.Forsyth {
887*37da2899SCharles.Forsyth 	char *e;
888*37da2899SCharles.Forsyth 	TkTtaginfo *t;
889*37da2899SCharles.Forsyth 	TkTindex i1, i2, istart, iend;
890*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
891*37da2899SCharles.Forsyth 
892*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
893*37da2899SCharles.Forsyth 	if(e != nil)
894*37da2899SCharles.Forsyth 		return e;
895*37da2899SCharles.Forsyth 	e = tktindparse(tk, &arg, &i1);
896*37da2899SCharles.Forsyth 	if(e != nil)
897*37da2899SCharles.Forsyth 		return e;
898*37da2899SCharles.Forsyth 	if(*arg != '\0') {
899*37da2899SCharles.Forsyth 		e = tktindparse(tk, &arg, &i2);
900*37da2899SCharles.Forsyth 		if(e != nil)
901*37da2899SCharles.Forsyth 			return e;
902*37da2899SCharles.Forsyth 	}
903*37da2899SCharles.Forsyth 	else
904*37da2899SCharles.Forsyth 		tktendind(tkt, &i2);
905*37da2899SCharles.Forsyth 
906*37da2899SCharles.Forsyth 	if(tkttagnrange(tkt, t->id, &i1, &i2, &istart, &iend))
907*37da2899SCharles.Forsyth 		return tkvalue(val, "%d.%d %d.%d",
908*37da2899SCharles.Forsyth 			tktlinenum(tkt, &istart), tktlinepos(tkt, &istart),
909*37da2899SCharles.Forsyth 			tktlinenum(tkt, &iend), tktlinepos(tkt, &iend));
910*37da2899SCharles.Forsyth 
911*37da2899SCharles.Forsyth 	return nil;
912*37da2899SCharles.Forsyth }
913*37da2899SCharles.Forsyth 
914*37da2899SCharles.Forsyth static char*
tkttagprevrange(Tk * tk,char * arg,char ** val)915*37da2899SCharles.Forsyth tkttagprevrange(Tk *tk, char *arg, char **val)
916*37da2899SCharles.Forsyth {
917*37da2899SCharles.Forsyth 	char *e;
918*37da2899SCharles.Forsyth 	TkTtaginfo *t;
919*37da2899SCharles.Forsyth 	TkTindex i1, i2, istart, iend;
920*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
921*37da2899SCharles.Forsyth 
922*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
923*37da2899SCharles.Forsyth 	if(e != nil)
924*37da2899SCharles.Forsyth 		return e;
925*37da2899SCharles.Forsyth 	e = tktindparse(tk, &arg, &i1);
926*37da2899SCharles.Forsyth 	if(e != nil)
927*37da2899SCharles.Forsyth 		return e;
928*37da2899SCharles.Forsyth 	if(*arg != '\0') {
929*37da2899SCharles.Forsyth 		e = tktindparse(tk, &arg, &i2);
930*37da2899SCharles.Forsyth 		if(e != nil)
931*37da2899SCharles.Forsyth 			return e;
932*37da2899SCharles.Forsyth 	}
933*37da2899SCharles.Forsyth 	else
934*37da2899SCharles.Forsyth 		tktstartind(tkt, &i2);
935*37da2899SCharles.Forsyth 
936*37da2899SCharles.Forsyth 	if(tkttagprange(tkt, t->id, &i1, &i2, &istart, &iend))
937*37da2899SCharles.Forsyth 		return tkvalue(val, "%d.%d %d.%d",
938*37da2899SCharles.Forsyth 			tktlinenum(tkt, &istart), tktlinepos(tkt, &istart),
939*37da2899SCharles.Forsyth 			tktlinenum(tkt, &iend), tktlinepos(tkt, &iend));
940*37da2899SCharles.Forsyth 
941*37da2899SCharles.Forsyth 	return nil;
942*37da2899SCharles.Forsyth }
943*37da2899SCharles.Forsyth 
944*37da2899SCharles.Forsyth static char*
tkttagraise(Tk * tk,char * arg,char ** val)945*37da2899SCharles.Forsyth tkttagraise(Tk *tk, char *arg, char **val)
946*37da2899SCharles.Forsyth {
947*37da2899SCharles.Forsyth 	TkText *tkt;
948*37da2899SCharles.Forsyth 	TkTindex ix;
949*37da2899SCharles.Forsyth 	TkTtaginfo *t, *tabove, *f, **l;
950*37da2899SCharles.Forsyth 	char *e;
951*37da2899SCharles.Forsyth 
952*37da2899SCharles.Forsyth 	USED(val);
953*37da2899SCharles.Forsyth 
954*37da2899SCharles.Forsyth 	tkt = TKobj(TkText, tk);
955*37da2899SCharles.Forsyth 
956*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
957*37da2899SCharles.Forsyth 	if(e != nil)
958*37da2899SCharles.Forsyth 		return e;
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth 	if(*arg != '\0') {
961*37da2899SCharles.Forsyth 		e = tkttagparse(tk, &arg, &tabove);
962*37da2899SCharles.Forsyth 		if(e != nil)
963*37da2899SCharles.Forsyth 			return e;
964*37da2899SCharles.Forsyth 	}
965*37da2899SCharles.Forsyth 	else
966*37da2899SCharles.Forsyth 		tabove = nil;
967*37da2899SCharles.Forsyth 
968*37da2899SCharles.Forsyth 	tktunlinktag(tkt, t);
969*37da2899SCharles.Forsyth 
970*37da2899SCharles.Forsyth 	if(tabove != nil) {
971*37da2899SCharles.Forsyth 		l = &tkt->tags;
972*37da2899SCharles.Forsyth 		for(f = *l; f != nil; f = f->next) {
973*37da2899SCharles.Forsyth 			if(f == tabove) {
974*37da2899SCharles.Forsyth 				*l = t;
975*37da2899SCharles.Forsyth 				t->next = tabove;
976*37da2899SCharles.Forsyth 				break;
977*37da2899SCharles.Forsyth 			}
978*37da2899SCharles.Forsyth 			l = &f->next;
979*37da2899SCharles.Forsyth 		}
980*37da2899SCharles.Forsyth 	}
981*37da2899SCharles.Forsyth 	else {
982*37da2899SCharles.Forsyth 		t->next = tkt->tags;
983*37da2899SCharles.Forsyth 		tkt->tags = t;
984*37da2899SCharles.Forsyth 	}
985*37da2899SCharles.Forsyth 
986*37da2899SCharles.Forsyth 	if(tkttagind(tk, t->name, 1, &ix)) {
987*37da2899SCharles.Forsyth 		tktfixgeom(tk, tktprevwrapline(tk, ix.line), tkt->end.prev, 0);
988*37da2899SCharles.Forsyth 		tktextsize(tk, 1);
989*37da2899SCharles.Forsyth 	}
990*37da2899SCharles.Forsyth 	return nil;
991*37da2899SCharles.Forsyth }
992*37da2899SCharles.Forsyth 
993*37da2899SCharles.Forsyth static char*
tkttagranges(Tk * tk,char * arg,char ** val)994*37da2899SCharles.Forsyth tkttagranges(Tk *tk, char *arg, char **val)
995*37da2899SCharles.Forsyth {
996*37da2899SCharles.Forsyth 	char *e, *fmt;
997*37da2899SCharles.Forsyth 	TkTtaginfo *t;
998*37da2899SCharles.Forsyth 	TkTindex i1, i2, istart, iend;
999*37da2899SCharles.Forsyth 	TkText *tkt = TKobj(TkText, tk);
1000*37da2899SCharles.Forsyth 
1001*37da2899SCharles.Forsyth 	e = tkttagparse(tk, &arg, &t);
1002*37da2899SCharles.Forsyth 	if(e != nil)
1003*37da2899SCharles.Forsyth 		return e;
1004*37da2899SCharles.Forsyth 
1005*37da2899SCharles.Forsyth 	tktstartind(tkt, &i1);
1006*37da2899SCharles.Forsyth 	tktendind(tkt, &i2);
1007*37da2899SCharles.Forsyth 
1008*37da2899SCharles.Forsyth 	fmt = "%d.%d %d.%d";
1009*37da2899SCharles.Forsyth 	while(tkttagnrange(tkt, t->id, &i1, &i2, &istart, &iend)) {
1010*37da2899SCharles.Forsyth 		e = tkvalue(val, fmt,
1011*37da2899SCharles.Forsyth 			tktlinenum(tkt, &istart), tktlinepos(tkt, &istart),
1012*37da2899SCharles.Forsyth 			tktlinenum(tkt, &iend), tktlinepos(tkt, &iend));
1013*37da2899SCharles.Forsyth 		if(e != nil)
1014*37da2899SCharles.Forsyth 			return e;
1015*37da2899SCharles.Forsyth 
1016*37da2899SCharles.Forsyth 		fmt = " %d.%d %d.%d";
1017*37da2899SCharles.Forsyth 		i1 = iend;
1018*37da2899SCharles.Forsyth 	}
1019*37da2899SCharles.Forsyth 
1020*37da2899SCharles.Forsyth 	return nil;
1021*37da2899SCharles.Forsyth }
1022*37da2899SCharles.Forsyth 
1023*37da2899SCharles.Forsyth static char*
tkttagremove(Tk * tk,char * arg,char ** val)1024*37da2899SCharles.Forsyth tkttagremove(Tk *tk, char *arg, char **val)
1025*37da2899SCharles.Forsyth {
1026*37da2899SCharles.Forsyth 	USED(val);
1027*37da2899SCharles.Forsyth 
1028*37da2899SCharles.Forsyth 	return tkttagaddrem(tk, arg, 0);
1029*37da2899SCharles.Forsyth }
1030