ref: 7aeae86d36a1a04e93bb4be2216cb735acfab714
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 "guifs.h"
#define Eparse "could not parse property"
int
allspace(char *r)
{
while(*r){
if(!isspace(*r))
return 0;
r++;
}
return 1;
}
PropVal
defbackground(void)
{
PropVal v;
v.colour = mkcolour(DWhite);
return v;
}
PropVal
defspacing(void)
{
PropVal v;
v.spacing = emalloc(sizeof(Spacing));
return v;
}
PropVal
deforientation(void)
{
PropVal v;
v.orientation = Horizontal;
return v;
}
PropVal
defbordercolour(void)
{
PropVal v;
v.colour = mkcolour(DRed);
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 *
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;
}
PropVal
getprop(GuiElement *g, int tag)
{
PropVal *v = nil;
rlock(&g->lock);
for(int i = 0; i < g->nprops && v == nil; i++)
if(g->props[i].tag == tag)
v = &g->props[i].val;
runlock(&g->lock);
if(v == nil)
sysfatal("invalid prop for this gui element");
else
return *v;
}
void
setprop(GuiElement *g, int tag, PropVal val)
{
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;
wunlock(&g->lock);
updategui(0);
}
PropSpec propspecs[Pmax] = {
[Pbackground] = {"background", defbackground, printcolour, parsecolour},
[Pborder] = {"border", defspacing, printspacing, parsespacing},
[Pmargin] = {"margin", defspacing, printspacing, parsespacing},
[Ppadding] = {"padding", defspacing, printspacing, parsespacing},
[Porientation] = {"orientation", deforientation, printorientation, parseorientation},
[Pbordercolour] = {"bordercolour", defbordercolour, printcolour, parsecolour},
};
int baseprops[nbaseprops] = {Pborder, Pmargin, Ppadding, Pbordercolour};