rofi 2.1.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 int32_t type;
59 const char *name;
60 union {
61 unsigned int *num;
62 int *snum;
63 char **str;
64 void *pointer;
65 char *charc;
66 } value;
67 char *mem;
68 const char *comment;
69} XrmOption;
70
75 {xrm_String, CONFIG_DEFAULT, "switchers", {.str = &config.modes}, NULL, ""},
78 "modi",
79 {.str = &config.modes},
80 NULL,
81 "Enabled modes"},
84 "modes",
85 {.str = &config.modes},
86 NULL,
87 "Enable modes"},
88 {
91 "font",
92 {.str = &config.menu_font},
93 NULL,
94 "Font to use",
95 },
96 {
99 "location",
100 {.num = &config.location},
101 NULL,
102 "Location on screen",
103 },
104 {
107 "wayland-layer",
108 {.str = &config.wayland_layer},
109 NULL,
110 "On Wayland, specifies the layer where rofi is rendered. "
111 "Available layers are background, bottom, top, overlay.",
112 },
113 {
116 "yoffset",
117 {.snum = &config.y_offset},
118 NULL,
119 "Y-offset relative to location. *DEPRECATED* see rofi-theme manpage "
120 "for "
121 "new option",
122 },
123 {
126 "xoffset",
127 {.snum = &config.x_offset},
128 NULL,
129 "X-offset relative to location. *DEPRECATED* see rofi-theme manpage "
130 "for "
131 "new option",
132 },
133 {
136 "fixed-num-lines",
137 {.num = &config.fixed_num_lines},
138 NULL,
139 "Always show number of lines",
140 },
141
142 {
145 "show-icons",
146 {.snum = &config.show_icons},
147 NULL,
148 "Whether to load and show icons in the default theme",
149 },
150
151 {
154 "preview-cmd",
155 {.str = &config.preview_cmd},
156 NULL,
157 "Custom command to generate preview icons",
158 },
159
160 {
163 "on-selection-changed",
165 NULL,
166 "Custom command to call when menu selection changes",
167 },
168 {
171 "on-mode-changed",
172 {.str = &config.on_mode_changed},
173 NULL,
174 "Custom command to call when menu mode changes",
175 },
176 {
179 "on-entry-accepted",
180 {.str = &config.on_entry_accepted},
181 NULL,
182 "Custom command to call when menu entry is accepted",
183 },
184 {
187 "on-menu-canceled",
188 {.str = &config.on_menu_canceled},
189 NULL,
190 "Custom command to call when menu is canceled",
191 },
192 {
195 "on-menu-error",
196 {.str = &config.on_menu_error},
197 NULL,
198 "Custom command to call when menu finds errors",
199 },
200 {
203 "on-screenshot-taken",
204 {.str = &config.on_screenshot_taken},
205 NULL,
206 "Custom command to call when menu screenshot is taken",
207 },
208
209 {
212 "terminal",
213 {.str = &config.terminal_emulator},
214 NULL,
215 "Terminal to use",
216 },
217 {
220 "ssh-client",
221 {.str = &config.ssh_client},
222 NULL,
223 "Ssh client to use",
224 },
225 {
228 "ssh-command",
229 {.str = &config.ssh_command},
230 NULL,
231 "Ssh command to execute",
232 },
233 {
236 "run-command",
237 {.str = &config.run_command},
238 NULL,
239 "Run command to execute",
240 },
241 {
244 "run-list-command",
245 {.str = &config.run_list_command},
246 NULL,
247 "Command to get extra run targets",
248 },
249 {
252 "run-shell-command",
253 {.str = &config.run_shell_command},
254 NULL,
255 "Run command to execute that runs in shell",
256 },
257 {
260 "window-command",
261 {.str = &config.window_command},
262 NULL,
263 "Command to executed when -kb-accept-alt binding is hit on selected "
264 "window ",
265 },
266 {
269 "window-match-fields",
270 {.str = &config.window_match_fields},
271 NULL,
272 "Window fields to match in window mode",
273 },
274 {
277 "icon-theme",
278 {.str = &config.icon_theme},
279 NULL,
280 "Theme to use to look for icons",
281 },
282
283 {
286 "drun-match-fields",
287 {.str = &config.drun_match_fields},
288 NULL,
289 "Desktop entry fields to match in drun",
290 },
291 {
294 "drun-categories",
295 {.str = &config.drun_categories},
296 NULL,
297 "Only show Desktop entry from these categories",
298 },
299 {
302 "drun-exclude-categories",
304 NULL,
305 "Exclude Desktop entries from these categories",
306 },
307 {
310 "drun-show-actions",
311 {.num = &config.drun_show_actions},
312 NULL,
313 "Desktop entry show actions.",
314 },
315 {
318 "drun-display-format",
319 {.str = &config.drun_display_format},
320 NULL,
321 "DRUN format string. (Supports: generic,name,comment,exec,categories)",
322 },
323 {
326 "drun-url-launcher",
327 {.str = &config.drun_url_launcher},
328 NULL,
329 "Command to open a Desktop Entry that is a Link.",
330 },
331
332 {
335 "disable-history",
336 {.num = &config.disable_history},
337 NULL,
338 "Disable history in run/ssh",
339 },
340 {
343 "ignored-prefixes",
344 {.str = &config.ignored_prefixes},
345 NULL,
346 "Programs ignored for history",
347 },
348 {
351 "sort",
352 {.num = &config.sort},
353 NULL,
354 "Sort menu when filtered",
355 },
356 {
359 "sorting-method",
360 {.str = &config.sorting_method},
361 NULL,
362 "Choose sort strategy: normal (levenshtein) or fzf.",
363 },
364 {
367 "case-sensitive",
368 {.num = &config.case_sensitive},
369 NULL,
370 "Set case-sensitivity",
371 },
372 {
375 "case-smart",
376 {.num = &config.case_smart},
377 NULL,
378 "Set smartcase like vim (determine case-sensitivity by input)",
379 },
380 {
383 "cycle",
384 {.num = &config.cycle},
385 NULL,
386 "Cycle through the results list",
387 },
388 {
391 "sidebar-mode",
392 {.num = &config.sidebar_mode},
393 NULL,
394 "Enable sidebar-mode",
395 },
396 {
399 "hover-select",
400 {.snum = &config.hover_select},
401 NULL,
402 "Enable hover-select",
403 },
404 {
407 "eh",
408 {.snum = &config.element_height},
409 NULL,
410 "Row height (in chars)",
411 },
412 {
415 "auto-select",
416 {.num = &config.auto_select},
417 NULL,
418 "Enable auto select mode",
419 },
420 {
423 "parse-hosts",
424 {.num = &config.parse_hosts},
425 NULL,
426 "Parse hosts file for ssh mode",
427 },
428 {
431 "parse-known-hosts",
432 {.num = &config.parse_known_hosts},
433 NULL,
434 "Parse known_hosts file for ssh mode",
435 },
436 {
439 "combi-modi",
440 {.str = &config.combi_modes},
441 NULL,
442 "Set the modes to combine in combi mode",
443 },
444 {
447 "combi-modes",
448 {.str = &config.combi_modes},
449 NULL,
450 "Set the modes to combine in combi mode",
451 },
452 {
455 "matching",
456 {.str = &config.matching},
457 NULL,
458 "Set the matching algorithm. (normal, regex, glob, fuzzy, prefix)",
459 },
460 {
463 "tokenize",
464 {.num = &config.tokenize},
465 NULL,
466 "Tokenize input string",
467 },
468 {
471 "monitor",
472 {.str = &config.monitor},
473 NULL,
474 "",
475 },
476 /* Alias for dmenu compatibility. */
477 {
480 "m",
481 {.str = &config.monitor},
482 NULL,
483 "Monitor id to show on",
484 },
485 {
488 "filter",
489 {.str = &config.filter},
490 NULL,
491 "Pre-set filter",
492 },
493 {
496 "dpi",
497 {.snum = &config.dpi},
498 NULL,
499 "DPI",
500 },
501 {
504 "threads",
505 {.num = &config.threads},
506 NULL,
507 "Threads to use for string matching",
508 },
509 {
512 "scroll-method",
513 {.num = &config.scroll_method},
514 NULL,
515 "Scrolling method. (0: Page, 1: Centered)",
516 },
517 {
520 "window-format",
521 {.str = &config.window_format},
522 NULL,
523 "Window Format. w (desktop name), t (title), n (name), r (role), c "
524 "(class)",
525 },
526 {
529 "click-to-exit",
530 {.snum = &config.click_to_exit},
531 NULL,
532 "Click outside the window to exit",
533 },
534 {
537 "touch-scroll-step",
538 {.snum = &config.touch_scroll_step},
539 NULL,
540 "Touch swipe in pixels per scroll step, 0 for one list element "
541 "(wayland)",
542 },
543 {
546 "global-kb",
547 {.snum = &config.global_kb},
548 NULL,
549 "Inhibit compositor shortcuts so they can be reused in rofi (wayland)",
550 },
551 {
554 "theme",
555 {.str = &config.theme},
556 NULL,
557 "New style theme file",
558 },
559 {
562 "max-history-size",
563 {.num = &config.max_history_size},
564 NULL,
565 "Max history size (WARNING: can cause slowdowns when set too high).",
566 },
567 {
570 "combi-hide-mode-prefix",
572 NULL,
573 "Hide the prefix mode prefix on the combi view.**deprecated** use "
574 "combi-display-format",
575 },
576 {
579 "combi-display-format",
581 NULL,
582 "Combi format string. (Supports: mode, text)",
583 },
584 {
585 xrm_Char,
587 "matching-negate-char",
588 {.charc = &config.matching_negate_char},
589 NULL,
590 "Set the character used to negate the matching. ('\\0' to disable)",
591 },
592 {
595 "cache-dir",
596 {.str = &config.cache_dir},
597 NULL,
598 "Directory where history and temporary files are stored.",
599 },
600 {
603 "window-thumbnail",
604 {.snum = &config.window_thumbnail},
605 NULL,
606 "Show window thumbnail (if available) as icon in window switcher.",
607 },
608 {
611 "drun-use-desktop-cache",
613 NULL,
614 "DRUN: build and use a cache with desktop file content.",
615 },
616 {
619 "drun-reload-desktop-cache",
621 NULL,
622 "DRUN: If enabled, reload the cache with desktop file content.",
623 },
624 {
627 "normalize-match",
628 {.snum = &config.normalize_match},
629 NULL,
630 "Normalize string when matching (disables match highlighting).",
631 },
632 {
635 "steal-focus",
636 {.snum = &config.steal_focus},
637 NULL,
638 "Steal focus on launch and restore to window that had it on rofi start "
639 "on "
640 "close .",
641 },
642 {
645 "application-fallback-icon",
647 NULL,
648 "Fallback icon to use when the application icon is not found in "
649 "run/drun.",
650 },
651 {
654 "refilter-timeout-limit",
655 {.num = &(config.refilter_timeout_limit)},
656 NULL,
657 "When filtering takes more then this time (in ms) switch to delayed "
658 "filter.",
659 },
660 {
663 "xserver-i300-workaround",
664 {.snum = &(config.xserver_i300_workaround)},
665 NULL,
666 "Workaround for XServer issue #300 (issue #611 for rofi.)",
667 },
668 {xrm_String,
670 "completer-mode",
671 {.str = &(config.completer_mode)},
672 NULL,
673 "What completer to use for drun/run."},
676 "imdkit",
677 {.snum = &config.enable_imdkit},
678 NULL,
679 "Whether to enable imdkit"},
680 {xrm_String,
682 "fallback-icon-themes",
684 NULL,
685 "List of fallback icon themes"},
686};
687
691unsigned int num_extra_options = 0;
692
695
696static gboolean __config_parser_set_property(XrmOption *option,
697 const Property *p, char **error);
698
699void config_parser_add_option(XrmOptionType type, const char *key, void **value,
700 const char *comment) {
702 g_realloc(extra_options, (num_extra_options + 1) * sizeof(XrmOption));
703
706 extra_options[num_extra_options].value.pointer = value;
709 switch (type) {
710 case xrm_String:
711 extra_options[num_extra_options].mem = ((char *)(*value));
712 break;
713 default:
715 break;
716 }
717
718 for (GList *iter = g_list_first(extra_parsed_options); iter != NULL;
719 iter = g_list_next(iter)) {
720 if (g_strcmp0(((Property *)(iter->data))->name, key) == 0) {
721 char *error = NULL;
722 g_debug("Setting property from backup list: %s", key);
724 (Property *)(iter->data), &error)) {
725 g_debug("Failed to set property on custom entry: %s", key);
726 g_free(error);
727 }
729 return;
730 }
731 }
733}
734
738static void config_parse_cmd_option(XrmOption *option) {
739 // Prepend a - to the option name.
740 char *key = g_strdup_printf("-%s", option->name);
741 switch (option->type) {
742 case xrm_Number:
743 if (find_arg_uint(key, option->value.num) == TRUE) {
744 option->source = (option->source & ~3) | CONFIG_CMDLINE;
745 }
746 break;
747 case xrm_SNumber:
748 if (find_arg_int(key, option->value.snum) == TRUE) {
749 option->source = (option->source & ~3) | CONFIG_CMDLINE;
750 }
751 break;
752 case xrm_String:
753 if (find_arg_str(key, option->value.str) == TRUE) {
754 if (option->mem != NULL) {
755 g_free(option->mem);
756 option->mem = NULL;
757 }
758 option->source = (option->source & ~3) | CONFIG_CMDLINE;
759 }
760 break;
761 case xrm_Boolean:
762 if (find_arg(key) >= 0) {
763 *(option->value.num) = TRUE;
764 option->source = (option->source & ~3) | CONFIG_CMDLINE;
765 } else {
766 g_free(key);
767 key = g_strdup_printf("-no-%s", option->name);
768 if (find_arg(key) >= 0) {
769 *(option->value.num) = FALSE;
770 option->source = (option->source & ~3) | CONFIG_CMDLINE;
771 }
772 }
773 break;
774 case xrm_Char:
775 if (find_arg_char(key, option->value.charc) == TRUE) {
776 option->source = (option->source & ~3) | CONFIG_CMDLINE;
777 }
778 break;
779 default:
780 break;
781 }
782 g_free(key);
783}
784
785static gboolean config_parser_form_rasi_format(GString *str, char **tokens,
786 int count, char *argv,
787 gboolean string) {
788 if (strlen(argv) > 4096) {
789 return FALSE;
790 }
791 for (int j = 0; j < (count - 1); j++) {
792 g_string_append_printf(str, "%s { ", tokens[j]);
793 }
794 if (string) {
795 char *esc = g_strescape(argv, NULL);
796 g_string_append_printf(str, "%s: \"%s\";", tokens[count - 1], esc);
797 g_free(esc);
798 } else {
799 g_string_append_printf(str, "%s: %s;", tokens[count - 1], argv);
800 }
801 for (int j = 0; j < (count - 1); j++) {
802 g_string_append(str, " } ");
803 }
804 return TRUE;
805}
806
808 for (unsigned int i = 0; i < sizeof(xrmOptions) / sizeof(XrmOption); ++i) {
809 XrmOption *op = &(xrmOptions[i]);
811 }
812 for (unsigned int i = 0; i < num_extra_options; ++i) {
813 XrmOption *op = &(extra_options[i]);
815 }
816
818 extern int stored_argc;
820 extern char **stored_argv;
821 for (int in = 1; in < (stored_argc - 1); in++) {
822 if (stored_argv[in][0] == '-') {
823 if (stored_argv[in + 1][0] == '-') {
824 continue;
825 }
827 char **tokens = g_strsplit(stored_argv[in], "-", 3);
828 int count = 1;
829 for (int j = 1; tokens && tokens[j]; j++) {
830 count++;
831 }
832 if (count >= 2) {
833 if (g_str_has_prefix(tokens[1], "theme")) {
834 g_strfreev(tokens);
835 tokens = g_strsplit(stored_argv[in], "+", 0);
836 count = g_strv_length(tokens);
837 if (count > 2) {
838 GString *str = g_string_new("");
839 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
840 stored_argv[in + 1], FALSE);
841 if (rofi_theme_parse_string(str->str) == 1) {
843 g_strfreev(tokens);
844 g_string_free(str, TRUE);
845 return;
846 }
847 g_string_free(str, TRUE);
848 }
849 } else if (g_strcmp0(tokens[1], "no") != 0) {
850 GString *str = g_string_new("configuration { ");
851 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
852 stored_argv[in + 1], FALSE);
853 g_string_append(str, "}");
854 g_debug("str: \"%s\"\n", str->str);
855 if (rofi_theme_parse_string(str->str) == 1) {
858 g_string_assign(str, "configuration { ");
859 config_parser_form_rasi_format(str, &(tokens[1]), count - 1,
860 stored_argv[in + 1], TRUE);
861 g_string_append(str, "}");
862 g_debug("str: \"%s\"\n", str->str);
863 if (rofi_theme_parse_string(str->str) == 1) {
866 }
867 }
868 g_string_free(str, TRUE);
869 }
870 in++;
871 }
872 g_strfreev(tokens);
873 }
874 }
875}
876
878 const Property *p, char **error) {
879 if (option->type == xrm_String) {
880 if (p->type != P_STRING && (p->type != P_LIST && p->type != P_INTEGER)) {
881 *error =
882 g_strdup_printf("Option: %s needs to be set with a string not a %s.",
883 option->name, PropertyTypeName[p->type]);
884 return TRUE;
885 }
886 gchar *value = NULL;
887 if (p->type == P_LIST) {
888 for (GList *iter = p->value.list; iter != NULL;
889 iter = g_list_next(iter)) {
890 Property *p2 = (Property *)iter->data;
891 if (value == NULL) {
892 value = g_strdup((char *)(p2->value.s));
893 } else {
894 char *nv = g_strjoin(",", value, (char *)(p2->value.s), NULL);
895 g_free(value);
896 value = nv;
897 }
898 }
899 } else if (p->type == P_INTEGER) {
900 value = g_strdup_printf("%d", p->value.i);
901 } else {
902 value = g_strdup(p->value.s);
903 }
904 if ((option)->mem != NULL) {
905 g_free(option->mem);
906 option->mem = NULL;
907 }
908 *(option->value.str) = value;
909
910 // Memory
911 (option)->mem = *(option->value.str);
912 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
913 } else if (option->type == xrm_Number) {
914 if (p->type != P_INTEGER) {
915 *error =
916 g_strdup_printf("Option: %s needs to be set with a number not a %s.",
917 option->name, PropertyTypeName[p->type]);
918 return TRUE;
919 }
920 *(option->value.snum) = p->value.i;
921 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
922 } else if (option->type == xrm_SNumber) {
923 if (p->type != P_INTEGER) {
924 *error =
925 g_strdup_printf("Option: %s needs to be set with a number not a %s.",
926 option->name, PropertyTypeName[p->type]);
927 return TRUE;
928 }
929 *(option->value.num) = (unsigned int)(p->value.i);
930 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
931 } else if (option->type == xrm_Boolean) {
932 if (p->type != P_BOOLEAN) {
933 *error =
934 g_strdup_printf("Option: %s needs to be set with a boolean not a %s.",
935 option->name, PropertyTypeName[p->type]);
936 return TRUE;
937 }
938 *(option->value.num) = (p->value.b);
939 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
940 } else if (option->type == xrm_Char) {
941
942 if (p->type != P_STRING) {
943 *error =
944 g_strdup_printf("Option: %s needs to be set with a string not a %s.",
945 option->name, PropertyTypeName[p->type]);
946 return TRUE;
947 }
948 *(option->value.charc) = (p->value.s[0]);
949 option->source = (option->source & ~3) | CONFIG_FILE_THEME;
950 } else {
951 // TODO add type
952 *error = g_strdup_printf("Option: %s is not of a supported type: %s.",
953 option->name, PropertyTypeName[p->type]);
954 return TRUE;
955 }
956 return FALSE;
957}
958
959gboolean config_parse_set_property(const Property *p, char **error) {
960 if (g_ascii_strcasecmp(p->name, "theme") == 0) {
961 if (p->type == P_STRING) {
962 *error = g_strdup_printf("The option:\n<b>\nconfiguration\n{\n\ttheme: "
963 "\"%s\";\n}</b>\nis deprecated. Please replace "
964 "with: <b>@theme \"%s\"</b> "
965 "after the configuration block.",
966 p->value.s, p->value.s);
967 } else {
968 *error = g_strdup_printf("The option:\n<b>\nconfiguration\n{\n\ttheme: "
969 "\"%s\";\n}</b>\nis deprecated. Please replace "
970 "with: <b>@theme \"%s\"</b> "
971 "after the configuration block.",
972 "myTheme", "myTheme");
973 }
974 return TRUE;
975 }
976 for (unsigned int i = 0; i < sizeof(xrmOptions) / sizeof(XrmOption); ++i) {
977 XrmOption *op = &(xrmOptions[i]);
978 if (g_strcmp0(op->name, p->name) == 0) {
979 return __config_parser_set_property(op, p, error);
980 }
981 }
982 for (unsigned int i = 0; i < num_extra_options; ++i) {
983 XrmOption *op = &(extra_options[i]);
984 if (g_strcmp0(op->name, p->name) == 0) {
985 return __config_parser_set_property(op, p, error);
986 }
987 }
988 //*error = g_strdup_printf("Option: %s is not found.", p->name);
989 g_debug("Option: %s is not found.", p->name);
990
991 for (GList *iter = g_list_first(extra_parsed_options); iter != NULL;
992 iter = g_list_next(iter)) {
993 if (g_strcmp0(((Property *)(iter->data))->name, p->name) == 0) {
994 rofi_theme_property_free((Property *)(iter->data));
995 iter->data = (void *)rofi_theme_property_copy(p, NULL);
996 return FALSE;
997 }
998 }
999 g_debug("Adding option: %s to backup list.", p->name);
1001 g_list_append(extra_parsed_options, rofi_theme_property_copy(p, NULL));
1002
1003 return FALSE;
1004}
1005
1007 for (unsigned int i = 0; i < (sizeof(xrmOptions) / sizeof(*xrmOptions));
1008 ++i) {
1009 if (xrmOptions[i].mem != NULL) {
1010 g_free(xrmOptions[i].mem);
1011 xrmOptions[i].mem = NULL;
1012 }
1013 }
1014 for (unsigned int i = 0; i < num_extra_options; ++i) {
1015 if (extra_options[i].mem != NULL) {
1016 g_free(extra_options[i].mem);
1017 extra_options[i].mem = NULL;
1018 }
1019 }
1020 if (extra_options != NULL) {
1021 g_free(extra_options);
1022 }
1023 g_list_free_full(extra_parsed_options,
1024 (GDestroyNotify)rofi_theme_property_free);
1025}
1026
1027static void config_parse_dump_config_option(FILE *out, XrmOption *option) {
1028 if (option->type == xrm_Char || (option->source & 3) == CONFIG_DEFAULT) {
1029 fprintf(out, "/*");
1030 }
1031 fprintf(out, "\t%s: ", option->name);
1032 switch (option->type) {
1033 case xrm_Number:
1034 fprintf(out, "%u", *(option->value.num));
1035 break;
1036 case xrm_SNumber:
1037 fprintf(out, "%i", *(option->value.snum));
1038 break;
1039 case xrm_String:
1040 if ((*(option->value.str)) != NULL) {
1041 // TODO should this be escaped?
1042 fprintf(out, "\"%s\"", *(option->value.str));
1043 }
1044 break;
1045 case xrm_Boolean:
1046 fprintf(out, "%s", (*(option->value.num) == TRUE) ? "true" : "false");
1047 break;
1048 case xrm_Char:
1049 // TODO
1050 if (*(option->value.charc) > 32 && *(option->value.charc) < 127) {
1051 fprintf(out, "'%c'", *(option->value.charc));
1052 } else {
1053 fprintf(out, "'\\x%02X'", *(option->value.charc));
1054 }
1055 fprintf(out, " /* unsupported */");
1056 break;
1057 default:
1058 break;
1059 }
1060
1061 fprintf(out, ";");
1062 if (option->type == xrm_Char || (option->source & 3) == CONFIG_DEFAULT) {
1063 fprintf(out, "*/");
1064 }
1065 fprintf(out, "\n");
1066}
1067
1068void config_parse_dump_config_rasi_format(FILE *out, gboolean changes) {
1069 fprintf(out, "configuration {\n");
1070
1071 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
1072 for (unsigned int i = 0; i < entries; ++i) {
1073 // Skip duplicates.
1074 if ((i + 1) < entries) {
1075 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
1076 continue;
1077 }
1078 }
1079 if ((xrmOptions[i].source & CONFIG_NO_DISPLAY) == CONFIG_NO_DISPLAY) {
1080 continue;
1081 }
1082 if (!changes || (xrmOptions[i].source & 3) != CONFIG_DEFAULT) {
1084 }
1085 }
1086 for (unsigned int i = 0; i < num_extra_options; i++) {
1087 if ((extra_options[i].source & CONFIG_NO_DISPLAY) == CONFIG_NO_DISPLAY) {
1088 continue;
1089 }
1090 if (!changes || (extra_options[i].source & 3) != CONFIG_DEFAULT) {
1091
1093 }
1094 }
1095
1096 for (unsigned int index = 0; index < rofi_configuration->num_widgets;
1097 index++) {
1099 }
1100
1101 fprintf(out, "}\n");
1102
1103 if (config.theme != NULL) {
1104 fprintf(out, "@theme \"%s\"\r\n", config.theme);
1105 }
1106}
1107
1108static void print_option_string(XrmOption *xo, int is_term) {
1109 int l = strlen(xo->name);
1110 if (is_term) {
1111 printf("\t" color_bold "-%s" color_reset " [string]%-*c%s\n", xo->name,
1112 30 - l, ' ', xo->comment);
1113 printf("\t" color_italic "%s" color_reset,
1114 (*(xo->value.str) == NULL) ? "(unset)" : (*(xo->value.str)));
1115 printf(" " color_green "(%s)" color_reset "\n",
1116 ConfigSourceStr[xo->source & 3]);
1117 } else {
1118 printf("\t-%s [string]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
1119 printf("\t\t%s",
1120 (*(xo->value.str) == NULL) ? "(unset)" : (*(xo->value.str)));
1121 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1122 }
1123}
1124static void print_option_number(XrmOption *xo, int is_term) {
1125 int l = strlen(xo->name);
1126 if (is_term) {
1127 printf("\t" color_bold "-%s" color_reset " [number]%-*c%s\n", xo->name,
1128 30 - l, ' ', xo->comment);
1129 printf("\t" color_italic "%u" color_reset, *(xo->value.num));
1130 printf(" " color_green "(%s)" color_reset "\n",
1131 ConfigSourceStr[xo->source & 3]);
1132 } else {
1133 printf("\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
1134 printf("\t\t%u", *(xo->value.num));
1135 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1136 }
1137}
1138static void print_option_snumber(XrmOption *xo, int is_term) {
1139 int l = strlen(xo->name);
1140 if (is_term) {
1141 printf("\t" color_bold "-%s" color_reset " [number]%-*c%s\n", xo->name,
1142 30 - l, ' ', xo->comment);
1143 printf("\t" color_italic "%d" color_reset, *(xo->value.snum));
1144 printf(" " color_green "(%s)" color_reset "\n",
1145 ConfigSourceStr[xo->source & 3]);
1146 } else {
1147 printf("\t-%s [number]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
1148 printf("\t\t%d", *(xo->value.snum));
1149 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1150 }
1151}
1152static void print_option_char(XrmOption *xo, int is_term) {
1153 int l = strlen(xo->name);
1154 if (is_term) {
1155 printf("\t" color_bold "-%s" color_reset " [character]%-*c%s\n", xo->name,
1156 30 - l, ' ', xo->comment);
1157 printf("\t" color_italic "%c" color_reset, *(xo->value.charc));
1158 printf(" " color_green "(%s)" color_reset "\n",
1159 ConfigSourceStr[xo->source & 3]);
1160 } else {
1161 printf("\t-%s [character]%-*c%s\n", xo->name, 30 - l, ' ', xo->comment);
1162 printf("\t\t%c", *(xo->value.charc));
1163 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1164 }
1165}
1166static void print_option_boolean(XrmOption *xo, int is_term) {
1167 int l = strlen(xo->name);
1168 if (is_term) {
1169 printf("\t" color_bold "-[no-]%s" color_reset " %-*c%s\n", xo->name, 33 - l,
1170 ' ', xo->comment);
1171 printf("\t" color_italic "%s" color_reset,
1172 (*(xo->value.snum)) ? "True" : "False");
1173 printf(" " color_green "(%s)" color_reset "\n",
1174 ConfigSourceStr[xo->source & 3]);
1175 } else {
1176 printf("\t-[no-]%s %-*c%s\n", xo->name, 33 - l, ' ', xo->comment);
1177 printf("\t\t%s", (*(xo->value.snum)) ? "True" : "False");
1178 printf(" (%s)\n", ConfigSourceStr[xo->source & 3]);
1179 }
1180}
1181
1182static void print_option(XrmOption *xo, int is_term) {
1184 return;
1185 }
1186 switch (xo->type) {
1187 case xrm_String:
1188 print_option_string(xo, is_term);
1189 break;
1190 case xrm_Number:
1191 print_option_number(xo, is_term);
1192 break;
1193 case xrm_SNumber:
1194 print_option_snumber(xo, is_term);
1195 break;
1196 case xrm_Boolean:
1197 print_option_boolean(xo, is_term);
1198 break;
1199 case xrm_Char:
1200 print_option_char(xo, is_term);
1201 break;
1202 default:
1203 break;
1204 }
1205}
1206void print_options(void) {
1207 // Check output filedescriptor
1208 int is_term = isatty(fileno(stdout));
1209 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
1210 for (unsigned int i = 0; i < entries; ++i) {
1211 if ((i + 1) < entries) {
1212 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
1213 continue;
1214 }
1215 }
1216 print_option(&xrmOptions[i], is_term);
1217 }
1218 for (unsigned int i = 0; i < num_extra_options; i++) {
1219 print_option(&extra_options[i], is_term);
1220 }
1221}
1222
1223void print_help_msg(const char *option, const char *type, const char *text,
1224 const char *def, int isatty) {
1225 int l = 37 - strlen(option) - strlen(type);
1226 if (isatty) {
1227 printf("\t%s%s%s %s %-*c%s\n", color_bold, option, color_reset, type, l,
1228 ' ', text);
1229 if (def != NULL) {
1230 printf("\t\t%s%s%s\n", color_italic, def, color_reset);
1231 }
1232 } else {
1233 printf("\t%s %s %-*c%s\n", option, type, l, ' ', text);
1234 if (def != NULL) {
1235 printf("\t\t%s\n", def);
1236 }
1237 }
1238}
1239
1241 size_t l) {
1242 int ll = (int)l;
1243 switch (option->type) {
1244 case xrm_Number:
1245 return g_markup_printf_escaped(
1246 "<b%-*s</b> (%u) <span style='italic' size='small'>%s</span>", ll,
1247 option->name, *(option->value.num), option->comment);
1248 case xrm_SNumber:
1249 return g_markup_printf_escaped(
1250 "<b%-*s</b> (%d) <span style='italic' size='small'>%s</span>", ll,
1251 option->name, *(option->value.snum), option->comment);
1252 case xrm_String:
1253 return g_markup_printf_escaped(
1254 "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>", ll,
1255 option->name,
1256 (*(option->value.str) != NULL) ? *(option->value.str) : "null",
1257 option->comment);
1258 case xrm_Boolean:
1259 return g_markup_printf_escaped(
1260 "<b>%-*s</b> (%s) <span style='italic' size='small'>%s</span>", ll,
1261 option->name, (*(option->value.num) == TRUE) ? "true" : "false",
1262 option->comment);
1263 case xrm_Char:
1264 if (*(option->value.charc) > 32 && *(option->value.charc) < 127) {
1265 return g_markup_printf_escaped(
1266 "<b>%-*s</b> (%c) <span style='italic' size='small'>%s</span>", ll,
1267 option->name, *(option->value.charc), option->comment);
1268 } else {
1269 return g_markup_printf_escaped(
1270 "<b%-*s</b> (\\x%02X) <span style='italic' size='small'>%s</span>",
1271 ll, option->name, *(option->value.charc), option->comment);
1272 }
1273 default:
1274 break;
1275 }
1276
1277 return g_strdup("failed");
1278}
1279
1280char **config_parser_return_display_help(unsigned int *length) {
1281 unsigned int entries = sizeof(xrmOptions) / sizeof(*xrmOptions);
1282 char **retv = NULL;
1286 size_t max_length = 0;
1287 for (unsigned int i = 0; i < entries; ++i) {
1288 size_t l = strlen(xrmOptions[i].name);
1289 max_length = MAX(max_length, l);
1290 }
1291 for (unsigned int i = 0; i < num_extra_options; i++) {
1292 size_t l = strlen(extra_options[i].name);
1293 max_length = MAX(max_length, l);
1294 }
1298 for (unsigned int i = 0; i < entries; ++i) {
1299 if ((i + 1) < entries) {
1300 if (xrmOptions[i].value.str == xrmOptions[i + 1].value.str) {
1301 continue;
1302 }
1303 }
1304 if (strncmp(xrmOptions[i].name, "kb", 2) != 0 &&
1305 strncmp(xrmOptions[i].name, "ml", 2) != 0 &&
1306 strncmp(xrmOptions[i].name, "me", 2) != 0) {
1307 continue;
1308 }
1309
1310 retv = g_realloc(retv, ((*length) + 2) * sizeof(char *));
1311
1312 retv[(*length)] =
1314 (*length)++;
1315 }
1316 for (unsigned int i = 0; i < num_extra_options; i++) {
1317 if (strncmp(extra_options[i].name, "kb", 2) != 0 &&
1318 strncmp(extra_options[i].name, "ml", 2) != 0 &&
1319 strncmp(extra_options[i].name, "me", 2) != 0) {
1320 continue;
1321 }
1322 retv = g_realloc(retv, ((*length) + 2) * sizeof(char *));
1323 retv[(*length)] =
1325 (*length)++;
1326 }
1327 if ((*length) > 0) {
1328 retv[(*length)] = NULL;
1329 }
1330 return retv;
1331}
void config_parse_cmd_options(void)
Definition xrmoptions.c:807
void print_options(void)
void config_parser_add_option(XrmOptionType type, const char *key, void **value, const char *comment)
Definition xrmoptions.c:699
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:959
void config_parse_dump_config_rasi_format(FILE *out, gboolean changes)
Dump configuration in rasi format.
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)
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:123
#define color_bold
Definition rofi.h:125
void rofi_clear_error_messages(void)
Definition rofi.c:100
#define color_italic
Definition rofi.h:127
#define color_green
Definition rofi.h:129
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
WindowLocation location
Definition settings.h:110
unsigned int threads
Definition settings.h:173
unsigned int disable_history
Definition settings.h:118
char * application_fallback_icon
Definition settings.h:214
char * matching
Definition settings.h:163
char * preview_cmd
Definition settings.h:71
char * on_screenshot_taken
Definition settings.h:84
int x_offset
Definition settings.h:114
unsigned int parse_known_hosts
Definition settings.h:160
char * cache_dir
Definition settings.h:198
char * window_format
Definition settings.h:176
unsigned int scroll_method
Definition settings.h:174
gboolean drun_reload_desktop_cache
Definition settings.h:205
char * on_mode_changed
Definition settings.h:76
char * drun_match_fields
Definition settings.h:129
unsigned int tokenize
Definition settings.h:165
char * drun_url_launcher
Definition settings.h:139
char * fallback_icon_themes
Definition settings.h:227
char * run_command
Definition settings.h:92
char * ignored_prefixes
Definition settings.h:120
char * combi_modes
Definition settings.h:162
unsigned int fixed_num_lines
Definition settings.h:116
gboolean normalize_match
Definition settings.h:210
int y_offset
Definition settings.h:112
char * terminal_emulator
Definition settings.h:86
gboolean xserver_i300_workaround
Definition settings.h:221
char * modes
Definition settings.h:63
char * theme
Definition settings.h:185
char * run_shell_command
Definition settings.h:94
char * window_command
Definition settings.h:98
char * on_entry_accepted
Definition settings.h:78
gboolean global_kb
Definition settings.h:183
unsigned int drun_show_actions
Definition settings.h:135
int touch_scroll_step
Definition settings.h:180
unsigned int case_smart
Definition settings.h:144
gboolean steal_focus
Definition settings.h:212
unsigned int auto_select
Definition settings.h:156
int click_to_exit
Definition settings.h:178
char * filter
Definition settings.h:169
unsigned int max_history_size
Definition settings.h:190
unsigned int case_sensitive
Definition settings.h:142
char * run_list_command
Definition settings.h:96
unsigned int parse_hosts
Definition settings.h:158
char * sorting_method
Definition settings.h:126
char * drun_display_format
Definition settings.h:137
gboolean combi_hide_mode_prefix
Definition settings.h:191
char * drun_categories
Definition settings.h:131
char * icon_theme
Definition settings.h:102
char * drun_exclude_categories
Definition settings.h:133
char * ssh_command
Definition settings.h:90
unsigned int sort
Definition settings.h:122
char * wayland_layer
Definition settings.h:108
char * window_match_fields
Definition settings.h:100
gboolean enable_imdkit
Definition settings.h:225
gboolean show_icons
Definition settings.h:68
gboolean window_thumbnail
Definition settings.h:201
char * menu_font
Definition settings.h:65
unsigned int sidebar_mode
Definition settings.h:150
char matching_negate_char
Definition settings.h:195
int dpi
Definition settings.h:171
char * on_menu_error
Definition settings.h:82
unsigned int refilter_timeout_limit
Definition settings.h:218
char * completer_mode
Definition settings.h:223
char * on_selection_changed
Definition settings.h:74
gboolean drun_use_desktop_cache
Definition settings.h:204
char * on_menu_canceled
Definition settings.h:80
char * ssh_client
Definition settings.h:88
gboolean hover_select
Definition settings.h:152
int element_height
Definition settings.h:148
char * combi_display_format
Definition settings.h:193
char * monitor
Definition settings.h:167
unsigned int cycle
Definition settings.h:146
struct ThemeWidget ** widgets
Definition rofi-types.h:337
unsigned int num_widgets
Definition rofi-types.h:336
char * mem
Definition xrmoptions.c:67
const char * comment
Definition xrmoptions.c:68
const char * name
Definition xrmoptions.c:59
union XrmOption::@244212033047230145217067100004346177247122154202 value
enum ConfigSource source
Definition xrmoptions.c:58
int32_t type
Definition xrmoptions.c:57
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)
static void print_option_snumber(XrmOption *xo, int is_term)
static void print_option(XrmOption *xo, int is_term)
const char *const ConfigSourceStr[]
Definition xrmoptions.c:45
XrmOption * extra_options
Definition xrmoptions.c:689
static gboolean __config_parser_set_property(XrmOption *option, const Property *p, char **error)
Definition xrmoptions.c:877
static void print_option_char(XrmOption *xo, int is_term)
GList * extra_parsed_options
Definition xrmoptions.c:694
static gboolean config_parser_form_rasi_format(GString *str, char **tokens, int count, char *argv, gboolean string)
Definition xrmoptions.c:785
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)
static char * config_parser_return_display_help_entry(XrmOption *option, size_t l)
unsigned int num_extra_options
Definition xrmoptions.c:691
static void print_option_number(XrmOption *xo, int is_term)
static void config_parse_cmd_option(XrmOption *option)
Definition xrmoptions.c:738
static void config_parse_dump_config_option(FILE *out, XrmOption *option)
static void print_option_string(XrmOption *xo, int is_term)