rofi  1.5.1
dmenu.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2017 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 "Dialogs.DMenu"
29 
30 #include <config.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <strings.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdint.h>
38 #include <errno.h>
39 #include <gio/gio.h>
40 #include <gio/gunixinputstream.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include "rofi.h"
45 #include "settings.h"
46 #include "widgets/textbox.h"
47 #include "dialogs/dmenu.h"
48 #include "helper.h"
49 #include "xrmoptions.h"
50 #include "view.h"
51 
52 static inline unsigned int bitget ( uint32_t *array, unsigned int index )
53 {
54  uint32_t bit = index % 32;
55  uint32_t val = array[index / 32];
56  return ( val >> bit ) & 1;
57 }
58 
59 static inline void bittoggle ( uint32_t *array, unsigned int index )
60 {
61  uint32_t bit = index % 32;
62  uint32_t *v = &array[index / 32];
63  *v ^= 1 << bit;
64 }
65 
66 typedef struct
67 {
69  // Separator.
70  char separator;
71 
72  unsigned int selected_line;
73  char *message;
74  char *format;
76  unsigned int num_urgent_list;
78  unsigned int num_active_list;
79  uint32_t *selected_list;
80  unsigned int num_selected_list;
81  unsigned int do_markup;
82  // List with entries.
83  char **cmd_list;
84  unsigned int cmd_list_real_length;
85  unsigned int cmd_list_length;
86  unsigned int only_selected;
87  unsigned int selected_count;
88 
89  gchar **columns;
91  gboolean multi_select;
92 
93  GCancellable *cancel;
94  gulong cancel_source;
95  GInputStream *input_stream;
96  GDataInputStream *data_input_stream;
98 
99 static void async_close_callback ( GObject *source_object, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data )
100 {
101  g_input_stream_close_finish ( G_INPUT_STREAM ( source_object ), res, NULL );
102  g_debug ( "Closing data stream." );
103 }
104 
105 static void read_add ( DmenuModePrivateData * pd, char *data, gsize len )
106 {
107  if ( ( pd->cmd_list_length + 2 ) > pd->cmd_list_real_length ) {
108  pd->cmd_list_real_length = MAX ( pd->cmd_list_real_length * 2, 512 );
109  pd->cmd_list = g_realloc ( pd->cmd_list, ( pd->cmd_list_real_length ) * sizeof ( char* ) );
110  }
111  char *utfstr = rofi_force_utf8 ( data, len );
112  pd->cmd_list[pd->cmd_list_length] = utfstr;
113  pd->cmd_list[pd->cmd_list_length + 1] = NULL;
114 
115  pd->cmd_list_length++;
116 }
117 static void async_read_callback ( GObject *source_object, GAsyncResult *res, gpointer user_data )
118 {
119  GDataInputStream *stream = (GDataInputStream *) source_object;
120  DmenuModePrivateData *pd = (DmenuModePrivateData *) user_data;
121  gsize len;
122  char *data = g_data_input_stream_read_upto_finish ( stream, res, &len, NULL );
123  if ( data != NULL ) {
124  // Absorb separator, already in buffer so should not block.
125  g_data_input_stream_read_byte ( stream, NULL, NULL );
126  read_add ( pd, data, len );
127  g_free ( data );
128  rofi_view_reload ();
129 
130  g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel,
131  async_read_callback, pd );
132  return;
133  }
134  else {
135  GError *error = NULL;
136  // Absorb separator, already in buffer so should not block.
137  // If error == NULL end of stream..
138  g_data_input_stream_read_byte ( stream, NULL, &error );
139  if ( error == NULL ) {
140  // Add empty line.
141  read_add ( pd, "", 0 );
142  rofi_view_reload ();
143 
144  g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel,
145  async_read_callback, pd );
146  return;
147  }
148  else {
149  g_error_free ( error );
150  }
151  }
152  if ( !g_cancellable_is_cancelled ( pd->cancel ) ) {
153  // Hack, don't use get active.
154  g_debug ( "Clearing overlay" );
156  g_input_stream_close_async ( G_INPUT_STREAM ( stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd );
157  }
158 }
159 
160 static void async_read_cancel ( G_GNUC_UNUSED GCancellable *cancel, G_GNUC_UNUSED gpointer data )
161 {
162  g_debug ( "Cancelled the async read." );
163 }
164 
165 static int get_dmenu_async ( DmenuModePrivateData *pd, int sync_pre_read )
166 {
167  while ( sync_pre_read-- ) {
168  gsize len = 0;
169  char *data = g_data_input_stream_read_upto ( pd->data_input_stream, &( pd->separator ), 1, &len, NULL, NULL );
170  if ( data == NULL ) {
171  g_input_stream_close_async ( G_INPUT_STREAM ( pd->input_stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd );
172  return FALSE;
173  }
174  g_data_input_stream_read_byte ( pd->data_input_stream, NULL, NULL );
175  read_add ( pd, data, len );
176  g_free ( data );
177  }
178  g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel,
179  async_read_callback, pd );
180  return TRUE;
181 }
183 {
184  while ( TRUE ) {
185  gsize len = 0;
186  char *data = g_data_input_stream_read_upto ( pd->data_input_stream, &( pd->separator ), 1, &len, NULL, NULL );
187  if ( data == NULL ) {
188  break;
189  }
190  g_data_input_stream_read_byte ( pd->data_input_stream, NULL, NULL );
191  read_add ( pd, data, len );
192  g_free ( data );
193  }
194  g_input_stream_close_async ( G_INPUT_STREAM ( pd->input_stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd );
195 }
196 
197 static unsigned int dmenu_mode_get_num_entries ( const Mode *sw )
198 {
199  const DmenuModePrivateData *rmpd = (const DmenuModePrivateData *) mode_get_private_data ( sw );
200  return rmpd->cmd_list_length;
201 }
202 
203 static gchar * dmenu_format_output_string ( const DmenuModePrivateData *pd, const char *input )
204 {
205  if ( pd->columns == NULL ) {
206  return g_strdup ( input );
207  }
208  char *retv = NULL;
209  char ** splitted = g_regex_split_simple ( pd->column_separator, input, G_REGEX_CASELESS, 00 );
210  uint32_t ns = 0;
211  for (; splitted && splitted[ns]; ns++ ) {
212  ;
213  }
214  for ( uint32_t i = 0; pd->columns && pd->columns[i]; i++ ) {
215  unsigned int index = (unsigned int ) g_ascii_strtoull ( pd->columns[i], NULL, 10 );
216  if ( index < ns && index > 0 ) {
217  if ( retv == NULL ) {
218  retv = g_strdup ( splitted[index - 1] );
219  }
220  else {
221  gchar *t = g_strjoin ( "\t", retv, splitted[index - 1], NULL );
222  g_free ( retv );
223  retv = t;
224  }
225  }
226  }
227  g_strfreev ( splitted );
228  return retv ? retv : g_strdup ( "" );
229 }
230 
231 static char *get_display_data ( const Mode *data, unsigned int index, int *state, G_GNUC_UNUSED GList **list, int get_entry )
232 {
233  Mode *sw = (Mode *) data;
235  char **retv = (char * *) pd->cmd_list;
236  for ( unsigned int i = 0; i < pd->num_active_list; i++ ) {
237  if ( index >= pd->active_list[i].start && index <= pd->active_list[i].stop ) {
238  *state |= ACTIVE;
239  }
240  }
241  for ( unsigned int i = 0; i < pd->num_urgent_list; i++ ) {
242  if ( index >= pd->urgent_list[i].start && index <= pd->urgent_list[i].stop ) {
243  *state |= URGENT;
244  }
245  }
246  if ( pd->selected_list && bitget ( pd->selected_list, index ) == TRUE ) {
247  *state |= SELECTED;
248  }
249  if ( pd->do_markup ) {
250  *state |= MARKUP;
251  }
252  return get_entry ? dmenu_format_output_string ( pd, retv[index] ) : NULL;
253 }
254 
255 static void dmenu_mode_free ( Mode *sw )
256 {
257  if ( mode_get_private_data ( sw ) == NULL ) {
258  return;
259  }
261  if ( pd != NULL ) {
262  if ( pd->cancel ) {
263  // If open, cancel reads.
264  if ( pd->input_stream && !g_input_stream_is_closed ( pd->input_stream ) ) {
265  g_cancellable_cancel ( pd->cancel );
266  }
267  // This blocks until cancel is done.
268  g_cancellable_disconnect ( pd->cancel, pd->cancel_source );
269  if ( pd->input_stream ) {
270  // Should close the stream if not yet done.
271  g_object_unref ( pd->data_input_stream );
272  g_object_unref ( pd->input_stream );
273  }
274  g_object_unref ( pd->cancel );
275  }
276 
277  for ( size_t i = 0; i < pd->cmd_list_length; i++ ) {
278  if ( pd->cmd_list[i] ) {
279  free ( pd->cmd_list[i] );
280  }
281  }
282  g_free ( pd->cmd_list );
283  g_free ( pd->urgent_list );
284  g_free ( pd->active_list );
285  g_free ( pd->selected_list );
286 
287  g_free ( pd );
288  mode_set_private_data ( sw, NULL );
289  }
290 }
291 
292 static int dmenu_mode_init ( Mode *sw )
293 {
294  if ( mode_get_private_data ( sw ) != NULL ) {
295  return TRUE;
296  }
297  mode_set_private_data ( sw, g_malloc0 ( sizeof ( DmenuModePrivateData ) ) );
299 
300  pd->separator = '\n';
301  pd->selected_line = UINT32_MAX;
302 
303  find_arg_str ( "-mesg", &( pd->message ) );
304 
305  // Input data separator.
306  find_arg_char ( "-sep", &( pd->separator ) );
307 
308  find_arg_uint ( "-selected-row", &( pd->selected_line ) );
309  // By default we print the unescaped line back.
310  pd->format = "s";
311 
312  // Allow user to override the output format.
313  find_arg_str ( "-format", &( pd->format ) );
314  // Urgent.
315  char *str = NULL;
316  find_arg_str ( "-u", &str );
317  if ( str != NULL ) {
318  parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) );
319  }
320  // Active
321  str = NULL;
322  find_arg_str ( "-a", &str );
323  if ( str != NULL ) {
324  parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) );
325  }
326 
327  // DMENU COMPATIBILITY
328  find_arg_uint ( "-l", &( config.menu_lines ) );
329 
334  if ( find_arg ( "-b" ) >= 0 ) {
335  config.location = 6;
336  }
337  /* -i case insensitive */
338  config.case_sensitive = TRUE;
339  if ( find_arg ( "-i" ) >= 0 ) {
340  config.case_sensitive = FALSE;
341  }
342  int fd = STDIN_FILENO;
343  str = NULL;
344  if ( find_arg_str ( "-input", &str ) ) {
345  char *estr = rofi_expand_path ( str );
346  fd = open ( str, O_RDONLY );
347  if ( fd < 0 ) {
348  char *msg = g_markup_printf_escaped ( "Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr, g_strerror ( errno ) );
349  rofi_view_error_dialog ( msg, TRUE );
350  g_free ( msg );
351  g_free ( estr );
352  return TRUE;
353  }
354  g_free ( estr );
355  }
356  // If input is stdin, and a tty, do not read as rofi grabs input and therefor blocks.
357  if ( !( fd == STDIN_FILENO && isatty ( fd ) == 1 ) ) {
358  pd->cancel = g_cancellable_new ();
359  pd->cancel_source = g_cancellable_connect ( pd->cancel, G_CALLBACK ( async_read_cancel ), pd, NULL );
360  pd->input_stream = g_unix_input_stream_new ( fd, fd != STDIN_FILENO );
361  pd->data_input_stream = g_data_input_stream_new ( pd->input_stream );
362  }
363  gchar *columns = NULL;
364  if ( find_arg_str ( "-display-columns", &columns ) ) {
365  pd->columns = g_strsplit ( columns, ",", 0 );
366  pd->column_separator = "\t";
367  find_arg_str ( "-display-column-separator", &pd->column_separator );
368  }
369  return TRUE;
370 }
371 
372 static int dmenu_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index )
373 {
375  return helper_token_match ( tokens, rmpd->cmd_list[index] );
376 }
377 static char *dmenu_get_message ( const Mode *sw )
378 {
380  if ( pd->message ) {
381  return g_strdup ( pd->message );
382  }
383  return NULL;
384 }
385 
386 #include "mode-private.h"
389 {
390  .name = "dmenu",
391  .cfg_name_key = "display-combi",
392  ._init = dmenu_mode_init,
393  ._get_num_entries = dmenu_mode_get_num_entries,
394  ._result = NULL,
395  ._destroy = dmenu_mode_free,
396  ._token_match = dmenu_token_match,
397  ._get_display_value = get_display_data,
398  ._get_completion = NULL,
399  ._preprocess_input = NULL,
400  ._get_message = dmenu_get_message,
401  .private_data = NULL,
402  .free = NULL,
403  .display_name = "dmenu"
404 };
405 
406 static void dmenu_finish ( RofiViewState *state, int retv )
407 {
408  if ( retv == FALSE ) {
409  rofi_set_return_code ( EXIT_FAILURE );
410  }
411  else if ( retv >= 10 ) {
412  rofi_set_return_code ( retv );
413  }
414  else{
415  rofi_set_return_code ( EXIT_SUCCESS );
416  }
417  rofi_view_set_active ( NULL );
418  rofi_view_free ( state );
420 }
421 
422 static void dmenu_print_results ( DmenuModePrivateData *pd, const char *input )
423 {
424  char **cmd_list = pd->cmd_list;
425  int seen = FALSE;
426  if ( pd->selected_list != NULL ) {
427  for ( unsigned int st = 0; st < pd->cmd_list_length; st++ ) {
428  if ( bitget ( pd->selected_list, st ) ) {
429  seen = TRUE;
430  rofi_output_formatted_line ( pd->format, cmd_list[st], st, input );
431  }
432  }
433  }
434  if ( !seen ) {
435  const char *cmd = input;
436  if ( pd->selected_line != UINT32_MAX ) {
437  cmd = cmd_list[pd->selected_line];
438  }
439  rofi_output_formatted_line ( pd->format, cmd, pd->selected_line, input );
440  }
441 }
442 
443 static void dmenu_finalize ( RofiViewState *state )
444 {
445  int retv = FALSE;
447  unsigned int cmd_list_length = pd->cmd_list_length;
448  char **cmd_list = pd->cmd_list;
449 
450  char *input = g_strdup ( rofi_view_get_user_input ( state ) );
452  MenuReturn mretv = rofi_view_get_return_value ( state );
453  unsigned int next_pos = rofi_view_get_next_position ( state );
454  int restart = 0;
455  // Special behavior.
456  if ( pd->only_selected ) {
460  restart = 1;
461  // Skip if no valid item is selected.
462  if ( ( mretv & MENU_CANCEL ) == MENU_CANCEL ) {
463  // In no custom mode we allow canceling.
464  restart = ( find_arg ( "-only-match" ) >= 0 );
465  }
466  else if ( pd->selected_line != UINT32_MAX ) {
467  if ( ( mretv & MENU_CUSTOM_ACTION ) && pd->multi_select ) {
468  restart = TRUE;
469  if ( pd->selected_list == NULL ) {
470  pd->selected_list = g_malloc0 ( sizeof ( uint32_t ) * ( pd->cmd_list_length / 32 + 1 ) );
471  }
472  pd->selected_count += ( bitget ( pd->selected_list, pd->selected_line ) ? ( -1 ) : ( 1 ) );
474  // Move to next line.
475  pd->selected_line = MIN ( next_pos, cmd_list_length - 1 );
476  if ( pd->selected_count > 0 ) {
477  char *str = g_strdup_printf ( "%u/%u", pd->selected_count, pd->cmd_list_length );
478  rofi_view_set_overlay ( state, str );
479  g_free ( str );
480  }
481  else {
482  rofi_view_set_overlay ( state, NULL );
483  }
484  }
485  else if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && cmd_list[pd->selected_line] != NULL ) {
486  dmenu_print_results ( pd, input );
487  retv = TRUE;
488  if ( ( mretv & MENU_QUICK_SWITCH ) ) {
489  retv = 10 + ( mretv & MENU_LOWER_MASK );
490  }
491  g_free ( input );
492  dmenu_finish ( state, retv );
493  return;
494  }
495  else {
496  pd->selected_line = next_pos - 1;
497  }
498  }
499  // Restart
500  rofi_view_restart ( state );
502  if ( !restart ) {
503  dmenu_finish ( state, retv );
504  }
505  return;
506  }
507  // We normally do not want to restart the loop.
508  restart = FALSE;
509  // Normal mode
510  if ( ( mretv & MENU_OK ) && pd->selected_line != UINT32_MAX && cmd_list[pd->selected_line] != NULL ) {
511  if ( ( mretv & MENU_CUSTOM_ACTION ) && pd->multi_select ) {
512  restart = TRUE;
513  if ( pd->selected_list == NULL ) {
514  pd->selected_list = g_malloc0 ( sizeof ( uint32_t ) * ( pd->cmd_list_length / 32 + 1 ) );
515  }
516  pd->selected_count += ( bitget ( pd->selected_list, pd->selected_line ) ? ( -1 ) : ( 1 ) );
518  // Move to next line.
519  pd->selected_line = MIN ( next_pos, cmd_list_length - 1 );
520  if ( pd->selected_count > 0 ) {
521  char *str = g_strdup_printf ( "%u/%u", pd->selected_count, pd->cmd_list_length );
522  rofi_view_set_overlay ( state, str );
523  g_free ( str );
524  }
525  else {
526  rofi_view_set_overlay ( state, NULL );
527  }
528  }
529  else {
530  dmenu_print_results ( pd, input );
531  }
532  retv = TRUE;
533  }
534  // Custom input
535  else if ( ( mretv & ( MENU_CUSTOM_INPUT ) ) ) {
536  dmenu_print_results ( pd, input );
537 
538  retv = TRUE;
539  }
540  // Quick switch with entry selected.
541  else if ( ( mretv & MENU_QUICK_SWITCH ) ) {
542  dmenu_print_results ( pd, input );
543 
544  restart = FALSE;
545  retv = 10 + ( mretv & MENU_LOWER_MASK );
546  }
547  g_free ( input );
548  if ( restart ) {
549  rofi_view_restart ( state );
551  }
552  else {
553  dmenu_finish ( state, retv );
554  }
555 }
556 
558 {
559  mode_init ( &dmenu_mode );
560  MenuFlags menu_flags = MENU_NORMAL;
562  int async = TRUE;
563 
564  // For now these only work in sync mode.
565  if ( find_arg ( "-sync" ) >= 0 || find_arg ( "-dump" ) >= 0 || find_arg ( "-select" ) >= 0
566  || find_arg ( "-no-custom" ) >= 0 || find_arg ( "-only-match" ) >= 0 || config.auto_select ||
567  find_arg ( "-selected-row" ) >= 0 ) {
568  async = FALSE;
569  }
570  // Check if the subsystem is setup for reading, otherwise do not read.
571  if ( pd->cancel != NULL ) {
572  if ( async ) {
573  unsigned int pre_read = 25;
574  find_arg_uint ( "-async-pre-read", &pre_read );
575  async = get_dmenu_async ( pd, pre_read );
576  }
577  else {
578  get_dmenu_sync ( pd );
579  }
580  }
581  char *input = NULL;
582  unsigned int cmd_list_length = pd->cmd_list_length;
583  char **cmd_list = pd->cmd_list;
584 
585  pd->only_selected = FALSE;
586  pd->multi_select = FALSE;
587  if ( find_arg ( "-multi-select" ) >= 0 ) {
588  menu_flags = MENU_INDICATOR;
589  pd->multi_select = TRUE;
590  }
591  if ( find_arg ( "-markup-rows" ) >= 0 ) {
592  pd->do_markup = TRUE;
593  }
594  if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) {
595  pd->only_selected = TRUE;
596  if ( cmd_list_length == 0 ) {
597  return TRUE;
598  }
599  }
600  if ( config.auto_select && cmd_list_length == 1 ) {
601  rofi_output_formatted_line ( pd->format, cmd_list[0], 0, config.filter );
602  return TRUE;
603  }
604  if ( find_arg ( "-password" ) >= 0 ) {
605  menu_flags |= MENU_PASSWORD;
606  }
607  /* copy filter string */
608  input = g_strdup ( config.filter );
609 
610  char *select = NULL;
611  find_arg_str ( "-select", &select );
612  if ( select != NULL ) {
613  rofi_int_matcher **tokens = helper_tokenize ( select, config.case_sensitive );
614  unsigned int i = 0;
615  for ( i = 0; i < cmd_list_length; i++ ) {
616  if ( helper_token_match ( tokens, cmd_list[i] ) ) {
617  pd->selected_line = i;
618  break;
619  }
620  }
621  helper_tokenize_free ( tokens );
622  }
623  if ( find_arg ( "-dump" ) >= 0 ) {
625  unsigned int i = 0;
626  for ( i = 0; i < cmd_list_length; i++ ) {
627  if ( tokens == NULL || helper_token_match ( tokens, cmd_list[i] ) ) {
628  rofi_output_formatted_line ( pd->format, cmd_list[i], i, config.filter );
629  }
630  }
631  helper_tokenize_free ( tokens );
633  g_free ( input );
634  return TRUE;
635  }
636  find_arg_str ( "-p", &( dmenu_mode.display_name ) );
637  RofiViewState *state = rofi_view_create ( &dmenu_mode, input, menu_flags, dmenu_finalize );
638  // @TODO we should do this better.
639  if ( async && ( pd->cancel != NULL ) ) {
640  rofi_view_set_overlay ( state, "Loading.. " );
641  }
643  rofi_view_set_active ( state );
644 
645  return FALSE;
646 }
647 
648 void print_dmenu_options ( void )
649 {
650  int is_term = isatty ( fileno ( stdout ) );
651  print_help_msg ( "-mesg", "[string]", "Print a small user message under the prompt (uses pango markup)", NULL, is_term );
652  print_help_msg ( "-p", "[string]", "Prompt to display left of entry field", NULL, is_term );
653  print_help_msg ( "-selected-row", "[integer]", "Select row", NULL, is_term );
654  print_help_msg ( "-format", "[string]", "Output format string", "s", is_term );
655  print_help_msg ( "-u", "[list]", "List of row indexes to mark urgent", NULL, is_term );
656  print_help_msg ( "-a", "[list]", "List of row indexes to mark active", NULL, is_term );
657  print_help_msg ( "-l", "[integer] ", "Number of rows to display", NULL, is_term );
658  print_help_msg ( "-i", "", "Set filter to be case insensitive", NULL, is_term );
659  print_help_msg ( "-only-match", "", "Force selection or custom entry", NULL, is_term );
660  print_help_msg ( "-no-custom", "", "Don't accept custom entry", NULL, is_term );
661  print_help_msg ( "-select", "[string]", "Select the first row that matches", NULL, is_term );
662  print_help_msg ( "-password", "", "Do not show what the user inputs. Show '*' instead.", NULL, is_term );
663  print_help_msg ( "-markup-rows", "", "Allow and render pango markup as input data.", NULL, is_term );
664  print_help_msg ( "-sep", "[char]", "Element separator.", "'\\n'", is_term );
665  print_help_msg ( "-input", "[filename]", "Read input from file instead from standard input.", NULL, is_term );
666  print_help_msg ( "-sync", "", "Force dmenu to first read all input data, then show dialog.", NULL, is_term );
667  print_help_msg ( "-async-pre-read", "[number]", "Read several entries blocking before switching to async mode", "25", is_term );
668  print_help_msg ( "-w", "windowid", "Position over window with X11 windowid.", NULL, is_term );
669 }
char * message
Definition: dmenu.c:73
MenuReturn
Definition: mode.h:66
unsigned int cmd_list_real_length
Definition: dmenu.c:84
unsigned int auto_select
Definition: settings.h:122
void rofi_set_return_code(int code)
Definition: rofi.c:118
WindowLocation location
Definition: settings.h:94
int find_arg_char(const char *const key, char *val)
Definition: helper.c:399
static char * get_display_data(const Mode *data, unsigned int index, int *state, G_GNUC_UNUSED GList **list, int get_entry)
Definition: dmenu.c:231
unsigned int case_sensitive
Definition: settings.h:112
Definition: mode.h:69
static void async_read_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
Definition: dmenu.c:117
Mode dmenu_mode
Definition: dmenu.c:388
static int dmenu_mode_init(Mode *sw)
Definition: dmenu.c:292
void rofi_view_reload(void)
Definition: view.c:424
unsigned int cmd_list_length
Definition: dmenu.c:85
gboolean multi_select
Definition: dmenu.c:91
gchar * column_separator
Definition: dmenu.c:90
unsigned int menu_lines
Definition: settings.h:59
Mode * rofi_view_get_mode(RofiViewState *state)
Definition: view.c:1849
struct rofi_range_pair * active_list
Definition: dmenu.c:77
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:537
unsigned int selected_count
Definition: dmenu.c:87
int dmenu_switcher_dialog(void)
Definition: dmenu.c:557
char ** cmd_list
Definition: dmenu.c:83
static unsigned int dmenu_mode_get_num_entries(const Mode *sw)
Definition: dmenu.c:197
gulong cancel_source
Definition: dmenu.c:94
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition: view.c:474
void print_dmenu_options(void)
Definition: dmenu.c:648
uint32_t * selected_list
Definition: dmenu.c:79
static gchar * dmenu_format_output_string(const DmenuModePrivateData *pd, const char *input)
Definition: dmenu.c:203
RofiViewState * rofi_view_get_active(void)
Definition: view.c:446
int find_arg_uint(const char *const key, unsigned int *val)
Definition: helper.c:347
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:512
int find_arg_str(const char *const key, char **val)
Definition: helper.c:305
static void dmenu_finalize(RofiViewState *state)
Definition: dmenu.c:443
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition: helper.c:256
void rofi_view_free(RofiViewState *state)
Definition: view.c:490
gchar ** columns
Definition: dmenu.c:89
static int get_dmenu_async(DmenuModePrivateData *pd, int sync_pre_read)
Definition: dmenu.c:165
unsigned int only_selected
Definition: dmenu.c:86
void * mode_get_private_data(const Mode *mode)
Definition: mode.c:128
void print_help_msg(const char *option, const char *type, const char *text, const char *def, int isatty)
Definition: xrmoptions.c:744
void mode_destroy(Mode *mode)
Definition: mode.c:49
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition: view.c:522
unsigned int selected_line
Definition: dmenu.c:72
unsigned int num_active_list
Definition: dmenu.c:78
static void dmenu_print_results(DmenuModePrivateData *pd, const char *input)
Definition: dmenu.c:422
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
Definition: helper.c:473
unsigned int num_urgent_list
Definition: dmenu.c:76
static char * dmenu_get_message(const Mode *sw)
Definition: dmenu.c:377
static int dmenu_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
Definition: dmenu.c:372
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:451
void * private_data
Definition: mode-private.h:185
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:1726
struct rofi_range_pair * urgent_list
Definition: dmenu.c:75
static void get_dmenu_sync(DmenuModePrivateData *pd)
Definition: dmenu.c:182
Definition: textbox.h:98
static void bittoggle(uint32_t *array, unsigned int index)
Definition: dmenu.c:59
static void async_close_callback(GObject *source_object, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data)
Definition: dmenu.c:99
char * rofi_expand_path(const char *input)
Definition: helper.c:669
GInputStream * input_stream
Definition: dmenu.c:95
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
Definition: helper.c:1148
char * filter
Definition: settings.h:138
static void async_read_cancel(G_GNUC_UNUSED GCancellable *cancel, G_GNUC_UNUSED gpointer data)
Definition: dmenu.c:160
static void read_add(DmenuModePrivateData *pd, char *data, gsize len)
Definition: dmenu.c:105
void mode_set_private_data(Mode *mode, void *pd)
Definition: mode.c:134
char * rofi_force_utf8(const gchar *data, ssize_t length)
Definition: helper.c:753
void rofi_view_restart(RofiViewState *state)
Definition: view.c:440
char * display_name
Definition: mode-private.h:158
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition: helper.c:155
unsigned int start
Definition: rofi-types.h:225
unsigned int num_selected_list
Definition: dmenu.c:80
unsigned int do_markup
Definition: dmenu.c:81
static void dmenu_finish(RofiViewState *state, int retv)
Definition: dmenu.c:406
void rofi_output_formatted_line(const char *format, const char *string, int selected_line, const char *filter)
Definition: helper.c:1182
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:517
Settings config
int find_arg(const char *const key)
Definition: helper.c:295
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition: view.c:1854
static void dmenu_mode_free(Mode *sw)
Definition: dmenu.c:255
GCancellable * cancel
Definition: dmenu.c:93
GDataInputStream * data_input_stream
Definition: dmenu.c:96
static unsigned int bitget(uint32_t *array, unsigned int index)
Definition: dmenu.c:52
char * name
Definition: mode-private.h:156
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition: view.c:1654
MenuFlags
Definition: view.h:43
int mode_init(Mode *mode)
Definition: mode.c:42