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