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