ref: 58363833ce933924ef340eb53f0caa4d0d1f6ae5
dir: /props.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <ctype.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include <mouse.h> #include "guifs.h" #define Eparse "could not parse property" int allspace(char *r) { while(*r){ if(!isspace(*r)) return 0; r++; } return 1; } PropVal defcolour(int gtag, int ptag) { PropVal v; ulong col = DTransparent; switch(ptag){ case Pbackground: switch(gtag){ case Gcontainer: col = DWhite; break; case Gtextbox: col = 0xFFFFEAFF; break; } break; case Pbordercolour: switch(gtag){ case Gtextbox: col = DYellowgreen; break; default: col = DRed; break; } break; case Ptextcolour: col = DBlack; break; } v.colour = mkcolour(col); return v; } PropVal defspacing(int gtag, int ptag) { PropVal v; v.spacing = emalloc(sizeof(Spacing)); int space = 0; switch(ptag){ case Pborder: switch(gtag){ case Gtextbox: space = 4; break; } break; case Ppadding: switch(gtag){ case Gtextbox: space = 2; break; } break; } v.spacing->up = v.spacing->down = v.spacing->left = v.spacing->right = space; return v; } PropVal deforientation(int gtag, int ptag) { USED(gtag); USED(ptag); PropVal v; v.orientation = Horizontal; return v; } PropVal deftext(int gtag, int ptag) { USED(gtag); USED(ptag); PropVal v; v.text = emalloc(sizeof(Rune)); v.text[0] = 0; return v; } char * printcolour(PropVal p) { int bufsize = 64; char *buf = emalloc(bufsize); snprint(buf, bufsize, "%08ulX\n", p.colour->code); return buf; } char * printspacing(PropVal p) { int bufsize = 256; char *buf = emalloc(bufsize); snprint(buf, bufsize, "%d %d %d %d\n", p.spacing->up, p.spacing->right, p.spacing->down, p.spacing->left); return buf; } char * printorientation(PropVal p) { char *str; switch(p.orientation){ case Horizontal: str = estrdup9p("horizontal\n"); break; case Vertical: str = estrdup9p("vertical\n"); break; default: str = estrdup9p("???\n"); break; } return str; } char * printtext(PropVal p) { char *str = smprint("%S", p.text); if(str == nil) sysfatal("smprint failed"); return str; } char * parsecolour(char *str, PropVal *p) { char *r; ulong c = strtoul(str, &r, 16); if((r - str) != 8 || !allspace(r)) return Eparse; (*p).colour = mkcolour(c); return nil; } char * parsespacing(char *str, PropVal *p) { USED(p); char *fields[5]; int spacings[4]; int n = getfields(str, fields, nelem(fields), 0, " "); if(!(n == 4 || n == 2 || n == 1)) return Eparse; for(int i = 0; i < n; i++){ char *r; spacings[i] = strtol(fields[i], &r, 10); if(!allspace(r)) return Eparse; } Spacing *s = emalloc(sizeof(Spacing)); switch(n){ case 1: s->up = s->down = s->left = s->right = spacings[0]; break; case 2: s->up = s->down = spacings[0]; s->left = s->right = spacings[1]; break; case 4: s->up = spacings[0]; s->right = spacings[1]; s->down = spacings[2]; s->left = spacings[3]; break; } (*p).spacing = s; return nil; } char * parseorientation(char *str, PropVal *p) { if(strncmp(str, "horizontal", 10) == 0 && allspace(str+10)) (*p).orientation = Horizontal; else if(strncmp(str, "vertical", 8) == 0 && allspace(str+8)) (*p).orientation = Vertical; else return Eparse; return nil; } char * parsetext(char *str, PropVal *p) { Rune *rstr = runesmprint("%s", str); if(rstr == nil) sysfatal("runesmprint failed"); (*p).text = rstr; return nil; } PropVal getprop(GuiElement *g, int tag, int lock) { PropVal *v = nil; if(lock) rlock(&g->lock); for(int i = 0; i < g->nprops && v == nil; i++) if(g->props[i].tag == tag) v = &g->props[i].val; if(lock) runlock(&g->lock); if(v == nil) sysfatal("invalid prop for this gui element"); else return *v; } void setprop(GuiElement *g, int tag, PropVal val, int lock) { if(lock) wlock(&g->lock); /* TODO: free old propval */ for(int i = 0; i < g->nprops; i++) if(g->props[i].tag == tag) g->props[i].val = val; if(lock){ wunlock(&g->lock); updategui(0); /* Can't update gui if the user has write-locked g */ } } PropSpec propspecs[Pmax] = { [Pbackground] = {"background", defcolour, printcolour, parsecolour}, [Pborder] = {"border", defspacing, printspacing, parsespacing}, [Pmargin] = {"margin", defspacing, printspacing, parsespacing}, [Ppadding] = {"padding", defspacing, printspacing, parsespacing}, [Porientation] = {"orientation", deforientation, printorientation, parseorientation}, [Pbordercolour] = {"bordercolour", defcolour, printcolour, parsecolour}, [Ptext] = {"text", deftext, printtext, parsetext}, [Ptextcolour] = {"textcolour", defcolour, printcolour, parsecolour}, }; int baseprops[nbaseprops] = {Pbackground, Pborder, Pmargin, Ppadding, Pbordercolour};