From a8fcc550dd127f09929ba09be6c68bab363288e3 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 21 May 2010 11:56:19 -0400 Subject: [PATCH] add the new theme framework --- obtheme/.gitignore | 4 + obtheme/main.c | 35 ++++ obtheme/obtheme.c | 156 +++++++++++++++ obtheme/obtheme.h | 118 ++++++++++++ obtheme/obtheme.l | 176 +++++++++++++++++ obtheme/obtheme.y | 429 ++++++++++++++++++++++++++++++++++++++++++ obtheme/theme.obtheme | 106 +++++++++++ 7 files changed, 1024 insertions(+) create mode 100644 obtheme/.gitignore create mode 100644 obtheme/main.c create mode 100644 obtheme/obtheme.c create mode 100644 obtheme/obtheme.h create mode 100644 obtheme/obtheme.l create mode 100644 obtheme/obtheme.y create mode 100644 obtheme/theme.obtheme diff --git a/obtheme/.gitignore b/obtheme/.gitignore new file mode 100644 index 00000000..75b5c165 --- /dev/null +++ b/obtheme/.gitignore @@ -0,0 +1,4 @@ +*.o +obtheme +obtheme.lex.* +obtheme.tab.* diff --git a/obtheme/main.c b/obtheme/main.c new file mode 100644 index 00000000..8fd3794c --- /dev/null +++ b/obtheme/main.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include "obtheme.h" + +struct obthemedata themedata; + +int main(int argc, char **argv) +{ + int err; + struct theme *thm; + Rect br; + Strut bstrut; + + themedata.themes = g_hash_table_new(g_str_hash, g_str_equal); + themedata.materials = g_hash_table_new(g_str_hash, g_str_equal); + err = obtheme_parse(&themedata, argv[1]); + if (err) { + printf("Fix the script\n"); + exit(1); + } + printf("err = %d\n", err); + +// g_hash_table_foreach(themedata.materials, material_print, NULL); + +// g_hash_table_foreach(themedata.themes, theme_print, NULL); + + thm = g_hash_table_lookup(themedata.themes, "awesome"); + obtheme_decorate_window(thm, "regular_window"); + obtheme_calc_bound(thm, "regular_window", &br, &bstrut); + printf("bounding rectangle: (%d %d) - (%d %d)\n", br.x, br.y, br.x + br.width, br.y + br.height); + + return 0; +} diff --git a/obtheme/obtheme.c b/obtheme/obtheme.c new file mode 100644 index 00000000..dcafd842 --- /dev/null +++ b/obtheme/obtheme.c @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include "obtheme.h" +#include "geom.h" + +static double variable_lookup(struct variable *in) +{ + if (strcmp("client", in->base) == 0) { + if (strcmp("width", in->member) == 0) { + return 640; + } else + return 480; + } + if (strcmp("font", in->base) == 0) { + return 15.0; + } + return 0.0; +} + +static double expression_eval(struct expression *in) +{ + switch (in->op) { + case OB_THEME_INV: + return - expression_eval(in->a); + break; + case OB_THEME_MUL: + return expression_eval(in->a) * expression_eval(in->b); + break; + case OB_THEME_DIV: + return expression_eval(in->a) / expression_eval(in->b); + break; + case OB_THEME_ADD: + return expression_eval(in->a) + expression_eval(in->b); + break; + case OB_THEME_SUB: + return expression_eval(in->a) - expression_eval(in->b); + break; + case OB_THEME_EQL: + if (in->v.base == NULL) { + return in->v.number; + } else return variable_lookup(&in->v); + break; + default: + assert(!!!"OH NOES!!!"); + } + return 0; +} + +static void decor_print(gpointer data, gpointer user_data) +{ + struct decor *decor = data; + printf(" decor id %s\n", decor->name); +printf(" anchor.x = %f\n", expression_eval(&decor->space.anchor.x)); + if (decor->texture.present) { + if (decor->texture.internal) + printf(" texture internal: %s\n", decor->texture.name); + else + printf(" texture file: %s\n", decor->texture.name); + } +// printf(" anchor (%d %d %d)\n", decor->space.anchor.x, decor->space.anchor.y, decor->space.anchor.z); +// printf(" up (%d %d %d)\n", decor->space.up.x, decor->space.up.y, decor->space.up.z); + if (decor->children) + g_slist_foreach(decor->children, decor_print, NULL); +} + +static void style_print(gpointer key, gpointer value, gpointer user_data) +{ + char *stylename = key; + struct style *style = value; + + printf(" style %s\n", stylename); + g_slist_foreach(style->tree, decor_print, NULL); +} + +static void theme_print(gpointer key, gpointer value, gpointer user_data) +{ + char *name = key; + struct theme *thm = value; + printf("name = %s\n", name); + g_hash_table_foreach(thm->styles, style_print, NULL); +} + +static void material_print(gpointer key, gpointer value, gpointer user_data) +{ + char *name = key; + struct material *mat = value; + printf("name = %s\n", name); + printf(" opacity = %f\n", mat->opacity); +} + +static void decor_render(gpointer data, gpointer user_data) +{ + struct decor *decor = data; + struct box *box = &decor->geometry.box; + struct vector *a = &decor->space.anchor; + double x, y; + + printf("%s:", decor->name); + x = expression_eval(&a->x); + y = expression_eval(&a->y); + printf("rectangle(%f %f) - (%f %f)\n", x + expression_eval(&box->start.x), y + expression_eval(&box->start.y), + x + expression_eval(&box->end.x), y + expression_eval(&box->end.y)); + if (decor->children) + g_slist_foreach(decor->children, decor_render, NULL); +} + +struct boundstuff { + Rect r; + Strut s; +}; + +static void decor_bound(gpointer data, gpointer user_data) +{ + struct boundstuff *bs = user_data; + struct decor *decor = data; + struct box *box = &decor->geometry.box; + struct vector *a = &decor->space.anchor; + Rect newrect, temprect; + double x1, y1, x2, y2; + + x1 = expression_eval(&a->x); + y1 = expression_eval(&a->y); + x2 = x1; + y2 = y1; + x1 += expression_eval(&box->start.x); + y1 += expression_eval(&box->start.y); + x2 += expression_eval(&box->end.x); + y2 += expression_eval(&box->end.y); + RECT_SET(temprect, x1, y1, x2-x1, y2-y2); + RECT_ADD(newrect, temprect, bs->r); + bs->r = newrect; + + if (decor->children) + g_slist_foreach(decor->children, decor_bound, bs); +} + +void obtheme_calc_bound(struct theme *thm, char *name, Rect *r, Strut *s) +{ + struct style *sty; + struct boundstuff bs; + + RECT_SET(bs.r, 0, 0 ,0 ,0); + sty = g_hash_table_lookup(thm->styles, name); + assert(sty); + g_slist_foreach(sty->tree, decor_bound, &bs); + *r = bs.r; +} + +void obtheme_decorate_window(struct theme *thm, char *name) +{ + struct style *sty; + sty = g_hash_table_lookup(thm->styles, name); + g_slist_foreach(sty->tree, decor_render, NULL); +} diff --git a/obtheme/obtheme.h b/obtheme/obtheme.h new file mode 100644 index 00000000..59bf310f --- /dev/null +++ b/obtheme/obtheme.h @@ -0,0 +1,118 @@ +#ifndef __THEME_PARSE_H__ +#define __THEME_PARSE_H__ + +#include +#include "frame.h" +#include "misc.h" + +#undef YY_DECL +#define YY_DECL int obthemelex(YYSTYPE *yylval, struct parser_control *pc) + +#define YYDEBUG 1 +#define YYLEX_PARAM pc + +#define MAX_INCLUDE_DEPTH 32 +#define LINE pc->currline[pc->include_stack_ptr] + +extern int themedebug; + +struct boundrect { + double x1, y1, x2, y2; +}; + +typedef enum { + OB_THEME_INV, + OB_THEME_ADD, + OB_THEME_SUB, + OB_THEME_MUL, + OB_THEME_DIV, + OB_THEME_EQL +} ObThemeOp; + +struct variable { + char *base; + char *member; + double number; +}; + +struct expression { + ObThemeOp op; + struct expression *a; + struct expression *b; + struct variable v; +}; + +struct material { + float opacity; +}; + +struct style { + char *name; + GSList *tree; +}; + +struct obthemedata { + GHashTable *themes; + GHashTable *materials; +}; + +struct theme { + char *name; + GHashTable *styles; +}; + +struct vector { + struct expression x; + struct expression y; + struct expression z; +}; + +struct space { + struct vector anchor; + struct vector up; +}; + +struct texture { + gboolean present; + gboolean internal; + char *name; +}; + +struct box { + struct vector start; + struct vector end; +}; + +struct geometry { + struct box box; +}; + +struct decor { + char *name; + GSList *children; + struct space space; + ObDirection cursor; + ObFrameContext context; + struct texture texture; + struct material *material; + struct geometry geometry; +}; + +struct parser_control { + struct yy_buffer_state *include_stack[MAX_INCLUDE_DEPTH]; + int currline[MAX_INCLUDE_DEPTH]; + char currfile[MAX_INCLUDE_DEPTH][501]; + int include_stack_ptr; + char error_buf[4096]; + struct obthemedata *target; +}; + +void obthemeerror(struct parser_control *pc, char *s); +int obtheme_parse(struct obthemedata *td, const char *filename); +struct parser_control *parser_init(struct obthemedata *td); +int obthemeparse(struct parser_control *); +void parser_finish(struct parser_control *); +void obtheme_calc_bound(struct theme *thm, char *name, Rect *r, Strut *s); +void obtheme_decorate_window(struct theme *thm, char *name); + +#endif /* __THEME_PARSE_H__ */ diff --git a/obtheme/obtheme.l b/obtheme/obtheme.l new file mode 100644 index 00000000..0806e10b --- /dev/null +++ b/obtheme/obtheme.l @@ -0,0 +1,176 @@ +%{ +#include +#include +#include +#include +#include +#include "frame.h" +#include "misc.h" +#include "render.h" +#include "obtheme.h" +#include "obtheme.tab.h" + +int yylex(YYSTYPE *yylval, struct parser_control *pc); + +void obthemeerror(struct parser_control *pc, char *s) +{ + printf("Parse error in file %s on line %d\n%s" + , pc->currfile[pc->include_stack_ptr] + , pc->currline[pc->include_stack_ptr] + 1 + , pc->error_buf); +} + +extern int parserparse(void *); + +int yywrap(void) +{ + return 1; +} + +int obtheme_parse(struct obthemedata *td, const char *filename) +{ + FILE *input; + int ret; + struct parser_control *pc; +//illdebug = 1; + pc = parser_init(td); + input = fopen(filename, "r"); + if (!input) + return 2; + yyin = input; + yyrestart(input); + BEGIN 0; + pc->include_stack_ptr = 0; + pc->currline[pc->include_stack_ptr] = 0; + strncpy(pc->currfile[pc->include_stack_ptr], filename, 500); + ret = obthemeparse(pc); + if (ret != 0) { + //XXX I THINK I NEED TO CLOSE ALL INCLUDE FILES HERE + //probably also fclose input and call parser_finish? + return ret; + } + fclose(input); + parser_finish(pc); + return ret; +} + +%} +%x comment +%x incl +%% + +include BEGIN(incl); +[ \t]* /* eat the whitespace */ +[^ \t\n]+ { /* got the include file name */ + char *incfile; + if ( pc->include_stack_ptr >= MAX_INCLUDE_DEPTH) { + fprintf( stderr, "Includes nested too deeply" ); + exit(1); + } + + pc->include_stack[pc->include_stack_ptr++] = YY_CURRENT_BUFFER; + incfile = malloc(strlen(yytext) + strlen("include/")+ 1); + strcpy(incfile, "include/"); + strcat(incfile, yytext); + yyin = fopen( incfile, "r" ); + free(incfile); + strncpy(pc->currfile[pc->include_stack_ptr], yytext, 500); + pc->currline[pc->include_stack_ptr] = 0; + if ( ! yyin ) { + printf("Could not find include file %s (%s)\n", yytext, incfile); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + + BEGIN(INITIAL); + } + +<> { + if ( --(pc->include_stack_ptr) < 0 ) + { + yy_delete_buffer(YY_CURRENT_BUFFER); + yyterminate(); + } + + else + { + yy_delete_buffer( YY_CURRENT_BUFFER ); + fclose(yyin); + yy_switch_to_buffer( + pc->include_stack[pc->include_stack_ptr] ); + } + } + + +"//"+[^\n]* ; +"/*" BEGIN(comment); +[^*\n]* ; +"*"+[^*/\n]* ; +"*"+"/" BEGIN(INITIAL); +\n LINE++; + +theme return THEME; +frame return FRAME; +decor return DECOR; +space return SPACE; +geometry return GEOMETRY; +material return MATERIAL; +gradient return GRADIENT; +context return CONTEXT; +cursor return CURSOR; +style return STYLE; +up return UP; +anchor return ANCHOR; +opacity return OPACITY; +shapeof return SHAPEOF; +texture return TEXTURE; +image return IMAGE; +to return TO; +box return BOX; +NORTH return NORTH; +NORTHEAST return NORTHEAST; +EAST return EAST; +SOUTHEAST return SOUTHEAST; +SOUTH return SOUTH; +SOUTHWEST return SOUTHWEST; +WEST return WEST; +NORTHWEST return NORTHWEST; +NONE return NONE; +UNCHANGED return UNCHANGED; + +0x[0-9A-Z]+ yylval->integer = strtol(yytext, (char **)NULL, 16); return NUMBER; +[0-9]+ yylval->integer = atoi(yytext); return NUMBER; +[a-zA-Z_][a-zA-Z0-9_]* yylval->string = g_strdup(yytext); return ID; +\".*\" { + yylval->string = g_strdup(yytext+1); + yylval->string[strlen(yylval->string)-1] = 0; + return STRING; + } +\`[^`]*\` { + yylval->string = g_strdup(yytext+1); + yylval->string[strlen(yylval->string)-1] = 0; + return STRING; + } + +\$[a-zA-Z_][a-zA-Z0-9_]* yylval->string = g_strdup(yytext+1); return ID; +\$[0-9]* yylval->integer = strtol(yytext + 1, (char **)NULL, 16); return SUBST; +\@ return AT; +: return COLON; +; return SEMICOLON; +"+" return PLUS; +"-" return MINUS; +"}" return RCB; +"{" return LCB; +")" return RB; +"(" return LB; +"<-" return LEFT_ARROW; +"->" return RIGHT_ARROW; +"<->" return DOUBLE_ARROW; +"." return DOT; +"*" return STAR; +"/" return SLASH; +"," return COMMA; +\n LINE++; /* zap EOL */ +[ \t]+ ; /* and whitespace */ +. return 0; +%% diff --git a/obtheme/obtheme.y b/obtheme/obtheme.y new file mode 100644 index 00000000..e4e07dc2 --- /dev/null +++ b/obtheme/obtheme.y @@ -0,0 +1,429 @@ +%pure-parser +%name-prefix "obtheme" +%parse-param {struct parser_control *pc} +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include "frame.h" +#include "misc.h" +#include "render.h" +#include "obtheme.h" +#include "obtheme.tab.h" + +YY_DECL; + +struct context_table_item { + char *name; + ObFrameContext val; +}; + +/* some of these contexts don't make any sense for a theme... */ +static struct context_table_item contexts[OB_FRAME_NUM_CONTEXTS] = { + {"none", OB_FRAME_CONTEXT_NONE}, + {"desktop", OB_FRAME_CONTEXT_DESKTOP}, + {"root", OB_FRAME_CONTEXT_ROOT}, + {"client", OB_FRAME_CONTEXT_CLIENT}, + {"titlebar", OB_FRAME_CONTEXT_TITLEBAR}, + {"frame", OB_FRAME_CONTEXT_FRAME}, + {"blcorner", OB_FRAME_CONTEXT_BLCORNER}, + {"brcorner", OB_FRAME_CONTEXT_BRCORNER}, + {"tlcorner", OB_FRAME_CONTEXT_TLCORNER}, + {"trcorner", OB_FRAME_CONTEXT_TRCORNER}, + {"top", OB_FRAME_CONTEXT_TOP}, + {"bottom", OB_FRAME_CONTEXT_BOTTOM}, + {"left", OB_FRAME_CONTEXT_LEFT}, + {"right", OB_FRAME_CONTEXT_RIGHT}, + {"maximize", OB_FRAME_CONTEXT_MAXIMIZE}, + {"alldesktops", OB_FRAME_CONTEXT_ALLDESKTOPS}, + {"shade", OB_FRAME_CONTEXT_SHADE}, + {"iconify", OB_FRAME_CONTEXT_ICONIFY}, + {"icon", OB_FRAME_CONTEXT_ICON}, + {"close", OB_FRAME_CONTEXT_CLOSE}, + {"moveresize", OB_FRAME_CONTEXT_MOVE_RESIZE} +}; + +static ObFrameContext context_from_string(char *str) +{ + int i; + for (i = 0; i < OB_FRAME_NUM_CONTEXTS; i++) + if (strcmp(contexts[i].name, str) == 1) + return contexts[i].val; + return -1; +} + +struct gradient_table_item { + char *name; + RrSurfaceColorType val; +}; + +struct gradient_table_item gradients[RR_SURFACE_NUM_TYPES] = { + {"none", RR_SURFACE_NONE}, + {"parentrel", RR_SURFACE_PARENTREL}, + {"solid", RR_SURFACE_SOLID}, + {"split", RR_SURFACE_SPLIT_VERTICAL}, + {"horizontal", RR_SURFACE_HORIZONTAL}, + {"vertical", RR_SURFACE_VERTICAL}, + {"diagonal", RR_SURFACE_DIAGONAL}, + {"cross_diagonal", RR_SURFACE_CROSS_DIAGONAL}, + {"pyramid", RR_SURFACE_PYRAMID}, + {"mirror_horizontal", RR_SURFACE_MIRROR_HORIZONTAL}, +}; + +static RrSurfaceColorType gradient_from_string(char *str) +{ + int i; + + for (i = 0; i < RR_SURFACE_NUM_TYPES; i++) + if (strcmp(gradients[i].name, str) == 1) + return gradients[i].val; + + return -1; +} + +struct parser_control *parser_init(struct obthemedata *otd) +{ + struct parser_control *out; + out = calloc(1, sizeof(struct parser_control)); + out->include_stack_ptr = 0; + out->target = otd; + return out; +} + +void parser_finish(struct parser_control *c) +{ + free(c); +} + +struct expression *exdup(struct expression in) +{ + struct expression *out; + out = malloc(sizeof(struct expression)); + *out = in; + return out; +} + +%} +%start theme_objects + +%union { + int integer; + float realnum; + char *string; + struct decor decor; + struct space space; + struct theme theme; + struct material material; + struct style style; + GSList *list; + GHashTable *hash; + struct vector vector; + ObCursor dir; + ObFrameContext context; + RrSurfaceColorType gradient; + struct expression expr; + struct variable var; + struct texture tex; + struct material *matptr; + struct box box; + struct geometry geometry; +} + +%token NORTH NORTHEAST EAST SOUTHEAST SOUTH SOUTHWEST +%token WEST NORTHWEST NONE UNCHANGED +%token LCB RCB LB RB TO +%token LEFT_ARROW RIGHT_ARROW DOUBLE_ARROW +%token SEMICOLON AT COLON DEFAULT NOT +%token PLUS MINUS STAR SLASH COMMA BOX +%token STRING ID +%token NUMBER SUBST BULK BIG LITTLE +%token THEME FRAME SPACE GEOMETRY MATERIAL GRADIENT +%token CONTEXT CURSOR UP ANCHOR STYLE TEXTURE OPACITY +%token SHAPEOF DECOR DOT IMAGE +%type decor +%type decoritems styleitem +%type space +%type