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