rofi  1.6.1
xrmoptions.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2020 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 #include <config.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <xcb/xcb.h>
34 #include <xcb/xkb.h>
35 #include <xcb/xcb_xrm.h>
36 #include <glib.h>
37 #include "xcb.h"
38 #include "xcb-internal.h"
39 #include "rofi.h"
40 #include "xrmoptions.h"
41 #include "settings.h"
42 #include "helper.h"
43 #include "rofi-types.h"
44 
46 const char * const ConfigSourceStr[] = {
47  "Default",
48  "XResources",
49  "File",
50  "Rasi File",
51  "Commandline",
52 };
55 {
60  CONFIG_CMDLINE = 4
61 };
62 
63 typedef struct
64 {
65  int type;
66  const char * name;
67  union
68  {
69  unsigned int * num;
70  int * snum;
71  char ** str;
72  void *pointer;
73  char * charc;
74  } value;
75  char *mem;
76  const char *comment;
77  enum ConfigSource source;
78 } XrmOption;
83 static XrmOption xrmOptions[] = {
84  { xrm_String, "switchers", { .str = &config.modi }, NULL,
85  "", CONFIG_DEFAULT },
86  { xrm_String, "modi", { .str = &config.modi }, NULL,
87  "Enabled modi", CONFIG_DEFAULT },
88  { xrm_SNumber, "width", { .snum = &config.menu_width }, NULL,
89  "Window width", CONFIG_DEFAULT },
90  { xrm_Number, "lines", { .num = &config.menu_lines }, NULL,
91  "Number of lines", CONFIG_DEFAULT },
92  { xrm_Number, "columns", { .num = &config.menu_columns }, NULL,
93  "Number of columns", CONFIG_DEFAULT },
94 
95  { xrm_String, "font", { .str = &config.menu_font }, NULL,
96  "Font to use", CONFIG_DEFAULT },
97  { xrm_Number, "borderwidth", { .num = &config.menu_bw }, NULL,
98  "", CONFIG_DEFAULT },
99  { xrm_Number, "bw", { .num = &config.menu_bw }, NULL,
100  "Border width", CONFIG_DEFAULT },
101 
102  { xrm_Number, "location", { .num = &config.location }, NULL,
103  "Location on screen", CONFIG_DEFAULT },
104 
105  { xrm_Number, "padding", { .num = &config.padding }, NULL,
106  "Padding", CONFIG_DEFAULT },
107  { xrm_SNumber, "yoffset", { .snum = &config.y_offset }, NULL,
108  "Y-offset relative to location", CONFIG_DEFAULT },
109  { xrm_SNumber, "xoffset", { .snum = &config.x_offset }, NULL,
110  "X-offset relative to location", CONFIG_DEFAULT },
111  { xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL,
112  "Always show number of lines", CONFIG_DEFAULT },
113 
114  { xrm_Boolean, "show-icons", { .snum = &config.show_icons }, NULL,
115  "Whether to load and show icons", CONFIG_DEFAULT },
116 
117  { xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL,
118  "Terminal to use", CONFIG_DEFAULT },
119  { xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL,
120  "Ssh client to use", CONFIG_DEFAULT },
121  { xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL,
122  "Ssh command to execute", CONFIG_DEFAULT },
123  { xrm_String, "run-command", { .str = &config.run_command }, NULL,
124  "Run command to execute", CONFIG_DEFAULT },
125  { xrm_String, "run-list-command", { .str = &config.run_list_command }, NULL,
126  "Command to get extra run targets", CONFIG_DEFAULT },
127  { xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL,
128  "Run command to execute that runs in shell", CONFIG_DEFAULT },
129  { xrm_String, "window-command", { .str = &config.window_command }, NULL,
130  "Command to executed when -kb-accept-alt binding is hit on selected window ", CONFIG_DEFAULT },
131  { xrm_String, "window-match-fields", { .str = &config.window_match_fields }, NULL,
132  "Window fields to match in window mode", CONFIG_DEFAULT },
133  { xrm_String, "icon-theme", { .str = &config.icon_theme }, NULL,
134  "Theme to use to look for icons", CONFIG_DEFAULT },
135 
136  { xrm_String, "drun-match-fields", { .str = &config.drun_match_fields }, NULL,
137  "Desktop entry fields to match in drun", CONFIG_DEFAULT },
138  { xrm_String, "drun-categories", { .str = &config.drun_categories }, NULL,
139  "Only show Desktop entry from these categories", CONFIG_DEFAULT },
140  { xrm_Boolean, "drun-show-actions", { .num = &config.drun_show_actions }, NULL,
141  "Desktop entry show actions.", CONFIG_DEFAULT },
142  { xrm_String, "drun-display-format", { .str = &config.drun_display_format }, NULL,
143  "DRUN format string. (Supports: generic,name,comment,exec,categories)", CONFIG_DEFAULT },
144  { xrm_String, "drun-url-launcher", { .str = &config.drun_url_launcher }, NULL,
145  "Command to open an Desktop Entry that is a Link.", CONFIG_DEFAULT },
146 
147  { xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL,
148  "Disable history in run/ssh", CONFIG_DEFAULT },
149  { xrm_String, "ignored-prefixes", { .str = &config.ignored_prefixes }, NULL,
150  "Programs ignored for history", CONFIG_DEFAULT },
151  { xrm_Boolean, "sort", { .num = &config.sort }, NULL,
152  "Use sorting", CONFIG_DEFAULT },
153  { xrm_String, "sorting-method", { .str = &config.sorting_method }, NULL,
154  "Choose the strategy used for sorting: normal (levenshtein) or fzf.", CONFIG_DEFAULT },
155  { xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL,
156  "Set case-sensitivity", CONFIG_DEFAULT },
157  { xrm_Boolean, "cycle", { .num = &config.cycle }, NULL,
158  "Cycle through the results list", CONFIG_DEFAULT },
159  { xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL,
160  "Enable sidebar-mode", CONFIG_DEFAULT },
161  { xrm_SNumber, "eh", { .snum = &config.element_height }, NULL,
162  "Row height (in chars)", CONFIG_DEFAULT },
163  { xrm_Boolean, "auto-select", { .num = &config.auto_select }, NULL,
164  "Enable auto select mode", CONFIG_DEFAULT },
165  { xrm_Boolean, "parse-hosts", { .num = &config.parse_hosts }, NULL,
166  "Parse hosts file for ssh mode", CONFIG_DEFAULT },
167  { xrm_Boolean, "parse-known-hosts", { .num = &config.parse_known_hosts }, NULL,
168  "Parse known_hosts file for ssh mode", CONFIG_DEFAULT },
169  { xrm_String, "combi-modi", { .str = &config.combi_modi }, NULL,
170  "Set the modi to combine in combi mode", CONFIG_DEFAULT },
171  { xrm_String, "matching", { .str = &config.matching }, NULL,
172  "Set the matching algorithm. (normal, regex, glob, fuzzy)", CONFIG_DEFAULT },
173  { xrm_Boolean, "tokenize", { .num = &config.tokenize }, NULL,
174  "Tokenize input string", CONFIG_DEFAULT },
175  { xrm_String, "monitor", { .str = &config.monitor }, NULL,
176  "", CONFIG_DEFAULT },
177  /* Alias for dmenu compatibility. */
178  { xrm_String, "m", { .str = &config.monitor }, NULL,
179  "Monitor id to show on", CONFIG_DEFAULT },
180  { xrm_Number, "line-margin", { .num = &config.line_margin }, NULL,
181  "Margin between rows *DEPRECATED*", CONFIG_DEFAULT },
182  { xrm_Number, "line-padding", { .num = &config.line_padding }, NULL,
183  "Padding within rows *DEPRECATED*", CONFIG_DEFAULT },
184  { xrm_String, "filter", { .str = &config.filter }, NULL,
185  "Pre-set filter", CONFIG_DEFAULT },
186  { xrm_String, "separator-style", { .str = &config.separator_style }, NULL,
187  "Separator style (none, dash, solid) *DEPRECATED*", CONFIG_DEFAULT },
188  { xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL,
189  "Hide scroll-bar *DEPRECATED*", CONFIG_DEFAULT },
190  { xrm_Boolean, "fullscreen", { .num = &config.fullscreen }, NULL,
191  "Fullscreen", CONFIG_DEFAULT },
192  { xrm_Boolean, "fake-transparency", { .num = &config.fake_transparency }, NULL,
193  "Fake transparency *DEPRECATED*", CONFIG_DEFAULT },
194  { xrm_SNumber, "dpi", { .snum = &config.dpi }, NULL,
195  "DPI", CONFIG_DEFAULT },
196  { xrm_Number, "threads", { .num = &config.threads }, NULL,
197  "Threads to use for string matching", CONFIG_DEFAULT },
198  { xrm_Number, "scrollbar-width", { .num = &config.scrollbar_width }, NULL,
199  "Scrollbar width *DEPRECATED*", CONFIG_DEFAULT },
200  { xrm_Number, "scroll-method", { .num = &config.scroll_method }, NULL,
201  "Scrolling method. (0: Page, 1: Centered)", CONFIG_DEFAULT },
202  { xrm_String, "fake-background", { .str = &config.fake_background }, NULL,
203  "Background to use for fake transparency. (background or screenshot) *DEPRECATED*", CONFIG_DEFAULT },
204  { xrm_String, "window-format", { .str = &config.window_format }, NULL,
205  "Window Format. w (desktop name), t (title), n (name), r (role), c (class)", CONFIG_DEFAULT },
206  { xrm_Boolean, "click-to-exit", { .snum = &config.click_to_exit }, NULL,
207  "Click outside the window to exit", CONFIG_DEFAULT },
208  { xrm_Boolean, "show-match", { .snum = &config.show_match }, NULL,
209  "Indicate how it match by underlining it.", CONFIG_DEFAULT },
210  { xrm_String, "theme", { .str = &config.theme }, NULL,
211  "New style theme file", CONFIG_DEFAULT },
212  { xrm_String, "color-normal", { .str = &config.color_normal }, NULL,
213  "Color scheme for normal row", CONFIG_DEFAULT },
214  { xrm_String, "color-urgent", { .str = &config.color_urgent }, NULL,
215  "Color scheme for urgent row", CONFIG_DEFAULT },
216  { xrm_String, "color-active", { .str = &config.color_active }, NULL,
217  "Color scheme for active row", CONFIG_DEFAULT },
218  { xrm_String, "color-window", { .str = &config.color_window }, NULL,
219  "Color scheme window", CONFIG_DEFAULT },
220  { xrm_Number, "max-history-size", { .num = &config.max_history_size }, NULL,
221  "Max history size (WARNING: can cause slowdowns when set to high).", CONFIG_DEFAULT },
222  { xrm_Boolean, "combi-hide-mode-prefix", { .snum = &config.combi_hide_mode_prefix }, NULL,
223  "Hide the prefix mode prefix on the combi view.", CONFIG_DEFAULT },
224  { xrm_Char, "matching-negate-char", { .charc = &config.matching_negate_char }, NULL,
225  "Set the character used to negate the matching. ('\\0' to disable)", CONFIG_DEFAULT },
226  { xrm_String, "cache-dir", { .str = &config.cache_dir }, NULL,
227  "Directory where history and temporary files are stored.", CONFIG_DEFAULT },
228  { xrm_Boolean, "window-thumbnail", { .snum = &config.window_thumbnail }, NULL,
229  "Show window thumbnail (if available) as icon in window switcher.", CONFIG_DEFAULT },
230  { xrm_Boolean, "drun-use-desktop-cache", { .snum = &config.drun_use_desktop_cache }, NULL,
231  "DRUN: build and use a cache with desktop file content.", CONFIG_DEFAULT },
232  { xrm_Boolean, "drun-reload-desktop-cache", { .snum = &config.drun_reload_desktop_cache }, NULL,
233  "DRUN: If enabled, reload the cache with desktop file content.", CONFIG_DEFAULT },
234  { xrm_Boolean, "normalize-match", { .snum = &config.normalize_match }, NULL,
235  "Normalize string when matching (implies -no-show-match).", CONFIG_DEFAULT },
236 };
237 
241 unsigned int num_extra_options = 0;
242 
243 void config_parser_add_option ( XrmOptionType type, const char *key, void **value, const char *comment )
244 {
245  extra_options = g_realloc ( extra_options, ( num_extra_options + 1 ) * sizeof ( XrmOption ) );
246 
252  switch ( type )
253  {
254  case xrm_String:
255  extra_options[num_extra_options].mem = ( (char *) ( *value ) );
256  break;
257  default:
259  break;
260  }
261 
263 }
264 
265 static void config_parser_set ( XrmOption *option, char *xrmValue, enum ConfigSource source )
266 {
267  switch ( option->type )
268  {
269  case xrm_String:
270  if ( ( option )->mem != NULL ) {
271  g_free ( option->mem );
272  option->mem = NULL;
273  }
274  *( option->value.str ) = g_strchomp ( g_strdup ( xrmValue ) );
275 
276  // Memory
277  ( option )->mem = *( option->value.str );
278  break;
279  case xrm_Number:
280  *( option->value.num ) = (unsigned int) g_ascii_strtoull ( xrmValue, NULL, 10 );
281  break;
282  case xrm_SNumber:
283  *( option->value.snum ) = (int) g_ascii_strtoll ( xrmValue, NULL, 10 );
284  break;
285  case xrm_Boolean:
286  if ( strlen ( xrmValue ) > 0 &&
287  g_ascii_strcasecmp ( xrmValue, "true" ) == 0 ) {
288  *( option->value.num ) = TRUE;
289  }
290  else{
291  *( option->value.num ) = FALSE;
292  }
293  break;
294  case xrm_Char:
295  *( option->value.charc ) = helper_parse_char ( xrmValue );
296  break;
297  }
298  option->source = source;
299 }
300 
301 static void __config_parse_xresource_options ( xcb_xrm_database_t *xDB, enum ConfigSource source )
302 {
303  const char * namePrefix = "rofi";
304 
305  for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( XrmOption ); ++i ) {
306  char *name = g_strdup_printf ( "%s.%s", namePrefix, xrmOptions[i].name );
307 
308  char *xrmValue = NULL;
309  if ( xcb_xrm_resource_get_string ( xDB, name, NULL, &xrmValue ) == 0 ) {
310  config_parser_set ( &( xrmOptions[i] ), xrmValue, source );
311  }
312  if ( xrmValue ) {
313  free ( xrmValue );
314  }
315 
316  g_free ( name );
317  }
318 }
319 static void __config_parse_xresource_options_dynamic ( xcb_xrm_database_t *xDB, enum ConfigSource source )
320 {
321  const char * namePrefix = "rofi";
322 
323  for ( unsigned int i = 0; i < num_extra_options; ++i ) {
324  char *name;
325 
326  name = g_strdup_printf ( "%s.%s", namePrefix, extra_options[i].name );
327  char *xrmValue = NULL;
328  if ( xcb_xrm_resource_get_string ( xDB, name, NULL, &xrmValue ) == 0 ) {
329  config_parser_set ( &( extra_options[i] ), xrmValue, source );
330  }
331  if ( xrmValue ) {
332  free ( xrmValue );
333  }
334 
335  g_free ( name );
336  }
337 }
339 {
340  xcb_xrm_database_t *xDB = xcb_xrm_database_from_default ( xcb->connection );
341  if ( xDB ) {
344  xcb_xrm_database_free ( xDB );
345  }
346 }
347 void config_parse_xresource_options_file ( const char *filename )
348 {
349  if ( !filename ) {
350  return;
351  }
352  // Map Xresource entries to rofi config options.
353  xcb_xrm_database_t *xDB = xcb_xrm_database_from_file ( filename );
354  if ( xDB == NULL ) {
355  return;
356  }
359  xcb_xrm_database_free ( xDB );
360 }
361 
365 static void config_parse_cmd_option ( XrmOption *option )
366 {
367  // Prepend a - to the option name.
368  char *key = g_strdup_printf ( "-%s", option->name );
369  switch ( option->type )
370  {
371  case xrm_Number:
372  if ( find_arg_uint ( key, option->value.num ) == TRUE ) {
373  option->source = CONFIG_CMDLINE;
374  }
375  break;
376  case xrm_SNumber:
377  if ( find_arg_int ( key, option->value.snum ) == TRUE ) {
378  option->source = CONFIG_CMDLINE;
379  }
380  break;
381  case xrm_String:
382  if ( find_arg_str ( key, option->value.str ) == TRUE ) {
383  if ( option->mem != NULL ) {
384  g_free ( option->mem );
385  option->mem = NULL;
386  }
387  option->source = CONFIG_CMDLINE;
388  }
389  break;
390  case xrm_Boolean:
391  if ( find_arg ( key ) >= 0 ) {
392  *( option->value.num ) = TRUE;
393  option->source = CONFIG_CMDLINE;
394  }
395  else {
396  g_free ( key );
397  key = g_strdup_printf ( "-no-%s", option->name );
398  if ( find_arg ( key ) >= 0 ) {
399  *( option->value.num ) = FALSE;
400  option->source = CONFIG_CMDLINE;
401  }
402  }
403  break;
404  case xrm_Char:
405  if ( find_arg_char ( key, option->value.charc ) == TRUE ) {
406  option->source = CONFIG_CMDLINE;
407  }
408  break;
409  default:
410  break;
411  }
412  g_free ( key );
413 }
414 
416 {
417  for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( XrmOption ); ++i ) {
418  XrmOption *op = &( xrmOptions[i] );
420  }
421  for ( unsigned int i = 0; i < num_extra_options; ++i ) {
422  XrmOption *op = &( extra_options[i] );
424  }
425 }
426 
427 static gboolean __config_parser_set_property ( XrmOption *option, const Property *p, char **error )
428 {
429  if ( option->type == xrm_String ) {
430  if ( p->type != P_STRING && p->type != P_LIST ) {
431  *error = g_strdup_printf ( "Option: %s needs to be set with a string not a %s.", option->name, PropertyTypeName[p->type] );
432  return TRUE;
433  }
434  gchar *value = NULL;
435  if ( p->type == P_LIST ) {
436  for ( GList *iter = p->value.list; iter != NULL; iter = g_list_next ( iter ) ) {
437  if ( value == NULL ) {
438  value = g_strdup ( (char *) ( iter->data ) );
439  }
440  else {
441  char *nv = g_strjoin ( ",", value, (char *) ( iter->data ), NULL );
442  g_free ( value );
443  value = nv;
444  }
445  }
446  }
447  else {
448  value = g_strdup ( p->value.s );
449  }
450  if ( ( option )->mem != NULL ) {
451  g_free ( option->mem );
452  option->mem = NULL;
453  }
454  *( option->value.str ) = value;
455 
456  // Memory
457  ( option )->mem = *( option->value.str );
458  option->source = CONFIG_FILE_THEME;
459  }
460  else if ( option->type == xrm_Number ) {
461  if ( p->type != P_INTEGER ) {
462  *error = g_strdup_printf ( "Option: %s needs to be set with a number not a %s.", option->name, PropertyTypeName[p->type] );
463  return TRUE;
464  }
465  *( option->value.snum ) = p->value.i;
466  option->source = CONFIG_FILE_THEME;
467  }
468  else if ( option->type == xrm_SNumber ) {
469  if ( p->type != P_INTEGER ) {
470  *error = g_strdup_printf ( "Option: %s needs to be set with a number not a %s.", option->name, PropertyTypeName[p->type] );
471  return TRUE;
472  }
473  *( option->value.num ) = (unsigned int ) ( p->value.i );
474  option->source = CONFIG_FILE_THEME;
475  }
476  else if ( option->type == xrm_Boolean ) {
477  if ( p->type != P_BOOLEAN ) {
478  *error = g_strdup_printf ( "Option: %s needs to be set with a boolean not a %s.", option->name, PropertyTypeName[p->type] );
479  return TRUE;
480  }
481  *( option->value.num ) = ( p->value.b );
482  option->source = CONFIG_FILE_THEME;
483  }
484  else if ( option->type == xrm_Char ) {
485  if ( p->type != P_CHAR ) {
486  *error = g_strdup_printf ( "Option: %s needs to be set with a character not a %s.", option->name, PropertyTypeName[p->type] );
487  return TRUE;
488  }
489  *( option->value.charc ) = ( p->value.c );
490  option->source = CONFIG_FILE_THEME;
491  }
492  else {
493  // TODO add type
494  *error = g_strdup_printf ( "Option: %s is not of a supported type: %s.", option->name, PropertyTypeName[p->type] );
495  return TRUE;
496  }
497  return FALSE;
498 }
499 
500 gboolean config_parse_set_property ( const Property *p, char **error )
501 {
502  for ( unsigned int i = 0; i < sizeof ( xrmOptions ) / sizeof ( XrmOption ); ++i ) {
503  XrmOption *op = &( xrmOptions[i] );
504  if ( g_strcmp0 ( op->name, p->name ) == 0 ) {
505  return __config_parser_set_property ( op, p, error );
506  }
507  }
508  for ( unsigned int i = 0; i < num_extra_options; ++i ) {
509  XrmOption *op = &( extra_options[i] );
510  if ( g_strcmp0 ( op->name, p->name ) == 0 ) {
511  return __config_parser_set_property ( op, p, error );
512  }
513  }
514  *error = g_strdup_printf ( "Option: %s is not found.", p->name );
515  return TRUE;
516 }
517 
519 {
520  for ( unsigned int i = 0; i < ( sizeof ( xrmOptions ) / sizeof ( *xrmOptions ) ); ++i ) {
521  if ( xrmOptions[i].mem != NULL ) {
522  g_free ( xrmOptions[i].mem );
523  xrmOptions[i].mem = NULL;
524  }
525  }
526  for ( unsigned int i = 0; i < num_extra_options; ++i ) {
527  if ( extra_options[i].mem != NULL ) {
528  g_free ( extra_options[i].mem );
529  extra_options[i].mem = NULL;
530  }
531  }
532  if ( extra_options != NULL ) {
533  g_free ( extra_options );
534  }
535 }
536 
537 static void xresource_dump_entry ( const char *namePrefix, XrmOption *option )
538 {
539  printf ( "! \"%s\" ", option->comment );
540  printf ( "Set from: %s\n", ConfigSourceStr[option->source] );
541  if ( option->source == CONFIG_DEFAULT ) {
542  printf ( "! " );
543  }
544  printf ( "%s.%s: %*s", namePrefix, option->name,
545  (int) ( 30 - strlen ( option->name ) ), "" );
546  switch ( option->type )
547  {
548  case xrm_Number:
549  printf ( "%u", *( option->value.num ) );
550  break;
551  case xrm_SNumber:
552  printf ( "%i", *( option->value.snum ) );
553  break;
554  case xrm_String:
555  if ( ( *( option->value.str ) ) != NULL ) {
556  printf ( "%s", *( option->value.str ) );
557  }
558  break;
559  case xrm_Boolean:
560  printf ( "%s", ( *( option->value.num ) == TRUE ) ? "true" : "false" );
561  break;
562  case xrm_Char:
563  if ( *( option->value.charc ) > 32 && *( option->value.charc ) < 127 ) {
564  printf ( "%c", *( option->value.charc ) );
565  }
566  else {
567  printf ( "\\x%02X", *( option->value.charc ) );
568  }
569  break;
570  default:
571  break;
572  }
573  printf ( "\n" );
574 }
575 
577 {
578  const char * namePrefix = "rofi";
579  unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions );
580  for ( unsigned int i = 0; i < entries; ++i ) {
581  // Skip duplicates.
582  if ( ( i + 1 ) < entries ) {
583  if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) {
584  continue;
585  }
586  }
587  xresource_dump_entry ( namePrefix, &( xrmOptions[i] ) );
588  }
589  for ( unsigned int i = 0; i < num_extra_options; i++ ) {
590  xresource_dump_entry ( namePrefix, &( extra_options[i] ) );
591  }
592 }
593 
594 static void config_parse_dump_config_option ( FILE *out, XrmOption *option )
595 {
596  if ( option->type == xrm_Char || option->source == CONFIG_DEFAULT ) {
597  fprintf ( out, "/*" );
598  }
599  fprintf ( out, "\t%s: ", option->name );
600  switch ( option->type )
601  {
602  case xrm_Number:
603  fprintf ( out, "%u", *( option->value.num ) );
604  break;
605  case xrm_SNumber:
606  fprintf ( out, "%i", *( option->value.snum ) );
607  break;
608  case xrm_String:
609  if ( ( *( option->value.str ) ) != NULL ) {
610  // TODO should this be escaped?
611  fprintf ( out, "\"%s\"", *( option->value.str ) );
612  }
613  break;
614  case xrm_Boolean:
615  fprintf ( out, "%s", ( *( option->value.num ) == TRUE ) ? "true" : "false" );
616  break;
617  case xrm_Char:
618  // TODO
619  if ( *( option->value.charc ) > 32 && *( option->value.charc ) < 127 ) {
620  fprintf ( out, "'%c'", *( option->value.charc ) );
621  }
622  else {
623  fprintf ( out, "'\\x%02X'", *( option->value.charc ) );
624  }
625  fprintf ( out, " /* unsupported */" );
626  break;
627  default:
628  break;
629  }
630 
631  fprintf ( out, ";" );
632  if ( option->type == xrm_Char || option->source == CONFIG_DEFAULT ) {
633  fprintf ( out, "*/" );
634  }
635  fprintf ( out, "\n" );
636 }
637 
638 void config_parse_dump_config_rasi_format ( FILE *out, gboolean changes )
639 {
640  fprintf ( out, "configuration {\n" );
641 
642  unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions );
643  for ( unsigned int i = 0; i < entries; ++i ) {
644  // Skip duplicates.
645  if ( ( i + 1 ) < entries ) {
646  if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) {
647  continue;
648  }
649  }
650  if ( !changes || xrmOptions[i].source != CONFIG_DEFAULT ) {
652  }
653  }
654  for ( unsigned int i = 0; i < num_extra_options; i++ ) {
655  if ( !changes || extra_options[i].source != CONFIG_DEFAULT ) {
657  }
658  }
659 
660  fprintf ( out, "}\n" );
661 }
662 
663 static void print_option_string ( XrmOption *xo, int is_term )
664 {
665  int l = strlen ( xo->name );
666  if ( is_term ) {
667  printf ( "\t"color_bold "-%s"color_reset " [string]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
668  printf ( "\t"color_italic "%s"color_reset, ( *( xo->value.str ) == NULL ) ? "(unset)" : ( *( xo->value.str ) ) );
669  printf ( " "color_green "(%s)"color_reset "\n", ConfigSourceStr[xo->source] );
670  }
671  else {
672  printf ( "\t-%s [string]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
673  printf ( "\t\t%s", ( *( xo->value.str ) == NULL ) ? "(unset)" : ( *( xo->value.str ) ) );
674  printf ( " (%s)\n", ConfigSourceStr[xo->source] );
675  }
676 }
677 static void print_option_number ( XrmOption *xo, int is_term )
678 {
679  int l = strlen ( xo->name );
680  if ( is_term ) {
681  printf ( "\t"color_bold "-%s"color_reset " [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
682  printf ( "\t"color_italic "%u"color_reset, *( xo->value.num ) );
683  printf ( " "color_green "(%s)"color_reset "\n", ConfigSourceStr[xo->source] );
684  }
685  else {
686  printf ( "\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
687  printf ( "\t\t%u", *( xo->value.num ) );
688  printf ( " (%s)\n", ConfigSourceStr[xo->source] );
689  }
690 }
691 static void print_option_snumber ( XrmOption *xo, int is_term )
692 {
693  int l = strlen ( xo->name );
694  if ( is_term ) {
695  printf ( "\t"color_bold "-%s"color_reset " [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
696  printf ( "\t"color_italic "%d"color_reset, *( xo->value.snum ) );
697  printf ( " "color_green "(%s)"color_reset "\n", ConfigSourceStr[xo->source] );
698  }
699  else {
700  printf ( "\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
701  printf ( "\t\t%d", *( xo->value.snum ) );
702  printf ( " (%s)\n", ConfigSourceStr[xo->source] );
703  }
704 }
705 static void print_option_char ( XrmOption *xo, int is_term )
706 {
707  int l = strlen ( xo->name );
708  if ( is_term ) {
709  printf ( "\t"color_bold "-%s"color_reset " [character]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
710  printf ( "\t"color_italic "%c"color_reset, *( xo->value.charc ) );
711  printf ( " "color_green "(%s)"color_reset "\n", ConfigSourceStr[xo->source] );
712  }
713  else {
714  printf ( "\t-%s [character]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment );
715  printf ( "\t\t%c", *( xo->value.charc ) );
716  printf ( " (%s)\n", ConfigSourceStr[xo->source] );
717  }
718 }
719 static void print_option_boolean ( XrmOption *xo, int is_term )
720 {
721  int l = strlen ( xo->name );
722  if ( is_term ) {
723  printf ( "\t"color_bold "-[no-]%s"color_reset " %-*c%s\n", xo->name, 33 - l, ' ', xo->comment );
724  printf ( "\t"color_italic "%s"color_reset, ( *( xo->value.snum ) ) ? "True" : "False" );
725  printf ( " "color_green "(%s)"color_reset "\n", ConfigSourceStr[xo->source] );
726  }
727  else {
728  printf ( "\t-[no-]%s %-*c%s\n", xo->name, 33 - l, ' ', xo->comment );
729  printf ( "\t\t%s", ( *( xo->value.snum ) ) ? "True" : "False" );
730  printf ( " (%s)\n", ConfigSourceStr[xo->source] );
731  }
732 }
733 
734 static void print_option ( XrmOption *xo, int is_term )
735 {
736  switch ( xo->type )
737  {
738  case xrm_String:
739  print_option_string ( xo, is_term );
740  break;
741  case xrm_Number:
742  print_option_number ( xo, is_term );
743  break;
744  case xrm_SNumber:
745  print_option_snumber ( xo, is_term );
746  break;
747  case xrm_Boolean:
748  print_option_boolean ( xo, is_term );
749  break;
750  case xrm_Char:
751  print_option_char ( xo, is_term );
752  break;
753  default:
754  break;
755  }
756 }
757 void print_options ( void )
758 {
759  // Check output filedescriptor
760  int is_term = isatty ( fileno ( stdout ) );
761  unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions );
762  for ( unsigned int i = 0; i < entries; ++i ) {
763  if ( ( i + 1 ) < entries ) {
764  if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) {
765  continue;
766  }
767  }
768  print_option ( &xrmOptions[i], is_term );
769  }
770  for ( unsigned int i = 0; i < num_extra_options; i++ ) {
771  print_option ( &extra_options[i], is_term );
772  }
773 }
774 
775 void print_help_msg ( const char *option, const char *type, const char*text, const char *def, int isatty )
776 {
777  int l = 37 - strlen ( option ) - strlen ( type );
778  if ( isatty ) {
779  printf ( "\t%s%s%s %s %-*c%s\n", color_bold, option, color_reset, type, l, ' ', text );
780  if ( def != NULL ) {
781  printf ( "\t\t%s%s%s\n", color_italic, def, color_reset );
782  }
783  }
784  else{
785  printf ( "\t%s %s %-*c%s\n", option, type, l, ' ', text );
786  if ( def != NULL ) {
787  printf ( "\t\t%s\n", def );
788  }
789  }
790 }
791 
792 static char * config_parser_return_display_help_entry ( XrmOption *option, size_t l )
793 {
794  int ll = (int) l;
795  switch ( option->type )
796  {
797  case xrm_Number:
798  return g_markup_printf_escaped ( "<b%-*s</b> (%u) <span style='italic' size='small'>%s</span>",
799  ll, option->name, *( option->value.num ), option->comment );
800  case xrm_SNumber:
801  return g_markup_printf_escaped ( "<b%-*s</b> (%d) <span style='italic' size='small'>%s</span>",
802  ll, option->name, *( option->value.snum ), option->comment );
803  case xrm_String:
804  return g_markup_printf_escaped ( "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>",
805  ll, option->name,
806  ( *( option->value.str ) != NULL ) ? *( option->value.str ) : "null",
807  option->comment
808  );
809  case xrm_Boolean:
810  return g_markup_printf_escaped ( "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>",
811  ll, option->name, ( *( option->value.num ) == TRUE ) ? "true" : "false", option->comment );
812  case xrm_Char:
813  if ( *( option->value.charc ) > 32 && *( option->value.charc ) < 127 ) {
814  return g_markup_printf_escaped ( "<b>%-*s</b> (%c) <span style='italic' size='small'>%s</span>",
815  ll, option->name, *( option->value.charc ), option->comment );
816  }
817  else {
818  return g_markup_printf_escaped ( "<b%-*s</b> (\\x%02X) <span style='italic' size='small'>%s</span>",
819  ll, option->name, *( option->value.charc ), option->comment );
820  }
821  default:
822  break;
823  }
824 
825  return g_strdup ( "failed" );
826 }
827 
828 char ** config_parser_return_display_help ( unsigned int *length )
829 {
830  unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions );
831  char **retv = NULL;
835  size_t max_length = 0;
836  for ( unsigned int i = 0; i < entries; ++i ) {
837  size_t l = strlen ( xrmOptions[i].name );
838  max_length = MAX ( max_length, l );
839  }
840  for ( unsigned int i = 0; i < num_extra_options; i++ ) {
841  size_t l = strlen ( extra_options[i].name );
842  max_length = MAX ( max_length, l );
843  }
847  for ( unsigned int i = 0; i < entries; ++i ) {
848  if ( ( i + 1 ) < entries ) {
849  if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) {
850  continue;
851  }
852  }
853  if ( strncmp ( xrmOptions[i].name, "kb", 2 ) != 0 && strncmp ( xrmOptions[i].name, "ml", 2 ) != 0 && strncmp ( xrmOptions[i].name, "me", 2 ) != 0 ) {
854  continue;
855  }
856 
857  retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
858 
859  retv[( *length )] = config_parser_return_display_help_entry ( &xrmOptions[i], max_length );
860  ( *length )++;
861  }
862  for ( unsigned int i = 0; i < num_extra_options; i++ ) {
863  if ( strncmp ( extra_options[i].name, "kb", 2 ) != 0 && strncmp ( extra_options[i].name, "ml", 2 ) != 0 && strncmp ( extra_options[i].name, "me", 2 ) != 0 ) {
864  continue;
865  }
866  retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
867  retv[( *length )] = config_parser_return_display_help_entry ( &extra_options[i], max_length );
868  ( *length )++;
869  }
870  if ( ( *length ) > 0 ) {
871  retv[( *length )] = NULL;
872  }
873  return retv;
874 }
void config_parse_cmd_options(void)
Definition: xrmoptions.c:415
void config_parse_xresource_options_file(const char *filename)
Definition: xrmoptions.c:347
void print_options(void)
Definition: xrmoptions.c:757
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition: xrmoptions.c:243
XrmOptionType
Definition: xrmoptions.h:70
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
Definition: xrmoptions.c:775
gboolean config_parse_set_property(const Property *p, char **error)
Set config option.
Definition: xrmoptions.c:500
void config_parse_dump_config_rasi_format(FILE *out, gboolean changes)
Dump configuration in rasi format.
Definition: xrmoptions.c:638
char ** config_parser_return_display_help(unsigned int *length)
Definition: xrmoptions.c:828
@ xrm_SNumber
Definition: xrmoptions.h:76
@ xrm_Boolean
Definition: xrmoptions.h:78
@ xrm_Number
Definition: xrmoptions.h:74
@ xrm_Char
Definition: xrmoptions.h:80
@ xrm_String
Definition: xrmoptions.h:72
void config_xresource_free(void)
Definition: xrmoptions.c:518
void config_parse_xresource_dump(void)
Definition: xrmoptions.c:576
void config_parse_xresource_options(xcb_stuff *xcb)
Definition: xrmoptions.c:338
int find_arg_char(const char *const key, char *val)
Definition: helper.c:403
char helper_parse_char(const char *arg)
Definition: helper.c:362
int find_arg_int(const char *const key, int *val)
Definition: helper.c:341
int find_arg_str(const char *const key, char **val)
Definition: helper.c:309
int find_arg_uint(const char *const key, unsigned int *val)
Definition: helper.c:351
int find_arg(const char *const key)
Definition: helper.c:299
#define color_reset
Definition: rofi.h:90
#define color_bold
Definition: rofi.h:92
#define color_italic
Definition: rofi.h:94
#define color_green
Definition: rofi.h:96
const char *const PropertyTypeName[P_NUM_TYPES]
Definition: rofi-types.c:6
@ P_INTEGER
Definition: rofi-types.h:13
@ P_CHAR
Definition: rofi-types.h:19
@ P_LIST
Definition: rofi-types.h:33
@ P_BOOLEAN
Definition: rofi-types.h:21
@ P_STRING
Definition: rofi-types.h:17
Settings config
PropertyValue value
Definition: rofi-types.h:253
PropertyType type
Definition: rofi-types.h:251
char * name
Definition: rofi-types.h:249
WindowLocation location
Definition: settings.h:103
unsigned int threads
Definition: settings.h:173
unsigned int disable_history
Definition: settings.h:113
unsigned int line_padding
Definition: settings.h:159
unsigned int line_margin
Definition: settings.h:158
char * combi_modi
Definition: settings.h:151
char * matching
Definition: settings.h:152
int x_offset
Definition: settings.h:109
unsigned int parse_known_hosts
Definition: settings.h:149
gboolean show_match
Definition: settings.h:182
char * cache_dir
Definition: settings.h:195
int menu_width
Definition: settings.h:66
char * window_format
Definition: settings.h:179
char * fake_background
Definition: settings.h:177
unsigned int scroll_method
Definition: settings.h:174
gboolean drun_reload_desktop_cache
Definition: settings.h:202
char * drun_match_fields
Definition: settings.h:124
unsigned int tokenize
Definition: settings.h:154
char * drun_url_launcher
Definition: settings.h:132
char * run_command
Definition: settings.h:90
char * ignored_prefixes
Definition: settings.h:115
unsigned int fixed_num_lines
Definition: settings.h:111
gboolean normalize_match
Definition: settings.h:207
int y_offset
Definition: settings.h:107
char * terminal_emulator
Definition: settings.h:84
char * theme
Definition: settings.h:184
char * run_shell_command
Definition: settings.h:92
char * window_command
Definition: settings.h:96
unsigned int drun_show_actions
Definition: settings.h:128
unsigned int padding
Definition: settings.h:105
unsigned int auto_select
Definition: settings.h:145
int click_to_exit
Definition: settings.h:181
char * color_urgent
Definition: settings.h:77
char * filter
Definition: settings.h:161
unsigned int max_history_size
Definition: settings.h:189
unsigned int case_sensitive
Definition: settings.h:135
char * run_list_command
Definition: settings.h:94
char * color_normal
Definition: settings.h:75
unsigned int parse_hosts
Definition: settings.h:147
char * sorting_method
Definition: settings.h:121
char * drun_display_format
Definition: settings.h:130
char * color_window
Definition: settings.h:78
char * separator_style
Definition: settings.h:163
char * modi
Definition: settings.h:62
gboolean combi_hide_mode_prefix
Definition: settings.h:190
char * drun_categories
Definition: settings.h:126
char * icon_theme
Definition: settings.h:100
char * ssh_command
Definition: settings.h:88
unsigned int fullscreen
Definition: settings.h:167
unsigned int scrollbar_width
Definition: settings.h:175
unsigned int sort
Definition: settings.h:117
char * window_match_fields
Definition: settings.h:98
gboolean show_icons
Definition: settings.h:81
gboolean window_thumbnail
Definition: settings.h:198
char * menu_font
Definition: settings.h:72
unsigned int hide_scrollbar
Definition: settings.h:165
unsigned int fake_transparency
Definition: settings.h:169
unsigned int sidebar_mode
Definition: settings.h:141
char matching_negate_char
Definition: settings.h:192
int dpi
Definition: settings.h:171
unsigned int menu_lines
Definition: settings.h:68
unsigned int menu_columns
Definition: settings.h:70
gboolean drun_use_desktop_cache
Definition: settings.h:201
char * color_active
Definition: settings.h:76
char * ssh_client
Definition: settings.h:86
int element_height
Definition: settings.h:139
char * monitor
Definition: settings.h:156
unsigned int menu_bw
Definition: settings.h:64
unsigned int cycle
Definition: settings.h:137
int type
Definition: xrmoptions.c:65
char * mem
Definition: xrmoptions.c:75
const char * comment
Definition: xrmoptions.c:76
void * pointer
Definition: xrmoptions.c:72
union XrmOption::@3 value
char ** str
Definition: xrmoptions.c:71
const char * name
Definition: xrmoptions.c:66
unsigned int * num
Definition: xrmoptions.c:69
enum ConfigSource source
Definition: xrmoptions.c:77
int * snum
Definition: xrmoptions.c:70
char * charc
Definition: xrmoptions.c:73
xcb_connection_t * connection
Definition: xcb-internal.h:47
GList * list
Definition: rofi-types.h:240
gboolean b
Definition: rofi-types.h:222
xcb_stuff * xcb
Definition: xcb.c:86
static void print_option_snumber(XrmOption *xo, int is_term)
Definition: xrmoptions.c:691
static void print_option(XrmOption *xo, int is_term)
Definition: xrmoptions.c:734
const char *const ConfigSourceStr[]
Definition: xrmoptions.c:46
XrmOption * extra_options
Definition: xrmoptions.c:239
static gboolean __config_parser_set_property(XrmOption *option, const Property *p, char **error)
Definition: xrmoptions.c:427
static char * config_parser_return_display_help_entry(XrmOption *option, size_t l)
Definition: xrmoptions.c:792
static void print_option_char(XrmOption *xo, int is_term)
Definition: xrmoptions.c:705
static XrmOption xrmOptions[]
Definition: xrmoptions.c:83
ConfigSource
Definition: xrmoptions.c:55
@ CONFIG_DEFAULT
Definition: xrmoptions.c:56
@ CONFIG_FILE
Definition: xrmoptions.c:58
@ CONFIG_FILE_THEME
Definition: xrmoptions.c:59
@ CONFIG_XRESOURCES
Definition: xrmoptions.c:57
@ CONFIG_CMDLINE
Definition: xrmoptions.c:60
static void config_parser_set(XrmOption *option, char *xrmValue, enum ConfigSource source)
Definition: xrmoptions.c:265
static void print_option_boolean(XrmOption *xo, int is_term)
Definition: xrmoptions.c:719
static void __config_parse_xresource_options_dynamic(xcb_xrm_database_t *xDB, enum ConfigSource source)
Definition: xrmoptions.c:319
unsigned int num_extra_options
Definition: xrmoptions.c:241
static void print_option_number(XrmOption *xo, int is_term)
Definition: xrmoptions.c:677
static void config_parse_cmd_option(XrmOption *option)
Definition: xrmoptions.c:365
static void config_parse_dump_config_option(FILE *out, XrmOption *option)
Definition: xrmoptions.c:594
static void print_option_string(XrmOption *xo, int is_term)
Definition: xrmoptions.c:663
static void __config_parse_xresource_options(xcb_xrm_database_t *xDB, enum ConfigSource source)
Definition: xrmoptions.c:301
static void xresource_dump_entry(const char *namePrefix, XrmOption *option)
Definition: xrmoptions.c:537