rofi 2.0.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
29#define G_LOG_DOMAIN "Modes.Script"
30
31#include "modes/script.h"
32#include "display.h"
33#include "helper.h"
34#include "rofi.h"
35#include <assert.h>
36#include <ctype.h>
37#include <errno.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <strings.h>
42#include <unistd.h>
43
44#include "widgets/textbox.h"
45
46#include "mode-private.h"
47
48#include "rofi-icon-fetcher.h"
49
51
52typedef struct {
54 unsigned int id;
58 unsigned int cmd_list_length;
59
62 unsigned int num_urgent_list;
65 unsigned int num_active_list;
67 char *message;
68 char *prompt;
69 char *data;
70 gboolean do_markup;
73 char delim;
75 gboolean no_custom;
77 gboolean keep_filter;
78
79 gboolean use_hot_keys;
81
85void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
86 DmenuScriptEntry *entry, char *buffer,
87 G_GNUC_UNUSED size_t length) {
88 gchar **extras = g_strsplit(buffer, "\x1f", -1);
89 gchar **extra = extras;
90 for (; *extra != NULL && *(extra + 1) != NULL; extra += 2) {
91 gchar *key = *extra;
92 gchar *value = *(extra + 1);
93 // Mark NULL
94 *(extra) = NULL;
95 *(extra + 1) = NULL;
96 if (strcasecmp(key, "icon") == 0) {
97 entry->icon_name = value;
98 } else if (strcasecmp(key, "display") == 0) {
99 entry->display = value;
100 } else if (strcasecmp(key, "meta") == 0) {
101 entry->meta = value;
102 } else if (strcasecmp(key, "info") == 0) {
103 entry->info = value;
104 } else if (strcasecmp(key, "nonselectable") == 0) {
105 entry->nonselectable = g_ascii_strcasecmp(value, "true") == 0;
106 g_free(value);
107 } else if (strcasecmp(key, "permanent") == 0) {
108 entry->permanent = g_ascii_strcasecmp(value, "true") == 0;
109 g_free(value);
110 } else if (strcasecmp(key, "urgent") == 0) {
111 entry->urgent = g_ascii_strcasecmp(value, "true") == 0;
112 g_free(value);
113 } else if (strcasecmp(key, "active") == 0) {
114 entry->active = g_ascii_strcasecmp(value, "true") == 0;
115 g_free(value);
116 } else {
117 g_free(value);
118 }
119 g_free(key);
120 }
121 // Got an extra entry.. lets free it.
122 if (*extras != NULL) {
123 g_free(*extras);
124 }
125 g_free(extras);
126}
127
131
132static void parse_header_entry(Mode *sw, char *line, ssize_t length) {
134 ssize_t length_key = 0; // strlen ( line );
135 while (length_key < length && line[length_key] != '\x1f') {
136 length_key++;
137 }
138
139 if ((length_key + 1) < length) {
140 line[length_key] = '\0';
141 char *value = line + length_key + 1;
142 if (strcasecmp(line, "message") == 0) {
143 g_free(pd->message);
144 pd->message = strlen(value) ? g_strdup(value) : NULL;
145 } else if (strcasecmp(line, "prompt") == 0) {
146 g_free(pd->prompt);
147 pd->prompt = g_strdup(value);
148 sw->display_name = pd->prompt;
149 } else if (strcasecmp(line, "markup-rows") == 0) {
150 pd->do_markup = (strcasecmp(value, "true") == 0);
151 } else if (strcasecmp(line, "urgent") == 0) {
152 parse_ranges(value, &(pd->urgent_list), &(pd->num_urgent_list));
153 } else if (strcasecmp(line, "active") == 0) {
154 parse_ranges(value, &(pd->active_list), &(pd->num_active_list));
155 } else if (strcasecmp(line, "delim") == 0) {
156 pd->delim = helper_parse_char(value);
157 } else if (strcasecmp(line, "no-custom") == 0) {
158 pd->no_custom = (strcasecmp(value, "true") == 0);
159 } else if (strcasecmp(line, "use-hot-keys") == 0) {
160 pd->use_hot_keys = (strcasecmp(value, "true") == 0);
161 } else if (strcasecmp(line, "keep-selection") == 0) {
162 pd->keep_selection = (strcasecmp(value, "true") == 0);
163 } else if (strcasecmp(line, "keep-filter") == 0) {
164 pd->keep_filter = (strcasecmp(value, "true") == 0);
165 } else if (strcasecmp(line, "new-selection") == 0) {
166 pd->new_selection = (int64_t)g_ascii_strtoll(value, NULL, 0);
167 } else if (strcasecmp(line, "data") == 0) {
168 g_free(pd->data);
169 pd->data = g_strdup(value);
170 } else if (strcasecmp(line, "theme") == 0) {
171 if (rofi_theme_parse_string((const char *)value)) {
172 g_warning("Failed to parse: '%s'", value);
174 }
175 }
176 }
177}
178
180 unsigned int *length, int value,
181 DmenuScriptEntry *entry) {
183 int fd = -1;
184 GError *error = NULL;
185 DmenuScriptEntry *retv = NULL;
186 char **argv = NULL;
187 int argc = 0;
188 *length = 0;
189 // Reset these between runs.
190 pd->new_selection = -1;
191 pd->keep_selection = 0;
192 pd->keep_filter = 0;
193 // Environment
194 char **env = g_get_environ();
195
196 char *str_value = g_strdup_printf("%d", value);
197 env = g_environ_setenv(env, "ROFI_RETV", str_value, TRUE);
198 g_free(str_value);
199
200 str_value = g_strdup_printf("%d", (int)getpid());
201 env = g_environ_setenv(env, "ROFI_OUTSIDE", str_value, TRUE);
202 g_free(str_value);
203
204 if (entry && entry->info) {
205 env = g_environ_setenv(env, "ROFI_INFO", entry->info, TRUE);
206 }
207 if (pd->data) {
208 env = g_environ_setenv(env, "ROFI_DATA", pd->data, TRUE);
209 }
210
211 if (g_shell_parse_argv(sw->ed, &argc, &argv, &error)) {
212 argv = g_realloc(argv, (argc + 2) * sizeof(char *));
213 argv[argc] = g_strdup(arg);
214 argv[argc + 1] = NULL;
215 g_spawn_async_with_pipes(NULL, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL,
216 NULL, NULL, &fd, NULL, &error);
217 }
218 g_strfreev(env);
219 if (error != NULL) {
220 char *msg = g_strdup_printf("Failed to execute: '%s'\nError: '%s'",
221 (char *)sw->ed, error->message);
222 rofi_view_error_dialog(msg, FALSE);
223 g_free(msg);
224 // print error.
225 g_error_free(error);
226 fd = -1;
227 }
228 if (fd >= 0) {
229 FILE *inp = fdopen(fd, "r");
230 if (inp) {
231 char *buffer = NULL;
232 size_t buffer_length = 0;
233 ssize_t read_length = 0;
234 size_t actual_size = 0;
235 while ((read_length = getdelim(&buffer, &buffer_length, pd->delim, inp)) >
236 0) {
237 // Filter out line-end.
238 if (buffer[read_length - 1] == pd->delim) {
239 buffer[read_length - 1] = '\0';
240 }
241 if (buffer[0] == '\0') {
242 parse_header_entry(sw, &buffer[1], read_length - 1);
243 } else {
244 if (actual_size < ((*length) + 2)) {
245 actual_size += 256;
246 retv = g_realloc(retv, (actual_size) * sizeof(DmenuScriptEntry));
247 }
248 if (retv) {
249 size_t buf_length = strlen(buffer) + 1;
250#if GLIB_CHECK_VERSION(2, 68, 0)
251 retv[(*length)].entry = g_memdup2(buffer, buf_length);
252#else
253 retv[(*length)].entry = g_memdup(buffer, buf_length);
254#endif
255 retv[(*length)].icon_name = NULL;
256 retv[(*length)].display = NULL;
257 retv[(*length)].meta = NULL;
258 retv[(*length)].info = NULL;
259 retv[(*length)].active = FALSE;
260 retv[(*length)].urgent = FALSE;
261 retv[(*length)].icon_fetch_uid = 0;
262 retv[(*length)].icon_fetch_size = 0;
263 retv[(*length)].icon_fetch_scale = 0;
264 retv[(*length)].nonselectable = FALSE;
265 retv[(*length)].permanent = FALSE;
266 if (buf_length > 0 && (read_length > (ssize_t)buf_length)) {
267 dmenuscript_parse_entry_extras(sw, &(retv[(*length)]),
268 buffer + buf_length,
269 read_length - buf_length);
270 }
271 memset(&(retv[(*length) + 1]), 0, sizeof(DmenuScriptEntry));
272 (*length)++;
273 }
274 }
275 }
276 if (buffer) {
277 free(buffer);
278 }
279 if (fclose(inp) != 0) {
280 g_warning("Failed to close stdout off executor script: '%s'",
281 g_strerror(errno));
282 }
283 }
284 }
285 g_strfreev(argv);
286 return retv;
287}
288
289static void script_switcher_free(Mode *sw) {
290 if (sw == NULL) {
291 return;
292 }
293 g_free(sw->name);
294 g_free(sw->ed);
295 g_free(sw);
296}
297
298static int script_mode_init(Mode *sw) {
299 if (sw->private_data == NULL) {
300 ScriptModePrivateData *pd = g_malloc0(sizeof(*pd));
301 pd->delim = '\n';
302 sw->private_data = (void *)pd;
303 pd->cmd_list = execute_executor(sw, NULL, &(pd->cmd_list_length), 0, NULL);
304 }
305 return TRUE;
306}
307static unsigned int script_mode_get_num_entries(const Mode *sw) {
308 const ScriptModePrivateData *rmpd =
310 return rmpd->cmd_list_length;
311}
312
315
316 rmpd->num_urgent_list = 0;
317 g_free(rmpd->urgent_list);
318 rmpd->urgent_list = NULL;
319 rmpd->num_active_list = 0;
320 g_free(rmpd->active_list);
321 rmpd->active_list = NULL;
322}
323
324static ModeMode script_mode_result(Mode *sw, int mretv, char **input,
325 unsigned int selected_line) {
327 ModeMode retv = MODE_EXIT;
328 DmenuScriptEntry *new_list = NULL;
329 unsigned int new_length = 0;
330 // store them as they might be different on next executor and reset.
331 gboolean keep_filter = rmpd->keep_filter;
332 gboolean keep_selection = rmpd->keep_selection;
333
334 if ((mretv & MENU_CUSTOM_COMMAND)) {
335 if (rmpd->use_hot_keys) {
337 if (selected_line != UINT32_MAX) {
338 new_list = execute_executor(sw, rmpd->cmd_list[selected_line].entry,
339 &new_length, 10 + (mretv & MENU_LOWER_MASK),
340 &(rmpd->cmd_list[selected_line]));
341 } else {
342 if (rmpd->no_custom == FALSE) {
343 new_list = execute_executor(sw, *input, &new_length,
344 10 + (mretv & MENU_LOWER_MASK), NULL);
345 } else {
346 return RELOAD_DIALOG;
347 }
348 }
349 } else {
350 retv = (mretv & MENU_LOWER_MASK);
351 return retv;
352 }
353 } else if ((mretv & MENU_ENTRY_DELETE) && selected_line != UINT32_MAX) {
355 new_list = execute_executor(sw, rmpd->cmd_list[selected_line].entry, &new_length,
356 3, &(rmpd->cmd_list[selected_line]));
357 } else if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) {
358 if (rmpd->cmd_list[selected_line].nonselectable) {
359 return RELOAD_DIALOG;
360 }
362 new_list =
363 execute_executor(sw, rmpd->cmd_list[selected_line].entry, &new_length,
364 1, &(rmpd->cmd_list[selected_line]));
365 } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL) {
366 if (rmpd->no_custom == FALSE) {
368 new_list = execute_executor(sw, *input, &new_length, 2, NULL);
369 } else {
370 return RELOAD_DIALOG;
371 }
372 }
373
374 // If a new list was generated, use that an loop around.
375 if (new_list != NULL) {
376 for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) {
377 g_free(rmpd->cmd_list[i].entry);
378 g_free(rmpd->cmd_list[i].icon_name);
379 g_free(rmpd->cmd_list[i].display);
380 g_free(rmpd->cmd_list[i].meta);
381 g_free(rmpd->cmd_list[i].info);
382 }
383 g_free(rmpd->cmd_list);
384
385 rmpd->cmd_list = new_list;
386 rmpd->cmd_list_length = new_length;
387 if (keep_selection) {
388 if (rmpd->new_selection >= 0 &&
389 rmpd->new_selection < rmpd->cmd_list_length) {
391 rmpd->new_selection);
392 } else {
394 }
395 } else {
397 }
398 if (keep_filter == FALSE) {
399 g_free(*input);
400 *input = NULL;
401 }
402 retv = RELOAD_DIALOG;
403 }
404 return retv;
405}
406
407static void script_mode_destroy(Mode *sw) {
409 if (rmpd != NULL) {
410 for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) {
411 g_free(rmpd->cmd_list[i].entry);
412 g_free(rmpd->cmd_list[i].icon_name);
413 g_free(rmpd->cmd_list[i].display);
414 g_free(rmpd->cmd_list[i].meta);
415 }
416 g_free(rmpd->cmd_list);
417 g_free(rmpd->message);
418 g_free(rmpd->prompt);
419 g_free(rmpd->data);
420 g_free(rmpd->urgent_list);
421 g_free(rmpd->active_list);
422 g_free(rmpd);
423 sw->private_data = NULL;
424 }
425}
426static inline unsigned int get_index(unsigned int length, int index) {
427 if (index >= 0) {
428 return index;
429 }
430 if (((unsigned int)-index) <= length) {
431 return length + index;
432 }
433 // Out of range.
434 return UINT_MAX;
435}
436static char *_get_display_value(const Mode *sw, unsigned int selected_line,
437 G_GNUC_UNUSED int *state,
438 G_GNUC_UNUSED GList **list, int get_entry) {
440 for (unsigned int i = 0; i < pd->num_active_list; i++) {
441 unsigned int start =
443 unsigned int stop = get_index(pd->cmd_list_length, pd->active_list[i].stop);
444 if (selected_line >= start && selected_line <= stop) {
445 *state |= ACTIVE;
446 }
447 }
448 for (unsigned int i = 0; i < pd->num_urgent_list; i++) {
449 unsigned int start =
451 unsigned int stop = get_index(pd->cmd_list_length, pd->urgent_list[i].stop);
452 if (selected_line >= start && selected_line <= stop) {
453 *state |= URGENT;
454 }
455 }
456 if (pd->cmd_list[selected_line].urgent) {
457 *state |= URGENT;
458 }
459 if (pd->cmd_list[selected_line].active) {
460 *state |= ACTIVE;
461 }
462 if (pd->do_markup) {
463 *state |= MARKUP;
464 }
465 if (pd->cmd_list[selected_line].display) {
466 return get_entry ? g_strdup(pd->cmd_list[selected_line].display) : NULL;
467 } else {
468 return get_entry ? g_strdup(pd->cmd_list[selected_line].entry) : NULL;
469 }
470}
471
472static int script_token_match(const Mode *sw, rofi_int_matcher **tokens,
473 unsigned int index) {
476 char *esc = NULL;
477
478 if (rmpd->cmd_list[index].permanent == TRUE) {
479 // Always match
480 return 1;
481 }
482
483 if (rmpd->do_markup) {
484 pango_parse_markup(rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL,
485 NULL);
486 } else {
487 esc = rmpd->cmd_list[index].entry;
488 }
489 if (esc) {
490 int match = 1;
491 if (tokens) {
492 for (int j = 0; match && tokens[j] != NULL; j++) {
493 rofi_int_matcher *ftokens[2] = {tokens[j], NULL};
494 int test = 0;
495 test = helper_token_match(ftokens, esc);
496 if (test == tokens[j]->invert && rmpd->cmd_list[index].meta) {
497 test = helper_token_match(ftokens, rmpd->cmd_list[index].meta);
498 }
499
500 if (test == 0) {
501 match = 0;
502 }
503 }
504 }
505 if (rmpd->do_markup) {
506 g_free(esc);
507 }
508 return match;
509 }
510 return FALSE;
511}
512static char *script_get_message(const Mode *sw) {
514 return g_strdup(pd->message);
515}
516static cairo_surface_t *script_get_icon(const Mode *sw,
517 unsigned int selected_line,
518 unsigned int height) {
521 const guint scale = display_scale();
522 g_return_val_if_fail(pd->cmd_list != NULL, NULL);
523 DmenuScriptEntry *dr = &(pd->cmd_list[selected_line]);
524 if (dr->icon_name == NULL) {
525 return NULL;
526 }
527 if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height &&
528 dr->icon_fetch_scale == scale) {
530 }
532 dr->icon_fetch_size = height;
533 dr->icon_fetch_scale = scale;
535}
536
537#include "mode-private.h"
538
542typedef struct ScriptUser {
544 char *name;
546 char *path;
548
552size_t num_scripts = 0;
553
555 for (size_t i = 0; i < num_scripts; i++) {
556 g_free(user_scripts[i].name);
557 g_free(user_scripts[i].path);
558 }
559 g_free(user_scripts);
560}
562 const char *cpath = g_get_user_config_dir();
563 char *script_dir = g_build_filename(cpath, "rofi", "scripts", NULL);
564 if (g_file_test(script_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ==
565 FALSE) {
566 g_free(script_dir);
567 return;
568 }
569 GDir *sd = g_dir_open(script_dir, 0, NULL);
570 if (sd) {
571 const char *file = NULL;
572 while ((file = g_dir_read_name(sd)) != NULL) {
573 char *sp = g_build_filename(cpath, "rofi", "scripts", file, NULL);
575 g_realloc(user_scripts, sizeof(ScriptUser) * (num_scripts + 1));
576 user_scripts[num_scripts].path = sp;
577 user_scripts[num_scripts].name = g_strdup(file);
578 char *dot = strrchr(user_scripts[num_scripts].name, '.');
579 if (dot) {
580 *dot = '\0';
581 }
582 num_scripts++;
583 }
584 g_dir_close(sd);
585 }
586
587 g_free(script_dir);
588}
589
590static int script_mode_has_user_script(char const *const user) {
591
592 for (size_t i = 0; i < num_scripts; i++) {
593 if (g_strcmp0(user_scripts[i].name, user) == 0) {
594 return i;
595 }
596 }
597 return -1;
598}
599
600Mode *script_mode_parse_setup(const char *str) {
601 int ui = 0;
602 if ((ui = script_mode_has_user_script(str)) >= 0) {
603 Mode *sw = g_malloc0(sizeof(*sw));
604 sw->name = g_strdup(user_scripts[ui].name);
605 sw->ed = g_strdup(user_scripts[ui].path);
614 sw->_get_completion = NULL, sw->_preprocess_input = NULL,
617 return sw;
618 }
619 Mode *sw = g_malloc0(sizeof(*sw));
620 unsigned int index = 0;
621 const char *const sep = ":";
622 char **tokens = g_strsplit(str, sep, 2);
623 if (tokens) {
624 index = g_strv_length(tokens);
625 sw->name = g_strdup(tokens[0]);
626 sw->ed = (void *)rofi_expand_path(tokens[1]);
627 g_strfreev(tokens);
628 }
629 if (index == 2) {
638 sw->_get_completion = NULL, sw->_preprocess_input = NULL,
641
642 return sw;
643 }
644 fprintf(
645 stderr,
646 "The script command '%s' has %u options, but needs 2: <name>:<script>.",
647 str, index);
649 return NULL;
650}
651
652gboolean script_mode_is_valid(const char *token) {
653 if (script_mode_has_user_script(token) >= 0) {
654 return TRUE;
655 }
656 return strchr(token, ':') != NULL;
657}
658
659void script_user_list(gboolean is_term) {
660
661 for (unsigned int i = 0; i < num_scripts; i++) {
662 printf(" • %s%s%s (%s)\n", is_term ? (color_bold) : "",
663 user_scripts[i].name, is_term ? color_reset : "",
664 user_scripts[i].path);
665 }
666}
guint display_scale(void)
Definition display.c:42
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)
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
Definition helper.c:1277
char helper_parse_char(const char *arg)
Definition helper.c:383
char * rofi_expand_path(const char *input)
Definition helper.c:782
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
Definition helper.c:541
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
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:114
#define color_bold
Definition rofi.h:116
void rofi_clear_error_messages(void)
Definition rofi.c:96
void script_mode_gather_user_scripts(void)
Definition script.c:561
gboolean script_mode_is_valid(const char *token)
Definition script.c:652
void script_user_list(gboolean is_term)
Definition script.c:659
void script_mode_cleanup(void)
Definition script.c:554
Mode * script_mode_parse_setup(const char *str)
Definition script.c:600
@ 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:1915
RofiViewState * rofi_view_get_active(void)
Definition view.c:299
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition view.c:330
@ MODE_TYPE_SWITCHER
struct rofi_int_matcher_t rofi_int_matcher
static void script_mode_destroy(Mode *sw)
Definition script.c:407
static void script_switcher_free(Mode *sw)
Definition script.c:289
static void parse_header_entry(Mode *sw, char *line, ssize_t length)
Definition script.c:132
static ModeMode script_mode_result(Mode *sw, int mretv, char **input, unsigned int selected_line)
Definition script.c:324
static cairo_surface_t * script_get_icon(const Mode *sw, unsigned int selected_line, unsigned int height)
Definition script.c:516
void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length)
Definition script.c:85
static unsigned int get_index(unsigned int length, int index)
Definition script.c:426
static char * script_get_message(const Mode *sw)
Definition script.c:512
ScriptUser * user_scripts
Definition script.c:550
static int script_mode_has_user_script(char const *const user)
Definition script.c:590
size_t num_scripts
Definition script.c:552
static void script_mode_reset_highlight(Mode *sw)
Definition script.c:313
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:436
static int script_mode_init(Mode *sw)
Definition script.c:298
static DmenuScriptEntry * execute_executor(Mode *sw, char *arg, unsigned int *length, int value, DmenuScriptEntry *entry)
Definition script.c:179
static int script_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
Definition script.c:472
static unsigned int script_mode_get_num_entries(const Mode *sw)
Definition script.c:307
struct rofi_range_pair * urgent_list
Definition script.c:61
gboolean no_custom
Definition script.c:75
struct rofi_range_pair * active_list
Definition script.c:64
gboolean use_hot_keys
Definition script.c:79
gboolean do_markup
Definition script.c:70
unsigned int num_urgent_list
Definition script.c:62
int64_t new_selection
Definition script.c:72
unsigned int id
Definition script.c:54
unsigned int cmd_list_length
Definition script.c:58
gboolean keep_filter
Definition script.c:77
unsigned int num_active_list
Definition script.c:65
DmenuScriptEntry * cmd_list
Definition script.c:56
gboolean keep_selection
Definition script.c:71
char * name
Definition script.c:544
char * path
Definition script.c:546
_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)