137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "kernel.h"
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
737da2899SCharles.Forsyth
837da2899SCharles.Forsyth static char* pdist(TkTop*, TkOption*, void*, char**, char*, char*);
937da2899SCharles.Forsyth static char* pstab(TkTop*, TkOption*, void*, char**, char*, char*);
1037da2899SCharles.Forsyth static char* ptext(TkTop*, TkOption*, void*, char**, char*, char*);
1137da2899SCharles.Forsyth static char* pwinp(TkTop*, TkOption*, void*, char**, char*, char*);
1237da2899SCharles.Forsyth static char* pbmap(TkTop*, TkOption*, void*, char**, char*, char*);
1337da2899SCharles.Forsyth static char* pbool(TkTop*, TkOption*, void*, char**, char*, char*);
1437da2899SCharles.Forsyth static char* pfont(TkTop*, TkOption*, void*, char**, char*, char*);
1537da2899SCharles.Forsyth static char* pfrac(TkTop*, TkOption*, void*, char**, char*, char*);
1637da2899SCharles.Forsyth static char* pnnfrac(TkTop*, TkOption*, void*, char**, char*, char*);
1737da2899SCharles.Forsyth static char* pctag(TkTop*, TkOption*, void*, char**, char*, char*);
1837da2899SCharles.Forsyth static char* ptabs(TkTop*, TkOption*, void*, char**, char*, char*);
1937da2899SCharles.Forsyth static char* pcolr(TkTop*, TkOption*, void*, char**, char*, char*);
2037da2899SCharles.Forsyth static char* pimag(TkTop*, TkOption*, void*, char**, char*, char*);
2137da2899SCharles.Forsyth static char* psize(TkTop*, TkOption*, void*, char**, char*, char*);
2237da2899SCharles.Forsyth static char* pnndist(TkTop*, TkOption*, void*, char**, char*, char*);
2337da2899SCharles.Forsyth static char* pact(TkTop*, TkOption*, void*, char**, char*, char*);
2437da2899SCharles.Forsyth static char* pignore(TkTop*, TkOption*, void*, char**, char*, char*);
2537da2899SCharles.Forsyth static char* psticky(TkTop*, TkOption*, void*, char**, char*, char*);
2637da2899SCharles.Forsyth static char* plist(TkTop*, TkOption*, void*, char**, char*, char*);
2737da2899SCharles.Forsyth
2837da2899SCharles.Forsyth static char* (*oparse[])(TkTop*, TkOption*, void*, char**, char*, char*) =
2937da2899SCharles.Forsyth {
3037da2899SCharles.Forsyth /* OPTdist */ pdist,
3137da2899SCharles.Forsyth /* OPTstab */ pstab,
3237da2899SCharles.Forsyth /* OPTtext */ ptext,
3337da2899SCharles.Forsyth /* OPTwinp */ pwinp,
3437da2899SCharles.Forsyth /* OPTflag */ pstab,
3537da2899SCharles.Forsyth /* OPTbmap */ pbmap,
3637da2899SCharles.Forsyth /* OPTbool */ pbool,
3737da2899SCharles.Forsyth /* OPTfont */ pfont,
3837da2899SCharles.Forsyth /* OPTfrac */ pfrac,
3937da2899SCharles.Forsyth /* OPTnnfrac */ pnnfrac,
4037da2899SCharles.Forsyth /* OPTctag */ pctag,
4137da2899SCharles.Forsyth /* OPTtabs */ ptabs,
4237da2899SCharles.Forsyth /* OPTcolr */ pcolr,
4337da2899SCharles.Forsyth /* OPTimag */ pimag,
4437da2899SCharles.Forsyth /* OPTsize */ psize,
4537da2899SCharles.Forsyth /* OPTnndist */ pnndist,
4637da2899SCharles.Forsyth /* OPTact */ pact,
4737da2899SCharles.Forsyth /* OPTignore */ pignore,
4837da2899SCharles.Forsyth /* OPTsticky */ psticky,
4937da2899SCharles.Forsyth /* OPTlist */ plist,
50f94b359dSforsyth /* OPTflags */ pstab,
5137da2899SCharles.Forsyth };
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth char*
tkskip(char * s,char * bl)5437da2899SCharles.Forsyth tkskip(char *s, char *bl)
5537da2899SCharles.Forsyth {
5637da2899SCharles.Forsyth char *p;
5737da2899SCharles.Forsyth
5837da2899SCharles.Forsyth while(*s) {
5937da2899SCharles.Forsyth for(p = bl; *p; p++)
6037da2899SCharles.Forsyth if(*p == *s)
6137da2899SCharles.Forsyth break;
6237da2899SCharles.Forsyth if(*p == '\0')
6337da2899SCharles.Forsyth return s;
6437da2899SCharles.Forsyth s++;
6537da2899SCharles.Forsyth }
6637da2899SCharles.Forsyth return s;
6737da2899SCharles.Forsyth }
6837da2899SCharles.Forsyth
6937da2899SCharles.Forsyth /* XXX - Tad: error propagation? */
7037da2899SCharles.Forsyth char*
tkword(TkTop * t,char * str,char * buf,char * ebuf,int * gotarg)7137da2899SCharles.Forsyth tkword(TkTop *t, char *str, char *buf, char *ebuf, int *gotarg)
7237da2899SCharles.Forsyth {
7337da2899SCharles.Forsyth int c, lev, tmp;
7437da2899SCharles.Forsyth char *val, *e, *p, *cmd;
7537da2899SCharles.Forsyth if (gotarg == nil)
7637da2899SCharles.Forsyth gotarg = &tmp;
7737da2899SCharles.Forsyth
7837da2899SCharles.Forsyth /*
7937da2899SCharles.Forsyth * ebuf is one beyond last byte in buf; leave room for nul byte in
8037da2899SCharles.Forsyth * all cases.
8137da2899SCharles.Forsyth */
8237da2899SCharles.Forsyth --ebuf;
8337da2899SCharles.Forsyth
8437da2899SCharles.Forsyth str = tkskip(str, " \t");
8537da2899SCharles.Forsyth *gotarg = 1;
8637da2899SCharles.Forsyth lev = 1;
8737da2899SCharles.Forsyth switch(*str) {
8837da2899SCharles.Forsyth case '{':
8937da2899SCharles.Forsyth /* XXX - DBK: According to Ousterhout (p.37), while back=
9037da2899SCharles.Forsyth * slashed braces don't count toward finding the matching
9137da2899SCharles.Forsyth * closing braces, the backslashes should not be removed.
9237da2899SCharles.Forsyth * Presumably this also applies to other backslashed
9337da2899SCharles.Forsyth * characters: the backslash should not be removed.
9437da2899SCharles.Forsyth */
9537da2899SCharles.Forsyth str++;
9637da2899SCharles.Forsyth while(*str && buf < ebuf) {
9737da2899SCharles.Forsyth c = *str++;
9837da2899SCharles.Forsyth if(c == '\\') {
9937da2899SCharles.Forsyth if(*str == '}' || *str == '{' || *str == '\\')
10037da2899SCharles.Forsyth c = *str++;
101c9ccdbd5Sforsyth } else if(c == '}') {
10237da2899SCharles.Forsyth lev--;
10337da2899SCharles.Forsyth if(lev == 0)
10437da2899SCharles.Forsyth break;
105c9ccdbd5Sforsyth } else if(c == '{')
10637da2899SCharles.Forsyth lev++;
10737da2899SCharles.Forsyth *buf++ = c;
10837da2899SCharles.Forsyth }
10937da2899SCharles.Forsyth break;
11037da2899SCharles.Forsyth case '[':
11137da2899SCharles.Forsyth /* XXX - DBK: According to Ousterhout (p. 33) command
11237da2899SCharles.Forsyth * substitution may occur anywhere within a word, not
11337da2899SCharles.Forsyth * only (as here) at the beginning.
11437da2899SCharles.Forsyth */
11537da2899SCharles.Forsyth cmd = malloc(strlen(str)); /* not strlen+1 because the first character is skipped */
11637da2899SCharles.Forsyth if ( cmd == nil ) {
11737da2899SCharles.Forsyth buf[0] = '\0'; /* DBK - Why not an error message? */
11837da2899SCharles.Forsyth return str;
11937da2899SCharles.Forsyth }
12037da2899SCharles.Forsyth p = cmd;
12137da2899SCharles.Forsyth str++;
12237da2899SCharles.Forsyth while(*str) {
12337da2899SCharles.Forsyth c = *str++;
12437da2899SCharles.Forsyth if(c == '\\') {
12537da2899SCharles.Forsyth if(*str == ']' || *str == '[' || *str == '\\')
12637da2899SCharles.Forsyth c = *str++;
127c9ccdbd5Sforsyth } else if(c == ']') {
12837da2899SCharles.Forsyth lev--;
12937da2899SCharles.Forsyth if(lev == 0)
13037da2899SCharles.Forsyth break;
131c9ccdbd5Sforsyth } else if(c == '[')
13237da2899SCharles.Forsyth lev++;
13337da2899SCharles.Forsyth *p++ = c;
13437da2899SCharles.Forsyth }
13537da2899SCharles.Forsyth *p = '\0';
13637da2899SCharles.Forsyth val = nil;
13737da2899SCharles.Forsyth e = tkexec(t, cmd, &val);
13837da2899SCharles.Forsyth free(cmd);
13937da2899SCharles.Forsyth /* XXX - Tad: is this appropriate behavior?
14037da2899SCharles.Forsyth * Am I sure that the error doesn't need to be
14137da2899SCharles.Forsyth * propagated back to the caller?
14237da2899SCharles.Forsyth */
14337da2899SCharles.Forsyth if(e == nil && val != nil) {
14437da2899SCharles.Forsyth strncpy(buf, val, ebuf-buf);
14537da2899SCharles.Forsyth buf = ebuf;
14637da2899SCharles.Forsyth free(val);
14737da2899SCharles.Forsyth }
14837da2899SCharles.Forsyth break;
14937da2899SCharles.Forsyth case '\'':
15037da2899SCharles.Forsyth str++;
15137da2899SCharles.Forsyth while(*str && buf < ebuf)
15237da2899SCharles.Forsyth *buf++ = *str++;
15337da2899SCharles.Forsyth break;
15437da2899SCharles.Forsyth case '\0':
15537da2899SCharles.Forsyth *gotarg = 0;
15637da2899SCharles.Forsyth break;
15737da2899SCharles.Forsyth default:
15837da2899SCharles.Forsyth /* XXX - DBK: See comment above about command substitution.
15937da2899SCharles.Forsyth * Also, any backslashed character should be replaced by
16037da2899SCharles.Forsyth * itself (e.g. to put a space, tab, or [ into a word.
16137da2899SCharles.Forsyth * We assume that the C compiler has already done the
16237da2899SCharles.Forsyth * standard ANSI C substitutions. (But should we?)
16337da2899SCharles.Forsyth */
16437da2899SCharles.Forsyth while(*str && *str != ' ' && *str != '\t' && buf < ebuf)
16537da2899SCharles.Forsyth *buf++ = *str++;
16637da2899SCharles.Forsyth }
16737da2899SCharles.Forsyth *buf = '\0';
16837da2899SCharles.Forsyth return str;
16937da2899SCharles.Forsyth }
17037da2899SCharles.Forsyth
17137da2899SCharles.Forsyth static TkOption*
Getopt(TkOption * o,char * buf)17237da2899SCharles.Forsyth Getopt(TkOption *o, char *buf)
17337da2899SCharles.Forsyth {
17437da2899SCharles.Forsyth while(o->o != nil) {
17537da2899SCharles.Forsyth if(strcmp(buf, o->o) == 0)
17637da2899SCharles.Forsyth return o;
17737da2899SCharles.Forsyth o++;
17837da2899SCharles.Forsyth }
17937da2899SCharles.Forsyth return nil;
18037da2899SCharles.Forsyth }
18137da2899SCharles.Forsyth
18237da2899SCharles.Forsyth TkName*
tkmkname(char * name)18337da2899SCharles.Forsyth tkmkname(char *name)
18437da2899SCharles.Forsyth {
18537da2899SCharles.Forsyth TkName *n;
18637da2899SCharles.Forsyth
18737da2899SCharles.Forsyth n = malloc(sizeof(struct TkName)+strlen(name));
18837da2899SCharles.Forsyth if(n == nil)
18937da2899SCharles.Forsyth return nil;
19037da2899SCharles.Forsyth strcpy(n->name, name);
19137da2899SCharles.Forsyth n->link = nil;
19237da2899SCharles.Forsyth n->obj = nil;
19337da2899SCharles.Forsyth return n;
19437da2899SCharles.Forsyth }
19537da2899SCharles.Forsyth
19637da2899SCharles.Forsyth char*
tkparse(TkTop * t,char * str,TkOptab * ot,TkName ** nl)19737da2899SCharles.Forsyth tkparse(TkTop *t, char *str, TkOptab *ot, TkName **nl)
19837da2899SCharles.Forsyth {
19937da2899SCharles.Forsyth int l;
20037da2899SCharles.Forsyth TkOptab *ft;
20137da2899SCharles.Forsyth TkOption *o;
20237da2899SCharles.Forsyth TkName *f, *n;
20337da2899SCharles.Forsyth char *e, *buf, *ebuf;
20437da2899SCharles.Forsyth
20537da2899SCharles.Forsyth l = strlen(str);
20637da2899SCharles.Forsyth if (l < Tkmaxitem)
20737da2899SCharles.Forsyth l = Tkmaxitem;
20837da2899SCharles.Forsyth buf = malloc(l + 1);
20937da2899SCharles.Forsyth if(buf == 0)
21037da2899SCharles.Forsyth return TkNomem;
21137da2899SCharles.Forsyth ebuf = buf + l + 1;
21237da2899SCharles.Forsyth
21337da2899SCharles.Forsyth e = nil;
21437da2899SCharles.Forsyth while(e == nil) {
21537da2899SCharles.Forsyth str = tkword(t, str, buf, ebuf, nil);
21637da2899SCharles.Forsyth switch(*buf) {
21737da2899SCharles.Forsyth case '\0':
21837da2899SCharles.Forsyth goto done;
21937da2899SCharles.Forsyth case '-':
22037da2899SCharles.Forsyth if (buf[1] != '\0') {
22137da2899SCharles.Forsyth for(ft = ot; ft->ptr; ft++) {
22237da2899SCharles.Forsyth o = Getopt(ft->optab, buf+1);
22337da2899SCharles.Forsyth if(o != nil) {
22437da2899SCharles.Forsyth e = oparse[o->type](t, o, ft->ptr, &str, buf, ebuf);
22537da2899SCharles.Forsyth break;
22637da2899SCharles.Forsyth }
22737da2899SCharles.Forsyth }
22837da2899SCharles.Forsyth if(ft->ptr == nil){
22937da2899SCharles.Forsyth e = TkBadop;
23037da2899SCharles.Forsyth tkerr(t, buf);
23137da2899SCharles.Forsyth }
23237da2899SCharles.Forsyth break;
23337da2899SCharles.Forsyth }
23437da2899SCharles.Forsyth /* fall through if we've got a singleton '-' */
23537da2899SCharles.Forsyth default:
23637da2899SCharles.Forsyth if(nl == nil) {
23737da2899SCharles.Forsyth e = TkBadop;
23837da2899SCharles.Forsyth tkerr(t, buf);
23937da2899SCharles.Forsyth break;
24037da2899SCharles.Forsyth }
24137da2899SCharles.Forsyth n = tkmkname(buf);
24237da2899SCharles.Forsyth if(n == nil) {
24337da2899SCharles.Forsyth e = TkNomem;
24437da2899SCharles.Forsyth break;
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth if(*nl == nil)
24737da2899SCharles.Forsyth *nl = n;
24837da2899SCharles.Forsyth else {
24937da2899SCharles.Forsyth for(f = *nl; f->link; f = f->link)
25037da2899SCharles.Forsyth ;
25137da2899SCharles.Forsyth f->link = n;
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth }
25437da2899SCharles.Forsyth }
25537da2899SCharles.Forsyth
25637da2899SCharles.Forsyth if(e != nil && nl != nil)
25737da2899SCharles.Forsyth tkfreename(*nl);
25837da2899SCharles.Forsyth done:
25937da2899SCharles.Forsyth free(buf);
26037da2899SCharles.Forsyth return e;
26137da2899SCharles.Forsyth }
26237da2899SCharles.Forsyth
26337da2899SCharles.Forsyth char*
tkconflist(TkOptab * ot,char ** val)26437da2899SCharles.Forsyth tkconflist(TkOptab *ot, char **val)
26537da2899SCharles.Forsyth {
26637da2899SCharles.Forsyth TkOption *o;
26737da2899SCharles.Forsyth char *f, *e;
26837da2899SCharles.Forsyth
26937da2899SCharles.Forsyth f = "-%s";
27037da2899SCharles.Forsyth while(ot->ptr != nil) {
27137da2899SCharles.Forsyth o = ot->optab;
27237da2899SCharles.Forsyth while(o->o != nil) {
27337da2899SCharles.Forsyth e = tkvalue(val, f, o->o);
27437da2899SCharles.Forsyth if(e != nil)
27537da2899SCharles.Forsyth return e;
27637da2899SCharles.Forsyth f = " -%s";
27737da2899SCharles.Forsyth o++;
27837da2899SCharles.Forsyth }
27937da2899SCharles.Forsyth ot++;
28037da2899SCharles.Forsyth }
28137da2899SCharles.Forsyth return nil;
28237da2899SCharles.Forsyth }
28337da2899SCharles.Forsyth
28437da2899SCharles.Forsyth char*
tkgencget(TkOptab * ft,char * arg,char ** val,TkTop * t)28537da2899SCharles.Forsyth tkgencget(TkOptab *ft, char *arg, char **val, TkTop *t)
28637da2899SCharles.Forsyth {
28737da2899SCharles.Forsyth Tk *w;
28837da2899SCharles.Forsyth char *c;
28937da2899SCharles.Forsyth Point g;
29037da2899SCharles.Forsyth TkEnv *e;
29137da2899SCharles.Forsyth TkStab *s;
29237da2899SCharles.Forsyth TkOption *o;
29337da2899SCharles.Forsyth int wh, con, i, n, flag, *v;
294f94b359dSforsyth char *r, *buf, *fmt, *out;
29537da2899SCharles.Forsyth
29637da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
29737da2899SCharles.Forsyth if(buf == nil)
29837da2899SCharles.Forsyth return TkNomem;
29937da2899SCharles.Forsyth
30037da2899SCharles.Forsyth tkitem(buf, arg);
30137da2899SCharles.Forsyth r = buf;
30237da2899SCharles.Forsyth if(*r == '-')
30337da2899SCharles.Forsyth r++;
30437da2899SCharles.Forsyth o = nil;
30537da2899SCharles.Forsyth while(ft->ptr) {
30637da2899SCharles.Forsyth o = Getopt(ft->optab, r);
30737da2899SCharles.Forsyth if(o != nil)
30837da2899SCharles.Forsyth break;
30937da2899SCharles.Forsyth ft++;
31037da2899SCharles.Forsyth }
31137da2899SCharles.Forsyth if(o == nil) {
31237da2899SCharles.Forsyth tkerr(t, r);
31337da2899SCharles.Forsyth free(buf);
31437da2899SCharles.Forsyth return TkBadop;
31537da2899SCharles.Forsyth }
31637da2899SCharles.Forsyth
31737da2899SCharles.Forsyth switch(o->type) {
31837da2899SCharles.Forsyth default:
31937da2899SCharles.Forsyth tkerr(t, r);
32037da2899SCharles.Forsyth free(buf);
32137da2899SCharles.Forsyth return TkBadop;
32237da2899SCharles.Forsyth case OPTignore:
32337da2899SCharles.Forsyth return nil;
32437da2899SCharles.Forsyth case OPTact:
32537da2899SCharles.Forsyth w = ft->ptr;
32637da2899SCharles.Forsyth g = tkposn(w);
32737da2899SCharles.Forsyth n = g.y;
32837da2899SCharles.Forsyth if(o->aux == 0)
32937da2899SCharles.Forsyth n = g.x;
33037da2899SCharles.Forsyth free(buf);
33137da2899SCharles.Forsyth return tkvalue(val, "%d", n);
33237da2899SCharles.Forsyth case OPTdist:
33337da2899SCharles.Forsyth case OPTnndist:
33437da2899SCharles.Forsyth free(buf);
33537da2899SCharles.Forsyth return tkvalue(val, "%d", OPTION(ft->ptr, int, o->offset));
33637da2899SCharles.Forsyth case OPTsize:
33737da2899SCharles.Forsyth w = ft->ptr;
33837da2899SCharles.Forsyth if(strcmp(r, "width") == 0)
33937da2899SCharles.Forsyth wh = w->req.width;
34037da2899SCharles.Forsyth else
34137da2899SCharles.Forsyth wh = w->req.height;
34237da2899SCharles.Forsyth free(buf);
34337da2899SCharles.Forsyth return tkvalue(val, "%d", wh);
34437da2899SCharles.Forsyth case OPTtext:
34537da2899SCharles.Forsyth c = OPTION(ft->ptr, char*, o->offset);
34637da2899SCharles.Forsyth if(c == nil)
34737da2899SCharles.Forsyth c = "";
34837da2899SCharles.Forsyth free(buf);
34937da2899SCharles.Forsyth return tkvalue(val, "%s", c);
35037da2899SCharles.Forsyth case OPTwinp:
35137da2899SCharles.Forsyth w = OPTION(ft->ptr, Tk*, o->offset);
35237da2899SCharles.Forsyth if(w == nil || w->name == nil)
35337da2899SCharles.Forsyth c = "";
35437da2899SCharles.Forsyth else
35537da2899SCharles.Forsyth c = w->name->name;
35637da2899SCharles.Forsyth free(buf);
35737da2899SCharles.Forsyth return tkvalue(val, "%s", c);
35837da2899SCharles.Forsyth case OPTstab:
35937da2899SCharles.Forsyth s = o->aux;
36037da2899SCharles.Forsyth c = "";
36137da2899SCharles.Forsyth con = OPTION(ft->ptr, int, o->offset);
36237da2899SCharles.Forsyth while(s->val) {
36337da2899SCharles.Forsyth if(con == s->con) {
36437da2899SCharles.Forsyth c = s->val;
36537da2899SCharles.Forsyth break;
36637da2899SCharles.Forsyth }
36737da2899SCharles.Forsyth s++;
36837da2899SCharles.Forsyth }
36937da2899SCharles.Forsyth free(buf);
37037da2899SCharles.Forsyth return tkvalue(val, "%s", c);
37137da2899SCharles.Forsyth case OPTflag:
37237da2899SCharles.Forsyth con = OPTION(ft->ptr, int, o->offset);
37337da2899SCharles.Forsyth flag = 0;
37437da2899SCharles.Forsyth for (s = o->aux; s->val != nil; s++)
37537da2899SCharles.Forsyth flag |= s->con;
37637da2899SCharles.Forsyth c = "";
37737da2899SCharles.Forsyth for (s = o->aux; s->val != nil; s++) {
37837da2899SCharles.Forsyth if ((con & flag) == s->con) {
37937da2899SCharles.Forsyth c = s->val;
38037da2899SCharles.Forsyth break;
38137da2899SCharles.Forsyth }
38237da2899SCharles.Forsyth }
38337da2899SCharles.Forsyth free(buf);
38437da2899SCharles.Forsyth return tkvalue(val, "%s", c);
385f94b359dSforsyth case OPTflags:
386f94b359dSforsyth con = OPTION(ft->ptr, int, o->offset);
387f94b359dSforsyth out = mallocz(Tkmaxitem, 0);
388f94b359dSforsyth if(out == nil) {
389f94b359dSforsyth free(buf);
390f94b359dSforsyth return TkNomem;
391f94b359dSforsyth }
392f94b359dSforsyth c = out;
393f94b359dSforsyth for (s = o->aux; s->val != nil; s++) {
394*61d0ba9cSforsyth if (s->con == (s->con&-s->con) && (con & s->con) != 0)
395f94b359dSforsyth c = seprint(c, out+Tkmaxitem, " %s", s->val); /* should this be quoted? */
396f94b359dSforsyth }
397f94b359dSforsyth free(buf);
398f94b359dSforsyth *c = 0;
399f94b359dSforsyth r = tkvalue(val, "%s", out);
400f94b359dSforsyth free(out);
401f94b359dSforsyth return r;
40237da2899SCharles.Forsyth case OPTfont:
40337da2899SCharles.Forsyth e = OPTION(ft->ptr, TkEnv*, o->offset);
40437da2899SCharles.Forsyth free(buf);
40537da2899SCharles.Forsyth if (e->font != nil)
40637da2899SCharles.Forsyth return tkvalue(val, "%s", e->font->name);
40737da2899SCharles.Forsyth return nil;
40837da2899SCharles.Forsyth case OPTcolr:
40937da2899SCharles.Forsyth e = OPTION(ft->ptr, TkEnv*, o->offset);
41037da2899SCharles.Forsyth i = AUXI(o->aux);
41137da2899SCharles.Forsyth free(buf);
41237da2899SCharles.Forsyth return tkvalue(val, "#%.8lux", e->colors[i]);
41337da2899SCharles.Forsyth case OPTfrac:
41437da2899SCharles.Forsyth case OPTnnfrac:
41537da2899SCharles.Forsyth v = &OPTION(ft->ptr, int, o->offset);
41637da2899SCharles.Forsyth n = (int)o->aux;
41737da2899SCharles.Forsyth if(n == 0)
41837da2899SCharles.Forsyth n = 1;
41937da2899SCharles.Forsyth fmt = "%s";
42037da2899SCharles.Forsyth for(i = 0; i < n; i++) {
42137da2899SCharles.Forsyth tkfprint(buf, *v++);
42237da2899SCharles.Forsyth r = tkvalue(val, fmt, buf);
42337da2899SCharles.Forsyth if(r != nil) {
42437da2899SCharles.Forsyth free(buf);
42537da2899SCharles.Forsyth return r;
42637da2899SCharles.Forsyth }
42737da2899SCharles.Forsyth fmt = " %s";
42837da2899SCharles.Forsyth }
42937da2899SCharles.Forsyth free(buf);
43037da2899SCharles.Forsyth return nil;
43137da2899SCharles.Forsyth case OPTbmap:
432f94b359dSforsyth //free(buf);
43337da2899SCharles.Forsyth return tkvalue(val, "%d", OPTION(ft->ptr, Image*, o->offset) != nil);
43437da2899SCharles.Forsyth case OPTimag:
435f94b359dSforsyth //free(buf);
43637da2899SCharles.Forsyth return tkvalue(val, "%d", OPTION(ft->ptr, TkImg*, o->offset) != nil);
43737da2899SCharles.Forsyth }
43837da2899SCharles.Forsyth }
43937da2899SCharles.Forsyth
44037da2899SCharles.Forsyth static char*
pact(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)44137da2899SCharles.Forsyth pact(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
44237da2899SCharles.Forsyth {
44337da2899SCharles.Forsyth USED(buf);
44437da2899SCharles.Forsyth USED(ebuf);
44537da2899SCharles.Forsyth USED(str);
44637da2899SCharles.Forsyth USED(place);
44737da2899SCharles.Forsyth tkerr(t, o->o);
44837da2899SCharles.Forsyth return TkBadop;
44937da2899SCharles.Forsyth }
45037da2899SCharles.Forsyth
45137da2899SCharles.Forsyth static char*
pignore(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)45237da2899SCharles.Forsyth pignore(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
45337da2899SCharles.Forsyth {
45437da2899SCharles.Forsyth char *p;
45537da2899SCharles.Forsyth USED(t);
45637da2899SCharles.Forsyth USED(o);
45737da2899SCharles.Forsyth USED(place);
45837da2899SCharles.Forsyth
45937da2899SCharles.Forsyth p = tkword(t, *str, buf, ebuf, nil);
46037da2899SCharles.Forsyth if(*buf == '\0')
46137da2899SCharles.Forsyth return TkOparg;
46237da2899SCharles.Forsyth *str = p;
46337da2899SCharles.Forsyth return nil;
46437da2899SCharles.Forsyth }
46537da2899SCharles.Forsyth
46637da2899SCharles.Forsyth static char*
pdist(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)46737da2899SCharles.Forsyth pdist(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
46837da2899SCharles.Forsyth {
46937da2899SCharles.Forsyth int d;
47037da2899SCharles.Forsyth char *e;
47137da2899SCharles.Forsyth TkEnv *env;
47237da2899SCharles.Forsyth
47337da2899SCharles.Forsyth USED(buf);
47437da2899SCharles.Forsyth USED(ebuf);
47537da2899SCharles.Forsyth
47637da2899SCharles.Forsyth /*
47737da2899SCharles.Forsyth * this is a bit of a hack, as 0 is a valid option offset,
47837da2899SCharles.Forsyth * but a nil aux is commonly used when 'w' and 'h' suffixes
47937da2899SCharles.Forsyth * aren't appropriate.
48037da2899SCharles.Forsyth * just make sure that no structure placed in TkOptab->ptr
48137da2899SCharles.Forsyth * with an OPTdist element has a TkEnv as its first member.
48237da2899SCharles.Forsyth */
48337da2899SCharles.Forsyth
48437da2899SCharles.Forsyth if (o->aux == nil)
48537da2899SCharles.Forsyth env = nil;
48637da2899SCharles.Forsyth else
48737da2899SCharles.Forsyth env = OPTION(place, TkEnv*, AUXI(o->aux));
48837da2899SCharles.Forsyth e = tkfracword(t, str, &d, env);
48937da2899SCharles.Forsyth if(e != nil)
49037da2899SCharles.Forsyth return e;
49137da2899SCharles.Forsyth OPTION(place, int, o->offset) = TKF2I(d);
49237da2899SCharles.Forsyth return nil;
49337da2899SCharles.Forsyth }
49437da2899SCharles.Forsyth
49537da2899SCharles.Forsyth static char*
pnndist(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)49637da2899SCharles.Forsyth pnndist(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
49737da2899SCharles.Forsyth {
49837da2899SCharles.Forsyth char* e;
49937da2899SCharles.Forsyth int oldv;
50037da2899SCharles.Forsyth
50137da2899SCharles.Forsyth oldv = OPTION(place, int, o->offset);
50237da2899SCharles.Forsyth e = pdist(t, o, place, str, buf, ebuf);
50337da2899SCharles.Forsyth if(e == nil && OPTION(place, int, o->offset) < 0) {
50437da2899SCharles.Forsyth OPTION(place, int, o->offset) = oldv;
50537da2899SCharles.Forsyth return TkBadvl;
50637da2899SCharles.Forsyth }
50737da2899SCharles.Forsyth return e;
50837da2899SCharles.Forsyth }
50937da2899SCharles.Forsyth
51037da2899SCharles.Forsyth static char*
psize(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)51137da2899SCharles.Forsyth psize(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
51237da2899SCharles.Forsyth {
51337da2899SCharles.Forsyth Tk *tk;
51437da2899SCharles.Forsyth char *e;
51537da2899SCharles.Forsyth int d, off;
51637da2899SCharles.Forsyth
51737da2899SCharles.Forsyth USED(ebuf);
51837da2899SCharles.Forsyth e = tkfracword(t, str, &d, OPTION(place, TkEnv*, AUXI(o->aux)));
51937da2899SCharles.Forsyth if (e != nil)
52037da2899SCharles.Forsyth return e;
52137da2899SCharles.Forsyth if(d < 0)
52237da2899SCharles.Forsyth return TkBadvl;
52337da2899SCharles.Forsyth
52437da2899SCharles.Forsyth tk = place;
52537da2899SCharles.Forsyth /*
52637da2899SCharles.Forsyth * XXX there's no way of resetting Tksetwidth or Tksetheight.
52737da2899SCharles.Forsyth * could perhaps allow it by setting width/height to {}
52837da2899SCharles.Forsyth */
52937da2899SCharles.Forsyth if(strcmp(buf+1, "width") == 0) {
53037da2899SCharles.Forsyth tk->flag |= Tksetwidth;
53137da2899SCharles.Forsyth off = O(Tk, req.width);
53237da2899SCharles.Forsyth }
53337da2899SCharles.Forsyth else {
53437da2899SCharles.Forsyth tk->flag |= Tksetheight;
53537da2899SCharles.Forsyth off = O(Tk, req.height);
53637da2899SCharles.Forsyth }
53737da2899SCharles.Forsyth OPTION(place, int, off) = TKF2I(d);
53837da2899SCharles.Forsyth return nil;
53937da2899SCharles.Forsyth }
54037da2899SCharles.Forsyth
541f94b359dSforsyth static TkStab*
lookstab(TkStab * s,char * word)542f94b359dSforsyth lookstab(TkStab *s, char *word)
543f94b359dSforsyth {
544f94b359dSforsyth for(; s->val != nil; s++)
545f94b359dSforsyth if(strcmp(s->val, word) == 0)
546f94b359dSforsyth return s;
547f94b359dSforsyth return nil;
548f94b359dSforsyth }
549f94b359dSforsyth
55037da2899SCharles.Forsyth static char*
pstab(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)55137da2899SCharles.Forsyth pstab(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
55237da2899SCharles.Forsyth {
553f94b359dSforsyth char *p, *fields[8];
554f94b359dSforsyth int mask, val, nf;
55537da2899SCharles.Forsyth TkStab *s, *c;
55637da2899SCharles.Forsyth
55737da2899SCharles.Forsyth p = tkword(t, *str, buf, ebuf, nil);
55837da2899SCharles.Forsyth if(*buf == '\0')
55937da2899SCharles.Forsyth return TkOparg;
56037da2899SCharles.Forsyth
56137da2899SCharles.Forsyth if(o->type == OPTstab) {
562f94b359dSforsyth s = lookstab(o->aux, buf);
563f94b359dSforsyth if(s == nil)
564f94b359dSforsyth return TkBadvl;
565f94b359dSforsyth *str = p;
56637da2899SCharles.Forsyth OPTION(place, int, o->offset) = s->con;
56737da2899SCharles.Forsyth return nil;
56837da2899SCharles.Forsyth }
56937da2899SCharles.Forsyth
570f94b359dSforsyth nf = getfields(buf, fields, nelem(fields), 1, " \t,");
571f94b359dSforsyth if(nf < 1 || nf > 1 && o->type != OPTflags)
572f94b359dSforsyth return TkBadvl;
573f94b359dSforsyth
57437da2899SCharles.Forsyth mask = 0;
57537da2899SCharles.Forsyth for(c = o->aux; c->val; c++)
57637da2899SCharles.Forsyth mask |= c->con;
57737da2899SCharles.Forsyth
578f94b359dSforsyth val = 0;
579f94b359dSforsyth while(--nf >= 0) {
580f94b359dSforsyth s = lookstab(o->aux, fields[nf]);
581f94b359dSforsyth if(s == nil)
582f94b359dSforsyth return TkBadvl;
583f94b359dSforsyth val |= s->con;
584f94b359dSforsyth }
585f94b359dSforsyth *str = p;
586f94b359dSforsyth
58737da2899SCharles.Forsyth OPTION(place, int, o->offset) &= ~mask;
588f94b359dSforsyth OPTION(place, int, o->offset) |= val;
58937da2899SCharles.Forsyth
59037da2899SCharles.Forsyth /*
59137da2899SCharles.Forsyth * a hack, but otherwise we have to dirty the focus order
59237da2899SCharles.Forsyth * every time any command is executed on a widget
59337da2899SCharles.Forsyth */
594f94b359dSforsyth if(strcmp(o->o, "takefocus") == 0)
59537da2899SCharles.Forsyth tkdirtyfocusorder(t);
59637da2899SCharles.Forsyth return nil;
59737da2899SCharles.Forsyth }
59837da2899SCharles.Forsyth
59937da2899SCharles.Forsyth enum {
60037da2899SCharles.Forsyth Stickyn = (1<<0),
60137da2899SCharles.Forsyth Stickye = (1<<1),
60237da2899SCharles.Forsyth Stickys = (1<<2),
60337da2899SCharles.Forsyth Stickyw = (1<<3)
60437da2899SCharles.Forsyth };
60537da2899SCharles.Forsyth
60637da2899SCharles.Forsyth static int stickymap[16] =
60737da2899SCharles.Forsyth {
60837da2899SCharles.Forsyth 0,
60937da2899SCharles.Forsyth Tknorth,
61037da2899SCharles.Forsyth Tkeast,
61137da2899SCharles.Forsyth Tknorth|Tkeast,
61237da2899SCharles.Forsyth Tksouth,
61337da2899SCharles.Forsyth Tkfilly,
61437da2899SCharles.Forsyth Tksouth|Tkeast,
61537da2899SCharles.Forsyth Tkeast|Tkfilly,
61637da2899SCharles.Forsyth Tkwest,
61737da2899SCharles.Forsyth Tknorth|Tkwest,
61837da2899SCharles.Forsyth Tkfillx,
61937da2899SCharles.Forsyth Tknorth|Tkfillx,
62037da2899SCharles.Forsyth Tksouth|Tkwest,
62137da2899SCharles.Forsyth Tkwest|Tkfilly,
62237da2899SCharles.Forsyth Tksouth|Tkfillx,
62337da2899SCharles.Forsyth Tkfillx|Tkfilly,
62437da2899SCharles.Forsyth };
62537da2899SCharles.Forsyth
62637da2899SCharles.Forsyth static char*
psticky(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)62737da2899SCharles.Forsyth psticky(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
62837da2899SCharles.Forsyth {
62937da2899SCharles.Forsyth char *p, *s;
63037da2899SCharles.Forsyth int flag, sflag;
63137da2899SCharles.Forsyth
63237da2899SCharles.Forsyth p = tkword(t, *str, buf, ebuf, nil);
63337da2899SCharles.Forsyth *str = p;
63437da2899SCharles.Forsyth
63537da2899SCharles.Forsyth flag = 0;
63637da2899SCharles.Forsyth for (s = buf; *s; s++) {
63737da2899SCharles.Forsyth switch (*s) {
63837da2899SCharles.Forsyth case 'n':
63937da2899SCharles.Forsyth flag |= Stickyn;
64037da2899SCharles.Forsyth break;
64137da2899SCharles.Forsyth case 's':
64237da2899SCharles.Forsyth flag |= Stickys;
64337da2899SCharles.Forsyth break;
64437da2899SCharles.Forsyth case 'e':
64537da2899SCharles.Forsyth flag |= Stickye;
64637da2899SCharles.Forsyth break;
64737da2899SCharles.Forsyth case 'w':
64837da2899SCharles.Forsyth flag |= Stickyw;
64937da2899SCharles.Forsyth break;
65037da2899SCharles.Forsyth case ' ':
65137da2899SCharles.Forsyth case ',':
65237da2899SCharles.Forsyth break;
65337da2899SCharles.Forsyth default:
65437da2899SCharles.Forsyth return TkBadvl;
65537da2899SCharles.Forsyth }
65637da2899SCharles.Forsyth }
65737da2899SCharles.Forsyth sflag = OPTION(place, int, o->offset) & ~(Tkanchor|Tkfill);
65837da2899SCharles.Forsyth OPTION(place, int, o->offset) = sflag | stickymap[flag];
65937da2899SCharles.Forsyth return nil;
66037da2899SCharles.Forsyth }
66137da2899SCharles.Forsyth
66237da2899SCharles.Forsyth static char*
ptext(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)66337da2899SCharles.Forsyth ptext(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
66437da2899SCharles.Forsyth {
66537da2899SCharles.Forsyth char **p;
66637da2899SCharles.Forsyth
66737da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
66837da2899SCharles.Forsyth
66937da2899SCharles.Forsyth p = &OPTION(place, char*, o->offset);
67037da2899SCharles.Forsyth if(*p != nil)
67137da2899SCharles.Forsyth free(*p);
67237da2899SCharles.Forsyth if(buf[0] == '\0')
67337da2899SCharles.Forsyth *p = nil;
67437da2899SCharles.Forsyth else {
67537da2899SCharles.Forsyth *p = strdup(buf);
67637da2899SCharles.Forsyth if(*p == nil)
67737da2899SCharles.Forsyth return TkNomem;
67837da2899SCharles.Forsyth }
67937da2899SCharles.Forsyth return nil;
68037da2899SCharles.Forsyth }
68137da2899SCharles.Forsyth
68237da2899SCharles.Forsyth static char*
pimag(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)68337da2899SCharles.Forsyth pimag(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
68437da2899SCharles.Forsyth {
68537da2899SCharles.Forsyth int locked;
68637da2899SCharles.Forsyth Display *d;
68737da2899SCharles.Forsyth TkImg **p, *i;
68837da2899SCharles.Forsyth
68937da2899SCharles.Forsyth i = nil;
69037da2899SCharles.Forsyth p = &OPTION(place, TkImg*, o->offset);
69137da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
69237da2899SCharles.Forsyth if(*buf != '\0') {
69337da2899SCharles.Forsyth i = tkname2img(t, buf);
69437da2899SCharles.Forsyth if(i == nil)
69537da2899SCharles.Forsyth return TkBadvl;
69637da2899SCharles.Forsyth i->ref++;
69737da2899SCharles.Forsyth }
69837da2899SCharles.Forsyth
69937da2899SCharles.Forsyth if(*p != nil) {
70037da2899SCharles.Forsyth d = t->display;
70137da2899SCharles.Forsyth locked = lockdisplay(d);
70237da2899SCharles.Forsyth tkimgput(*p);
70337da2899SCharles.Forsyth if(locked)
70437da2899SCharles.Forsyth unlockdisplay(d);
70537da2899SCharles.Forsyth }
70637da2899SCharles.Forsyth *p = i;
70737da2899SCharles.Forsyth return nil;
70837da2899SCharles.Forsyth }
70937da2899SCharles.Forsyth
71037da2899SCharles.Forsyth static char*
pbmap(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)71137da2899SCharles.Forsyth pbmap(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
71237da2899SCharles.Forsyth {
71337da2899SCharles.Forsyth Display *d;
71437da2899SCharles.Forsyth Image *i, **p;
71537da2899SCharles.Forsyth int locked, fd;
71637da2899SCharles.Forsyth char *c;
71737da2899SCharles.Forsyth
71837da2899SCharles.Forsyth p = &OPTION(place, Image*, o->offset);
71937da2899SCharles.Forsyth
72037da2899SCharles.Forsyth d = t->display;
72137da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
72237da2899SCharles.Forsyth if(*buf == '\0' || *buf == '-') {
72337da2899SCharles.Forsyth if(*p != nil) {
72437da2899SCharles.Forsyth locked = lockdisplay(d);
72537da2899SCharles.Forsyth freeimage(*p);
72637da2899SCharles.Forsyth if(locked)
72737da2899SCharles.Forsyth unlockdisplay(d);
72837da2899SCharles.Forsyth *p = nil;
72937da2899SCharles.Forsyth }
73037da2899SCharles.Forsyth return nil;
73137da2899SCharles.Forsyth }
73237da2899SCharles.Forsyth
73337da2899SCharles.Forsyth if(buf[0] == '@')
73437da2899SCharles.Forsyth i = display_open(d, buf+1);
735c9ccdbd5Sforsyth else if(buf[0] == '<') {
73637da2899SCharles.Forsyth buf++;
73737da2899SCharles.Forsyth fd = strtoul(buf, &c, 0);
73837da2899SCharles.Forsyth if(c == buf) {
73937da2899SCharles.Forsyth return TkBadvl;
74037da2899SCharles.Forsyth }
74137da2899SCharles.Forsyth i = readimage(d, fd, 1);
74237da2899SCharles.Forsyth }
74337da2899SCharles.Forsyth else {
74437da2899SCharles.Forsyth char *file;
74537da2899SCharles.Forsyth
74637da2899SCharles.Forsyth file = mallocz(Tkmaxitem, 0);
74737da2899SCharles.Forsyth if(file == nil)
74837da2899SCharles.Forsyth return TkNomem;
74937da2899SCharles.Forsyth
75037da2899SCharles.Forsyth snprint(file, Tkmaxitem, "/icons/tk/%s", buf);
75137da2899SCharles.Forsyth i = display_open(d, file);
75237da2899SCharles.Forsyth free(file);
75337da2899SCharles.Forsyth }
75437da2899SCharles.Forsyth if(i == nil)
75537da2899SCharles.Forsyth return TkBadbm;
75637da2899SCharles.Forsyth
75737da2899SCharles.Forsyth if(*p != nil) {
75837da2899SCharles.Forsyth locked = lockdisplay(d);
75937da2899SCharles.Forsyth freeimage(*p);
76037da2899SCharles.Forsyth if(locked)
76137da2899SCharles.Forsyth unlockdisplay(d);
76237da2899SCharles.Forsyth }
76337da2899SCharles.Forsyth *p = i;
76437da2899SCharles.Forsyth return nil;
76537da2899SCharles.Forsyth }
76637da2899SCharles.Forsyth
76737da2899SCharles.Forsyth static char*
pfont(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)76837da2899SCharles.Forsyth pfont(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
76937da2899SCharles.Forsyth {
77037da2899SCharles.Forsyth TkEnv *e;
77137da2899SCharles.Forsyth Display *d;
77237da2899SCharles.Forsyth int locked;
77337da2899SCharles.Forsyth Font *font;
77437da2899SCharles.Forsyth
77537da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
77637da2899SCharles.Forsyth if(*buf == '\0')
77737da2899SCharles.Forsyth return TkOparg;
77837da2899SCharles.Forsyth
77937da2899SCharles.Forsyth d = t->display;
78037da2899SCharles.Forsyth font = font_open(d, buf);
78137da2899SCharles.Forsyth if(font == nil)
78237da2899SCharles.Forsyth return TkBadft;
78337da2899SCharles.Forsyth
78437da2899SCharles.Forsyth e = tkdupenv(&OPTION(place, TkEnv*, o->offset));
78537da2899SCharles.Forsyth if(e == nil) {
78637da2899SCharles.Forsyth freefont(font); /* XXX lockdisplay around this? */
78737da2899SCharles.Forsyth return TkNomem;
78837da2899SCharles.Forsyth }
78937da2899SCharles.Forsyth if(e->font)
79037da2899SCharles.Forsyth font_close(e->font);
79137da2899SCharles.Forsyth e->font = font;
79237da2899SCharles.Forsyth
79337da2899SCharles.Forsyth locked = lockdisplay(d);
79437da2899SCharles.Forsyth e->wzero = stringwidth(font, "0");
79537da2899SCharles.Forsyth if ( e->wzero <= 0 )
79637da2899SCharles.Forsyth e->wzero = e->font->height / 2;
79737da2899SCharles.Forsyth if(locked)
79837da2899SCharles.Forsyth unlockdisplay(d);
79937da2899SCharles.Forsyth
80037da2899SCharles.Forsyth return nil;
80137da2899SCharles.Forsyth }
80237da2899SCharles.Forsyth
80337da2899SCharles.Forsyth static int
hex(int c)80437da2899SCharles.Forsyth hex(int c)
80537da2899SCharles.Forsyth {
80637da2899SCharles.Forsyth if(c >= 'a')
80737da2899SCharles.Forsyth c -= 'a'-'A';
80837da2899SCharles.Forsyth if(c >= 'A')
80937da2899SCharles.Forsyth c = 10 + (c - 'A');
81037da2899SCharles.Forsyth else
81137da2899SCharles.Forsyth c -= '0';
81237da2899SCharles.Forsyth return c;
81337da2899SCharles.Forsyth }
81437da2899SCharles.Forsyth
81537da2899SCharles.Forsyth static ulong
changecol(TkEnv * e,int setcol,int col,ulong rgba)81637da2899SCharles.Forsyth changecol(TkEnv *e, int setcol, int col, ulong rgba)
81737da2899SCharles.Forsyth {
81837da2899SCharles.Forsyth if (setcol) {
81937da2899SCharles.Forsyth e->set |= (1<<col);
82037da2899SCharles.Forsyth } else {
82137da2899SCharles.Forsyth rgba = 0;
82237da2899SCharles.Forsyth e->set &= ~(1<<col);
82337da2899SCharles.Forsyth }
82437da2899SCharles.Forsyth e->colors[col] = rgba;
82537da2899SCharles.Forsyth return rgba;
82637da2899SCharles.Forsyth }
82737da2899SCharles.Forsyth
82837da2899SCharles.Forsyth char*
tkparsecolor(char * buf,ulong * rgba)82937da2899SCharles.Forsyth tkparsecolor(char *buf, ulong *rgba)
83037da2899SCharles.Forsyth {
83137da2899SCharles.Forsyth char *p, *q, *e;
83237da2899SCharles.Forsyth int R, G, B, A;
83337da2899SCharles.Forsyth int i, alpha, len, alen;
83437da2899SCharles.Forsyth /*
83537da2899SCharles.Forsyth * look for alpha modifier in *#AA or *0.5 format
83637da2899SCharles.Forsyth */
83737da2899SCharles.Forsyth len = strlen(buf);
83837da2899SCharles.Forsyth p = strchr(buf, '*');
83937da2899SCharles.Forsyth if(p != nil) {
84037da2899SCharles.Forsyth alen = len - (p - buf);
84137da2899SCharles.Forsyth if(p[1] == '#') {
84237da2899SCharles.Forsyth if(alen != 4)
84337da2899SCharles.Forsyth return TkBadvl;
84437da2899SCharles.Forsyth alpha = (hex(p[2])<<4) | (hex(p[3]));
84537da2899SCharles.Forsyth } else {
84637da2899SCharles.Forsyth q = p+1;
84737da2899SCharles.Forsyth e = tkfrac(&q, &alpha, nil);
84837da2899SCharles.Forsyth if (e != nil)
84937da2899SCharles.Forsyth return e;
85037da2899SCharles.Forsyth alpha = TKF2I(alpha * 0xff);
85137da2899SCharles.Forsyth }
85237da2899SCharles.Forsyth *p = '\0';
85337da2899SCharles.Forsyth len -= alen;
85437da2899SCharles.Forsyth } else
85537da2899SCharles.Forsyth alpha = 0xff;
85637da2899SCharles.Forsyth
85737da2899SCharles.Forsyth if (*buf == '#') {
85837da2899SCharles.Forsyth switch(len) {
85937da2899SCharles.Forsyth case 4: /* #RGB */
86037da2899SCharles.Forsyth R = hex(buf[1]);
86137da2899SCharles.Forsyth G = hex(buf[2]);
86237da2899SCharles.Forsyth B = hex(buf[3]);
86337da2899SCharles.Forsyth *rgba = (R<<28) | (G<<20) | (B<<12) | 0xff;
86437da2899SCharles.Forsyth break;
86537da2899SCharles.Forsyth case 7: /* #RRGGBB */
86637da2899SCharles.Forsyth R = (hex(buf[1])<<4)|(hex(buf[2]));
86737da2899SCharles.Forsyth G = (hex(buf[3])<<4)|(hex(buf[4]));
86837da2899SCharles.Forsyth B = (hex(buf[5])<<4)|(hex(buf[6]));
86937da2899SCharles.Forsyth *rgba = (R<<24) | (G<<16) | (B<<8) | 0xff;
87037da2899SCharles.Forsyth break;
87137da2899SCharles.Forsyth case 9: /* #RRGGBBAA */
87237da2899SCharles.Forsyth R = (hex(buf[1])<<4)|(hex(buf[2]));
87337da2899SCharles.Forsyth G = (hex(buf[3])<<4)|(hex(buf[4]));
87437da2899SCharles.Forsyth B = (hex(buf[5])<<4)|(hex(buf[6]));
87537da2899SCharles.Forsyth A = (hex(buf[7])<<4)|(hex(buf[8]));
87637da2899SCharles.Forsyth *rgba = (R<<24) | (G<<16) | (B<<8) | A;
87737da2899SCharles.Forsyth break;
87837da2899SCharles.Forsyth default:
87937da2899SCharles.Forsyth return TkBadvl;
88037da2899SCharles.Forsyth }
88137da2899SCharles.Forsyth } else {
88237da2899SCharles.Forsyth for(i = 0; tkcolortab[i].val != nil; i++)
88337da2899SCharles.Forsyth if (!strcmp(tkcolortab[i].val, buf))
88437da2899SCharles.Forsyth break;
88537da2899SCharles.Forsyth if (tkcolortab[i].val == nil)
88637da2899SCharles.Forsyth return TkBadvl;
88737da2899SCharles.Forsyth *rgba = tkcolortab[i].con;
88837da2899SCharles.Forsyth }
88937da2899SCharles.Forsyth if (alpha != 0xff) {
89037da2899SCharles.Forsyth tkrgbavals(*rgba, &R, &G, &B, &A);
89137da2899SCharles.Forsyth A = (A * alpha) / 255;
89237da2899SCharles.Forsyth *rgba = tkrgba(R, G, B, A);
89337da2899SCharles.Forsyth }
89437da2899SCharles.Forsyth return nil;
89537da2899SCharles.Forsyth }
89637da2899SCharles.Forsyth
89737da2899SCharles.Forsyth static char*
pcolr(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)89837da2899SCharles.Forsyth pcolr(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
89937da2899SCharles.Forsyth {
90037da2899SCharles.Forsyth TkEnv *env;
90137da2899SCharles.Forsyth char *e;
90237da2899SCharles.Forsyth ulong rgba, dark, light;
90337da2899SCharles.Forsyth int color, setcol;
90437da2899SCharles.Forsyth
90537da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
90637da2899SCharles.Forsyth rgba = 0;
90737da2899SCharles.Forsyth if(*buf == '\0') {
90837da2899SCharles.Forsyth setcol = 0;
90937da2899SCharles.Forsyth } else {
91037da2899SCharles.Forsyth setcol = 1;
91137da2899SCharles.Forsyth e = tkparsecolor(buf, &rgba);
91237da2899SCharles.Forsyth if(e != nil)
91337da2899SCharles.Forsyth return e;
91437da2899SCharles.Forsyth }
91537da2899SCharles.Forsyth
91637da2899SCharles.Forsyth env = tkdupenv(&OPTION(place, TkEnv*, o->offset));
91737da2899SCharles.Forsyth if(env == nil)
91837da2899SCharles.Forsyth return TkNomem;
91937da2899SCharles.Forsyth
92037da2899SCharles.Forsyth color = AUXI(o->aux);
92137da2899SCharles.Forsyth rgba = changecol(env, setcol, color, rgba);
92237da2899SCharles.Forsyth if(color == TkCbackgnd || color == TkCselectbgnd || color == TkCactivebgnd) {
92337da2899SCharles.Forsyth if (setcol) {
92437da2899SCharles.Forsyth light = tkrgbashade(rgba, TkLightshade);
92537da2899SCharles.Forsyth dark = tkrgbashade(rgba, TkDarkshade);
92637da2899SCharles.Forsyth } else
92737da2899SCharles.Forsyth light = dark = 0;
92837da2899SCharles.Forsyth changecol(env, setcol, color+1, light);
92937da2899SCharles.Forsyth changecol(env, setcol, color+2, dark);
93037da2899SCharles.Forsyth }
93137da2899SCharles.Forsyth return nil;
93237da2899SCharles.Forsyth }
93337da2899SCharles.Forsyth
93437da2899SCharles.Forsyth static char*
pbool(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)93537da2899SCharles.Forsyth pbool(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
93637da2899SCharles.Forsyth {
93737da2899SCharles.Forsyth USED(buf);
93837da2899SCharles.Forsyth USED(ebuf);
93937da2899SCharles.Forsyth USED(str);
94037da2899SCharles.Forsyth USED(t);
94137da2899SCharles.Forsyth OPTION(place, int, o->offset) = 1;
94237da2899SCharles.Forsyth return nil;
94337da2899SCharles.Forsyth }
94437da2899SCharles.Forsyth
94537da2899SCharles.Forsyth static char*
pwinp(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)94637da2899SCharles.Forsyth pwinp(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
94737da2899SCharles.Forsyth {
94837da2899SCharles.Forsyth Tk *f;
94937da2899SCharles.Forsyth char *p;
95037da2899SCharles.Forsyth
95137da2899SCharles.Forsyth p = tkword(t, *str, buf, ebuf, nil);
95237da2899SCharles.Forsyth if(*buf == '\0')
95337da2899SCharles.Forsyth return TkOparg;
95437da2899SCharles.Forsyth *str = p;
95537da2899SCharles.Forsyth
95637da2899SCharles.Forsyth f = tklook(t, buf, 0);
95737da2899SCharles.Forsyth if(f == nil){
95837da2899SCharles.Forsyth tkerr(t, buf);
95937da2899SCharles.Forsyth return TkBadwp;
96037da2899SCharles.Forsyth }
96137da2899SCharles.Forsyth
96237da2899SCharles.Forsyth OPTION(place, Tk*, o->offset) = f;
96337da2899SCharles.Forsyth return nil;
96437da2899SCharles.Forsyth }
96537da2899SCharles.Forsyth
96637da2899SCharles.Forsyth static char*
pctag(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)96737da2899SCharles.Forsyth pctag(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
96837da2899SCharles.Forsyth {
96937da2899SCharles.Forsyth char *p;
97037da2899SCharles.Forsyth TkName *n, *l;
97137da2899SCharles.Forsyth
97237da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
97337da2899SCharles.Forsyth
97437da2899SCharles.Forsyth l = nil;
97537da2899SCharles.Forsyth p = buf;
97637da2899SCharles.Forsyth while(*p) {
97737da2899SCharles.Forsyth p = tkskip(p, " \t");
97837da2899SCharles.Forsyth buf = p;
97937da2899SCharles.Forsyth while(*p && *p != ' ' && *p != '\t')
98037da2899SCharles.Forsyth p++;
98137da2899SCharles.Forsyth if(*p != '\0')
98237da2899SCharles.Forsyth *p++ = '\0';
98337da2899SCharles.Forsyth
98437da2899SCharles.Forsyth if(p == buf || buf[0] >= '0' && buf[0] <= '9') {
98537da2899SCharles.Forsyth tkfreename(l);
98637da2899SCharles.Forsyth return TkBadtg;
98737da2899SCharles.Forsyth }
98837da2899SCharles.Forsyth n = tkmkname(buf);
98937da2899SCharles.Forsyth if(n == nil) {
99037da2899SCharles.Forsyth tkfreename(l);
99137da2899SCharles.Forsyth return TkNomem;
99237da2899SCharles.Forsyth }
99337da2899SCharles.Forsyth n->link = l;
99437da2899SCharles.Forsyth l = n;
99537da2899SCharles.Forsyth }
99637da2899SCharles.Forsyth tkfreename(OPTION(place, TkName*, o->offset));
99737da2899SCharles.Forsyth OPTION(place, TkName*, o->offset) = l;
99837da2899SCharles.Forsyth return nil;
99937da2899SCharles.Forsyth }
100037da2899SCharles.Forsyth
100137da2899SCharles.Forsyth static char*
pfrac(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)100237da2899SCharles.Forsyth pfrac(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
100337da2899SCharles.Forsyth {
100437da2899SCharles.Forsyth char *p, *e;
100537da2899SCharles.Forsyth int i, n, d, *v;
100637da2899SCharles.Forsyth
100737da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
100837da2899SCharles.Forsyth
100937da2899SCharles.Forsyth v = &OPTION(place, int, o->offset);
101037da2899SCharles.Forsyth n = (int)o->aux;
101137da2899SCharles.Forsyth if(n == 0)
101237da2899SCharles.Forsyth n = 1;
101337da2899SCharles.Forsyth p = buf;
101437da2899SCharles.Forsyth for(i = 0; i < n; i++) {
101537da2899SCharles.Forsyth p = tkskip(p, " \t");
101637da2899SCharles.Forsyth if(*p == '\0')
101737da2899SCharles.Forsyth return TkOparg;
101837da2899SCharles.Forsyth e = tkfracword(t, &p, &d, nil);
101937da2899SCharles.Forsyth if (e != nil)
102037da2899SCharles.Forsyth return e;
102137da2899SCharles.Forsyth *v++ = d;
102237da2899SCharles.Forsyth }
102337da2899SCharles.Forsyth return nil;
102437da2899SCharles.Forsyth }
102537da2899SCharles.Forsyth
102637da2899SCharles.Forsyth /*
102737da2899SCharles.Forsyth * N.B. nnfrac only accepts aux==nil (can't deal with several items)
102837da2899SCharles.Forsyth */
102937da2899SCharles.Forsyth static char*
pnnfrac(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)103037da2899SCharles.Forsyth pnnfrac(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
103137da2899SCharles.Forsyth {
103237da2899SCharles.Forsyth int oldv;
103337da2899SCharles.Forsyth char *e;
103437da2899SCharles.Forsyth
103537da2899SCharles.Forsyth oldv = OPTION(place, int, o->offset);
103637da2899SCharles.Forsyth
103737da2899SCharles.Forsyth e = pfrac(t, o, place, str, buf, ebuf);
103837da2899SCharles.Forsyth if(e == nil && OPTION(place, int, o->offset) < 0) {
103937da2899SCharles.Forsyth OPTION(place, int, o->offset) = oldv;
104037da2899SCharles.Forsyth return TkBadvl;
104137da2899SCharles.Forsyth }
104237da2899SCharles.Forsyth return e;
104337da2899SCharles.Forsyth
104437da2899SCharles.Forsyth }
104537da2899SCharles.Forsyth
104637da2899SCharles.Forsyth typedef struct Tabspec {
104737da2899SCharles.Forsyth int dist;
104837da2899SCharles.Forsyth int just;
104937da2899SCharles.Forsyth TkEnv *env;
105037da2899SCharles.Forsyth } Tabspec;
105137da2899SCharles.Forsyth
105237da2899SCharles.Forsyth static char*
ptabs(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)105337da2899SCharles.Forsyth ptabs(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
105437da2899SCharles.Forsyth {
105537da2899SCharles.Forsyth char *e, *p, *eibuf;
105637da2899SCharles.Forsyth TkOption opd, opj;
105737da2899SCharles.Forsyth Tabspec tspec;
105837da2899SCharles.Forsyth TkTtabstop *tabfirst, *tab, *tabprev;
105937da2899SCharles.Forsyth char *ibuf;
106037da2899SCharles.Forsyth
106137da2899SCharles.Forsyth ibuf = mallocz(Tkmaxitem, 0);
106237da2899SCharles.Forsyth if(ibuf == nil)
106337da2899SCharles.Forsyth return TkNomem;
106437da2899SCharles.Forsyth eibuf = ibuf + Tkmaxitem;
106537da2899SCharles.Forsyth tspec.env = OPTION(place, TkEnv*, AUXI(o->aux));
106637da2899SCharles.Forsyth opd.offset = O(Tabspec, dist);
106737da2899SCharles.Forsyth opd.aux = IAUX(O(Tabspec, env));
106837da2899SCharles.Forsyth opj.offset = O(Tabspec, dist);
106937da2899SCharles.Forsyth opj.aux = tktabjust;
107037da2899SCharles.Forsyth tabprev = nil;
107137da2899SCharles.Forsyth tabfirst = nil;
107237da2899SCharles.Forsyth
107337da2899SCharles.Forsyth p = tkword(t, *str, buf, ebuf, nil);
107437da2899SCharles.Forsyth if(*buf == '\0') {
107537da2899SCharles.Forsyth free(ibuf);
107637da2899SCharles.Forsyth return TkOparg;
107737da2899SCharles.Forsyth }
107837da2899SCharles.Forsyth *str = p;
107937da2899SCharles.Forsyth
108037da2899SCharles.Forsyth p = buf;
108137da2899SCharles.Forsyth while(*p != '\0') {
108237da2899SCharles.Forsyth e = pdist(t, &opd, &tspec, &p, ibuf, eibuf);
108337da2899SCharles.Forsyth if(e != nil) {
108437da2899SCharles.Forsyth free(ibuf);
108537da2899SCharles.Forsyth return e;
108637da2899SCharles.Forsyth }
108737da2899SCharles.Forsyth
108837da2899SCharles.Forsyth e = pstab(t, &opj, &tspec, &p, ibuf, eibuf);
108937da2899SCharles.Forsyth if(e != nil)
109037da2899SCharles.Forsyth tspec.just = Tkleft;
109137da2899SCharles.Forsyth
109237da2899SCharles.Forsyth tab = malloc(sizeof(TkTtabstop));
109337da2899SCharles.Forsyth if(tab == nil) {
109437da2899SCharles.Forsyth free(ibuf);
109537da2899SCharles.Forsyth return TkNomem;
109637da2899SCharles.Forsyth }
109737da2899SCharles.Forsyth
109837da2899SCharles.Forsyth tab->pos = tspec.dist;
109937da2899SCharles.Forsyth tab->justify = tspec.just;
110037da2899SCharles.Forsyth tab->next = nil;
110137da2899SCharles.Forsyth if(tabfirst == nil)
110237da2899SCharles.Forsyth tabfirst = tab;
110337da2899SCharles.Forsyth else
110437da2899SCharles.Forsyth tabprev->next = tab;
110537da2899SCharles.Forsyth tabprev = tab;
110637da2899SCharles.Forsyth }
110737da2899SCharles.Forsyth free(ibuf);
110837da2899SCharles.Forsyth
110937da2899SCharles.Forsyth tab = OPTION(place, TkTtabstop*, o->offset);
111037da2899SCharles.Forsyth if(tab != nil)
111137da2899SCharles.Forsyth free(tab);
111237da2899SCharles.Forsyth OPTION(place, TkTtabstop*, o->offset) = tabfirst;
111337da2899SCharles.Forsyth return nil;
111437da2899SCharles.Forsyth }
111537da2899SCharles.Forsyth
111637da2899SCharles.Forsyth char*
tkxyparse(Tk * tk,char ** parg,Point * p)111737da2899SCharles.Forsyth tkxyparse(Tk* tk, char **parg, Point *p)
111837da2899SCharles.Forsyth {
111937da2899SCharles.Forsyth char *buf;
112037da2899SCharles.Forsyth
112137da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
112237da2899SCharles.Forsyth if(buf == nil)
112337da2899SCharles.Forsyth return TkNomem;
112437da2899SCharles.Forsyth
112537da2899SCharles.Forsyth *parg = tkword(tk->env->top, *parg, buf, buf+Tkmaxitem, nil);
112637da2899SCharles.Forsyth if(*buf == '\0') {
112737da2899SCharles.Forsyth free(buf);
112837da2899SCharles.Forsyth return TkOparg;
112937da2899SCharles.Forsyth }
113037da2899SCharles.Forsyth p->x = atoi(buf);
113137da2899SCharles.Forsyth
113237da2899SCharles.Forsyth *parg = tkword(tk->env->top, *parg, buf, buf+Tkmaxitem, nil);
113337da2899SCharles.Forsyth if(*buf == '\0') {
113437da2899SCharles.Forsyth free(buf);
113537da2899SCharles.Forsyth return TkOparg;
113637da2899SCharles.Forsyth }
113737da2899SCharles.Forsyth p->y = atoi(buf);
113837da2899SCharles.Forsyth
113937da2899SCharles.Forsyth free(buf);
114037da2899SCharles.Forsyth return nil;
114137da2899SCharles.Forsyth }
114237da2899SCharles.Forsyth
114337da2899SCharles.Forsyth static char*
plist(TkTop * t,TkOption * o,void * place,char ** str,char * buf,char * ebuf)114437da2899SCharles.Forsyth plist(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf)
114537da2899SCharles.Forsyth {
114637da2899SCharles.Forsyth char *w, ***p, *wbuf, *ewbuf, **v, **nv;
114737da2899SCharles.Forsyth int n, m, i, found;
114837da2899SCharles.Forsyth
114937da2899SCharles.Forsyth *str = tkword(t, *str, buf, ebuf, nil);
115037da2899SCharles.Forsyth n = strlen(buf) + 1;
115137da2899SCharles.Forsyth wbuf = mallocz(n, 0);
115237da2899SCharles.Forsyth if (wbuf == nil)
115337da2899SCharles.Forsyth return TkNomem; /* XXX should we free old values too? */
115437da2899SCharles.Forsyth ewbuf = &wbuf[n];
115537da2899SCharles.Forsyth
115637da2899SCharles.Forsyth p = &OPTION(place, char**, o->offset);
115737da2899SCharles.Forsyth if (*p != nil){
115837da2899SCharles.Forsyth for (v = *p; *v; v++)
115937da2899SCharles.Forsyth free(*v);
116037da2899SCharles.Forsyth free(*p);
116137da2899SCharles.Forsyth }
116237da2899SCharles.Forsyth n = 0;
116337da2899SCharles.Forsyth m = 4;
116437da2899SCharles.Forsyth w = buf;
116537da2899SCharles.Forsyth v = malloc(m * sizeof(char*));
116637da2899SCharles.Forsyth if (v == nil)
116737da2899SCharles.Forsyth goto Error;
116837da2899SCharles.Forsyth for (;;) {
116937da2899SCharles.Forsyth w = tkword(t, w, wbuf, ewbuf, &found);
117037da2899SCharles.Forsyth if (!found)
117137da2899SCharles.Forsyth break;
117237da2899SCharles.Forsyth if (n == m - 1) {
117337da2899SCharles.Forsyth m += m/2;
117437da2899SCharles.Forsyth nv = realloc(v, m * sizeof(char*));
117537da2899SCharles.Forsyth if (nv == nil)
117637da2899SCharles.Forsyth goto Error;
117737da2899SCharles.Forsyth v = nv;
117837da2899SCharles.Forsyth }
117937da2899SCharles.Forsyth v[n] = strdup(wbuf);
118037da2899SCharles.Forsyth if (v[n] == nil)
118137da2899SCharles.Forsyth goto Error;
118237da2899SCharles.Forsyth n++;
118337da2899SCharles.Forsyth }
118437da2899SCharles.Forsyth v[n++] = nil;
118537da2899SCharles.Forsyth *p = realloc(v, n * sizeof(char*));
118637da2899SCharles.Forsyth free(wbuf);
118737da2899SCharles.Forsyth return nil;
118837da2899SCharles.Forsyth Error:
118937da2899SCharles.Forsyth free(buf);
119037da2899SCharles.Forsyth for (i = 0; i < n; i++)
119137da2899SCharles.Forsyth free(v[i]);
119237da2899SCharles.Forsyth free(v);
119337da2899SCharles.Forsyth *p = nil;
119437da2899SCharles.Forsyth return TkNomem;
119537da2899SCharles.Forsyth }
1196