rofi 1.7.9
xrmoptions.c
Go to the documentation of this file.
1/*
2 * rofi
3 *
4 * MIT/X11 License
5 * Copyright © 2013-2023 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 */
28#define G_LOG_DOMAIN "XrmOptions"
29
30#include "xrmoptions.h"
31#include "helper.h"
32#include "rofi-types.h"
33#include "rofi.h"
34#include "settings.h"
35#include "xcb-internal.h"
36#include "xcb.h"
37#include <ctype.h>
38#include <glib.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43#include <xcb/xcb.h>
44#include <xcb/xkb.h>
45
47
49const char *const ConfigSourceStr[] = {"Default", "File", "Rasi File",
50 "Commandline", "Don't Display"};
51
59
60typedef struct {
61 int type;
62 const char *name;
63 union {
64 unsigned int *num;
65 int *snum;
66 char **str;
67 void *pointer;
68 char *charc;
69 } value;
70 char *mem;
71 const char *comment;
73} XrmOption;
74
79 {xrm_String, "switchers", {.str = &config.modes}, NULL, "", CONFIG_DEFAULT},
81 "modi",
82 {.str = &config.modes},
83 NULL,
84 "Enabled modes",
87 "modes",
88 {.str = &config.modes},
89 NULL,
90 "Enable modes",
93 "font",
94 {.str = &config.menu_font},
95 NULL,
96 "Font to use",
99 "location",
100 {.num = &config.location},
101 NULL,
102 "Location on screen",
105 "yoffset",
106 {.snum = &config.y_offset},
107 NULL,
108 "Y-offset relative to location. *DEPRECATED* see rofi-theme manpage for "
109 "new option",
112 "xoffset",
113 {.snum = &config.x_offset},
114 NULL,
115 "X-offset relative to location. *DEPRECATED* see rofi-theme manpage for "
116 "new option",
119 "fixed-num-lines",
120 {.num = &config.fixed_num_lines},
121 NULL,
122 "Always show number of lines",
124
126 "show-icons",
127 {.snum = &config.show_icons},
128 NULL,
129 "Whether to load and show icons",
131
132 {xrm_String,
133 "preview-cmd",
134 {.str = &config.preview_cmd},
135 NULL,
136 "Custom command to generate preview icons",
138
139 {xrm_String,
140 "on-selection-changed",
141 {.str = &config.on_selection_changed},
142 NULL,
143 "Custom command to call when menu selection changes",
145 {xrm_String,
146 "on-mode-changed",
147 {.str = &config.on_mode_changed},
148 NULL,
149 "Custom command to call when menu mode changes",
151 {xrm_String,
152 "on-entry-accepted",
153 {.str = &config.on_entry_accepted},
154 NULL,
155 "Custom command to call when menu entry is accepted",
157 {xrm_String,
158 "on-menu-canceled",
159 {.str = &config.on_menu_canceled},
160 NULL,
161 "Custom command to call when menu is canceled",
163 {xrm_String,
164 "on-menu-error",
165 {.str = &config.on_menu_error},
166 NULL,
167 "Custom command to call when menu finds errors",
169 {xrm_String,
170 "on-screenshot-taken",
171 {.str = &config.on_screenshot_taken},
172 NULL,
173 "Custom command to call when menu screenshot is taken",
175
176 {xrm_String,
177 "terminal",
178 {.str = &config.terminal_emulator},
179 NULL,
180 "Terminal to use",
182 {xrm_String,
183 "ssh-client",
184 {.str = &config.ssh_client},
185 NULL,
186 "Ssh client to use",
188 {xrm_String,
189 "ssh-command",
190 {.str = &config.ssh_command},
191 NULL,
192 "Ssh command to execute",
194 {xrm_String,
195 "run-command",
196 {.str = &config.run_command},
197 NULL,
198 "Run command to execute",
200 {xrm_String,
201 "run-list-command",
202 {.str = &config.run_list_command},
203 NULL,
204 "Command to get extra run targets",
206 {xrm_String,
207 "run-shell-command",
208 {.str = &config.run_shell_command},
209 NULL,
210 "Run command to execute that runs in shell",
212 {xrm_String,
213 "window-command",
214 {.str = &config.window_command},
215 NULL,
216 "Command to executed when -kb-accept-alt binding is hit on selected "
217 "window ",
219 {xrm_String,
220 "window-match-fields",
221 {.str = &config.window_match_fields},
222 NULL,
223 "Window fields to match in window mode",
225 {xrm_String,
226 "icon-theme",
227 {.str = &config.icon_theme},
228 NULL,
229 "Theme to use to look for icons",
231
232 {xrm_String,
233 "drun-match-fields",
234 {.str = &config.drun_match_fields},
235 NULL,
236 "Desktop entry fields to match in drun",
238 {xrm_String,
239 "drun-categories",
240 {.str = &config.drun_categories},
241 NULL,
242 "Only show Desktop entry from these categories",
244 {xrm_String,
245 "drun-exclude-categories",
246 {.str = &config.drun_exclude_categories},
247 NULL,
248 "Exclude Desktop entries from these categories",
251 "drun-show-actions",
252 {.num = &config.drun_show_actions},
253 NULL,
254 "Desktop entry show actions.",
256 {xrm_String,
257 "drun-display-format",
258 {.str = &config.drun_display_format},
259 NULL,
260 "DRUN format string. (Supports: generic,name,comment,exec,categories)",
262 {xrm_String,
263 "drun-url-launcher",
264 {.str = &config.drun_url_launcher},
265 NULL,
266 "Command to open a Desktop Entry that is a Link.",
268
270 "disable-history",
271 {.num = &config.disable_history},
272 NULL,
273 "Disable history in run/ssh",
275 {xrm_String,
276 "ignored-prefixes",
277 {.str = &config.ignored_prefixes},
278 NULL,
279 "Programs ignored for history",
282 "sort",
283 {.num = &config.sort},
284 NULL,
285 "Sort menu when filtered",
287 {xrm_String,
288 "sorting-method",
289 {.str = &config.sorting_method},
290 NULL,
291 "Choose sort strategy: normal (levenshtein) or fzf.",
294 "case-sensitive",
295 {.num = &config.case_sensitive},
296 NULL,
297 "Set case-sensitivity",
300 "case-smart",
301 {.num = &config.case_smart},
302 NULL,
303 "Set smartcase like vim (determine case-sensitivity by input)",
306 "cycle",
307 {.num = &config.cycle},
308 NULL,
309 "Cycle through the results list",
312 "sidebar-mode",
313 {.num = &config.sidebar_mode},
314 NULL,
315 "Enable sidebar-mode",
318 "hover-select",
319 {.snum = &config.hover_select},
320 NULL,
321 "Enable hover-select",
324 "eh",
325 {.snum = &config.element_height},
326 NULL,
327 "Row height (in chars)",
330 "auto-select",
331 {.num = &config.auto_select},
332 NULL,
333 "Enable auto select mode",
336 "parse-hosts",
337 {.num = &config.parse_hosts},
338 NULL,
339 "Parse hosts file for ssh mode",
342 "parse-known-hosts",
343 {.num = &config.parse_known_hosts},
344 NULL,
345 "Parse known_hosts file for ssh mode",
347 {xrm_String,
348 "combi-modi",
349 {.str = &config.combi_modes},
350 NULL,
351 "Set the modes to combine in combi mode",
353 {xrm_String,
354 "combi-modes",
355 {.str = &config.combi_modes},
356 NULL,
357 "Set the modes to combine in combi mode",
359 {xrm_String,
360 "matching",
361 {.str = &config.matching},
362 NULL,
363 "Set the matching algorithm. (normal, regex, glob, fuzzy, prefix)",
366 "tokenize",
367 {.num = &config.tokenize},
368 NULL,
369 "Tokenize input string",
371 {xrm_String, "monitor", {.str = &config.monitor}, NULL, "", CONFIG_DEFAULT},
372 /* Alias for dmenu compatibility. */
373 {xrm_String,
374 "m",
375 {.str = &config.monitor},
376 NULL,
377 "Monitor id to show on",
379 {xrm_String,
380 "filter",
381 {.str = &config.filter},
382 NULL,
383 "Pre-set filter",
385 {xrm_SNumber, "dpi", {.snum = &config.dpi}, NULL, "DPI", CONFIG_DEFAULT},
386 {xrm_Number,
387 "threads",
388 {.num = &config.threads},
389 NULL,
390 "Threads to use for string matching",
392 {xrm_Number,
393 "scroll-method",
394 {.num = &config.scroll_method},
395 NULL,
396 "Scrolling method. (0: Page, 1: Centered)",
398 {xrm_String,
399 "window-format",
400 {.str = &config.window_format},
401 NULL,
402 "Window Format. w (desktop name), t (title), n (name), r (role), c "
403 "(class)",
406 "click-to-exit",
407 {.snum = &config.click_to_exit},
408 NULL,
409 "Click outside the window to exit",
411 {xrm_String,
412 "theme",
413 {.str = &config.theme},
414 NULL,
415 "New style theme file",
417 {xrm_Number,
418 "max-history-size",
419 {.num = &config.max_history_size},
420 NULL,
421 "Max history size (WARNING: can cause slowdowns when set too high).",
424 "combi-hide-mode-prefix",
425 {.snum = &config.combi_hide_mode_prefix},
426 NULL,
427 "Hide the prefix mode prefix on the combi view.**deprecated** use "
428 "combi-display-format",
430 {xrm_String,
431 "combi-display-format",
432 {.str = &config.combi_display_format},
433 NULL,
434 "Combi format string. (Supports: mode, text)",
436 {xrm_Char,
437 "matching-negate-char",
438 {.charc = &config.matching_negate_char},
439 NULL,
440 "Set the character used to negate the matching. ('\\0' to disable)",
442 {xrm_String,
443 "cache-dir",
444 {.str = &config.cache_dir},
445 NULL,
446 "Directory where history and temporary files are stored.",
449 "window-thumbnail",
450 {.snum = &config.window_thumbnail},
451 NULL,
452 "Show window thumbnail (if available) as icon in window switcher.",
455 "drun-use-desktop-cache",
456 {.snum = &config.drun_use_desktop_cache},
457 NULL,
458 "DRUN: build and use a cache with desktop file content.",
461 "drun-reload-desktop-cache",
462 {.snum = &config.drun_reload_desktop_cache},
463 NULL,
464 "DRUN: If enabled, reload the cache with desktop file content.",
467 "normalize-match",
468 {.snum = &config.normalize_match},
469 NULL,
470 "Normalize string when matching (disables match highlighting).",
473 "steal-focus",
474 {.snum = &config.steal_focus},
475 NULL,
476 "Steal focus on launch and restore to window that had it on rofi start on "
477 "close .",
479 {xrm_String,
480 "application-fallback-icon",
481 {.str = &(config.application_fallback_icon)},
482 NULL,
483 "Fallback icon to use when the application icon is not found in run/drun.",
485 {xrm_Number,
486 "refilter-timeout-limit",
487 {.num = &(config.refilter_timeout_limit)},
488 NULL,
489 "When filtering takes more then this time (in ms) switch to delayed "
490 "filter.",
493 "xserver-i300-workaround",
494 {.snum = &(config.xserver_i300_workaround)},
495 NULL,
496 "Workaround for XServer issue #300 (issue #611 for rofi.)",
498 {xrm_String,
499 "completer-mode",
500 {.str = &(config.completer_mode)},
501 NULL,
502 "What completer to use for drun/run.",
505 "imdkit",
506 {.snum = &config.enable_imdkit},
507 NULL,
508 "Whether to enable imdkit",
510};
511
515unsigned int num_extra_options = 0;
516
519
520static gboolean __config_parser_set_property(XrmOption *option,
521 const Property *p, char **error);
522
523void config_parser_add_option(XrmOptionType type, const char *key, void **value,
524 const char *comment) {
526 g_realloc(extra_options, (num_extra_options + 1) * sizeof(XrmOption));
527
528 extra_options[num_extra_options].type = type;
530 extra_options[num_extra_options].value.pointer = value;
531 extra_options[num_extra_options].comment = comment;
533 switch (type) {
534 case xrm_String:
535 extra_options[num_extra_options].mem = ((char *)(*value));
536 break;
537 default:
539 break;
540 }
541
542 for (GList *iter = g_list_first(extra_parsed_options); iter != NULL;
543 iter = g_list_next(iter)) {
544 if (g_strcmp0(((Property *)(iter->data))->name, key) == 0) {
545 char *error = NULL;
546 g_debug("Setting property from backup list: %s", key);
548 (Property *)(iter->data), &error)) {
549 g_debug("Failed to set property on custom entry: %s", key);
550 g_free(error);
551 }
553 return;
554 }
555 }
557}
558
562static void config_parse_cmd_option(XrmOption *option) {
563 // Prepend a - to the option name.
564 char *key = g_strdup_printf("-%s", option->name);
565 switch (option->type) {
566 case xrm_Number:
567 if (find_arg_uint(key, option->value.num) == TRUE) {
568 option->source = (option->source & ~3) | CONFIG_CMDLINE;
569 }
570 break;
571 case xrm_SNumber:
572 if (find_arg_int(key, option->value.snum) == TRUE) {
573 option->source = (option->source & ~3) | CONFIG_CMDLINE;
574 }
575 break;
576 case xrm_String:
577 if (find_arg_str(key, option->value.str) == TRUE) {
578 if (option->mem != NULL) {
579 g_free(option->mem);
580 option->mem = NULL;
581 }
582 option->source = (option->source & ~3) | CONFIG_CMDLINE;
583 }
584 break;
585 case xrm_Boolean:
586 if (find_arg(key) >= 0) {
587 *(option->value.num) = TRUE;
588 option->source = (option->source & ~3) | CONFIG_CMDLINE;
589 } else {
590 g_free(key);
591 key = g_strdup_printf("-no-%s", option->name);
592 if (find_arg(key) >= 0) {
593 *(option->value.num) = FALSE;
594 option->source = (option->source & ~3) | CONFIG_CMDLINE;
595 }
596 }
597 break;
598 case xrm_Char:
599 if (find_arg_char(key, option->value.charc) == TRUE) {
600 option->source = (option->source & ~3) | CONFIG_CMDLINE;
601 }
602 break;
603 default:
604 break;
605 }
606 g_free(key);
607}
608
609static gboolean config_parser_form_rasi_format(GString *str, char **tokens,
610 int count, char *argv,
611 gboolean string) {
612 if (strlen(argv) > 4096) {
613 return FALSE;
614 }
615 for (int j = 0; j < (count - 1); j++) {
616 g_string_append_printf(str, "%s { ", tokens[j]);
617 }
618 if (string) {
619 char *esc = g_strescape(argv, NULL);
620 g_string_append_printf(str, "%s: \"%s\";", tokens[count - 1], esc);
621 g_free(esc);
622 } else {
623 g_string_append_printf(str, "%s: %s;", tokens[count - 1], argv);
624 }
625 for (int j = 0; j < (count - 1); j++) {
626 g_string_append(str, " } ");
627 }
628 return TRUE;
629}
630
632 for (unsigned int i = 0; i < sizeof(xrmOptions) / sizeof(XrmOption); ++i) {
633 XrmOption *op = &(xrmOptions[i]);
635 }
636 for (unsigned int i = 0; i < num_extra_options; ++i) {
637 XrmOption *op = &(extra_options[i]);
639 }
640
642 extern int stored_argc;
644 extern char **stored_argv;
645 for (int in = 1; in < (stored_argc - 1); in++) {
646 if (stored_argv[in][0] == '-') {
647 if (stored_argv[in + 1][0] == '-') {
648 continue;
649 }
651 char **tokens = g_strsplit(stored_argv[in], "-", 3);
652 int count = 1;
653 for (int j = 1; tokens && tokens[j]; j++) {
654 count++;
655 }
656 if (count >= 2) {
657 if (g_str_has_prefix(tokens[1], "theme")) {
658 g_strfreev(tokens);
659 tokens = g_strsplit(stored_argv[in], "+", 0);
660 count = g_strv_length(tokens);
661 if (count > 2) {
662 GString *str = g_string_new("");
663 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
664 stored_argv[in + 1], FALSE);
665 if (rofi_theme_parse_string(str->str) == 1) {
667 g_strfreev(tokens);
668 g_string_free(str, TRUE);
669 return;
670 }
671 g_string_free(str, TRUE);
672 }
673 } else if (g_strcmp0(tokens[1], "no") != 0) {
674 GString *str = g_string_new("configuration { ");
675 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
676 stored_argv[in + 1], FALSE);
677 g_string_append(str, "}");
678 g_debug("str: \"%s\"\n", str->str);
679 if (rofi_theme_parse_string(str->str) == 1) {
682 g_string_assign(str, "configuration { ");
683 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
684 stored_argv[in + 1], TRUE);
685 g_string_append(str, "}");
686 g_debug("str: \"%s\"\n", str->str);
687 if (rofi_theme_parse_string(str->str) == 1) {
690 }
691 }
692 g_string_free(str, TRUE);
693 }
694 in++;
695 }
696 g_strfreev(tokens);
697 }
698 }
699}
700
702 const Property *p, char **error) {
703 if (option->type == xrm_String) {
704 if (p->type != P_STRING && (p->type != P_LIST && p->type != P_INTEGER)) {
705 *error =
706 g_strdup_printf("Option: %s needs to be set with a string not a %s.",
707 option->name, PropertyTypeName[p->type]);
708 return TRUE;
709 }
710 gchar *value = NULL;
711 if (p->type == P_LIST) {
712 for (GList *iter = p->value.list; iter != NULL;
713 iter = g_list_next(iter)) {
714 Property *p2 = (Property *)iter->data;
715 if (value == NULL) {
716 value = g_strdup((char *)(p2->value.s));
717 } else {
718 char *nv = g_strjoin(",", value, (char *)(p2->value.s), NULL);
719 g_free(value);
720 value = nv;
721 }
722 }
723 } else if (p->type == P_INTEGER) {
724 value = g_strdup_printf("%d", p->value.i);
725 } else {
726 value = g_strdup(p->value.s);
727 }
728 if ((option)->mem != NULL) {
729 g_free(option->mem);
730 option->mem = NULL;
731 }
732 *(option->value.str) = value;
733
734 // Memory
735 (option)->mem = *(option->value.str);
736 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
737 } else if (option->type == xrm_Number) {
738 if (p->type != P_INTEGER) {
739 *error =
740 g_strdup_printf("Option: %s needs to be set with a number not a %s.",
741 option->name, PropertyTypeName[p->type]);
742 return TRUE;
743 }
744 *(option->value.snum) = p->value.i;
745 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
746 } else if (option->type == xrm_SNumber) {
747 if (p->type != P_INTEGER) {
748 *error =
749 g_strdup_printf("Option: %s needs to be set with a number not a %s.",
750 option->name, PropertyTypeName[p->type]);
751 return TRUE;
752 }
753 *(option->value.num) = (unsigned int)(p->value.i);
754 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
755 } else if (option->type == xrm_Boolean) {
756 if (p->type != P_BOOLEAN) {
757 *error =
758 g_strdup_printf("Option: %s needs to be set with a boolean not a %s.",
759 option->name, PropertyTypeName[p->type]);
760 return TRUE;
761 }
762 *(option->value.num) = (p->value.b);
763 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
764 } else if (option->type == xrm_Char) {
765
766 if (p->type != P_STRING) {
767 *error =
768 g_strdup_printf("Option: %s needs to be set with a string not a %s.",
769 option->name, PropertyTypeName[p->type]);
770 return TRUE;
771 }
772 *(option->value.charc) = (p->value.s[0]);
773 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
774 } else {
775 // TODO add type
776 *error = g_strdup_printf("Option: %s is not of a supported type: %s.",
777 option->name, PropertyTypeName[p->type]);
778 return TRUE;
779 }
780 return FALSE;
781}
782
783gboolean config_parse_set_property(const Property *p, char **error) {
784 if (g_ascii_strcasecmp(p->name, "theme") == 0) {
785 if (p->type == P_STRING) {
786 *error = g_strdup_printf("The option:\n<b>\nconfiguration\n{\n\ttheme: "
787 "\"%s\";\n}</b>\nis deprecated. Please replace "
788 "with: <b>@theme \"%s\"</b> "
789 "after the configuration block.",
790 p->value.s, p->value.s);
791 } else {
792 *error = g_strdup_printf("The option:\n<b>\nconfiguration\n{\n\ttheme: "
793 "\"%s\";\n}</b>\nis deprecated. Please replace "
794 "with: <b>@theme \"%s\"</b> "
795 "after the configuration block.",
796 "myTheme", "myTheme");
797 }
798 return TRUE;
799 }
800 for (unsigned int i = 0; i < sizeof(xrmOptions) / sizeof(XrmOption); ++i) {
801 XrmOption *op = &(xrmOptions[i]);
802 if (g_strcmp0(op->name, p->name) == 0) {
803 return __config_parser_set_property(op, p, error);
804 }
805 }
806 for (unsigned int i = 0; i < num_extra_options; ++i) {
807 XrmOption *op = &(extra_options[i]);
808 if (g_strcmp0(op->name, p->name) == 0) {
809 return __config_parser_set_property(op, p, error);
810 }
811 }
812 //*error = g_strdup_printf("Option: %s is not found.", p->name);
813 g_debug("Option: %s is not found.", p->name);
814
815 for (GList *iter = g_list_first(extra_parsed_options); iter != NULL;
816 iter = g_list_next(iter)) {
817 if (g_strcmp0(((Property *)(iter->data))->name, p->name) == 0) {
818 rofi_theme_property_free((Property *)(iter->data));
819 iter->data = (void *)rofi_theme_property_copy(p, NULL);
820 return FALSE;
821 }
822 }
823 g_debug("Adding option: %s to backup list.", p->name);
825 g_list_append(extra_parsed_options, rofi_theme_property_copy(p, NULL));
826
827 return FALSE;
828}
829
831 for (unsigned int i = 0; i < (sizeof(xrmOptions) / sizeof(*xrmOptions));
832 ++i) {
833 if (xrmOptions[i].mem != NULL) {
834 g_free(xrmOptions[i].mem);
835 xrmOptions[i].mem = NULL;
836 }
837 }
838 for (unsigned int i = 0; i < num_extra_options; ++i) {
839 if (extra_options[i].mem != NULL) {
840 g_free(extra_options[i].mem);
841 extra_options[i].mem = NULL;
842 }
843 }
844 if (extra_options != NULL) {
845 g_free(extra_options);
846 }
847 g_list_free_full(extra_parsed_options,
848 (GDestroyNotify)rofi_theme_property_free);
849}
850
851static void config_parse_dump_config_option(FILE *out, XrmOption *option) {
852 if (option->type == xrm_Char || (option->source & 3) == CONFIG_DEFAULT) {
853 fprintf(out, "/*");
854 }
855 fprintf(out, "\t%s: ", option->name);
856 switch (option->type) {
857 case xrm_Number:
858 fprintf(out, "%u", *(option->value.num));
859 break;
860 case xrm_SNumber:
861 fprintf(out, "%i", *(option->value.snum));
862 break;
863 case xrm_String:
864 if ((*(option->value.str)) != NULL) {
865 // TODO should this be escaped?
866 fprintf(out, "\"%s\"", *(option->value.str));
867 }
868 break;
869 case xrm_Boolean:
870 fprintf(out, "%s", (*(option->value.num) == TRUE) ? "true" : "false");
871 break;
872 case xrm_Char:
873 // TODO
874 if (*(option->value.charc) > 32 && *(option->value.charc) < 127) {
875 fprintf(out, "'%c'", *(option->value.charc));
876 } else {
877 fprintf(out, "'\\x%02X'", *(option->value.charc));
878 }
879 fprintf(out, " /* unsupported */");
880 break;
881 default:
882 break;
883 }
884
885 fprintf(out, ";");
886 if (option->type == xrm_Char || (option->source & 3) == CONFIG_DEFAULT) {
887 fprintf(out, "*/");
888 }
889 fprintf(out, "\n");
890}
891
892void config_parse_dump_config_rasi_format(FILE *out, gboolean changes) {
893 fprintf(out, "configuration {\n");
894
895 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
896 for (unsigned int i = 0; i < entries; ++i) {
897 // Skip duplicates.
898 if ((i + 1) < entries) {
899 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
900 continue;
901 }
902 }
903 if ((xrmOptions[i].source & CONFIG_NO_DISPLAY) == CONFIG_NO_DISPLAY) {
904 continue;
905 }
906 if (!changes || (xrmOptions[i].source & 3) != CONFIG_DEFAULT) {
908 }
909 }
910 for (unsigned int i = 0; i < num_extra_options; i++) {
912 continue;
913 }
914 if (!changes || (extra_options[i].source & 3) != CONFIG_DEFAULT) {
915
917 }
918 }
919
920 for (unsigned int index = 0; index < rofi_configuration->num_widgets;
921 index++) {
922 rofi_theme_print_index(rofi_configuration->widgets[index], 2);
923 }
924
925 fprintf(out, "}\n");
926
927 if (config.theme != NULL) {
928 fprintf(out, "@theme \"%s\"\r\n", config.theme);
929 }
930}
931
932static void print_option_string(XrmOption *xo, int is_term) {
933 int l = strlen(xo->name);
934 if (is_term) {
935 printf("\t" color_bold "-%s" color_reset " [string]%-*c%s\n", xo->name,
936 30 - l, ' ', xo->comment);
937 printf("\t" color_italic "%s" color_reset,
938 (*(xo->value.str) == NULL) ? "(unset)" : (*(xo->value.str)));
939 printf(" " color_green "(%s)" color_reset "\n",
940 ConfigSourceStr[xo->source & 3]);
941 } else {
942 printf("\t-%s [string]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
943 printf("\t\t%s",
944 (*(xo->value.str) == NULL) ? "(unset)" : (*(xo->value.str)));
945 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
946 }
947}
948static void print_option_number(XrmOption *xo, int is_term) {
949 int l = strlen(xo->name);
950 if (is_term) {
951 printf("\t" color_bold "-%s" color_reset " [number]%-*c%s\n", xo->name,
952 30 - l, ' ', xo->comment);
953 printf("\t" color_italic "%u" color_reset, *(xo->value.num));
954 printf(" " color_green "(%s)" color_reset "\n",
955 ConfigSourceStr[xo->source & 3]);
956 } else {
957 printf("\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
958 printf("\t\t%u", *(xo->value.num));
959 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
960 }
961}
962static void print_option_snumber(XrmOption *xo, int is_term) {
963 int l = strlen(xo->name);
964 if (is_term) {
965 printf("\t" color_bold "-%s" color_reset " [number]%-*c%s\n", xo->name,
966 30 - l, ' ', xo->comment);
967 printf("\t" color_italic "%d" color_reset, *(xo->value.snum));
968 printf(" " color_green "(%s)" color_reset "\n",
969 ConfigSourceStr[xo->source & 3]);
970 } else {
971 printf("\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
972 printf("\t\t%d", *(xo->value.snum));
973 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
974 }
975}
976static void print_option_char(XrmOption *xo, int is_term) {
977 int l = strlen(xo->name);
978 if (is_term) {
979 printf("\t" color_bold "-%s" color_reset " [character]%-*c%s\n", xo->name,
980 30 - l, ' ', xo->comment);
981 printf("\t" color_italic "%c" color_reset, *(xo->value.charc));
982 printf(" " color_green "(%s)" color_reset "\n",
983 ConfigSourceStr[xo->source & 3]);
984 } else {
985 printf("\t-%s [character]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
986 printf("\t\t%c", *(xo->value.charc));
987 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
988 }
989}
990static void print_option_boolean(XrmOption *xo, int is_term) {
991 int l = strlen(xo->name);
992 if (is_term) {
993 printf("\t" color_bold "-[no-]%s" color_reset " %-*c%s\n", xo->name, 33 - l,
994 ' ', xo->comment);
995 printf("\t" color_italic "%s" color_reset,
996 (*(xo->value.snum)) ? "True" : "False");
997 printf(" " color_green "(%s)" color_reset "\n",
998 ConfigSourceStr[xo->source & 3]);
999 } else {
1000 printf("\t-[no-]%s %-*c%s\n", xo->name, 33 - l, ' ', xo->comment);
1001 printf("\t\t%s", (*(xo->value.snum)) ? "True" : "False");
1002 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1003 }
1004}
1005
1006static void print_option(XrmOption *xo, int is_term) {
1008 return;
1009 }
1010 switch (xo->type) {
1011 case xrm_String:
1012 print_option_string(xo, is_term);
1013 break;
1014 case xrm_Number:
1015 print_option_number(xo, is_term);
1016 break;
1017 case xrm_SNumber:
1018 print_option_snumber(xo, is_term);
1019 break;
1020 case xrm_Boolean:
1021 print_option_boolean(xo, is_term);
1022 break;
1023 case xrm_Char:
1024 print_option_char(xo, is_term);
1025 break;
1026 default:
1027 break;
1028 }
1029}
1030void print_options(void) {
1031 // Check output filedescriptor
1032 int is_term = isatty(fileno(stdout));
1033 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
1034 for (unsigned int i = 0; i < entries; ++i) {
1035 if ((i + 1) < entries) {
1036 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
1037 continue;
1038 }
1039 }
1040 print_option(&xrmOptions[i], is_term);
1041 }
1042 for (unsigned int i = 0; i < num_extra_options; i++) {
1043 print_option(&extra_options[i], is_term);
1044 }
1045}
1046
1047void print_help_msg(const char *option, const char *type, const char *text,
1048 const char *def, int isatty) {
1049 int l = 37 - strlen(option) - strlen(type);
1050 if (isatty) {
1051 printf("\t%s%s%s %s %-*c%s\n", color_bold, option, color_reset, type, l,
1052 ' ', text);
1053 if (def != NULL) {
1054 printf("\t\t%s%s%s\n", color_italic, def, color_reset);
1055 }
1056 } else {
1057 printf("\t%s %s %-*c%s\n", option, type, l, ' ', text);
1058 if (def != NULL) {
1059 printf("\t\t%s\n", def);
1060 }
1061 }
1062}
1063
1065 size_t l) {
1066 int ll = (int)l;
1067 switch (option->type) {
1068 case xrm_Number:
1069 return g_markup_printf_escaped(
1070 "<b%-*s</b> (%u) <span style='italic' size='small'>%s</span>", ll,
1071 option->name, *(option->value.num), option->comment);
1072 case xrm_SNumber:
1073 return g_markup_printf_escaped(
1074 "<b%-*s</b> (%d) <span style='italic' size='small'>%s</span>", ll,
1075 option->name, *(option->value.snum), option->comment);
1076 case xrm_String:
1077 return g_markup_printf_escaped(
1078 "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>", ll,
1079 option->name,
1080 (*(option->value.str) != NULL) ? *(option->value.str) : "null",
1081 option->comment);
1082 case xrm_Boolean:
1083 return g_markup_printf_escaped(
1084 "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>", ll,
1085 option->name, (*(option->value.num) == TRUE) ? "true" : "false",
1086 option->comment);
1087 case xrm_Char:
1088 if (*(option->value.charc) > 32 && *(option->value.charc) < 127) {
1089 return g_markup_printf_escaped(
1090 "<b>%-*s</b> (%c) <span style='italic' size='small'>%s</span>", ll,
1091 option->name, *(option->value.charc), option->comment);
1092 } else {
1093 return g_markup_printf_escaped(
1094 "<b%-*s</b> (\\x%02X) <span style='italic' size='small'>%s</span>",
1095 ll, option->name, *(option->value.charc), option->comment);
1096 }
1097 default:
1098 break;
1099 }
1100
1101 return g_strdup("failed");
1102}
1103
1104char **config_parser_return_display_help(unsigned int *length) {
1105 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
1106 char **retv = NULL;
1110 size_t max_length = 0;
1111 for (unsigned int i = 0; i < entries; ++i) {
1112 size_t l = strlen(xrmOptions[i].name);
1113 max_length = MAX(max_length, l);
1114 }
1115 for (unsigned int i = 0; i < num_extra_options; i++) {
1116 size_t l = strlen(extra_options[i].name);
1117 max_length = MAX(max_length, l);
1118 }
1122 for (unsigned int i = 0; i < entries; ++i) {
1123 if ((i + 1) < entries) {
1124 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
1125 continue;
1126 }
1127 }
1128 if (strncmp(xrmOptions[i].name, "kb", 2) != 0 &&
1129 strncmp(xrmOptions[i].name, "ml", 2) != 0 &&
1130 strncmp(xrmOptions[i].name, "me", 2) != 0) {
1131 continue;
1132 }
1133
1134 retv = g_realloc(retv, ((*length) + 2) * sizeof(char *));
1135
1136 retv[(*length)] =
1138 (*length)++;
1139 }
1140 for (unsigned int i = 0; i < num_extra_options; i++) {
1141 if (strncmp(extra_options[i].name, "kb", 2) != 0 &&
1142 strncmp(extra_options[i].name, "ml", 2) != 0 &&
1143 strncmp(extra_options[i].name, "me", 2) != 0) {
1144 continue;
1145 }
1146 retv = g_realloc(retv, ((*length) + 2) * sizeof(char *));
1147 retv[(*length)] =
1149 (*length)++;
1150 }
1151 if ((*length) > 0) {
1152 retv[(*length)] = NULL;
1153 }
1154 return retv;
1155}
void config_parse_cmd_options(void)
Definition xrmoptions.c:631
void print_options(void)
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition xrmoptions.c:523
XrmOptionType
Definition xrmoptions.h:72
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
gboolean config_parse_set_property(const Property *p, char **error)
Set config option.
Definition xrmoptions.c:783
void config_parse_dump_config_rasi_format(FILE *out, gboolean changes)
Dump configuration in rasi format.
Definition xrmoptions.c:892
char ** config_parser_return_display_help(unsigned int *length)
@ xrm_SNumber
Definition xrmoptions.h:78
@ xrm_Boolean
Definition xrmoptions.h:80
@ xrm_Number
Definition xrmoptions.h:76
@ xrm_Char
Definition xrmoptions.h:82
@ xrm_String
Definition xrmoptions.h:74
void config_xresource_free(void)
Definition xrmoptions.c:830
int find_arg_char(const char *const key, char *val)
Definition helper.c:432
int find_arg_int(const char *const key, int *val)
Definition helper.c:365
int find_arg_str(const char *const key, char **val)
Definition helper.c:335
int find_arg_uint(const char *const key, unsigned int *val)
Definition helper.c:374
int find_arg(const char *const key)
Definition helper.c:326
#define color_reset
Definition rofi.h:115
#define color_bold
Definition rofi.h:117
void rofi_clear_error_messages(void)
Definition rofi.c:94
#define color_italic
Definition rofi.h:119
#define color_green
Definition rofi.h:121
char ** stored_argv
Definition helper.c:77
int stored_argc
Definition helper.c:75
const char *const PropertyTypeName[P_NUM_TYPES]
Definition rofi-types.c:6
@ P_INTEGER
Definition rofi-types.h:12
@ P_LIST
Definition rofi-types.h:32
@ P_BOOLEAN
Definition rofi-types.h:18
@ P_STRING
Definition rofi-types.h:16
Settings config
PropertyValue value
Definition rofi-types.h:293
PropertyType type
Definition rofi-types.h:291
char * name
Definition rofi-types.h:289
char * mem
Definition xrmoptions.c:70
const char * comment
Definition xrmoptions.c:71
void * pointer
Definition xrmoptions.c:67
char ** str
Definition xrmoptions.c:66
const char * name
Definition xrmoptions.c:62
unsigned int * num
Definition xrmoptions.c:64
enum ConfigSource source
Definition xrmoptions.c:72
int * snum
Definition xrmoptions.c:65
union XrmOption::@107061111126257051370212157274163204227103130150 value
char * charc
Definition xrmoptions.c:68
void rofi_theme_print_index(ThemeWidget *wid, int index)
Definition theme.c:533
Property * rofi_theme_property_copy(const Property *p, G_GNUC_UNUSED void *data)
Definition theme.c:131
void rofi_theme_property_free(Property *p)
Definition theme.c:203
gboolean rofi_theme_parse_string(const char *string)
unsigned long long count
Definition view.c:149
static void print_option_snumber(XrmOption *xo, int is_term)
Definition xrmoptions.c:962
static void print_option(XrmOption *xo, int is_term)
const char *const ConfigSourceStr[]
Definition xrmoptions.c:49
XrmOption * extra_options
Definition xrmoptions.c:513
static gboolean __config_parser_set_property(XrmOption *option, const Property *p, char **error)
Definition xrmoptions.c:701
static void print_option_char(XrmOption *xo, int is_term)
Definition xrmoptions.c:976
GList * extra_parsed_options
Definition xrmoptions.c:518
static gboolean config_parser_form_rasi_format(GString *str, char **tokens, int count, char *argv, gboolean string)
Definition xrmoptions.c:609
ThemeWidget * rofi_configuration
Definition xrmoptions.c:46
static XrmOption xrmOptions[]
Definition xrmoptions.c:78
ConfigSource
Definition xrmoptions.c:52
@ CONFIG_DEFAULT
Definition xrmoptions.c:53
@ CONFIG_NO_DISPLAY
Definition xrmoptions.c:57
@ CONFIG_FILE
Definition xrmoptions.c:54
@ CONFIG_FILE_THEME
Definition xrmoptions.c:55
@ CONFIG_CMDLINE
Definition xrmoptions.c:56
static void print_option_boolean(XrmOption *xo, int is_term)
Definition xrmoptions.c:990
static char * config_parser_return_display_help_entry(XrmOption *option, size_t l)
unsigned int num_extra_options
Definition xrmoptions.c:515
static void print_option_number(XrmOption *xo, int is_term)
Definition xrmoptions.c:948
static void config_parse_cmd_option(XrmOption *option)
Definition xrmoptions.c:562
static void config_parse_dump_config_option(FILE *out, XrmOption *option)
Definition xrmoptions.c:851
static void print_option_string(XrmOption *xo, int is_term)
Definition xrmoptions.c:932