29#define G_LOG_DOMAIN "Modes.DMenu"
43#include <gio/gunixinputstream.h>
59static cairo_surface_t *
63static inline unsigned int bitget(uint32_t
const *
const array,
65 uint32_t bit = index % 32;
66 uint32_t val = array[index / 32];
67 return (val >> bit) & 1;
70static inline void bittoggle(uint32_t *
const array,
unsigned int index) {
71 uint32_t bit = index % 32;
72 uint32_t *v = &array[index / 32];
116#define BLOCK_LINES_SIZE 2048
126 if ((*block) == NULL) {
127 (*block) = g_malloc0(
sizeof(
Block));
129 (*block)->length = 0;
131 gsize data_len = len;
133 (*block)->values[(*block)->length].icon_fetch_uid = 0;
134 (*block)->values[(*block)->length].icon_fetch_size = 0;
135 (*block)->values[(*block)->length].icon_name = NULL;
136 (*block)->values[(*block)->length].meta = NULL;
137 (*block)->values[(*block)->length].info = NULL;
138 (*block)->values[(*block)->length].nonselectable = FALSE;
140 while (end < data + len && *end !=
'\0') {
143 if (end != data + len) {
144 data_len = end - data;
146 end + 1, len - data_len);
149 (*block)->values[(*block)->length].entry = utfstr;
150 (*block)->values[(*block)->length + 1].entry = NULL;
156 gsize data_len = len;
170 while (end < data + len && *end !=
'\0') {
173 if (end != data + len) {
174 data_len = end - data;
176 end + 1, len - data_len);
195 gpointer user_data) {
199 if ((condition & G_IO_IN) != G_IO_IN) {
200 return G_SOURCE_CONTINUE;
203 if (read(fd, &command, 1) == 1) {
204 if (command ==
'r') {
206 gboolean changed = FALSE;
209 while ((block = g_async_queue_try_pop(pd->
async_queue)) != NULL) {
225 }
else if (command ==
'q') {
231 return G_SOURCE_CONTINUE;
238 while (pre_read > 0 &&
259 GTimer *tim = g_timer_new();
265 struct timeval tv = {.tv_sec = 0, .tv_usec = 250000};
269 FD_SET(pd->
pipefd[0], &rfds);
271 int retval = select(MAX(fd, pd->
pipefd[0]) + 1, &rfds, NULL, NULL, &tv);
273 g_warning(
"select failed, giving up.");
277 if (FD_ISSET(pd->
pipefd[0], &rfds)) {
281 if (FD_ISSET(fd, &rfds)) {
282 ssize_t readbytes = 0;
283 if ((nread + 1024) > len) {
284 line = g_realloc(line, (nread + 1024));
287 readbytes = read(fd, &line[nread], 1023);
296 memmove(&line[0], &line[i + 1], nread - (i + 1));
300 double elapsed = g_timer_elapsed(tim, NULL);
342 g_timer_destroy(tim);
357 const unsigned int index,
358 gboolean multi_select) {
367 return g_strdup(input);
373 for (; splitted && splitted[ns]; ns++) {
376 GString *str_retv = g_string_new(
"");
387 (
unsigned int)g_ascii_strtoull(pd->
columns[i], NULL, 10);
388 if (index <= ns && index > 0) {
390 g_string_append(str_retv, splitted[index - 1]);
392 g_string_append_c(str_retv,
'\t');
393 g_string_append(str_retv, splitted[index - 1]);
397 g_strfreev(splitted);
398 retv = str_retv->str;
399 g_string_free(str_retv, FALSE);
403static inline unsigned int get_index(
unsigned int length,
int index) {
407 if (((
unsigned int)-index) <= length) {
408 return length + index;
422 G_GNUC_UNUSED GList **list,
int get_entry) {
430 if (index >= start && index <= stop) {
438 if (index >= start && index <= stop) {
483 .cfg_name_key =
"display-combi",
492 ._preprocess_input = NULL,
494 .private_data = NULL,
496 .display_name =
"dmenu"};
547 p->
name = g_strdup(
"lines");
552 g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
555 g_hash_table_replace(table, p->
name, p);
557 g_hash_table_destroy(table);
579 pd->
fd = STDIN_FILENO;
582 pd->
fd = open(str, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
584 char *msg = g_markup_printf_escaped(
585 "Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr,
595 if (pipe(pd->
pipefd) == -1) {
596 g_error(
"Failed to create pipe");
599 g_error(
"Failed to create pipe");
613 char *msg = g_markup_printf_escaped(
614 "Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr,
626 gchar *columns = NULL;
628 pd->
columns = g_strsplit(columns,
",", 0);
636 unsigned int index) {
643 pango_parse_markup(rmpd->
cmd_list[index].
entry, -1, 0, NULL, &esc, NULL,
652 for (
int j = 0; match && tokens[j] != NULL; j++) {
656 if (test == tokens[j]->invert && rmpd->
cmd_list[index].
meta) {
680 unsigned int selected_line,
681 unsigned int height) {
684 g_return_val_if_fail(pd->
cmd_list != NULL, NULL);
708 write(pd->
pipefd[1],
"q", 1);
714 while ((block = g_async_queue_try_pop_unlocked(pd->
async_queue)) != NULL) {
730 }
else if (retv >= 10) {
752 const char *cmd = input;
785 restart = (
find_arg(
"-only-match") >= 0);
904 if (
find_arg(
"-multi-select") >= 0) {
907 if (
find_arg(
"-markup-rows") >= 0) {
912 if (cmd_list_length == 0) {
928 if (select != NULL) {
931 for (i = 0; i < cmd_list_length; i++) {
943 for (i = 0; i < cmd_list_length; i++) {
971 int is_term = isatty(fileno(stdout));
974 "Print a small user message under the prompt (uses pango markup)", NULL,
976 print_help_msg(
"-p",
"[string]",
"Prompt to display left of entry field",
978 print_help_msg(
"-selected-row",
"[integer]",
"Select row", NULL, is_term);
979 print_help_msg(
"-format",
"[string]",
"Output format string",
"s", is_term);
980 print_help_msg(
"-u",
"[list]",
"List of row indexes to mark urgent", NULL,
982 print_help_msg(
"-a",
"[list]",
"List of row indexes to mark active", NULL,
984 print_help_msg(
"-l",
"[integer] ",
"Number of rows to display", NULL,
986 print_help_msg(
"-window-title",
"[string] ",
"Set the dmenu window title",
988 print_help_msg(
"-i",
"",
"Set filter to be case insensitive", NULL, is_term);
990 "Force selection to be given entry, disallow no match", NULL,
992 print_help_msg(
"-no-custom",
"",
"Don't accept custom entry, allow no match",
994 print_help_msg(
"-select",
"[string]",
"Select the first row that matches",
997 "Do not show what the user inputs. Show '*' instead.", NULL,
1000 "Allow and render pango markup as input data.", NULL, is_term);
1001 print_help_msg(
"-sep",
"[char]",
"Element separator.",
"'\\n'", is_term);
1003 "Read input from file instead from standard input.", NULL,
1006 "Force dmenu to first read all input data, then show dialog.",
1008 print_help_msg(
"-w",
"windowid",
"Position over window with X11 windowid.",
1010 print_help_msg(
"-keep-right",
"",
"Set ellipsize to end.", NULL, is_term);
1011 print_help_msg(
"-display-columns",
"",
"Only show the selected columns", NULL,
1014 "Separator to use to split columns (regex)", NULL, is_term);
1016 "When multi-select is enabled prefix this string when element "
1020 "When multi-select is enabled prefix this string when element "
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
int find_arg_char(const char *const key, char *val)
void helper_tokenize_free(rofi_int_matcher **tokens)
void rofi_output_formatted_line(const char *format, const char *string, int selected_line, const char *filter)
char * rofi_expand_path(const char *input)
int find_arg_str(const char *const key, char **val)
int find_arg_uint(const char *const key, unsigned int *val)
int find_arg(const char *const key)
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
char * rofi_force_utf8(const gchar *data, ssize_t length)
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
void mode_destroy(Mode *mode)
int mode_init(Mode *mode)
void * mode_get_private_data(const Mode *mode)
void mode_set_private_data(Mode *mode, void *pd)
void rofi_set_return_code(int code)
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Mode * rofi_view_get_mode(RofiViewState *state)
void rofi_view_reload(void)
int rofi_view_error_dialog(const char *msg, int markup)
void rofi_view_set_active(RofiViewState *state)
RofiViewState * rofi_view_get_active(void)
void rofi_view_restart(RofiViewState *state)
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
const char * rofi_view_get_user_input(const RofiViewState *state)
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
void rofi_view_free(RofiViewState *state)
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
unsigned int rofi_view_get_next_position(const RofiViewState *state)
void rofi_view_ellipsize_start(RofiViewState *state)
void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length)
#define DEFAULT_MENU_LINES
DmenuModePrivateData * pd
DmenuScriptEntry values[BLOCK_LINES_SIZE]
unsigned int case_sensitive
ThemeWidget * rofi_theme_find_or_create_name(ThemeWidget *base, const char *name)
Property * rofi_theme_property_create(PropertyType type)
void rofi_theme_widget_add_properties(ThemeWidget *widget, GHashTable *table)
void rofi_theme_property_free(Property *p)