From b8e58b0342d267fc88a4649b45bc702ed82e91ab Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Fri, 16 Dec 2016 09:28:13 +0100 Subject: [PATCH] Make parser more flexible, allow global properties to be anywhere in file and allow multiple similar entries. --- INSTALL.md | 2 ++ Makefile.am | 11 +++++++++++ doc/themer.md | 2 +- include/theme.h | 1 + lexer/theme-parser.y | 28 ++++++++++++---------------- source/theme.c | 33 +++++++++++++++++++++++++++------ test/box-test.c | 12 ++++++------ test/textbox-test.c | 2 +- 8 files changed, 61 insertions(+), 30 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 1097c9e2..f7fa0383 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,6 +9,8 @@ * autoconf * automake (1.11.3 or up) * pkg-config +* flex +* bison * Developer packages of the external libraries ### External libraries diff --git a/Makefile.am b/Makefile.am index fbdb155c..5b9389ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -273,6 +273,10 @@ box_test_CFLAGS=$(textbox_test_CFLAGS) box_test_SOURCES=\ source/widgets/widget.c\ source/widgets/box.c\ + lexer/theme-parser.y\ + lexer/theme-lexer.l\ + source/theme.c\ + inlucde/theme.h\ test/box-test.c scrollbar_test_LDADD=$(textbox_test_LDADD) @@ -280,11 +284,18 @@ scrollbar_test_CFLAGS=$(textbox_test_CFLAGS) scrollbar_test_SOURCES=\ source/widgets/widget.c\ source/widgets/scrollbar.c\ + lexer/theme-parser.y\ + lexer/theme-lexer.l\ + source/theme.c\ + inlucde/theme.h\ test/scrollbar-test.c textbox_test_SOURCES=\ source/widgets/widget.c\ source/widgets/textbox.c\ + lexer/theme-parser.y\ + lexer/theme-lexer.l\ + source/theme.c\ config/config.c\ include/keyb.h\ include/rofi.h\ diff --git a/doc/themer.md b/doc/themer.md index 60dc85cd..3ed2d0b7 100644 --- a/doc/themer.md +++ b/doc/themer.md @@ -106,7 +106,7 @@ The file is structured as follows } ``` -The global properties has to be at the top of the file, the rest can freeĺy be mixed. +The global properties an freeĺy be mixed between entries. Each property is constructed like: ``` diff --git a/include/theme.h b/include/theme.h index 2eac4601..a78d08f2 100644 --- a/include/theme.h +++ b/include/theme.h @@ -58,6 +58,7 @@ Property *rofi_theme_property_create ( PropertyType type ); void rofi_theme_property_free ( Property *p ); void rofi_theme_free ( Widget * ); void rofi_theme_parse_file ( const char *file ); +void rofi_theme_widget_add_properties ( Widget *widget, GHashTable *table ); /** * Public API diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index 94a3691c..3c64ee2d 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -66,12 +66,11 @@ int yylex (YYSTYPE *, YYLTYPE *); %% start: + entries optional_properties - entries { - $$ = $2; - if ( $1 != NULL ) { - $$->properties = $1; - } + { + $$ = $1; + rofi_theme_widget_add_properties ( $$, $2 ); } ; entries: @@ -80,7 +79,12 @@ entries: $$ = rofi_theme = (Widget*)g_malloc0 (sizeof(Widget)); rofi_theme->name = g_strdup ( "Window" ); } -| entries entry { $$ = $1; } +| entries + optional_properties + entry { + $$ = $1; + rofi_theme_widget_add_properties ( $$, $2); + } ; entry: @@ -96,11 +100,7 @@ CLASS_PREFIX class_name state_path BOPEN optional_properties BCLOSE g_list_foreach ( $3, (GFunc)g_free , NULL ); g_list_free ( $3 ); widget->set = TRUE; - if ( widget->properties != NULL ) { - fprintf(stderr, "Properties already set on this widget.\n"); - exit ( EXIT_FAILURE ); - } - widget->properties = $5; + rofi_theme_widget_add_properties ( widget, $5); } | NAME_PREFIX name_path state_path BOPEN optional_properties BCLOSE { @@ -117,11 +117,7 @@ CLASS_PREFIX class_name state_path BOPEN optional_properties BCLOSE g_list_foreach ( $3, (GFunc)g_free , NULL ); g_list_free ( $3 ); widget->set = TRUE; - if ( widget->properties != NULL ) { - fprintf(stderr, "Properties already set on this widget.\n"); - exit ( EXIT_FAILURE ); - } - widget->properties = $5; + rofi_theme_widget_add_properties ( widget, $5); }; /** diff --git a/source/theme.c b/source/theme.c index bce3c419..f555e0de 100644 --- a/source/theme.c +++ b/source/theme.c @@ -52,7 +52,7 @@ void rofi_theme_free ( Widget *widget ) g_hash_table_destroy ( widget->properties ); } for ( unsigned int i = 0; i < widget->num_widgets; i++ ){ - rofi_theme_free ( widget->widgets[i] ); + rofi_theme_free ( widget->widgets[i] ); } g_free ( widget->widgets ); g_free ( widget->name ); @@ -68,10 +68,10 @@ static void rofi_theme_print_property_index ( int depth, Property *p ) switch ( p->type ) { case P_STRING: - printf("\"%s\"", p->value.s); + printf("\"%s\"", p->value.s); break; case P_INTEGER: - printf("%d", p->value.i); + printf("%d", p->value.i); break; case P_DOUBLE: printf("%.2f", p->value.f); @@ -122,6 +122,27 @@ void yyerror(YYLTYPE *yylloc, const char* s) { fprintf(stderr, "From line %d column %d to line %d column %d\n", yylloc->first_line, yylloc->first_column, yylloc->last_line, yylloc->last_column); exit(EXIT_FAILURE); } + +static gboolean rofi_theme_steal_property_int ( gpointer key, gpointer value, gpointer user_data) +{ + GHashTable *table = (GHashTable*)user_data; + g_hash_table_replace ( table, key, value); + return TRUE; +} +void rofi_theme_widget_add_properties ( Widget *widget, GHashTable *table ) +{ + if ( table == NULL ) { + return; + } + if ( widget->properties == NULL ){ + widget->properties = table; + return; + } + g_hash_table_foreach_steal ( table, rofi_theme_steal_property_int, widget->properties ); + g_hash_table_destroy ( table ); +} + + /** * Public API */ @@ -159,7 +180,7 @@ static Widget *rofi_theme_find ( Widget *widget , const char *name ) widget = f; found = TRUE; } - } + } g_strfreev(names); return widget; } @@ -172,7 +193,7 @@ static Property *rofi_theme_find_property ( Widget *widget, PropertyType type, c if ( p->type == type ){ return p; } - } + } widget = widget->parent; } return NULL; @@ -260,7 +281,7 @@ double rofi_theme_get_double ( const char *wclass, const char *name, const char } return def; } -void rofi_theme_get_color ( const char *wclass, const char *name, const char *state, const char *property, cairo_t *d) +void rofi_theme_get_color ( const char *wclass, const char *name, const char *state, const char *property, cairo_t *d) { if ( rofi_theme == NULL ) { return ; diff --git a/test/box-test.c b/test/box-test.c index b9283d44..ce4d0b31 100644 --- a/test/box-test.c +++ b/test/box-test.c @@ -31,8 +31,8 @@ static gboolean test_widget_clicked ( G_GNUC_UNUSED widget *wid, G_GNUC_UNUSED x int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) { { - box *b = box_create ( BOX_HORIZONTAL, 0, 0, 100, 20 ); - box_set_padding ( b, 5 ); + box *b = box_create ( "box", BOX_HORIZONTAL, 0, 0, 100, 20 ); + //box_set_padding ( b, 5 ); widget *wid1 = g_malloc0(sizeof(widget)); box_add ( b , WIDGET( wid1 ), TRUE, FALSE ); @@ -92,8 +92,8 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) widget_free ( WIDGET ( b ) ); } { - box *b = box_create ( BOX_VERTICAL, 0, 0, 20, 100 ); - box_set_padding ( b, 5 ); + box *b = box_create ( "box", BOX_VERTICAL, 0, 0, 20, 100 ); + //box_set_padding ( b, 5 ); widget *wid1 = g_malloc0(sizeof(widget)); box_add ( b , WIDGET( wid1 ), TRUE, FALSE ); @@ -152,8 +152,8 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) widget_free ( WIDGET ( b ) ); } { - box *b = box_create ( BOX_VERTICAL, 0, 0, 20, 100 ); - box_set_padding ( b, 5 ); + box *b = box_create ( "box", BOX_VERTICAL, 0, 0, 20, 100 ); + //box_set_padding ( b, 5 ); widget *wid1 = g_malloc0(sizeof(widget)); widget_enable(wid1); wid1->clicked = test_widget_clicked; diff --git a/test/textbox-test.c b/test/textbox-test.c index 3fa33344..3196ab0e 100644 --- a/test/textbox-test.c +++ b/test/textbox-test.c @@ -53,7 +53,7 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) PangoContext *p = pango_cairo_create_context ( draw ); textbox_set_pango_context ( p ); - textbox *box = textbox_create ( TB_EDITABLE | TB_AUTOWIDTH | TB_AUTOHEIGHT, 0, 0, -1, -1, + textbox *box = textbox_create ( "textbox", TB_EDITABLE | TB_AUTOWIDTH | TB_AUTOHEIGHT, 0, 0, -1, -1, NORMAL, "test" ); TASSERT ( box != NULL );