ref: ab90a480eb5233abc4d7122739c24656dd42cc94
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};