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 }
char * message
Definition: dmenu.c:77
MenuReturn
Definition: mode.h:66
unsigned int cmd_list_real_length
Definition: dmenu.c:88
unsigned int auto_select
Definition: settings.h:136
void rofi_set_return_code(int code)
Definition: rofi.c:124
WindowLocation location
Definition: settings.h:100
int find_arg_char(const char *const key, char *val)
Definition: helper.c:371
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
unsigned int case_sensitive
Definition: settings.h:126
Definition: mode.h:69
static void async_read_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
Definition: dmenu.c:130
Mode dmenu_mode
Definition: dmenu.c:416
static int dmenu_mode_init(Mode *sw)
Definition: dmenu.c:306
void rofi_view_reload(void)
Definition: view.c:425
unsigned int cmd_list_length
Definition: dmenu.c:89
gboolean multi_select
Definition: dmenu.c:95
gchar * column_separator
Definition: dmenu.c:94
unsigned int menu_lines
Definition: settings.h:65
Mode * rofi_view_get_mode(RofiViewState *state)
Definition: view.c:1886
struct rofi_range_pair * active_list
Definition: dmenu.c:81
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:535
unsigned int selected_count
Definition: dmenu.c:91
int dmenu_switcher_dialog(void)
Definition: dmenu.c:586
static unsigned int dmenu_mode_get_num_entries(const Mode *sw)
Definition: dmenu.c:210
gulong cancel_source
Definition: dmenu.c:98
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition: view.c:475
DmenuScriptEntry * cmd_list
Definition: dmenu.c:87
void print_dmenu_options(void)
Definition: dmenu.c:677
uint32_t * selected_list
Definition: dmenu.c:83
static gchar * dmenu_format_output_string(const DmenuModePrivateData *pd, const char *input)
Definition: dmenu.c:216
RofiViewState * rofi_view_get_active(void)
Definition: view.c:447
int find_arg_uint(const char *const key, unsigned int *val)
Definition: helper.c:319
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:510
int find_arg_str(const char *const key, char **val)
Definition: helper.c:277
static void dmenu_finalize(RofiViewState *state)
Definition: dmenu.c:472
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition: helper.c:228
cairo_surface_t * rofi_icon_fetcher_get(const uint32_t uid)
void rofi_view_free(RofiViewState *state)
Definition: view.c:491
gchar ** columns
Definition: dmenu.c:93
static int get_dmenu_async(DmenuModePrivateData *pd, int sync_pre_read)
Definition: dmenu.c:178
unsigned int only_selected
Definition: dmenu.c:90
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:754
void mode_destroy(Mode *mode)
Definition: mode.c:49
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition: view.c:520
unsigned int selected_line
Definition: dmenu.c:76
unsigned int num_active_list
Definition: dmenu.c:82
static void dmenu_print_results(DmenuModePrivateData *pd, const char *input)
Definition: dmenu.c:451
int helper_token_match(rofi_int_matcher *const *tokens, const char *input)
Definition: helper.c:445
unsigned int num_urgent_list
Definition: dmenu.c:80
uint32_t rofi_icon_fetcher_query(const char *name, const int size)
static char * dmenu_get_message(const Mode *sw)
Definition: dmenu.c:391
static int dmenu_token_match(const Mode *sw, rofi_int_matcher **tokens, unsigned int index)
Definition: dmenu.c:386
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:452
void * private_data
Definition: mode-private.h:185
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:1763
struct rofi_range_pair * urgent_list
Definition: dmenu.c:79
static void get_dmenu_sync(DmenuModePrivateData *pd)
Definition: dmenu.c:195
Definition: textbox.h:99
static void bittoggle(uint32_t *array, unsigned int index)
Definition: dmenu.c:63
static void async_close_callback(GObject *source_object, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data)
Definition: dmenu.c:103
char * rofi_expand_path(const char *input)
Definition: helper.c:658
GInputStream * input_stream
Definition: dmenu.c:99
void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length)
Definition: helper.c:1137
char * filter
Definition: settings.h:152
static void async_read_cancel(G_GNUC_UNUSED GCancellable *cancel, G_GNUC_UNUSED gpointer data)
Definition: dmenu.c:173
static void read_add(DmenuModePrivateData *pd, char *data, gsize len)
Definition: dmenu.c:109
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:742
void rofi_view_restart(RofiViewState *state)
Definition: view.c:441
char * display_name
Definition: mode-private.h:158
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition: helper.c:127
unsigned int start
Definition: rofi-types.h:227
unsigned int num_selected_list
Definition: dmenu.c:84
unsigned int do_markup
Definition: dmenu.c:85
static void dmenu_finish(RofiViewState *state, int retv)
Definition: dmenu.c:435
void rofi_output_formatted_line(const char *format, const char *string, int selected_line, const char *filter)
Definition: helper.c:1171
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:515
Settings config
int find_arg(const char *const key)
Definition: helper.c:267
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition: view.c:1891
static void dmenu_mode_free(Mode *sw)
Definition: dmenu.c:268
GCancellable * cancel
Definition: dmenu.c:97
GDataInputStream * data_input_stream
Definition: dmenu.c:100
void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, size_t length)
Definition: script.c:78
static unsigned int bitget(uint32_t *array, unsigned int index)
Definition: dmenu.c:56
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:1693
MenuFlags
Definition: view.h:43
static cairo_surface_t * dmenu_get_icon(const Mode *sw, unsigned int selected_line, int height)
Definition: dmenu.c:399
int mode_init(Mode *mode)
Definition: mode.c:42