From fd64bb7a41bf72ad19df772a2cae336ded484b87 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 12 Dec 2016 23:40:43 +0100 Subject: Improve lexer by adding support for modes. --- include/theme.h | 9 +++++---- lexer/theme-lexer.l | 40 ++++++++++++++++++++++++---------------- lexer/theme-parser.y | 34 +++++++++++++++++++++------------- source/theme.c | 32 ++++++++++++++++++++++++++------ source/view.c | 12 ++++++------ source/widgets/box.c | 2 +- source/widgets/listview.c | 14 +++++++------- source/widgets/separator.c | 2 +- 8 files changed, 91 insertions(+), 54 deletions(-) diff --git a/include/theme.h b/include/theme.h index ba0581ab..2eac4601 100644 --- a/include/theme.h +++ b/include/theme.h @@ -35,6 +35,7 @@ typedef struct { } Property; typedef struct _Widget { + int set; char *name; unsigned int num_widgets; @@ -62,9 +63,9 @@ void rofi_theme_parse_file ( const char *file ); * Public API */ -int rofi_theme_get_integer ( const char *name, const char *property, int def ); -int rofi_theme_get_boolean ( const char *name, const char *property, int def ); -char *rofi_theme_get_string ( const char *name, const char *property, char *def ); -double rofi_theme_get_double ( const char *name, const char *property, double def ); +int rofi_theme_get_integer ( const char *wclass, const char *name, const char *state, const char *property, int def ); +int rofi_theme_get_boolean ( const char *wclass, const char *name, const char *state, const char *property, int def ); +char *rofi_theme_get_string ( const char *wclass, const char *name, const char *state, const char *property, char *def ); +double rofi_theme_get_double ( const char *wclass, const char *name, const char *state, const char *property, double def ); void rofi_theme_get_color ( const char *wclass, const char *name, const char *state, const char *property, cairo_t *d); #endif diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l index a540c229..a645138a 100644 --- a/lexer/theme-lexer.l +++ b/lexer/theme-lexer.l @@ -22,6 +22,9 @@ WORD [_\-a-zA-Z0-9]+ STRING [ \t_\-a-zA-Z0-9]+ HEX [0-9a-fA-F] NUMBER [0-9] + +%x PROPERTIES +%x NAMESTR %% %{ @@ -64,20 +67,24 @@ YY_LLOC_START } "\{" { return BOPEN;} -"\}" { return BCLOSE;} -":" { return PSEP; } -";" { return PCLOSE;} -"." { return NSEP; } -"#" { return NAME_PREFIX;} -(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;} -{NUMBER}+ { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;} -{NUMBER}+\.{NUMBER}+ { yylval->fval = g_ascii_strtod(yytext, NULL); return T_DOUBLE;} -@{WORD} { yylval->sval = g_strdup(yytext); return CLASS_NAME; } +"@" { BEGIN(NAMESTR);return CLASS_PREFIX;} +"#" { BEGIN(NAMESTR);return NAME_PREFIX;} +"\}" { return BCLOSE;} +"." { return NSEP; } {WORD} { yylval->sval = g_strdup(yytext); return N_STRING;} -{WHITESPACE} ; // ignore all whitespace -\"{STRING}\" { yytext[yyleng-1] = '\0'; yylval->sval = g_strdup(&yytext[1]); return T_STRING;} +{WORD} { yylval->sval = g_strdup(yytext); return NAME_ELEMENT;} + +{WHITESPACE} { BEGIN(INITIAL);} +{WHITESPACE}+ ; // ignore all whitespace +{WHITESPACE}+ ; // ignore all whitespace -#{HEX}{8} { +":" { BEGIN(PROPERTIES); return PSEP; } +";" { BEGIN(0); return PCLOSE;} +(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;} +{NUMBER}+ { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;} +{NUMBER}+\.{NUMBER}+ { yylval->fval = g_ascii_strtod(yytext, NULL); return T_DOUBLE;} +\"{STRING}\" { yytext[yyleng-1] = '\0'; yylval->sval = g_strdup(&yytext[1]); return T_STRING;} +#{HEX}{8} { union { unsigned int val; struct { unsigned char b,g,r,a;};} val; val.val = (unsigned int)strtoull ( &yytext[1], NULL, 16); yylval->colorval.alpha = val.a/255.0; @@ -86,7 +93,7 @@ YY_LLOC_START yylval->colorval.blue = val.b/255.0; return T_COLOR; } -#{HEX}{6} { +#{HEX}{6} { union { unsigned int val; struct { unsigned char b,g,r,a;};} val; val.val = (unsigned int)g_ascii_strtoull ( &yytext[1], NULL, 16); yylval->colorval.alpha = 1.0; @@ -95,7 +102,7 @@ YY_LLOC_START yylval->colorval.blue = val.b/255.0; return T_COLOR; } -rgba\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3},[01](\.{NUMBER}+)?\) { +rgba\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3},[01](\.{NUMBER}+)?\) { char *endptr = &yytext[5]; yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10); yylval->colorval.green= g_ascii_strtoull ( endptr+1, &endptr, 10); @@ -103,7 +110,7 @@ rgba\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3},[01](\.{NUMBER}+)?\) { yylval->colorval.alpha= g_ascii_strtod ( endptr+1, NULL); return T_COLOR; } -rgb\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3}\) { +rgb\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3}\) { char *endptr = &yytext[4]; yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10); yylval->colorval.green = g_ascii_strtoull ( endptr+1, &endptr, 10); @@ -111,7 +118,8 @@ rgb\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3}\) { yylval->colorval.alpha = 1.0; return T_COLOR; } -(\r\n|\n) { + +<*>(\r\n|\n) { yylloc->last_column = 1; yylloc->last_line ++; }; diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index aa82cdcf..468691ac 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -1,5 +1,5 @@ %define api.pure -%glr-parser +%glr-parser %skeleton "glr.c" %locations %debug @@ -36,9 +36,11 @@ int yylex (YYSTYPE *, YYLTYPE *); %token T_DOUBLE %token T_STRING %token N_STRING +%token NAME_ELEMENT %token T_BOOLEAN %token T_COLOR %token CLASS_NAME +%token FIRST_NAME %token BOPEN "bracket open"; %token BCLOSE "bracket close"; @@ -46,10 +48,12 @@ int yylex (YYSTYPE *, YYLTYPE *); %token PCLOSE "property close"; %token NSEP "Name separator"; %token CLASS_PREFIX "Class prefix"; -%token NAME_PREFIX "Name prefix"; +%token NAME_PREFIX "Name prefix"; +%token WHITESPACE "White space"; %type entry %type pvalue +%type class_name %type entries %type start %type name_path @@ -80,23 +84,26 @@ entries: ; entry: -CLASS_NAME state_path BOPEN optional_properties BCLOSE +CLASS_PREFIX class_name state_path BOPEN optional_properties BCLOSE { - Widget *widget = rofi_theme_find_or_create_class ( rofi_theme , $1 ); - for ( GList *iter = g_list_first ( $2 ); iter ; iter = g_list_next ( iter ) ) { + gchar *classn = g_strconcat ( "@", $2, NULL); + Widget *widget = rofi_theme_find_or_create_class ( rofi_theme , classn ); + g_free(classn); + for ( GList *iter = g_list_first ( $3 ); iter ; iter = g_list_next ( iter ) ) { widget = rofi_theme_find_or_create_class ( widget, iter->data ); } - g_list_foreach ( $2, (GFunc)g_free , NULL ); - g_list_free ( $2 ); + 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 = $4; + widget->properties = $5; } | NAME_PREFIX name_path state_path BOPEN optional_properties BCLOSE { - Widget *widget = rofi_theme; + Widget *widget = rofi_theme; for ( GList *iter = g_list_first ( $2 ); iter ; iter = g_list_next ( iter ) ) { widget = rofi_theme_find_or_create_class ( widget, iter->data ); } @@ -107,6 +114,7 @@ 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 ); @@ -162,16 +170,16 @@ property ; pvalue: N_STRING { $$ = $1; } +class_name: NAME_ELEMENT {$$ = $1;} name_path: - %empty { $$ = NULL; } -| N_STRING { $$ = g_list_append ( NULL, $1 );} -| name_path NSEP N_STRING { $$ = g_list_append ( $1, $3);} +NAME_ELEMENT { $$ = g_list_append ( NULL, $1 );} +| name_path NSEP NAME_ELEMENT { $$ = g_list_append ( $1, $3);} ; state_path: %empty { $$ = NULL; } -| N_STRING { $$ = g_list_append ( NULL, $1 );} +| N_STRING { $$ = g_list_append ( NULL, $1 );} | state_path NSEP N_STRING { $$ = g_list_append ( $1, $3);} ; diff --git a/source/theme.c b/source/theme.c index 5f99d4b0..e15016a8 100644 --- a/source/theme.c +++ b/source/theme.c @@ -171,12 +171,17 @@ static Property *rofi_theme_find_property ( Widget *widget, PropertyType type, c return NULL; } -int rofi_theme_get_integer ( const char *name, const char *property, int def ) +int rofi_theme_get_integer ( const char *wclass, const char *name, const char *state, const char *property, int def ) { if ( rofi_theme == NULL ) { return def; } Widget *widget = rofi_theme_find ( rofi_theme, name ); + if ( widget == rofi_theme || widget->set == FALSE ){ + // Fall back to class + widget = rofi_theme_find ( rofi_theme, wclass); + } + widget = rofi_theme_find ( widget, state ); Property *p = rofi_theme_find_property ( widget, P_INTEGER, property ); if ( p ){ return p->value.i; @@ -184,12 +189,17 @@ int rofi_theme_get_integer ( const char *name, const char *property, int def ) return def; } -int rofi_theme_get_boolean ( const char *name, const char *property, int def ) +int rofi_theme_get_boolean ( const char *wclass, const char *name, const char *state, const char *property, int def ) { if ( rofi_theme == NULL ) { return def; } Widget *widget = rofi_theme_find ( rofi_theme, name ); + if ( widget == rofi_theme || widget->set == FALSE ){ + // Fall back to class + widget = rofi_theme_find ( rofi_theme, wclass); + } + widget = rofi_theme_find ( widget, state ); Property *p = rofi_theme_find_property ( widget, P_BOOLEAN, property ); if ( p ){ return p->value.b; @@ -197,24 +207,34 @@ int rofi_theme_get_boolean ( const char *name, const char *property, int def ) return def; } -char *rofi_theme_get_string ( const char *name, const char *property, char *def ) +char *rofi_theme_get_string ( const char *wclass, const char *name, const char *state, const char *property, char *def ) { if ( rofi_theme == NULL ) { return def; } Widget *widget = rofi_theme_find ( rofi_theme, name ); + if ( widget == rofi_theme || widget->set == FALSE ){ + // Fall back to class + widget = rofi_theme_find ( rofi_theme, wclass); + } + widget = rofi_theme_find ( widget, state ); Property *p = rofi_theme_find_property ( widget, P_STRING, property ); if ( p ){ return p->value.s; } return def; } -double rofi_theme_get_double ( const char *name, const char *property, double def ) +double rofi_theme_get_double ( const char *wclass, const char *name, const char *state, const char *property, double def ) { if ( rofi_theme == NULL ) { return def; } Widget *widget = rofi_theme_find ( rofi_theme, name ); + if ( widget == rofi_theme || widget->set == FALSE ){ + // Fall back to class + widget = rofi_theme_find ( rofi_theme, wclass); + } + widget = rofi_theme_find ( widget, state ); Property *p = rofi_theme_find_property ( widget, P_DOUBLE, property ); if ( p ){ return p->value.b; @@ -227,9 +247,9 @@ void rofi_theme_get_color ( const char *wclass, const char *name, const char *s return ; } Widget *widget = rofi_theme_find ( rofi_theme, name ); - if ( widget == rofi_theme ){ + if ( widget == rofi_theme || widget->set == FALSE ){ // Fall back to class - widget = rofi_theme_find ( widget, wclass); + widget = rofi_theme_find ( rofi_theme, wclass); } widget = rofi_theme_find ( widget, state ); Property *p = rofi_theme_find_property ( widget, P_COLOR, property ); diff --git a/source/view.c b/source/view.c index 416e4e24..104dcdff 100644 --- a/source/view.c +++ b/source/view.c @@ -586,7 +586,7 @@ void __create_window ( MenuFlags menu_flags ) pango_cairo_font_map_set_resolution ( (PangoCairoFontMap *) font_map, (double) config.dpi ); } // Setup font. - char *font = rofi_theme_get_string ("window", "font" , config.menu_font ); + char *font = rofi_theme_get_string ("@widnow" , "window", NULL, "font" , config.menu_font ); if ( font ) { PangoFontDescription *pfd = pango_font_description_from_string ( font ); pango_context_set_font_description ( p, pfd ); @@ -794,7 +794,7 @@ void rofi_view_update ( RofiViewState *state ) color_border ( d ); rofi_theme_get_color ( "@window", "window" , NULL, "foreground", d ); - int bw = rofi_theme_get_integer ( "window", "border-width" , config.menu_bw); + int bw = rofi_theme_get_integer ( "@window", "window", NULL, "border-width" , config.menu_bw); if ( bw > 0 ) { cairo_save ( d ); cairo_set_line_width ( d, bw ); @@ -1422,8 +1422,8 @@ RofiViewState *rofi_view_create ( Mode *sw, state->finalize = finalize; state->mouse_seen = FALSE; - state->border = rofi_theme_get_integer ( "window", "padding" , config.padding ); - state->border += rofi_theme_get_integer ( "window", "border-width" , config.menu_bw); + state->border = rofi_theme_get_integer ("@window", "window", NULL, "padding" , config.padding ); + state->border += rofi_theme_get_integer ("@window", "window", NULL, "border-width" , config.menu_bw); // Request the lines to show. state->num_lines = mode_get_num_entries ( sw ); @@ -1542,8 +1542,8 @@ int rofi_view_error_dialog ( const char *msg, int markup ) state->retv = MENU_CANCEL; state->menu_flags = MENU_ERROR_DIALOG; state->finalize = process_result; - state->border = rofi_theme_get_integer ( "window", "padding" , config.padding ); - state->border += rofi_theme_get_integer ( "window", "border-width" , config.menu_bw); + state->border = rofi_theme_get_integer ( "@window", "window", NULL, "padding" , config.padding ); + state->border += rofi_theme_get_integer ( "@window", "window", NULL, "border-width" , config.menu_bw); rofi_view_calculate_window_and_element_width ( state ); state->main_box = box_create ( "mainbox.box", BOX_VERTICAL, diff --git a/source/widgets/box.c b/source/widgets/box.c index 9fb14f0f..32680696 100644 --- a/source/widgets/box.c +++ b/source/widgets/box.c @@ -290,7 +290,7 @@ box * box_create ( const char *name, boxType type, short x, short y, short w, sh b->widget.motion_notify = box_motion_notify; b->widget.enabled = TRUE; - box_set_padding ( b, rofi_theme_get_integer ( b->widget.name, "padding",config.line_margin )); + box_set_padding ( b, rofi_theme_get_integer ( "@box", b->widget.name, NULL, "padding",config.line_margin )); return b; } diff --git a/source/widgets/listview.c b/source/widgets/listview.c index 6febaec2..2c248fb0 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -337,13 +337,13 @@ listview *listview_create ( const char *name, listview_update_callback cb, void lv->udata = udata; // Some settings. - lv->padding = rofi_theme_get_integer ( lv->widget.name, "padding", config.line_margin ); - lv->menu_lines = rofi_theme_get_integer ( lv->widget.name, "lines", config.menu_lines ); - lv->menu_columns = rofi_theme_get_integer ( lv->widget.name, "columns", config.menu_columns); - lv->fixed_num_lines = rofi_theme_get_boolean ( lv->widget.name, "fixed-height", config.fixed_num_lines ); - listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( lv->widget.name, "scrollbar", !config.hide_scrollbar )); - listview_set_scrollbar_width ( lv, rofi_theme_get_integer ( lv->widget.name, "scrollbar-width", config.scrollbar_width )); - lv->cycle = rofi_theme_get_boolean ( lv->widget.name, "cycle", config.cycle ); + lv->padding = rofi_theme_get_integer ("@listview", lv->widget.name, NULL, "padding", config.line_margin ); + lv->menu_lines = rofi_theme_get_integer ("@listview", lv->widget.name, NULL, "lines", config.menu_lines ); + lv->menu_columns = rofi_theme_get_integer ("@listview", lv->widget.name, NULL, "columns", config.menu_columns); + lv->fixed_num_lines = rofi_theme_get_boolean ("@listview", lv->widget.name, NULL, "fixed-height", config.fixed_num_lines ); + listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( "@listview", lv->widget.name, NULL, "scrollbar", !config.hide_scrollbar )); + listview_set_scrollbar_width ( lv, rofi_theme_get_integer ( "@listview", lv->widget.name, NULL, "scrollbar-width", config.scrollbar_width )); + lv->cycle = rofi_theme_get_boolean ( "@listview", lv->widget.name, NULL, "cycle", config.cycle ); return lv; diff --git a/source/widgets/separator.c b/source/widgets/separator.c index 46a65c1a..295ba95f 100644 --- a/source/widgets/separator.c +++ b/source/widgets/separator.c @@ -88,7 +88,7 @@ separator *separator_create ( const char *name, separator_type type, short sw ) // Enabled by default sb->widget.enabled = TRUE; - const char *line_style = rofi_theme_get_string ( sb->widget.name, "line-style", "solid"); + const char *line_style = rofi_theme_get_string ( "@scrollbar", sb->widget.name, NULL, "line-style", "solid"); separator_set_line_style_from_string ( sb, line_style ); return sb; } -- cgit v1.2.3