rofi  1.5.2
theme.c
Go to the documentation of this file.
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 
29 #define G_LOG_DOMAIN "Theme"
30 
31 #include "config.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <string.h>
36 // GFile stuff.
37 #include <gio/gio.h>
38 #include "theme.h"
39 #include "theme-parser.h"
40 #include "helper.h"
41 #include "settings.h"
42 #include "widgets/textbox.h"
43 #include "view.h"
44 #include "rofi.h"
45 #include "rofi-types.h"
46 
47 void yyerror ( YYLTYPE *yylloc, const char *, const char * );
48 static gboolean distance_compare ( RofiDistance d, RofiDistance e )
49 {
50  return d.type == e.type && d.distance == e.distance && d.style == e.style;
51 }
52 
54 {
55  for ( unsigned int i = 0; i < base->num_widgets; i++ ) {
56  if ( g_strcmp0 ( base->widgets[i]->name, name ) == 0 ) {
57  return base->widgets[i];
58  }
59  }
60 
61  base->widgets = g_realloc ( base->widgets, sizeof ( ThemeWidget* ) * ( base->num_widgets + 1 ) );
62  base->widgets[base->num_widgets] = g_slice_new0 ( ThemeWidget );
63  ThemeWidget *retv = base->widgets[base->num_widgets];
64  retv->parent = base;
65  retv->name = g_strdup ( name );
66  base->num_widgets++;
67  return retv;
68 }
73 {
74  Property *retv = g_slice_new0 ( Property );
75  retv->type = type;
76  return retv;
77 }
79 {
81  retv->name = g_strdup ( p->name );
82 
83  switch ( p->type )
84  {
85  case P_STRING:
86  retv->value.s = g_strdup ( p->value.s );
87  break;
88  case P_LIST:
89  retv->value.list = g_list_copy_deep ( p->value.list, (GCopyFunc) g_strdup, NULL );
90  break;
91  case P_LINK:
92  retv->value.link.name = g_strdup ( p->value.link.name );
93  retv->value.link.ref = NULL;
94  break;
95  default:
96  retv->value = p->value;
97  }
98  return retv;
99 }
100 
102 {
103  if ( p == NULL ) {
104  return;
105  }
106  g_free ( p->name );
107  if ( p->type == P_STRING ) {
108  g_free ( p->value.s );
109  }
110  else if ( p->type == P_LINK ) {
111  g_free ( p->value.link.name );
112  }
113  g_slice_free ( Property, p );
114 }
115 
116 void rofi_theme_reset ( void )
117 {
119  rofi_theme = g_slice_new0 ( ThemeWidget );
120  rofi_theme->name = g_strdup ( "Root" );
121 }
122 
124 {
125  if ( widget == NULL ) {
126  return;
127  }
128  if ( widget->properties ) {
129  g_hash_table_destroy ( widget->properties );
130  widget->properties = NULL;
131  }
132  for ( unsigned int i = 0; i < widget->num_widgets; i++ ) {
133  rofi_theme_free ( widget->widgets[i] );
134  }
135  g_free ( widget->widgets );
136  g_free ( widget->name );
137  g_slice_free ( ThemeWidget, widget );
138 }
139 
143 inline static void printf_double ( double d )
144 {
145  char buf[G_ASCII_DTOSTR_BUF_SIZE];
146  g_ascii_formatd ( buf, G_ASCII_DTOSTR_BUF_SIZE, "%.4lf", d );
147  fputs ( buf, stdout );
148 }
150 {
151  if ( d.type == ROFI_PU_PX ) {
152  printf ( "%upx ", (unsigned int) d.distance );
153  }
154  else if ( d.type == ROFI_PU_PERCENT ) {
155  printf_double ( d.distance );
156  fputs ( "%% ", stdout );
157  }
158  else {
159  printf_double ( d.distance );
160  fputs ( "em ", stdout );
161  }
162  if ( d.style == ROFI_HL_DASH ) {
163  printf ( "dash " );
164  }
165 }
167 const char * const WindowLocationStr[9] = {
168  "center",
169  "northwest",
170  "north",
171  "northeast",
172  "east",
173  "southeast",
174  "south",
175  "southwest",
176  "west"
177 };
178 
179 static void rofi_theme_print_property_index ( size_t pnl, int depth, Property *p )
180 {
181  int pl = strlen ( p->name );
182  printf ( "%*s%s:%*s ", depth, "", p->name, (int) pnl - pl, "" );
183  switch ( p->type )
184  {
185  case P_LIST:
186  printf ( "[ " );
187  for ( GList *iter = p->value.list; iter != NULL; iter = g_list_next ( iter ) ) {
188  printf ( "%s", (char *) ( iter->data ) );
189  if ( iter->next != NULL ) {
190  printf ( "," );
191  }
192  }
193  printf ( " ];" );
194  break;
195  case P_ORIENTATION:
196  printf ( "%s;", ( p->value.i == ROFI_ORIENTATION_HORIZONTAL ) ? "horizontal" : "vertical" );
197  break;
198  case P_HIGHLIGHT:
199  if ( p->value.highlight.style & ROFI_HL_BOLD ) {
200  printf ( "bold " );
201  }
202  if ( p->value.highlight.style & ROFI_HL_UNDERLINE ) {
203  printf ( "underline " );
204  }
206  printf ( "strikethrough " );
207  }
208  if ( p->value.highlight.style & ROFI_HL_ITALIC ) {
209  printf ( "italic " );
210  }
211  if ( p->value.highlight.style & ROFI_HL_COLOR ) {
212  printf ( "rgba ( %.0f, %.0f, %.0f, %.0f %% )",
213  ( p->value.highlight.color.red * 255.0 ),
214  ( p->value.highlight.color.green * 255.0 ),
215  ( p->value.highlight.color.blue * 255.0 ),
216  ( p->value.highlight.color.alpha * 100.0 ) );
217  }
218  printf ( ";" );
219  break;
220  case P_POSITION:
221  printf ( "%s;", WindowLocationStr[p->value.i] );
222  break;
223  case P_STRING:
224  printf ( "\"%s\";", p->value.s );
225  break;
226  case P_INTEGER:
227  printf ( "%d;", p->value.i );
228  break;
229  case P_DOUBLE:
230  printf ( "%.2f;", p->value.f );
231  break;
232  case P_BOOLEAN:
233  printf ( "%s;", p->value.b ? "true" : "false" );
234  break;
235  case P_COLOR:
236  printf ( "rgba ( %.0f, %.0f, %.0f, %.0f %% );",
237  ( p->value.color.red * 255.0 ),
238  ( p->value.color.green * 255.0 ),
239  ( p->value.color.blue * 255.0 ),
240  ( p->value.color.alpha * 100.0 ) );
241  break;
242  case P_PADDING:
247  }
248  else if ( distance_compare ( p->value.padding.top, p->value.padding.bottom ) &&
252  }
253  else if ( !distance_compare ( p->value.padding.top, p->value.padding.bottom ) &&
258  }
259  else {
264  }
265  printf ( ";" );
266  break;
267  case P_LINK:
268  printf ( "%s;", p->value.link.name );
269  break;
270  case P_INHERIT:
271  printf ( "inherit;" );
272  break;
273  default:
274  break;
275  }
276  putchar ( '\n' );
277 }
278 
280 {
281  GHashTableIter iter;
282  gpointer key, value;
283  if ( widget->properties ) {
284  int index = 0;
285  GList *list = NULL;
286  ThemeWidget *w = widget;
287  while ( w ) {
288  if ( g_strcmp0 ( w->name, "Root" ) == 0 ) {
289  break;
290  }
291  list = g_list_prepend ( list, w->name );
292  w = w->parent;
293  }
294  if ( g_list_length ( list ) > 0 ) {
295  index = 4;
296  for ( GList *iter = g_list_first ( list ); iter != NULL; iter = g_list_next ( iter ) ) {
297  char *name = (char *) iter->data;
298  fputs ( name, stdout );
299  if ( iter->prev == NULL && iter->next ) {
300  putchar ( ' ' );
301  }
302  else if ( iter->next ) {
303  putchar ( '.' );
304  }
305  }
306  printf ( " {\n" );
307  }
308  else {
309  index = 4;
310  printf ( "* {\n" );
311  }
312  size_t property_name_length = 0;
313  g_hash_table_iter_init ( &iter, widget->properties );
314  while ( g_hash_table_iter_next ( &iter, &key, &value ) ) {
315  Property *p = (Property *) value;
316  property_name_length = MAX ( strlen ( p->name ), property_name_length );
317  }
318  g_hash_table_iter_init ( &iter, widget->properties );
319  while ( g_hash_table_iter_next ( &iter, &key, &value ) ) {
320  Property *p = (Property *) value;
321  rofi_theme_print_property_index ( property_name_length, index, p );
322  }
323  printf ( "}\n" );
324  g_list_free ( list );
325  }
326  for ( unsigned int i = 0; i < widget->num_widgets; i++ ) {
327  rofi_theme_print_index ( widget->widgets[i] );
328  }
329 }
331 {
332  if ( widget != NULL ) {
333  printf ( "/**\n * rofi -dump-theme output.\n * Rofi version: %s\n **/\n", PACKAGE_VERSION );
335  }
336 }
337 
341 int yyparse ();
342 
346 void yylex_destroy ( void );
347 
351 extern FILE* yyin;
352 
360 void yyerror ( YYLTYPE *yylloc, const char *what, const char* s )
361 {
362  char *what_esc = what ? g_markup_escape_text ( what, -1 ) : g_strdup ( "" );
363  GString *str = g_string_new ( "" );
364  g_string_printf ( str, "<big><b>Error while parsing theme:</b></big> <i>%s</i>\n", what_esc );
365  g_free ( what_esc );
366  char *esc = g_markup_escape_text ( s, -1 );
367  g_string_append_printf ( str, "\tParser error: <span size=\"smaller\" style=\"italic\">%s</span>\n", esc );
368  g_free ( esc );
369  if ( yylloc->filename != NULL ) {
370  g_string_append_printf ( str, "\tLocation: line %d column %d to line %d column %d.\n" \
371  "\tFile '%s'\n", yylloc->first_line, yylloc->first_column, yylloc->last_line, yylloc->last_column, yylloc->filename );
372  }
373  else {
374  g_string_append_printf ( str, "\tLocation: line %d column %d to line %d column %d\n", yylloc->first_line, yylloc->first_column, yylloc->last_line, yylloc->last_column );
375  }
376  g_log ( "Parser", G_LOG_LEVEL_DEBUG, "Failed to parse theme:\n%s", str->str );
377  rofi_add_error_message ( str );
378 }
379 
380 static void rofi_theme_copy_property_int ( G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data )
381 {
382  GHashTable *table = (GHashTable *) user_data;
383  Property *p = rofi_theme_property_copy ( (Property *) value );
384  g_hash_table_replace ( table, p->name, p );
385 }
387 {
388  if ( table == NULL ) {
389  return;
390  }
391  if ( widget->properties == NULL ) {
392  widget->properties = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free );
393  }
394  g_hash_table_foreach ( table, rofi_theme_copy_property_int, widget->properties );
395 }
396 
401 static inline ThemeWidget *rofi_theme_find_single ( ThemeWidget *widget, const char *name )
402 {
403  for ( unsigned int j = 0; widget && j < widget->num_widgets; j++ ) {
404  if ( g_strcmp0 ( widget->widgets[j]->name, name ) == 0 ) {
405  return widget->widgets[j];
406  }
407  }
408  return widget;
409 }
410 
411 static ThemeWidget *rofi_theme_find ( ThemeWidget *widget, const char *name, const gboolean exact )
412 {
413  if ( widget == NULL || name == NULL ) {
414  return widget;
415  }
416  char *tname = g_strdup ( name );
417  char *saveptr = NULL;
418  int found = TRUE;
419  for ( const char *iter = strtok_r ( tname, ".", &saveptr ); iter != NULL; iter = strtok_r ( NULL, ".", &saveptr ) ) {
420  found = FALSE;
422  if ( f != widget ) {
423  widget = f;
424  found = TRUE;
425  }
426  else if ( exact ) {
427  break;
428  }
429  }
430  g_free ( tname );
431  if ( !exact || found ) {
432  return widget;
433  }
434  else {
435  return NULL;
436  }
437 }
438 
440 {
441  // Set name, remove '@' prefix.
442  const char *name = p->value.link.name + 1;
443  if ( depth > 20 ) {
444  g_warning ( "Found more then 20 redirects for property. Stopping." );
445  p->value.link.ref = p;
446  return;
447  }
448 
449  if ( rofi_theme->properties && g_hash_table_contains ( rofi_theme->properties, name ) ) {
450  Property *pr = g_hash_table_lookup ( rofi_theme->properties, name );
451  if ( pr->type == P_LINK ) {
452  if ( pr->value.link.ref == NULL ) {
454  }
455  if ( pr->value.link.ref != pr ) {
456  p->value.link.ref = pr->value.link.ref;
457  return;
458  }
459  }
460  else {
461  p->value.link.ref = pr;
462  return;
463  }
464  }
465 
466  // No found, set ref to self.
467  p->value.link.ref = p;
468 }
469 
470 Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact )
471 {
472  while ( widget ) {
473  if ( widget->properties && g_hash_table_contains ( widget->properties, property ) ) {
474  Property *p = g_hash_table_lookup ( widget->properties, property );
475  if ( p->type == P_INHERIT ) {
476  return p;
477  }
478  if ( p->type == P_LINK ) {
479  if ( p->value.link.ref == NULL ) {
480  // Resolve link.
482  }
483  if ( p->value.link.ref != NULL && p->value.link.ref->type == type ) {
484  return p->value.link.ref;
485  }
486  }
487  if ( p->type == type ) {
488  return p;
489  }
490  // RofiPadding and integer can be converted.
491  if ( p->type == P_INTEGER && type == P_PADDING ) {
492  return p;
493  }
494  g_debug ( "Found property: '%s' on '%s', but type %s does not match expected type %s.",
495  property, widget->name,
497  PropertyTypeName[type]
498  );
499  }
500  if ( exact ) {
501  return NULL;
502  }
503  // Fall back to defaults.
504  widget = widget->parent;
505  }
506  return NULL;
507 }
508 ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact )
509 {
510  // First find exact match based on name.
512  widget = rofi_theme_find ( widget, state, exact );
513 
514  return widget;
515 }
516 
517 int rofi_theme_get_position ( const widget *widget, const char *property, int def )
518 {
520  Property *p = rofi_theme_find_property ( wid, P_POSITION, property, FALSE );
521  if ( p ) {
522  if ( p->type == P_INHERIT ) {
523  if ( widget->parent ) {
524  return rofi_theme_get_position ( widget->parent, property, def );
525  }
526  return def;
527  }
528  return p->value.i;
529  }
530  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
531  return def;
532 }
533 
534 int rofi_theme_get_integer ( const widget *widget, const char *property, int def )
535 {
537  Property *p = rofi_theme_find_property ( wid, P_INTEGER, property, FALSE );
538  if ( p ) {
539  if ( p->type == P_INHERIT ) {
540  if ( widget->parent ) {
541  return rofi_theme_get_integer ( widget->parent, property, def );
542  }
543  return def;
544  }
545  return p->value.i;
546  }
547  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
548  return def;
549 }
550 RofiDistance rofi_theme_get_distance ( const widget *widget, const char *property, int def )
551 {
553  Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
554  if ( p ) {
555  if ( p->type == P_INHERIT ) {
556  if ( widget->parent ) {
557  return rofi_theme_get_distance ( widget->parent, property, def );
558  }
559  return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID };
560  }
561  if ( p->type == P_INTEGER ) {
562  return (RofiDistance){ p->value.i, ROFI_PU_PX, ROFI_HL_SOLID };
563  }
564  else {
565  return p->value.padding.left;
566  }
567  }
568  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
569  return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID };
570 }
571 
572 int rofi_theme_get_boolean ( const widget *widget, const char *property, int def )
573 {
575  Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, property, FALSE );
576  if ( p ) {
577  if ( p->type == P_INHERIT ) {
578  if ( widget->parent ) {
579  return rofi_theme_get_boolean ( widget->parent, property, def );
580  }
581  return def;
582  }
583  return p->value.b;
584  }
585  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
586  return def;
587 }
589 {
591  Property *p = rofi_theme_find_property ( wid, P_ORIENTATION, property, FALSE );
592  if ( p ) {
593  if ( p->type == P_INHERIT ) {
594  if ( widget->parent ) {
595  return rofi_theme_get_orientation ( widget->parent, property, def );
596  }
597  return def;
598  }
599  return p->value.b;
600  }
601  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
602  return def;
603 }
604 
605 const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def )
606 {
608  Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
609  if ( p ) {
610  if ( p->type == P_INHERIT ) {
611  if ( widget->parent ) {
612  return rofi_theme_get_string ( widget->parent, property, def );
613  }
614  return def;
615  }
616  return p->value.s;
617  }
618  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
619  return def;
620 }
621 double rofi_theme_get_double ( const widget *widget, const char *property, double def )
622 {
624  Property *p = rofi_theme_find_property ( wid, P_DOUBLE, property, FALSE );
625  if ( p ) {
626  if ( p->type == P_INHERIT ) {
627  if ( widget->parent ) {
628  return rofi_theme_get_double ( widget->parent, property, def );
629  }
630  return def;
631  }
632  return p->value.f;
633  }
634  // Fallback to integer if double is not found.
635  p = rofi_theme_find_property ( wid, P_INTEGER, property, FALSE );
636  if ( p ) {
637  if ( p->type == P_INHERIT ) {
638  if ( widget->parent ) {
639  return rofi_theme_get_double ( widget->parent, property, def );
640  }
641  return def;
642  }
643  return (double) p->value.i;
644  }
645  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
646  return def;
647 }
648 void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d )
649 {
651  Property *p = rofi_theme_find_property ( wid, P_COLOR, property, FALSE );
652  if ( p ) {
653  if ( p->type == P_INHERIT ) {
654  if ( widget->parent ) {
655  rofi_theme_get_color ( widget->parent, property, d );
656  }
657  return;
658  }
659  cairo_set_source_rgba ( d,
660  p->value.color.red,
661  p->value.color.green,
662  p->value.color.blue,
663  p->value.color.alpha
664  );
665  }
666  else {
667  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
668  }
669 }
670 RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property, RofiPadding pad )
671 {
673  Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
674  if ( p ) {
675  if ( p->type == P_INHERIT ) {
676  if ( widget->parent ) {
677  return rofi_theme_get_padding ( widget->parent, property, pad );
678  }
679  return pad;
680  }
681  if ( p->type == P_PADDING ) {
682  pad = p->value.padding;
683  }
684  else {
686  return (RofiPadding){ d, d, d, d };
687  }
688  }
689  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
690  return pad;
691 }
692 
693 GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults )
694 {
696  Property *p = rofi_theme_find_property ( wid2, P_LIST, property, TRUE );
697  if ( p ) {
698  if ( p->type == P_INHERIT ) {
699  if ( widget->parent ) {
700  return rofi_theme_get_list ( widget->parent, property, defaults );
701  }
702  }
703  else if ( p->type == P_LIST ) {
704  return g_list_copy_deep ( p->value.list, (GCopyFunc) g_strdup, NULL );
705  }
706  }
707  char **r = defaults ? g_strsplit ( defaults, ",", 0 ) : NULL;
708  if ( r ) {
709  GList *l = NULL;
710  for ( int i = 0; r[i] != NULL; i++ ) {
711  l = g_list_append ( l, r[i] );
712  }
713  g_free ( r );
714  return l;
715  }
716  return NULL;
717 }
718 
720 {
722  Property *p = rofi_theme_find_property ( wid, P_HIGHLIGHT, property, FALSE );
723  if ( p ) {
724  if ( p->type == P_INHERIT ) {
725  if ( widget->parent ) {
726  return rofi_theme_get_highlight ( widget->parent, property, th );
727  }
728  return th;
729  }
730  return p->value.highlight;
731  }
732  g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
733  return th;
734 }
735 
737 {
738  if ( d.type == ROFI_PU_EM ) {
740  }
741  else if ( d.type == ROFI_PU_CH ) {
742  return d.distance * textbox_get_estimated_ch ();
743  }
744  else if ( d.type == ROFI_PU_PERCENT ) {
745  if ( ori == ROFI_ORIENTATION_VERTICAL ) {
746  int height = 0;
747  rofi_view_get_current_monitor ( NULL, &height );
748  return ( d.distance * height ) / ( 100.0 );
749  }
750  else {
751  int width = 0;
752  rofi_view_get_current_monitor ( &width, NULL );
753  return ( d.distance * width ) / ( 100.0 );
754  }
755  }
756  return d.distance;
757 }
758 
759 void distance_get_linestyle ( RofiDistance d, cairo_t *draw )
760 {
761  if ( d.style == ROFI_HL_DASH ) {
762  const double dashes[1] = { 4 };
763  cairo_set_dash ( draw, dashes, 1, 0.0 );
764  }
765  else {
766  cairo_set_dash ( draw, NULL, 0, 0.0 );
767  }
768 }
769 
770 gboolean rofi_theme_is_empty ( void )
771 {
772  if ( rofi_theme == NULL ) {
773  return TRUE;
774  }
775  if ( rofi_theme->properties == NULL && rofi_theme->num_widgets == 0 ) {
776  return TRUE;
777  }
778 
779  return FALSE;
780 }
781 
782 #ifdef THEME_CONVERTER
783 
784 static char * rofi_theme_convert_color ( char *col )
785 {
786  char *r = g_strstrip ( col );
787  if ( *r == '#' && strlen ( r ) == 9 ) {
788  char a1 = r[1];
789  char a2 = r[2];
790  r[1] = r[3];
791  r[2] = r[4];
792  r[3] = r[5];
793  r[4] = r[6];
794  r[5] = r[7];
795  r[6] = r[8];
796  r[7] = a1;
797  r[8] = a2;
798  }
799 
800  return r;
801 }
802 void rofi_theme_convert_old ( void )
803 {
804  {
805  char *str = g_strdup_printf ( "#window { border: %d; padding: %d;}", config.menu_bw, config.padding );
806  rofi_theme_parse_string ( str );
807  g_free ( str );
808  }
809  if ( config.color_window ) {
810  char **retv = g_strsplit ( config.color_window, ",", -1 );
811  const char * const conf[] = {
812  "* { background: %s; }",
813  "* { border-color: %s; }",
814  "* { separatorcolor: %s; }"
815  };
816  for ( int i = 0; retv && i < 3 && retv[i]; i++ ) {
817  char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
818  rofi_theme_parse_string ( str );
819  g_free ( str );
820  }
821  g_strfreev ( retv );
822  }
823  if ( config.color_normal ) {
824  char **retv = g_strsplit ( config.color_normal, ",", -1 );
825  const char * const conf[] = {
826  "* { normal-background: %s; }",
827  "* { foreground: %s; normal-foreground: @foreground; alternate-normal-foreground: @foreground; }",
828  "* { alternate-normal-background: %s; }",
829  "* { selected-normal-background: %s; }",
830  "* { selected-normal-foreground: %s; }"
831  };
832  for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
833  char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
834  rofi_theme_parse_string ( str );
835  g_free ( str );
836  }
837  g_strfreev ( retv );
838  }
839  if ( config.color_urgent ) {
840  char **retv = g_strsplit ( config.color_urgent, ",", -1 );
841  const char * const conf[] = {
842  "* { urgent-background: %s; }",
843  "* { urgent-foreground: %s; alternate-urgent-foreground: @urgent-foreground;}",
844  "* { alternate-urgent-background: %s; }",
845  "* { selected-urgent-background: %s; }",
846  "* { selected-urgent-foreground: %s; }"
847  };
848  for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
849  char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
850  rofi_theme_parse_string ( str );
851  g_free ( str );
852  }
853  g_strfreev ( retv );
854  }
855  if ( config.color_active ) {
856  char **retv = g_strsplit ( config.color_active, ",", -1 );
857  const char * const conf[] = {
858  "* { active-background: %s; }",
859  "* { active-foreground: %s; alternate-active-foreground: @active-foreground;}",
860  "* { alternate-active-background: %s; }",
861  "* { selected-active-background: %s; }",
862  "* { selected-active-foreground: %s; }"
863  };
864  for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
865  char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
866  rofi_theme_parse_string ( str );
867  g_free ( str );
868  }
869  g_strfreev ( retv );
870  }
871 
872  if ( config.separator_style != NULL ) {
873  if ( g_strcmp0 ( config.separator_style, "none" ) == 0 ) {
874  const char *const str = "#listview { border: 0px; }";
875  rofi_theme_parse_string ( str );
876  const char *const str2 = "#sidebar { border: 0px; }";
877  rofi_theme_parse_string ( str2 );
878  const char *const str3 = "#message { border: 0px; }";
879  rofi_theme_parse_string ( str3 );
880  }
881  else if ( g_strcmp0 ( config.separator_style, "solid" ) == 0 ) {
882  const char *const str = "#listview { border: 2px solid 0px 0px 0px; }";
883  rofi_theme_parse_string ( str );
884  const char *const str2 = "#sidebar { border: 2px solid 0px 0px 0px; }";
885  rofi_theme_parse_string ( str2 );
886  const char *const str3 = "#message { border: 2px solid 0px 0px 0px; }";
887  rofi_theme_parse_string ( str3 );
888  } /* dash is default */
889  }
890  /* Line Margin */
891  {
892  char *str = g_strdup_printf ( "#listview { spacing: %dpx;}", config.line_margin );
893  rofi_theme_parse_string ( str );
894  g_free ( str );
895  }
896  /* Line Padding */
897  {
898  char *str = g_strdup_printf ( "#element, inputbar, message { padding: %dpx;}", config.line_padding );
899  rofi_theme_parse_string ( str );
900  g_free ( str );
901  }
902  if ( config.hide_scrollbar ) {
903  const char *str = "#listview { scrollbar: false; }";
904  rofi_theme_parse_string ( str );
905  }
906  else {
907  const char *str = "#listview { scrollbar: true; }";
908  rofi_theme_parse_string ( str );
909  char *str2 = g_strdup_printf ( "#scrollbar { handle-width: %dpx; }", config.scrollbar_width );
910  rofi_theme_parse_string ( str2 );
911  g_free ( str2 );
912  }
913  if ( config.fake_transparency ) {
914  char *str = g_strdup_printf ( "#window { transparency: \"%s\"; }", config.fake_background );
915  rofi_theme_parse_string ( str );
916  g_free ( str );
917  }
918 }
919 #endif // THEME_CONVERTER
920 
921 char * rofi_theme_parse_prepare_file ( const char *file, const char *parent_file )
922 {
923  char *filename = rofi_expand_path ( file );
924  // If no absolute path specified, expand it.
925  if ( parent_file != NULL && !g_path_is_absolute ( filename ) ) {
926  char *basedir = g_path_get_dirname ( parent_file );
927  char *path = g_build_filename ( basedir, filename, NULL );
928  g_free ( filename );
929  filename = path;
930  g_free ( basedir );
931  }
932  GFile *gf = g_file_new_for_path ( filename );
933  g_free ( filename );
934  filename = g_file_get_path ( gf );
935  g_object_unref ( gf );
936 
937  return filename;
938 }
xcb_depth_t * depth
Definition: xcb.c:92
static void rofi_theme_print_property_index(size_t pnl, int depth, Property *p)
Definition: theme.c:179
void rofi_theme_free(ThemeWidget *widget)
Definition: theme.c:123
GList * rofi_theme_get_list(const widget *widget, const char *property, const char *defaults)
Definition: theme.c:693
void rofi_view_get_current_monitor(int *width, int *height)
Definition: view.c:135
ThemeWidget * rofi_theme_find_or_create_name(ThemeWidget *base, const char *name)
Definition: theme.c:53
unsigned int fake_transparency
Definition: settings.h:158
double distance
Definition: rofi-types.h:95
void rofi_theme_get_color(const widget *widget, const char *property, cairo_t *d)
Definition: theme.c:648
void rofi_theme_widget_add_properties(ThemeWidget *widget, GHashTable *table)
Definition: theme.c:386
RofiDistance bottom
Definition: rofi-types.h:133
double blue
Definition: rofi-types.h:121
Property * rofi_theme_property_copy(Property *p)
Definition: theme.c:78
ThemeWidget * rofi_theme_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:508
unsigned int padding
Definition: settings.h:102
static void printf_double(double d)
Definition: theme.c:143
RofiPadding padding
Definition: rofi-types.h:192
int yyparse()
unsigned int menu_bw
Definition: settings.h:61
char * rofi_theme_parse_prepare_file(const char *file, const char *parent_file)
Definition: theme.c:921
ThemeColor color
Definition: rofi-types.h:190
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition: theme.c:470
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition: theme.c:605
double green
Definition: rofi-types.h:119
RofiHighlightStyle style
Definition: rofi-types.h:143
struct ThemeWidget ** widgets
Definition: theme.h:44
struct _widget * parent
double red
Definition: rofi-types.h:117
unsigned int scrollbar_width
Definition: settings.h:164
double rofi_theme_get_double(const widget *widget, const char *property, double def)
Definition: theme.c:621
RofiPadding rofi_theme_get_padding(const widget *widget, const char *property, RofiPadding pad)
Definition: theme.c:670
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:572
char * color_normal
Definition: settings.h:72
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:550
PropertyValue value
Definition: rofi-types.h:217
struct Property * ref
Definition: rofi-types.h:199
char * name
char * fake_background
Definition: settings.h:166
struct PropertyValue::@3 link
static void rofi_theme_print_distance(RofiDistance d)
Definition: theme.c:149
PropertyType type
Definition: rofi-types.h:215
void rofi_theme_property_free(Property *p)
Definition: theme.c:101
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:719
unsigned int num_widgets
Definition: theme.h:43
static void rofi_theme_resolve_link_property(Property *p, int depth)
Definition: theme.c:439
void yyerror(YYLTYPE *yylloc, const char *, const char *)
Definition: theme.c:360
gboolean b
Definition: rofi-types.h:188
Property * rofi_theme_property_create(PropertyType type)
Definition: theme.c:72
double textbox_get_estimated_ch(void)
Definition: textbox.c:918
RofiDistance right
Definition: rofi-types.h:132
char * name
Definition: rofi-types.h:213
struct _widget widget
Definition: widget.h:51
RofiLineStyle style
Definition: rofi-types.h:99
void rofi_theme_reset(void)
Definition: theme.c:116
RofiOrientation
Definition: rofi-types.h:105
char * color_window
Definition: settings.h:75
void rofi_add_error_message(GString *str)
Definition: rofi.c:89
char * rofi_expand_path(const char *input)
Definition: helper.c:687
void rofi_theme_print(ThemeWidget *widget)
Definition: theme.c:330
struct ThemeWidget * parent
Definition: theme.h:48
static void rofi_theme_print_index(ThemeWidget *widget)
Definition: theme.c:279
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:736
const char *const WindowLocationStr[9]
Definition: theme.c:167
double alpha
Definition: rofi-types.h:123
char * color_active
Definition: settings.h:73
RofiOrientation rofi_theme_get_orientation(const widget *widget, const char *property, RofiOrientation def)
Definition: theme.c:588
char * separator_style
Definition: settings.h:152
ThemeWidget * rofi_theme
unsigned int hide_scrollbar
Definition: settings.h:154
const char *const PropertyTypeName[P_NUM_TYPES]
Definition: rofi-types.c:6
char * color_urgent
Definition: settings.h:74
GList * list
Definition: rofi-types.h:204
static void rofi_theme_copy_property_int(G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data)
Definition: theme.c:380
const char * state
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition: theme.c:517
GHashTable * properties
Definition: theme.h:46
RofiHighlightColorStyle highlight
Definition: rofi-types.h:202
static ThemeWidget * rofi_theme_find(ThemeWidget *widget, const char *name, const gboolean exact)
Definition: theme.c:411
unsigned int line_margin
Definition: settings.h:147
Settings config
static gboolean distance_compare(RofiDistance d, RofiDistance e)
Definition: theme.c:48
static ThemeWidget * rofi_theme_find_single(ThemeWidget *widget, const char *name)
Definition: theme.c:401
double textbox_get_estimated_char_height(void)
Definition: textbox.c:896
void yylex_destroy(void)
PropertyType
Definition: rofi-types.h:10
RofiPixelUnit type
Definition: rofi-types.h:97
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:534
RofiDistance left
Definition: rofi-types.h:134
gboolean rofi_theme_parse_string(const char *string)
gboolean rofi_theme_is_empty(void)
Definition: theme.c:770
unsigned int line_padding
Definition: settings.h:148
void distance_get_linestyle(RofiDistance d, cairo_t *draw)
Definition: theme.c:759
char * name
Definition: theme.h:41
RofiDistance top
Definition: rofi-types.h:131
FILE * yyin