1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright 2013-2017 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
28 %define api.pure
29 %define parse.error verbose
30 %locations
31 %glr-parser
32 %skeleton "glr.c"
33 %debug
34 %parse-param {const char *what}
35 %code requires {
36 #include "theme.h"
37 #include "xrmoptions.h"
38 #include "css-colors.h"
39 
40 typedef struct YYLTYPE {
41   int first_line;
42   int first_column;
43   int last_line;
44   int last_column;
45   char *filename;
46 } YYLTYPE;
47 # define YYLTYPE_IS_DECLARED 1 /* alert the parser that we have our own definition */
48 
49 # define YYLLOC_DEFAULT(Current, Rhs, N)                               \
50     do                                                                 \
51       if (N)                                                           \
52         {                                                              \
53           (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;       \
54           (Current).first_column = YYRHSLOC (Rhs, 1).first_column;     \
55           (Current).last_line    = YYRHSLOC (Rhs, N).last_line;        \
56           (Current).last_column  = YYRHSLOC (Rhs, N).last_column;      \
57           (Current).filename     = YYRHSLOC (Rhs, 1).filename;         \
58         }                                                              \
59       else                                                             \
60         { /* empty RHS */                                              \
61           (Current).first_line   = (Current).last_line   =             \
62             YYRHSLOC (Rhs, 0).last_line;                               \
63           (Current).first_column = (Current).last_column =             \
64             YYRHSLOC (Rhs, 0).last_column;                             \
65           (Current).filename  = NULL;                        /* new */ \
66         }                                                              \
67     while (0)
68 }
69 %{
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <glib.h>
73 
74 #include "theme-parser.h"
75 ThemeWidget *rofi_theme = NULL;
76 void yyerror(YYLTYPE *yylloc, const char *what, const char* s);
77 int yylex (YYSTYPE *, YYLTYPE *);
78 
79 
check_in_range(double index,double low,double high,YYLTYPE * loc)80 static int check_in_range ( double index, double low, double high, YYLTYPE *loc )
81 {
82     if ( index > high || index < low ){
83         gchar *str = g_strdup_printf("Value out of range: \n\t\tValue: X = %.2lf;\n\t\tRange: %.2lf <= X <= %.2lf.", index, low, high );
84         yyerror ( loc, loc->filename, str);
85         g_free(str);
86         return FALSE;
87     }
88 
89     return TRUE;
90 }
91 
hue2rgb(double p,double q,double t)92 static double hue2rgb(double p, double q, double t){
93     t += (t<0)?1.0:0.0;
94     t -= (t>1)?1.0:0.0;
95     if( t < (1/6.0) ) {
96          return p + (q - p) * 6 * t;
97     }
98     if( t < (1/2.0) ) {
99          return q;
100     }
101     if( t < (2/3.0) ) {
102         return p + (q - p) * (2/3.0 - t) * 6;
103     }
104     return p;
105 }
hsl_to_rgb(double h,double s,double l)106 static ThemeColor hsl_to_rgb ( double h, double s, double l )
107 {
108     ThemeColor colour;
109     colour.alpha = 1.0;
110 
111     if(s <  0.001 && s > -0.001){
112         colour.red = colour.green = colour.blue = l; // achromatic
113     }else{
114 
115         double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
116         double p = 2 * l - q;
117         colour.red   = hue2rgb(p, q, h + 1/3.0);
118         colour.green = hue2rgb(p, q, h);
119         colour.blue  = hue2rgb(p, q, h - 1/3.0);
120     }
121 
122     return colour;
123 }
hwb_to_rgb(double h,double w,double b)124 static ThemeColor hwb_to_rgb ( double h, double w, double b)
125 {
126     ThemeColor retv = hsl_to_rgb ( h, 1.0, 0.5);
127     retv.red   *= ( 1. - w - b );
128     retv.red   += w;
129     retv.green *= ( 1. - w - b );
130     retv.green += w;
131     retv.blue  *= ( 1. - w - b );
132     retv.blue += w;
133     return retv;
134 }
135 %}
136 
137 %union {
138 	int           ival;
139 	double        fval;
140     char          *sval;
141     char          cval;
142     int           bval;
143     WindowLocation wloc;
144     ThemeColor    colorval;
145     ThemeWidget   *theme;
146     GList         *list;
147     Property      *property;
148     GHashTable    *property_list;
149     RofiDistance      distance;
150     RofiDistanceUnit  *distance_unit;
151 }
152 
153 %token <ival>     T_END              0  "end of file"
154 %token <ival>     T_ERROR            1  "error from file parser"
155 %token <ival>     T_ERROR_PROPERTY   2  "invalid property value"
156 %token <ival>     T_ERROR_SECTION    3  "invalid property name"
157 %token <ival>     T_ERROR_NAMESTRING 4  "invalid element name"
158 %token <ival>     T_ERROR_DEFAULTS   5  "invalid defaults name"
159 %token <ival>     T_ERROR_INCLUDE    6  "invalid import value"
160 %token <ival>     T_ERROR_ARGB_SPEC  7  "invalid argb color. Requires 8 (not 7) elements: argb:AARRGGBB."
161 %token <ival>     T_INT                 "Integer number"
162 %token <fval>     T_DOUBLE              "Floating-point number"
163 %token <sval>     T_STRING              "UTF-8 encoded string"
164 %token <cval>     T_CHAR                "Character"
165 %token <sval>     T_PROP_NAME           "property name"
166 %token <colorval> T_COLOR_NAME          "Color value by name"
167 %token <sval>     T_NAME_ELEMENT        "Element name"
168 %token <bval>     T_BOOLEAN             "Boolean value (true or false)"
169 %token <colorval> T_COLOR               "Hexidecimal color value"
170 %token <sval>     T_LINK                "Reference"
171 %token <sval>     T_ELEMENT             "Name of element"
172 %token T_POS_CENTER                     "Center"
173 %token T_POS_EAST                       "East"
174 %token T_POS_WEST                       "West"
175 %token T_POS_NORTH                      "North"
176 %token T_POS_SOUTH                      "South"
177 
178 %token T_MEDIA                          "@media"
179 
180 %token T_NONE                           "None"
181 %token T_BOLD                           "Bold"
182 %token T_ITALIC                         "Italic"
183 %token T_UNDERLINE                      "Underline"
184 %token T_STRIKETHROUGH                  "Strikethrough"
185 %token T_SMALLCAPS                      "Small CAPS"
186 %token T_DASH                           "Dash"
187 %token T_SOLID                          "Solid"
188 
189 %token T_UNIT_PX                        "pixels"
190 %token T_UNIT_MM                        "mm"
191 %token T_UNIT_EM                        "em"
192 %token T_UNIT_CH                        "ch"
193 %token T_UNIT_PERCENT                   "%"
194 
195 %token T_ANGLE_DEG                      "Degrees"
196 %token T_ANGLE_GRAD                     "Gradians"
197 %token T_ANGLE_RAD                      "Radians"
198 %token T_ANGLE_TURN                     "Turns"
199 
200 %token ORIENTATION_HORI                 "Horizontal"
201 %token ORIENTATION_VERT                 "Vertical"
202 
203 %token T_COL_RGBA                       "rgb[a] colorscheme"
204 %token T_COL_HSL                        "hsl colorscheme"
205 %token T_COL_HWB                        "hwb colorscheme"
206 %token T_COL_CMYK                       "cmyk colorscheme"
207 
208 %token T_PARENT_LEFT                    "Parent left ('(')"
209 %token T_PARENT_RIGHT                   "Parent right (')')"
210 %token T_COMMA                          "comma separator (',')"
211 %token T_OPTIONAL_COMMA                          "Optional comma separator (',')"
212 %token T_FORWARD_SLASH                  "forward slash ('/')"
213 %token T_PERCENT                        "Percent sign ('%')"
214 %token T_LIST_OPEN                      "List open ('[')"
215 %token T_LIST_CLOSE                     "List close (']')"
216 
217 %token T_MODIFIER_ADD                   "Add ('+')"
218 %token T_MODIFIER_SUBTRACT              "Subtract ('-')"
219 %token T_MODIFIER_MULTIPLY              "Multiply ('*')"
220 
221 %token T_MODIFIER_MAX                   "Max ('max')"
222 %token T_MODIFIER_MIN                   "Min ('min')"
223 
224 %token T_CALC                           "calc"
225 
226 %token T_BOPEN                          "bracket open ('{')"
227 %token T_BCLOSE                         "bracket close ('}')"
228 %token T_PSEP                           "property separator (':')"
229 %token T_PCLOSE                         "property close (';')"
230 %token T_NSEP                           "Name separator (' ' or '.')"
231 %token T_SSEP                           "Selector separator (',')"
232 %token T_NAME_PREFIX                    "Element section ('# {name} { ... }')"
233 %token T_WHITESPACE                     "White space"
234 %token T_PDEFAULTS                      "Default settings section ( '* { ... }')"
235 %token T_CONFIGURATION                  "Configuration block"
236 
237 %token T_COLOR_TRANSPARENT              "Transparent"
238 
239 %token T_INHERIT                        "Inherit"
240 
241 %token T_MEDIA_WIDTH                    "Width"
242 %token T_MEDIA_HEIGHT                   "Height"
243 
244 %token T_MEDIA_MIN                      "Min"
245 %token T_MEDIA_MONITOR_ID               "Monitor-ID"
246 %token T_MEDIA_MAX                      "Max"
247 %token T_MEDIA_SEP                      "-"
248 
249 %type <theme>          t_entry_list
250 %type <list>           t_entry_name_path
251 %type <list>           t_entry_name_path_selectors
252 %type <property>       t_property
253 %type <property>       t_property_element
254 %type <property_list>  t_property_list
255 %type <property_list>  t_property_list_optional
256 %type <colorval>       t_property_color
257 %type <fval>           t_property_color_value
258 %type <fval>           t_property_color_opt_alpha_c
259 %type <fval>           t_property_color_opt_alpha_ws
260 %type <fval>           t_property_color_value_unit
261 %type <fval>           t_property_color_value_angle
262 %type <sval>           t_property_name
263 %type <distance>       t_property_distance
264 %type <distance>       t_property_distance_zero
265 %type <distance_unit>  t_property_distance_unit_math
266 %type <distance_unit>  t_property_distance_unit_math2
267 %type <distance_unit>  t_property_distance_unit_math3
268 %type <distance_unit>  t_property_distance_unit
269 %type <ival>           t_property_unit
270 %type <wloc>           t_property_position
271 %type <wloc>           t_property_position_ew
272 %type <wloc>           t_property_position_sn
273 %type <ival>           t_property_highlight_styles
274 %type <ival>           t_property_highlight_style
275 %type <ival>           t_property_line_style
276 %type <list>           t_property_element_list
277 %type <list>           t_property_element_list_optional
278 %type <ival>           t_property_orientation
279 %type <ival>           t_name_prefix_optional
280 %start t_main
281 
282 %%
283 
284 /**
285  * First have the configuration blocks, then the theme.
286  */
287 t_main
288 : t_configuration_list t_entry_list {
289     // Dummy at this point.
290     if (rofi_theme == NULL ){
291       rofi_theme_reset();
292     }
293 
294 
295     rofi_theme_widget_add_properties ( rofi_theme, $2->properties );
296     for ( unsigned int i = 0; i < $2->num_widgets;i++) {
297         ThemeWidget *d = $2->widgets[i];
298         rofi_theme_parse_merge_widgets(rofi_theme, d);
299     }
300 }
301 ;
302 
303 t_configuration_list:
304  %empty {}
305 | t_configuration_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE {};
306 
307 
308 /**
309  * Small dummy object to make the prefix optional.
310  */
311 t_name_prefix_optional
312 : T_NAME_PREFIX {}
313 | %empty {}
314 ;
315 
316 t_entry_list:
317   %empty {
318     $$ = g_slice_new0 ( ThemeWidget );
319   }
320 |  t_entry_list t_name_prefix_optional t_entry_name_path_selectors T_BOPEN t_property_list_optional T_BCLOSE
321 {
322     for ( GList *liter = g_list_first ( $3); liter; liter = g_list_next ( liter ) ) {
323         ThemeWidget *widget = $1;
324         for ( GList *iter = g_list_first ( (GList*)liter->data ); widget && iter ; iter = g_list_next ( iter ) ) {
325             widget = rofi_theme_find_or_create_name ( widget, iter->data );
326         }
327         g_list_free_full ( (GList*)liter->data, g_free );
328         widget->set = TRUE;
329         rofi_theme_widget_add_properties ( widget, $5);
330     }
331     if ( $5 ) {
332         g_hash_table_destroy ( $5 );
333     }
334     g_list_free ( $3 );
335 }
336 | t_entry_list T_PDEFAULTS T_BOPEN t_property_list_optional T_BCLOSE {
337     rofi_theme_widget_add_properties ( $1, $4);
338     if ( $4 ) {
339         g_hash_table_destroy ( $4 );
340     }
341 }
342 | t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_INT T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE {
343     gchar *name = g_strdup_printf("@media ( %s: %d )",$4, $6);
344     ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name );
345     widget->set = TRUE;
346     widget->media = g_slice_new0(ThemeMedia);
347     widget->media->type = rofi_theme_parse_media_type ( $4 );
348     widget->media->value = (double)$6;
349     for ( unsigned int i = 0; i < $9->num_widgets;i++) {
350         ThemeWidget *d = $9->widgets[i];
351         rofi_theme_parse_merge_widgets(widget, d);
352     }
353     g_free ( name );
354 }
355 | t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_DOUBLE T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE {
356     gchar *name = g_strdup_printf("@media ( %s: %f )",$4, $6);
357     ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name );
358     widget->set = TRUE;
359     widget->media = g_slice_new0(ThemeMedia);
360     widget->media->type = rofi_theme_parse_media_type ( $4 );
361     widget->media->value = $6;
362     for ( unsigned int i = 0; i < $9->num_widgets;i++) {
363         ThemeWidget *d = $9->widgets[i];
364         rofi_theme_parse_merge_widgets(widget, d);
365     }
366     g_free ( name );
367 }
368 | t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_INT T_UNIT_PX T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE {
369     gchar *name = g_strdup_printf("@media ( %s: %d px )",$4, $6);
370     ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name );
371     widget->set = TRUE;
372     widget->media = g_slice_new0(ThemeMedia);
373     widget->media->type = rofi_theme_parse_media_type ( $4 );
374     widget->media->value = (double)$6;
375     for ( unsigned int i = 0; i < $10->num_widgets;i++) {
376         ThemeWidget *d = $10->widgets[i];
377         rofi_theme_parse_merge_widgets(widget, d);
378     }
379     g_free ( name );
380 }
381 ;
382 
383 t_config_property_list_optional
384 : %empty {}
385 | t_config_property_list
386 ;
387 
388 t_config_property_list
389 : t_config_property {
390 }
391 | t_config_property_list  t_config_property  {
392 };
393 
394 t_config_property
395 : t_property {
396     char *error = NULL;
397     if ( config_parse_set_property ( $1, &error ) ) {
398         // TODO Generate error.
399 #ifdef FATAL_CONFIG_ERROR
400         yyerror ( &(@$), @$.filename, error );
401 #else
402         g_warning("%s:%d:%d: %s\n", @$.filename, @$.first_line, @$.first_column, error);
403 #endif
404         g_free(error);
405     }
406     // We don't keep any reference to this after this point, so the property can be free'ed.
407     rofi_theme_property_free ( $1 );
408 }
409 
410 /**
411  * properties
412  */
413 t_property_list_optional
414           : %empty { $$ = NULL; }
415           | t_property_list { $$ = $1; }
416 ;
417 
418 t_property_list:
419   t_property {
420     $$ = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify)rofi_theme_property_free );
421     g_hash_table_replace ( $$, $1->name, $1 );
422   }
423 | t_property_list t_property {
424     // Old will be free'ed, and key/value will be replaced.
425     g_hash_table_replace ( $$, $2->name, $2 );
426   }
427 ;
428 
429 t_property
430 : t_property_name T_PSEP t_property_element T_PCLOSE {
431     $$ = $3;
432     $$->name = $1;
433    }
434 |   t_property_name T_PSEP T_PARENT_LEFT T_ELEMENT T_PARENT_RIGHT T_PCLOSE{
435         $$ = rofi_theme_property_create ( P_LINK );
436         $$->name = $1;
437         $$->value.link.name = $4;
438     }
439 |   t_property_name T_PSEP T_PARENT_LEFT T_ELEMENT T_COMMA t_property_element T_PARENT_RIGHT T_PCLOSE{
440         $$ = rofi_theme_property_create ( P_LINK );
441         $$->name = $1;
442         $$->value.link.name = $4;
443         $$->value.link.def_value = $6;
444     }
445 
446 t_property_element
447 :   T_INHERIT {
448         $$ = rofi_theme_property_create ( P_INHERIT );
449     }
450 |   T_INT {
451         $$ = rofi_theme_property_create ( P_INTEGER );
452         $$->value.i = $1;
453     }
454 |   T_DOUBLE {
455         $$ = rofi_theme_property_create ( P_DOUBLE );
456         $$->value.f = $1;
457     }
458 |   T_STRING {
459         $$ = rofi_theme_property_create ( P_STRING );
460         $$->value.s = $1;
461     }
462 |   T_CHAR {
463         $$ = rofi_theme_property_create ( P_CHAR );
464         $$->value.c = $1;
465     }
466 |   T_LINK {
467         $$ = rofi_theme_property_create ( P_LINK );
468         $$->value.link.name = $1;
469     }
470 |   T_BOOLEAN {
471         $$ = rofi_theme_property_create ( P_BOOLEAN );
472         $$->value.b = $1;
473     }
474 |  t_property_distance {
475         $$ = rofi_theme_property_create ( P_PADDING );
476         $$->value.padding = (RofiPadding){ $1, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1) };
477 }
478 |  t_property_distance_zero t_property_distance_zero {
479         $$ = rofi_theme_property_create ( P_PADDING );
480         $$->value.padding = (RofiPadding){ $1, $2, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($2) };
481 }
482 |  t_property_distance_zero t_property_distance_zero t_property_distance_zero {
483         $$ = rofi_theme_property_create ( P_PADDING );
484         $$->value.padding = (RofiPadding){ $1, $2, $3, rofi_theme_property_copy_distance($2) };
485 }
486 |  t_property_distance_zero t_property_distance_zero t_property_distance_zero t_property_distance_zero {
487         $$ = rofi_theme_property_create ( P_PADDING );
488         $$->value.padding = (RofiPadding){ $1, $2, $3, $4 };
489 }
490 | t_property_position {
491         $$ = rofi_theme_property_create ( P_POSITION );
492         $$->value.i = $1;
493 }
494 | t_property_highlight_styles t_property_color {
495         $$ = rofi_theme_property_create ( P_HIGHLIGHT );
496         $$->value.highlight.style = $1|ROFI_HL_COLOR;
497         $$->value.highlight.color = $2;
498 }
499 | t_property_highlight_styles {
500         $$ = rofi_theme_property_create ( P_HIGHLIGHT );
501         $$->value.highlight.style = $1;
502 }
503 | t_property_color {
504         $$ = rofi_theme_property_create ( P_COLOR );
505         $$->value.color = $1;
506 }
507 | T_LIST_OPEN t_property_element_list_optional T_LIST_CLOSE {
508         $$ = rofi_theme_property_create ( P_LIST );
509         $$->value.list = $2;
510 }
511 | t_property_orientation {
512         $$ = rofi_theme_property_create ( P_ORIENTATION );
513         $$->value.i = $1;
514 }
515 ;
516 
517 /** List of elements */
518 t_property_element_list_optional
519 : %empty { $$ = NULL; }
520 | t_property_element_list { $$ = $1; }
521 ;
522 
523 t_property_element_list
524 : T_ELEMENT { $$ = g_list_append ( NULL, $1); }
525 | t_property_element_list T_COMMA T_ELEMENT {
526     $$ = g_list_append ( $1, $3 );
527 }
528 ;
529 
530 /**
531  * Position can be either center,
532  * East or West, North Or South
533  * Or combi of East or West and North or South
534  */
535 t_property_position
536 : T_POS_CENTER { $$ =WL_CENTER;}
537 | t_property_position_ew
538 | t_property_position_sn
539 | t_property_position_ew t_property_position_sn { $$ = $1|$2;}
540 | t_property_position_sn t_property_position_ew { $$ = $1|$2;}
541 ;
542 t_property_position_ew
543 : T_POS_EAST   { $$ = WL_EAST;}
544 | T_POS_WEST   { $$ = WL_WEST;}
545 ;
546 t_property_position_sn
547 : T_POS_NORTH  { $$ = WL_NORTH;}
548 | T_POS_SOUTH  { $$ = WL_SOUTH;}
549 ;
550 
551 /**
552  * Highlight style, allow mulitple styles to be combined.
553  * Empty not allowed
554  */
555 t_property_highlight_styles
556 : t_property_highlight_style { $$ = $1;}
557 | t_property_highlight_styles t_property_highlight_style { $$ = $1|$2;}
558 ;
559 /** Single style. */
560 t_property_highlight_style
561 : T_NONE          { $$ = ROFI_HL_NONE; }
562 | T_BOLD          { $$ = ROFI_HL_BOLD; }
563 | T_UNDERLINE     { $$ = ROFI_HL_UNDERLINE; }
564 | T_STRIKETHROUGH { $$ = ROFI_HL_STRIKETHROUGH; }
565 | T_ITALIC        { $$ = ROFI_HL_ITALIC; }
566 | T_SMALLCAPS     { $$ = ROFI_HL_SMALL_CAPS; }
567 ;
568 
569 
570 t_property_distance_zero
571 : T_INT t_property_line_style {
572     $$.base.distance = (double) $1;
573     $$.base.type     = ROFI_PU_PX;
574     $$.base.left     = NULL;
575     $$.base.right    = NULL;
576     $$.base.modtype  = ROFI_DISTANCE_MODIFIER_NONE;
577     $$.style    = $2;
578 }
579 | t_property_distance { $$ = $1;}
580 ;
581 
582 /** Distance. */
583 t_property_distance_unit
584 : T_INT t_property_unit {
585     $$ = g_slice_new0(RofiDistanceUnit);
586     $$->distance = (double)$1;
587     $$->type     = $2;
588     $$->left     = NULL;
589     $$->right    = NULL;
590     $$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
591 }
592 | T_INT {
593     $$ = g_slice_new0(RofiDistanceUnit);
594     $$->distance = (double)$1;
595     $$->type     = ROFI_PU_PX;
596     $$->left     = NULL;
597     $$->right    = NULL;
598     $$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
599 }
600 | T_DOUBLE t_property_unit {
601     $$ = g_slice_new0(RofiDistanceUnit);
602     $$->distance = (double)$1;
603     $$->type     = $2;
604     $$->left     = NULL;
605     $$->right    = NULL;
606     $$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
607 }
608 | T_PARENT_LEFT t_property_distance_unit_math3 T_PARENT_RIGHT {
609     $$ = g_slice_new0(RofiDistanceUnit);
610     $$->distance = 0;
611     $$->type     = ROFI_PU_PX;
612     $$->left     = $2;
613     $$->right    = 0;
614     $$->modtype  = ROFI_DISTANCE_MODIFIER_GROUP;
615 };
616 
617 
618 /**
619  * Multiply/divide with auto-grouping.
620  */
621 t_property_distance_unit_math
622 : t_property_distance_unit_math T_MODIFIER_MULTIPLY t_property_distance_unit {
623     $$ = g_slice_new0(RofiDistanceUnit);
624     $$->left  = $1;
625     $$->right = $3;
626     $$->modtype = ROFI_DISTANCE_MODIFIER_MULTIPLY;
627 }
628 | t_property_distance_unit_math T_FORWARD_SLASH t_property_distance_unit {
629     $$ = g_slice_new0(RofiDistanceUnit);
630     $$->left  = $1;
631     $$->right = $3;
632     $$->modtype = ROFI_DISTANCE_MODIFIER_DIVIDE;
633 }
634 | t_property_distance_unit_math T_PERCENT t_property_distance_unit {
635     $$ = g_slice_new0(RofiDistanceUnit);
636     $$->left  = $1;
637     $$->right = $3;
638     $$->modtype = ROFI_DISTANCE_MODIFIER_MODULO;
639 }
640 | t_property_distance_unit {
641     $$ = $1;
642 };
643 
644 
645 /** Level 2  (+-)*/
646 t_property_distance_unit_math2
647 : t_property_distance_unit_math2 T_MODIFIER_ADD t_property_distance_unit_math {
648     $$ = g_slice_new0(RofiDistanceUnit);
649     $$->left = $1;
650     $$->right = $3;
651     $$->modtype = ROFI_DISTANCE_MODIFIER_ADD;
652 }
653 | t_property_distance_unit_math2 T_MODIFIER_SUBTRACT t_property_distance_unit_math {
654     $$ = g_slice_new0(RofiDistanceUnit);
655     $$->left = $1;
656     $$->right = $3;
657     $$->modtype = ROFI_DISTANCE_MODIFIER_SUBTRACT;
658 }
659 | t_property_distance_unit_math  {
660     $$ = $1;
661 };
662 /** Level 3  (min max)*/
663 t_property_distance_unit_math3
664 : t_property_distance_unit_math3 T_MODIFIER_MIN t_property_distance_unit_math2 {
665     $$ = g_slice_new0(RofiDistanceUnit);
666     $$->left = $1;
667     $$->right = $3;
668     $$->modtype = ROFI_DISTANCE_MODIFIER_MIN;
669 }
670 | t_property_distance_unit_math3 T_MODIFIER_MAX t_property_distance_unit_math2 {
671     $$ = g_slice_new0(RofiDistanceUnit);
672     $$->left = $1;
673     $$->right = $3;
674     $$->modtype = ROFI_DISTANCE_MODIFIER_MAX;
675 }
676 | t_property_distance_unit_math2  {
677     $$ = $1;
678 };
679 
680 
681 t_property_distance
682 /** Integer unit and line style */
683 : T_INT t_property_unit t_property_line_style {
684     $$.base.distance = (double)$1;
685     $$.base.type     = $2;
686     $$.base.left = NULL;
687     $$.base.right = NULL;
688     $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE;
689     $$.style    = $3;
690 }
691 /** Double unit and line style */
692 | T_DOUBLE t_property_unit t_property_line_style {
693     $$.base.distance = (double)$1;
694     $$.base.type     = $2;
695     $$.base.modtype  = ROFI_DISTANCE_MODIFIER_NONE;
696     $$.base.left = NULL;
697     $$.base.right = NULL;
698     $$.style    = $3;
699 }
700 | T_CALC T_PARENT_LEFT t_property_distance_unit_math3 T_PARENT_RIGHT t_property_line_style {
701     $$.base.distance = 0;
702     $$.base.type     = ROFI_PU_PX;
703     $$.base.left = $3;
704     $$.base.right = NULL;
705     $$.base.modtype  = ROFI_DISTANCE_MODIFIER_GROUP;
706     $$.style    = $5;
707 };
708 
709 /** distance unit. px, em, % */
710 t_property_unit
711 : T_UNIT_PX      { $$ = ROFI_PU_PX; }
712 | T_UNIT_MM      { $$ = ROFI_PU_MM; }
713 | T_UNIT_EM      { $$ = ROFI_PU_EM; }
714 | T_UNIT_CH      { $$ = ROFI_PU_CH; }
715 | T_PERCENT      { $$ = ROFI_PU_PERCENT; }
716 ;
717 /******
718  * Line style
719  * If not set, solid.
720  */
721 t_property_line_style
722 : %empty   { $$ = ROFI_HL_SOLID; }
723 | T_SOLID  { $$ = ROFI_HL_SOLID; }
724 | T_DASH   { $$ = ROFI_HL_DASH;  }
725 ;
726 
727 /**
728  * Color formats
729  */
730 t_property_color
731  /** rgba ( 0-255 , 0-255, 0-255, 0-1.0 ) */
732 : T_COL_RGBA T_PARENT_LEFT  T_INT T_COMMA T_INT T_COMMA T_INT t_property_color_opt_alpha_c T_PARENT_RIGHT {
733     if ( ! check_in_range($3,0,255, &(@$)) ) { YYABORT; }
734     if ( ! check_in_range($5,0,255, &(@$)) ) { YYABORT; }
735     if ( ! check_in_range($7,0,255, &(@$)) ) { YYABORT; }
736     $$.alpha = $8;
737     $$.red   = $3/255.0;
738     $$.green = $5/255.0;
739     $$.blue  = $7/255.0;
740 }
741  /** rgba ( 0-255   0-255  0-255  / 0-1.0 ) */
742 | T_COL_RGBA T_PARENT_LEFT  T_INT  T_INT  T_INT  t_property_color_opt_alpha_ws T_PARENT_RIGHT {
743     if ( ! check_in_range($3,0,255, &(@$)) ) { YYABORT; }
744     if ( ! check_in_range($4,0,255, &(@$)) ) { YYABORT; }
745     if ( ! check_in_range($5,0,255, &(@$)) ) { YYABORT; }
746     $$.alpha = $6;
747     $$.red   = $3/255.0;
748     $$.green = $4/255.0;
749     $$.blue  = $5/255.0;
750 }
751  /** rgba ( 0-100% , 0-100%, 0-100%, 0-1.0 ) */
752 | T_COL_RGBA T_PARENT_LEFT  t_property_color_value T_PERCENT T_COMMA t_property_color_value T_PERCENT T_COMMA t_property_color_value T_PERCENT t_property_color_opt_alpha_c T_PARENT_RIGHT {
753     if ( ! check_in_range($3,0,100, &(@$)) ) { YYABORT; }
754     if ( ! check_in_range($6,0,100, &(@$)) ) { YYABORT; }
755     if ( ! check_in_range($9,0,100, &(@$)) ) { YYABORT; }
756     $$.alpha = $11; $$.red   = $3/100.0; $$.green = $6/100.0; $$.blue  = $9/100.0;
757 }
758  /** rgba ( 0-100%   0-100%  0-100%  / 0-1.0 ) */
759 | T_COL_RGBA T_PARENT_LEFT  t_property_color_value T_PERCENT  t_property_color_value T_PERCENT  t_property_color_value T_PERCENT  t_property_color_opt_alpha_ws T_PARENT_RIGHT {
760     if ( ! check_in_range($3,0,100, &(@$)) ) { YYABORT; }
761     if ( ! check_in_range($5,0,100, &(@$)) ) { YYABORT; }
762     if ( ! check_in_range($7,0,100, &(@$)) ) { YYABORT; }
763     $$.alpha = $9; $$.red   = $3/100.0; $$.green = $5/100.0; $$.blue  = $7/100.0;
764 }
765  /** hwb with comma */
766 | T_COL_HWB T_PARENT_LEFT t_property_color_value_angle T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit t_property_color_opt_alpha_c T_PARENT_RIGHT {
767     double h = $3, w = $5, b = $7;
768     $$ = hwb_to_rgb ( h, w, b );
769     $$.alpha = $8;
770 }
771  /** hwb whitespace */
772 | T_COL_HWB T_PARENT_LEFT t_property_color_value_angle  t_property_color_value_unit  t_property_color_value_unit t_property_color_opt_alpha_ws T_PARENT_RIGHT {
773     double h = $3, w = $4, b = $5;
774     $$ = hwb_to_rgb ( h, w, b );
775     $$.alpha = $6;
776 }
777   /** cmyk  with comma */
778 | T_COL_CMYK T_PARENT_LEFT t_property_color_value_unit T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit t_property_color_opt_alpha_c T_PARENT_RIGHT {
779     $$.alpha = $10;
780     double  c= $3, m= $5, y= $7, k= $9;
781     $$.red   = (1.0-c)*(1.0-k);
782     $$.green = (1.0-m)*(1.0-k);
783     $$.blue  = (1.0-y)*(1.0-k);
784 }
785  /** cmyk whitespace edition. */
786 | T_COL_CMYK T_PARENT_LEFT t_property_color_value_unit  t_property_color_value_unit  t_property_color_value_unit t_property_color_value_unit t_property_color_opt_alpha_ws T_PARENT_RIGHT {
787     $$.alpha = $7;
788     double  c= $3, m= $4, y= $5, k= $6;
789     $$.red   = (1.0-c)*(1.0-k);
790     $$.green = (1.0-m)*(1.0-k);
791     $$.blue  = (1.0-y)*(1.0-k);
792 }
793  /** hsl ( 0-360 0-100  % 0 - 100  % / alpha) */
794 | T_COL_HSL T_PARENT_LEFT t_property_color_value_angle t_property_color_value_unit t_property_color_value_unit t_property_color_opt_alpha_ws T_PARENT_RIGHT {
795     double h = $3, s = $4, l = $5;
796     $$ = hsl_to_rgb ( h, s, l );
797     $$.alpha = $6;
798 }
799  /** hsl ( 0-360 , 0-100  %, 0 - 100  %) */
800 | T_COL_HSL T_PARENT_LEFT t_property_color_value_angle T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit t_property_color_opt_alpha_c T_PARENT_RIGHT {
801     double h = $3, s = $5, l = $7;
802     $$ = hsl_to_rgb ( h, s, l );
803     $$.alpha = $8;
804 }
805 /** Hex colors parsed by lexer. */
806 | T_COLOR {
807     $$ = $1;
808 }
809 | T_COLOR_TRANSPARENT {
810     $$.alpha = 0.0;
811     $$.red = $$.green = $$.blue = 0.0;
812 }
813 | T_COLOR_NAME t_property_color_opt_alpha_ws {
814     $$ = $1;
815     $$.alpha  = $2;
816 }
817 ;
818 t_property_color_opt_alpha_c
819 : %empty { $$ = 1.0; }
820 | T_COMMA t_property_color_value_unit { $$ = $2;}
821 ;
822 t_property_color_opt_alpha_ws
823 : %empty { $$ = 1.0; }
824 | T_FORWARD_SLASH t_property_color_value_unit { $$ = $2;}
825 ;
826  t_property_color_value_angle
827 : t_property_color_value              { $$ = $1/360.0;    if ( ! check_in_range ( $1, 0, 360, &(@$))){YYABORT;}}
828 | t_property_color_value T_ANGLE_DEG  { $$ = $1/360.0;    if ( ! check_in_range ( $1, 0, 360, &(@$))){YYABORT;}}
829 | t_property_color_value T_ANGLE_RAD  { $$ = $1/(2*G_PI); if ( ! check_in_range ( $1, 0.0, (2*G_PI), &(@$))){YYABORT;}}
830 | t_property_color_value T_ANGLE_GRAD { $$ = $1/400.0;    if ( ! check_in_range ( $1, 0, 400, &(@$))){YYABORT;}}
831 | t_property_color_value T_ANGLE_TURN { $$ = $1;          if ( ! check_in_range ( $1, 0.0, 1.0, &(@$))){YYABORT;}}
832 ;
833 
834 t_property_color_value_unit
835 : t_property_color_value T_PERCENT { $$ = $1/100.0; if ( !check_in_range ( $1, 0, 100, &(@$))){YYABORT;}}
836 | t_property_color_value           { $$ = $1;       if ( !check_in_range ( $1, 0.0, 1.0, &(@$))){YYABORT;}}
837 ;
838 /** Color value to be double or integer. */
839 t_property_color_value
840 : T_DOUBLE { $$ = $1; }
841 | T_INT    { $$ = $1; }
842 ;
843 
844 t_property_orientation
845 : ORIENTATION_HORI {  $$ = ROFI_ORIENTATION_HORIZONTAL; }
846 | ORIENTATION_VERT {  $$ = ROFI_ORIENTATION_VERTICAL;   }
847 ;
848 
849 /** Property name */
850 t_property_name
851 : T_PROP_NAME { $$ = $1; }
852 ;
853 
854 t_entry_name_path_selectors:
855 t_entry_name_path { $$ = g_list_append  ( NULL, $1 ); }
856 | t_entry_name_path_selectors T_SSEP t_entry_name_path {
857     $$ = g_list_append ( $1, $3);
858 }
859 | t_entry_name_path_selectors T_SSEP {
860    $$ = $1;
861 }
862 
863 ;
864 t_entry_name_path:
865 T_NAME_ELEMENT { $$ = g_list_append ( NULL, $1 );}
866 | t_entry_name_path T_NSEP T_NAME_ELEMENT { $$ = g_list_append ( $1, $3);}
867 | t_entry_name_path T_NSEP  { $$ = $1; }
868 ;
869 
870 %%
871 
872