rofi 2.1.0
script.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 */
27
28#define G_LOG_DOMAIN "Modes.Script"
29
31#include "glib.h"
32
33#include "display.h"
34#include "helper.h"
35#include "modes/script.h"
36#include "rofi.h"
37#include <assert.h>
38#include <ctype.h>
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <strings.h>
44#include <unistd.h>
45
46#include "widgets/textbox.h"
47
48#include "mode-private.h"
49
50#include "rofi-icon-fetcher.h"
51
53
54typedef struct {
56 unsigned int id;
60 unsigned int cmd_list_length;
61
64 unsigned int num_urgent_list;
67 unsigned int num_active_list;
69 char *message;
70 char *prompt;
71 char *data;
72 gboolean do_markup;
75 char delim;
77 gboolean no_custom;
79 gboolean keep_filter;
80
81 gboolean use_hot_keys;
82
85
89void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
90 DmenuScriptEntry *entry, char *buffer,
91 G_GNUC_UNUSED size_t length) {
92 gchar **extras = g_strsplit(buffer, "\x1f", -1);
93 gchar **extra = extras;
94 for (; *extra != NULL && *(extra + 1) != NULL; extra += 2) {
95 gchar *key = *extra;
96 gchar *value = *(extra + 1);
97 // Mark NULL
98 *(extra) = NULL;
99 *(extra + 1) = NULL;
100 if (strcasecmp(key, "icon") == 0) {
101 entry->icon_name = g_strsplit(value, ",", -1);
102 g_free(value);
103 } else if (strcasecmp(key, "display") == 0) {
104 entry->display = value;
105 } else if (strcasecmp(key, "meta") == 0) {
106 entry->meta = value;
107 } else if (strcasecmp(key, "info") == 0) {
108 entry->info = value;
109 } else if (strcasecmp(key, "nonselectable") == 0) {
110 entry->nonselectable = g_ascii_strcasecmp(value, "true") == 0;
111 g_free(value);
112 } else if (strcasecmp(key, "permanent") == 0) {
113 entry->permanent = g_ascii_strcasecmp(value, "true") == 0;
114 g_free(value);
115 } else if (strcasecmp(key, "urgent") == 0) {
116 entry->urgent = g_ascii_strcasecmp(value, "true") == 0;
117 g_free(value);
118 } else if (strcasecmp(key, "active") == 0) {
119 entry->active = g_ascii_strcasecmp(value, "true") == 0;
120 g_free(value);
121 } else {
122 g_free(value);
123 }
124 g_free(key);
125 }
126 // Got an extra entry.. lets free it.
127 if (*extras != NULL) {
128 g_free(*extras);
129 }
130 g_free(extras);
131}
132
136
137static void script_switch_mode(Mode *sw, char *value) {
138 int index = mode_lookup(value);
140
141 if (index >= 0) {
142 pd->switch_mode = index;
143 } else {
144 g_warning("Mode \"%s\" not found, please make sure it's enabled.\n", value);
145 }
146}
147
148static void parse_header_entry(Mode *sw, char *line, ssize_t length) {
150 ssize_t length_key = 0; // strlen ( line );
151 while (length_key < length && line[length_key] != '\x1f') {
152 length_key++;
153 }
154
155 if ((length_key + 1) < length) {
156 line[length_key] = '\0';
157 char *value = line + length_key + 1;
158 if (strcasecmp(line, "message") == 0) {
159 g_free(pd->message);
160 pd->message = strlen(value) ? g_strdup(value) : NULL;
161 } else if (strcasecmp(line, "prompt") == 0) {
162 g_free(pd->prompt);
163 pd->prompt = g_strdup(value);
164 sw->display_name = pd->prompt;
165 } else if (strcasecmp(line, "markup-rows") == 0) {
166 pd->do_markup = (strcasecmp(value, "true") == 0);
167 } else if (strcasecmp(line, "urgent") == 0) {
168 parse_ranges(value, &(pd->urgent_list), &(pd->num_urgent_list));
169 } else if (strcasecmp(line, "active") == 0) {
170 parse_ranges(value, &(pd->active_list), &(pd->num_active_list));
171 } else if (strcasecmp(line, "delim") == 0) {
172 pd->delim = helper_parse_char(value);
173 } else if (strcasecmp(line, "no-custom") == 0) {
174 pd->no_custom = (strcasecmp(value, "true") == 0);
175 } else if (strcasecmp(line, "use-hot-keys") == 0) {
176 pd->use_hot_keys = (strcasecmp(value, "true") == 0);
177 } else if (strcasecmp(line, "keep-selection") == 0) {
178 pd->keep_selection = (strcasecmp(value, "true") == 0);
179 } else if (strcasecmp(line, "keep-filter") == 0) {
180 pd->keep_filter = (strcasecmp(value, "true") == 0);
181 } else if (strcasecmp(line, "new-selection") == 0) {
182 pd->new_selection = (int64_t)g_ascii_strtoll(value, NULL, 0);
183 } else if (strcasecmp(line, "data") == 0) {
184 g_free(pd->data);
185 pd->data = g_strdup(value);
186 } else if (strcasecmp(line, "theme") == 0) {
187 if (rofi_theme_parse_string((const char *)value)) {
188 g_warning("Failed to parse: '%s'", value);
190 }
191 } else if (strcasecmp(line, "switch-mode") == 0) {
192 script_switch_mode(sw, value);
193 }
194 }
195}
196
198 unsigned int *length, int value,
199 DmenuScriptEntry *entry,
200 char *input) {
202 int fd = -1;
203 GError *error = NULL;
204 DmenuScriptEntry *retv = NULL;
205 char **argv = NULL;
206 int argc = 0;
207 *length = 0;
208 // Reset these between runs.
209 pd->new_selection = -1;
210 pd->keep_selection = 0;
211 pd->keep_filter = 0;
212 // Environment
213 char **env = g_get_environ();
214
215 char *str_value = g_strdup_printf("%d", value);
216 env = g_environ_setenv(env, "ROFI_RETV", str_value, TRUE);
217 g_free(str_value);
218
219 str_value = g_strdup_printf("%d", (int)getpid());
220 env = g_environ_setenv(env, "ROFI_OUTSIDE", str_value, TRUE);
221 g_free(str_value);
222
223 if (entry && entry->info) {
224 env = g_environ_setenv(env, "ROFI_INFO", entry->info, TRUE);
225 }
226 if (pd->data) {
227 env = g_environ_setenv(env, "ROFI_DATA", pd->data, TRUE);
228 }
229
230 if (input != NULL) {
231 env = g_environ_setenv(env, "ROFI_INPUT", input, TRUE);
232 }
233
234 if (g_shell_parse_argv(sw->ed, &argc, &argv, &error)) {
235 argv = g_realloc(argv, (argc + 2) * sizeof(char *));
236 argv[argc] = g_strdup(arg);
237 argv[argc + 1] = NULL;
238 g_spawn_async_with_pipes(NULL, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL,
239 NULL, NULL, &fd, NULL, &error);
240 }
241 g_strfreev(env);
242 if (error != NULL) {
243 char *msg = g_strdup_printf("Failed to execute: '%s'\nError: '%s'",
244 (char *)sw->ed, error->message);
245 rofi_view_error_dialog(msg, FALSE);
246 g_free(msg);
247 // print error.
248 g_error_free(error);
249 fd = -1;
250 }
251 if (fd >= 0) {
252 FILE *inp = fdopen(fd, "r");
253 if (inp) {
254 char *buffer = NULL;
255 size_t buffer_length = 0;
256 ssize_t read_length = 0;
257 size_t actual_size = 0;
258 while ((read_length = getdelim(&buffer, &buffer_length, pd->delim, inp)) >
259 0) {
260 // Filter out line-end.
261 if (buffer[read_length - 1] == pd->delim) {
262 buffer[read_length - 1] = '\0';
263 }
264 if (buffer[0] == '\0') {
265 parse_header_entry(sw, &buffer[1], read_length - 1);
266 } else {
267 if (actual_size < ((*length) + 2)) {
268 actual_size += 256;
269 // Check if it returns NULL, if it does, break out and show what we
270 // have so far.
271 DmenuScriptEntry *retvn =
272 g_realloc(retv, (actual_size) * sizeof(DmenuScriptEntry));
273 if (retvn == NULL) {
274 break;
275 }
276 retv = retvn;
277 }
278 if (retv) {
279 size_t buf_length = strlen(buffer);
280 retv[(*length)].entry = rofi_force_utf8(buffer, buf_length);
281 retv[(*length)].icon_name = NULL;
282 retv[(*length)].display = NULL;
283 retv[(*length)].meta = NULL;
284 retv[(*length)].info = NULL;
285 retv[(*length)].active = FALSE;
286 retv[(*length)].urgent = FALSE;
287 retv[(*length)].icon_fetch_uid = 0;
288 retv[(*length)].icon_fetch_size = 0;
289 retv[(*length)].icon_fetch_scale = 0;
290 /* The memset below only clears the next slot, leaving the
291 * first entry uninitialized. */
292 retv[(*length)].icon_fallback_index = 0;
293 retv[(*length)].nonselectable = FALSE;
294 retv[(*length)].permanent = FALSE;
295
296 // Skip the '\0'
297 buf_length++;
298 if (buf_length > 0 && (read_length > (ssize_t)buf_length)) {
299 dmenuscript_parse_entry_extras(sw, &(retv[(*length)]),
300 buffer + buf_length,
301 read_length - buf_length);
302 }
303 memset(&(retv[(*length) + 1]), 0, sizeof(DmenuScriptEntry));
304 (*length)++;
305 }
306 }
307 }
308 if (buffer) {
309 free(buffer);
310 }
311 if (fclose(inp) != 0) {
312 g_warning("Failed to close stdout off executor script: '%s'",
313 g_strerror(errno));
314 }
315 }
316 }
317 g_strfreev(argv);
318 return retv;
319}
320
321static void script_switcher_free(Mode *sw) {
322 if (sw == NULL) {
323 return;
324 }
325 g_free(sw->name);
326 g_free(sw->ed);
327 g_free(sw);
328}
329
330static int script_mode_init(Mode *sw) {
331 if (sw->private_data == NULL) {
332 ScriptModePrivateData *pd = g_malloc0(sizeof(*pd));
333 pd->delim = '\n';
334 sw->private_data = (void *)pd;
335 pd->cmd_list =
336 execute_executor(sw, NULL, &(pd->cmd_list_length), 0, NULL, NULL);
337 pd->switch_mode = -1;
338 }
339 return TRUE;
340}
341static unsigned int script_mode_get_num_entries(const Mode *sw) {
342 const ScriptModePrivateData *rmpd =
344 return rmpd->cmd_list_length;
345}
346
349
350 rmpd->num_urgent_list = 0;
351 g_free(rmpd->urgent_list);
352 rmpd->urgent_list = NULL;
353 rmpd->num_active_list = 0;
354 g_free(rmpd->active_list);
355 rmpd->active_list = NULL;
356}
357
359 unsigned int length) {
360 for (unsigned int i = 0; i < length; i++) {
361 g_free(list[i].entry);
362 g_strfreev(list[i].icon_name);
363 g_free(list[i].display);
364 g_free(list[i].meta);
365 g_free(list[i].info);
366 }
367 g_free(list);
368}
369static ModeMode script_mode_result(Mode *sw, int mretv, char **input,
370 unsigned int selected_line) {
372 ModeMode retv = MODE_EXIT;
373 DmenuScriptEntry *new_list = NULL;
374 unsigned int new_length = 0;
375 // store them as they might be different on next executor and reset.
376 gboolean keep_filter = rmpd->keep_filter;
377 gboolean keep_selection = rmpd->keep_selection;
378
379 if ((mretv & MENU_CUSTOM_COMMAND)) {
380 if (rmpd->use_hot_keys) {
382 if (selected_line != UINT32_MAX) {
383 new_list = execute_executor(sw, rmpd->cmd_list[selected_line].entry,
384 &new_length, 10 + (mretv & MENU_LOWER_MASK),
385 &(rmpd->cmd_list[selected_line]), *input);
386 } else {
387 if (rmpd->no_custom == FALSE) {
388 new_list =
389 execute_executor(sw, *input, &new_length,
390 10 + (mretv & MENU_LOWER_MASK), NULL, *input);
391 } else {
392 return RELOAD_DIALOG;
393 }
394 }
395 } else {
396 retv = (mretv & MENU_LOWER_MASK);
397 return retv;
398 }
399 } else if ((mretv & MENU_ENTRY_DELETE) && selected_line != UINT32_MAX) {
401 new_list =
402 execute_executor(sw, rmpd->cmd_list[selected_line].entry, &new_length,
403 3, &(rmpd->cmd_list[selected_line]), *input);
404 } else if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) {
405 if (rmpd->cmd_list[selected_line].nonselectable) {
406 return RELOAD_DIALOG;
407 }
409 new_list =
410 execute_executor(sw, rmpd->cmd_list[selected_line].entry, &new_length,
411 1, &(rmpd->cmd_list[selected_line]), *input);
412 } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL) {
413 if (rmpd->no_custom == FALSE) {
415 new_list = execute_executor(sw, *input, &new_length, 2, NULL, *input);
416 } else {
417 return RELOAD_DIALOG;
418 }
419 }
420
421 if (rmpd->switch_mode >= 0) {
422 script_mode_free_entry_list(new_list, new_length);
423 retv = rmpd->switch_mode;
424 free(*input);
425 *input = NULL;
426 rmpd->switch_mode = -1;
427 return retv;
428 }
429
430 // If a new list was generated, use that an loop around.
431 if (new_list != NULL) {
433 rmpd->cmd_list = new_list;
434 rmpd->cmd_list_length = new_length;
435 if (keep_selection) {
436 if (rmpd->new_selection >= 0 &&
437 rmpd->new_selection < rmpd->cmd_list_length) {
439 rmpd->new_selection);
440 } else {
442 }
443 } else {
445 }
446 if (keep_filter == FALSE) {
447 g_free(*input);
448 *input = NULL;
449 }
450 retv = RELOAD_DIALOG;
451 }
452 return retv;
453}
454
455static void script_mode_destroy(Mode *sw) {
457 if (rmpd != NULL) {
459 g_free(rmpd->message);
460 g_free(rmpd->prompt);
461 g_free(rmpd->data);
462 g_free(rmpd->urgent_list);
463 g_free(rmpd->active_list);
464 g_free(rmpd);
465 sw->private_data = NULL;
466 }
467}
468static inline unsigned int get_index(unsigned int length, int index) {
469 if (index >= 0) {
470 return index;
471 }
472 if (((unsigned int)-index) <= length) {
473 return length + index;
474 }
475 // Out of range.
476 return UINT_MAX;
477}
478static char *_get_display_value(const Mode *sw, unsigned int selected_line,
479 G_GNUC_UNUSED int *state,
480 G_GNUC_UNUSED GList **list, int get_entry) {
482 for (unsigned int i = 0; i < pd->num_active_list; i++) {
483 unsigned int start =
485 unsigned int stop = get_index(pd->cmd_list_length, pd->active_list[i].stop);
486 if (selected_line >= start && selected_line <= stop) {
487 *state |= ACTIVE;
488 }
489 }
490 for (unsigned int i = 0; i < pd->num_urgent_list; i++) {
491 unsigned int start =
493 unsigned int stop = get_index(pd->cmd_list_length, pd->urgent_list[i].stop);
494 if (selected_line >= start && selected_line <= stop) {
495 *state |= URGENT;
496 }
497 }
498 if (pd->cmd_list[selected_line].urgent) {
499 *state |= URGENT;
500 }
501 if (pd->cmd_list[selected_line].active) {
502 *state |= ACTIVE;
503 }
504 if (pd->do_markup) {
505 *state |= MARKUP;
506 }
507 if (pd->cmd_list[selected_line].display) {
508 return get_entry ? g_strdup(pd->cmd_list[selected_line].display) : NULL;
509 } else {
510 return get_entry ? g_strdup(pd->cmd_list[selected_line].entry) : NULL;
511 }
512}
513
514static int script_token_match(const Mode *sw, rofi_int_matcher **tokens,
515 unsigned int index) {
518 char *esc = NULL;
519
520 if (rmpd->cmd_list[index].permanent == TRUE) {
521 // Always match
522 return 1;
523 }
524
525 if (rmpd->do_markup) {
526 pango_parse_markup(rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL,
527 NULL);
528 } else {
529 esc = rmpd->cmd_list[index].entry;
530 }
531 if (esc) {
532 int match = 1;
533 if (tokens) {
534 for (int j = 0; match && tokens[j] != NULL; j++) {
535 rofi_int_matcher *ftokens[2] = {tokens[j], NULL};
536 int test = 0;
537 test = helper_token_match(ftokens, esc);
538 if (test == tokens[j]->invert && rmpd->cmd_list[index].meta) {
539 test = helper_token_match(ftokens, rmpd->cmd_list[index].meta);
540 }
541
542 if (test == 0) {
543 match = 0;
544 }
545 }
546 }
547 if (rmpd->do_markup) {
548 g_free(esc);
549 }
550 return match;
551 }
552 return FALSE;
553}
554static char *script_get_message(const Mode *sw) {
556 return g_strdup(pd->message);
557}
558static cairo_surface_t *script_get_icon(const Mode *sw,
559 unsigned int selected_line,
560 unsigned int height) {
563
564 const guint scale = display_scale();
565
566 g_return_val_if_fail(pd->cmd_list != NULL, NULL);
567 DmenuScriptEntry *dr = &(pd->cmd_list[selected_line]);
568 if (dr->icon_name == NULL) {
569 return NULL;
570 }
571
572 /* A row icon and icon-current-entry ask for the same entry at different
573 * sizes; one cached uid cannot serve both. */
574 cairo_surface_t *surface = NULL;
575 if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height &&
576 dr->icon_fetch_scale == scale) {
577 gboolean query_done =
579
580 if (surface != NULL) {
581 return surface;
582 } else if (query_done) {
584 dr->icon_fetch_uid = 0;
585 } else {
586 return NULL;
587 }
588 }
589
590 char *current_icon = NULL;
591 if (dr->icon_name && dr->icon_fallback_index >= 0) {
592 int icon_count = g_strv_length(dr->icon_name);
593 if (dr->icon_fallback_index < icon_count) {
594 current_icon = dr->icon_name[dr->icon_fallback_index];
595 }
596 }
597 if (current_icon) {
598 dr->icon_fetch_uid = rofi_icon_fetcher_query(current_icon, height);
599 dr->icon_fetch_size = height;
600 dr->icon_fetch_scale = scale;
601 /* The sizes alternate, so returning NULL would blank the icon on every
602 * frame, not just the first. */
604 return surface;
605 }
606
607 dr->icon_fetch_uid = 0;
608 return NULL;
609}
610
611#include "mode-private.h"
612
616typedef struct ScriptUser {
618 char *name;
620 char *path;
622
626size_t num_scripts = 0;
627
629 for (size_t i = 0; i < num_scripts; i++) {
630 g_free(user_scripts[i].name);
631 g_free(user_scripts[i].path);
632 }
633 g_free(user_scripts);
634}
636 const char *cpath = g_get_user_config_dir();
637 char *script_dir = g_build_filename(cpath, "rofi", "scripts", NULL);
638 if (g_file_test(script_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ==
639 FALSE) {
640 g_free(script_dir);
641 return;
642 }
643 GDir *sd = g_dir_open(script_dir, 0, NULL);
644 if (sd) {
645 const char *file = NULL;
646 while ((file = g_dir_read_name(sd)) != NULL) {
647 char *sp = g_build_filename(cpath, "rofi", "scripts", file, NULL);
649 g_realloc(user_scripts, sizeof(ScriptUser) * (num_scripts + 1));
650 user_scripts[num_scripts].path = sp;
651 user_scripts[num_scripts].name = g_strdup(file);
652 char *dot = strrchr(user_scripts[num_scripts].name, '.');
653 if (dot) {
654 *dot = '\0';
655 }
656 num_scripts++;
657 }
658 g_dir_close(sd);
659 }
660
661 g_free(script_dir);
662}
663
664static int script_mode_has_user_script(char const *const user) {
665
666 for (size_t i = 0; i < num_scripts; i++) {
667 if (g_strcmp0(user_scripts[i].name, user) == 0) {
668 return i;
669 }
670 }
671 return -1;
672}
673
674Mode *script_mode_parse_setup(const char *str) {
675 int ui = 0;
676 if ((ui = script_mode_has_user_script(str)) >= 0) {
677 Mode *sw = g_malloc0(sizeof(*sw));
678 sw->name = g_strdup(user_scripts[ui].name);
679 sw->ed = g_strdup(user_scripts[ui].path);
688 sw->_get_completion = NULL, sw->_preprocess_input = NULL,
691 return sw;
692 }
693 Mode *sw = g_malloc0(sizeof(*sw));
694 unsigned int index = 0;
695 const char *const sep = ":";
696 char **tokens = g_strsplit(str, sep, 2);
697 if (tokens) {
698 index = g_strv_length(tokens);
699 sw->name = g_strdup(tokens[0]);
700 sw->ed = (void *)rofi_expand_path(tokens[1]);
701 g_strfreev(tokens);
702 }
703 if (index == 2) {
712 sw->_get_completion = NULL, sw->_preprocess_input = NULL,
715
716 return sw;
717 }
718 fprintf(
719 stderr,
720 "The script command '%s' has %u options, but needs 2: <name>:<script>.",
721 str, index);
723 return NULL;
724}
725
726gboolean script_mode_is_valid(const char *token) {
727 if (script_mode_has_user_script(token) >= 0) {
728 return TRUE;
729 }
730 return strchr(token, ':') != NULL;
731}
732
733void script_user_list(gboolean is_term) {
734
735 for (unsigned int i = 0; i < num_scripts; i++) {
736 printf(" • %s%s%s (%s)\n", is_term ? (color_bold) : "",
737 user_scripts[i].name, is_term ? color_reset : "",
738 user_scripts[i].path);
739 }
740}
guint display_scale(void)
Definition display.c:78
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **attr_list, int get_entry)
const char * icon_name[NUM_FILE_TYPES]
Definition filebrowser.c:91
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
Definition helper.c:1669
char helper_parse_char(const char *arg)
Definition helper.c:383
char * rofi_expand_path(const char *input)
Definition helper.c:784
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
Definition helper.c:541
char * rofi_force_utf8(const gchar *data, ssize_t length)
Definition helper.c:862
gboolean rofi_icon_fetcher_get_ex(const uint32_t uid, cairo_surface_t **surface)
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
struct rofi_mode Mode
Definition mode.h:49
void * mode_get_private_data(const Mode *mode)
Definition mode.c:176
ModeMode
Definition mode.h:54
@ MENU_CUSTOM_COMMAND
Definition mode.h:84
@ MENU_LOWER_MASK
Definition mode.h:92
@ MENU_ENTRY_DELETE
Definition mode.h:80
@ MENU_OK
Definition mode.h:72
@ MENU_CUSTOM_INPUT
Definition mode.h:78
@ MODE_EXIT
Definition mode.h:56
@ RELOAD_DIALOG
Definition mode.h:60
#define color_reset
Definition rofi.h:123
#define color_bold
Definition rofi.h:125
void rofi_clear_error_messages(void)
Definition rofi.c:100
int mode_lookup(const char *name)
Definition rofi.c:161
void script_mode_gather_user_scripts(void)
Definition script.c:635
gboolean script_mode_is_valid(const char *token)
Definition script.c:726
void script_user_list(gboolean is_term)
Definition script.c:733
void script_mode_cleanup(void)
Definition script.c:628
Mode * script_mode_parse_setup(const char *str)
Definition script.c:674
@ URGENT
Definition textbox.h:107
@ ACTIVE
Definition textbox.h:109
@ MARKUP
Definition textbox.h:113
int rofi_view_error_dialog(const char *msg, int markup)
Definition view.c:1980
RofiViewState * rofi_view_get_active(void)
Definition view.c:321
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition view.c:369
@ MODE_TYPE_SWITCHER
struct rofi_int_matcher_t rofi_int_matcher
static void script_mode_destroy(Mode *sw)
Definition script.c:455
static void script_switcher_free(Mode *sw)
Definition script.c:321
static void parse_header_entry(Mode *sw, char *line, ssize_t length)
Definition script.c:148
static DmenuScriptEntry * execute_executor(Mode *sw, char *arg, unsigned int *length, int value, DmenuScriptEntry *entry, char *input)
Definition script.c:197
static ModeMode script_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
Definition script.c:369
static cairo_surface_t * script_get_icon(const Mode *sw, unsigned int selected_line, unsigned int height)
Definition script.c:558
void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length)
Definition script.c:89
static unsigned int get_index(unsigned int length, int index)
Definition script.c:468
static char * script_get_message(const Mode *sw)
Definition script.c:554
ScriptUser * user_scripts
Definition script.c:624
static int script_mode_has_user_script(char const *const user)
Definition script.c:664
static void script_switch_mode(Mode *sw, char *value)
Definition script.c:137
size_t num_scripts
Definition script.c:626
static void script_mode_free_entry_list(DmenuScriptEntry *list, unsigned int length)
Definition script.c:358
static void script_mode_reset_highlight(Mode *sw)
Definition script.c:347
static char * _get_display_value(const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry)
Definition script.c:478
static int script_mode_init(Mode *sw)
Definition script.c:330
static int script_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
Definition script.c:514
static unsigned int script_mode_get_num_entries(const Mode *sw)
Definition script.c:341
struct rofi_range_pair * urgent_list
Definition script.c:63
gboolean no_custom
Definition script.c:77
struct rofi_range_pair * active_list
Definition script.c:66
gboolean use_hot_keys
Definition script.c:81
gboolean do_markup
Definition script.c:72
unsigned int num_urgent_list
Definition script.c:64
int64_t new_selection
Definition script.c:74
unsigned int id
Definition script.c:56
unsigned int cmd_list_length
Definition script.c:60
gboolean keep_filter
Definition script.c:79
unsigned int num_active_list
Definition script.c:67
DmenuScriptEntry * cmd_list
Definition script.c:58
gboolean keep_selection
Definition script.c:73
char * name
Definition script.c:618
char * path
Definition script.c:620
_mode_result _result
__mode_get_num_entries _get_num_entries
__mode_destroy _destroy
_mode_preprocess_input _preprocess_input
char * display_name
_mode_free free
_mode_token_match _token_match
_mode_get_display_value _get_display_value
_mode_get_icon _get_icon
_mode_get_completion _get_completion
__mode_init _init
ModeType type
char * name
_mode_get_message _get_message
void * private_data
gboolean rofi_theme_parse_string(const char *string)