This source file includes following definitions.
- strip_ext
- check_patterns
- extract_arg
- test_type
- test_condition
- debug_out
- test_line
- execute_menu_command
- menu_file_own
- check_format_view
- check_format_cd
- check_format_var
- expand_format
- user_menu_cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include <config.h>
32
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "lib/global.h"
39 #include "lib/fileloc.h"
40 #include "lib/tty/tty.h"
41 #include "lib/skin.h"
42 #include "lib/search.h"
43 #include "lib/vfs/vfs.h"
44 #include "lib/strutil.h"
45 #include "lib/util.h"
46
47 #ifdef USE_INTERNAL_EDIT
48 #include "src/editor/edit.h"
49 #endif
50 #include "src/viewer/mcviewer.h"
51
52 #include "src/args.h"
53 #include "src/execute.h"
54 #include "src/setup.h"
55 #include "src/history.h"
56 #include "src/util.h"
57
58 #include "src/filemanager/dir.h"
59 #include "src/filemanager/filemanager.h"
60 #include "src/filemanager/layout.h"
61
62 #include "usermenu.h"
63
64
65
66
67
68 #define MAX_ENTRY_LEN 60
69
70
71
72
73
74
75
76 static gboolean debug_flag = FALSE;
77 static gboolean debug_error = FALSE;
78 static char *menu = NULL;
79
80
81
82
83
84
85 static char *
86 strip_ext (char *ss)
87 {
88 char *s;
89 char *e = NULL;
90
91 if (ss == NULL)
92 return NULL;
93
94 for (s = ss; *s != '\0'; s++)
95 {
96 if (*s == '.')
97 e = s;
98 if (IS_PATH_SEP (*s) && e != NULL)
99 e = NULL;
100 }
101
102 if (e != NULL)
103 *e = '\0';
104
105 return (*ss == '\0' ? NULL : ss);
106 }
107
108
109
110
111
112
113
114
115 static char *
116 check_patterns (char *p)
117 {
118 static const char def_name[] = "shell_patterns=";
119 char *p0 = p;
120
121 if (strncmp (p, def_name, sizeof (def_name) - 1) != 0)
122 return p0;
123
124 p += sizeof (def_name) - 1;
125 if (*p == '1')
126 easy_patterns = TRUE;
127 else if (*p == '0')
128 easy_patterns = FALSE;
129 else
130 return p0;
131
132
133 p++;
134 while (whiteness (*p))
135 p++;
136 return p;
137 }
138
139
140
141
142
143 static char *
144 extract_arg (char *p, char *arg, int size)
145 {
146 while (*p != '\0' && whiteness (*p))
147 p++;
148
149
150 while (*p != '\0' && (*p != ' ' || *(p - 1) == '\\') && *p != '\t' && *p != '\n')
151 {
152 char *np;
153
154 np = str_get_next_char (p);
155 if (np - p >= size)
156 break;
157 memcpy (arg, p, np - p);
158 arg += np - p;
159 size -= np - p;
160 p = np;
161 }
162 *arg = '\0';
163 if (*p == '\0' || *p == '\n')
164 str_prev_char (&p);
165 return p;
166 }
167
168
169
170
171
172 static gboolean
173 test_type (WPanel *panel, char *arg)
174 {
175 const file_entry_t *fe;
176 int result = 0;
177 mode_t st_mode;
178
179 fe = panel_current_entry (panel);
180 if (fe == NULL)
181 return FALSE;
182
183 st_mode = fe->st.st_mode;
184
185 for (; *arg != '\0'; arg++)
186 {
187 switch (*arg)
188 {
189 case 'n':
190 result |= !S_ISDIR (st_mode);
191 break;
192 case 'r':
193 result |= S_ISREG (st_mode);
194 break;
195 case 'd':
196 result |= S_ISDIR (st_mode);
197 break;
198 case 'l':
199 result |= S_ISLNK (st_mode);
200 break;
201 case 'c':
202 result |= S_ISCHR (st_mode);
203 break;
204 case 'b':
205 result |= S_ISBLK (st_mode);
206 break;
207 case 'f':
208 result |= S_ISFIFO (st_mode);
209 break;
210 case 's':
211 result |= S_ISSOCK (st_mode);
212 break;
213 case 'x':
214 result |= (st_mode & 0111) != 0 ? 1 : 0;
215 break;
216 case 't':
217 result |= panel->marked != 0 ? 1 : 0;
218 break;
219 default:
220 debug_error = TRUE;
221 break;
222 }
223 }
224
225 return (result != 0);
226 }
227
228
229
230
231
232 static char *
233 test_condition (const Widget *edit_widget, char *p, gboolean *condition)
234 {
235 char arg[256];
236 const mc_search_type_t search_type = easy_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
237 #ifdef USE_INTERNAL_EDIT
238 const WEdit *e = CONST_EDIT (edit_widget);
239 #endif
240
241
242 for (; *p != '\n' && *p != '&' && *p != '|'; p++)
243 {
244 WPanel *panel = NULL;
245
246
247 if ((*p == ' ' && *(p - 1) != '\\') || *p == '\t')
248 continue;
249 if (*p >= 'a')
250 panel = current_panel;
251 else if (get_other_type () == view_listing)
252 panel = other_panel;
253
254 *p |= 0x20;
255
256 switch (*p++)
257 {
258 case '!':
259 p = test_condition (edit_widget, p, condition);
260 *condition = !*condition;
261 str_prev_char (&p);
262 break;
263 case 'f':
264 p = extract_arg (p, arg, sizeof (arg));
265 #ifdef USE_INTERNAL_EDIT
266 if (e != NULL)
267 {
268 const char *edit_filename = edit_get_file_name (e);
269
270 *condition = mc_search (arg, NULL, edit_filename, search_type);
271 }
272 else
273 #endif
274 {
275 if (panel == NULL)
276 *condition = FALSE;
277 else
278 {
279 const file_entry_t *fe = panel_current_entry (panel);
280
281 *condition = fe != NULL && mc_search (arg, NULL, fe->fname->str, search_type);
282 }
283 }
284 break;
285 case 'y':
286 #ifdef USE_INTERNAL_EDIT
287 if (e != NULL)
288 {
289 const char *syntax_type = edit_get_syntax_type (e);
290
291 if (syntax_type != NULL)
292 {
293 p = extract_arg (p, arg, sizeof (arg));
294 *condition = mc_search (arg, NULL, syntax_type, MC_SEARCH_T_NORMAL);
295 }
296 }
297 #endif
298 break;
299 case 'd':
300 p = extract_arg (p, arg, sizeof (arg));
301 *condition = panel != NULL
302 && mc_search (arg, NULL, vfs_path_as_str (panel->cwd_vpath), search_type);
303 break;
304 case 't':
305 p = extract_arg (p, arg, sizeof (arg));
306 *condition = panel != NULL && test_type (panel, arg);
307 break;
308 case 'x':
309 {
310 struct stat status;
311
312 p = extract_arg (p, arg, sizeof (arg));
313 *condition = stat (arg, &status) == 0 && is_exe (status.st_mode);
314 break;
315 }
316 default:
317 debug_error = TRUE;
318 break;
319 }
320 }
321 return p;
322 }
323
324
325
326
327 static void
328 debug_out (char *start, char *end, gboolean condition)
329 {
330 static char *msg = NULL;
331
332 if (start == NULL && end == NULL)
333 {
334
335 if (debug_flag && msg != NULL)
336 {
337 size_t len;
338
339 len = strlen (msg);
340 if (len != 0)
341 msg[len - 1] = '\0';
342 message (D_NORMAL, _ ("Debug"), "%s", msg);
343 }
344 debug_flag = FALSE;
345 MC_PTR_FREE (msg);
346 }
347 else
348 {
349 const char *type;
350 char *p;
351
352
353 if (!debug_flag)
354 return;
355
356 if (debug_error)
357 {
358 type = _ ("ERROR:");
359 debug_error = FALSE;
360 }
361 else if (condition)
362 type = _ ("True:");
363 else
364 type = _ ("False:");
365
366 if (end == NULL)
367 p = g_strdup_printf ("%s %s %c \n", msg ? msg : "", type, *start);
368 else
369 p = g_strdup_printf ("%s %s %.*s \n", msg ? msg : "", type, (int) (end - start), start);
370 g_free (msg);
371 msg = p;
372 }
373 }
374
375
376
377
378
379 static char *
380 test_line (const Widget *edit_widget, char *p, gboolean *result)
381 {
382 char operator;
383
384
385 while (*p != '\0' && *p != '\n')
386 {
387 char *debug_start, *debug_end;
388 gboolean condition = TRUE;
389
390
391 while ((*p == ' ' && *(p - 1) != '\\') || *p == '\t')
392 p++;
393 if (*p == '\0' || *p == '\n')
394 break;
395 operator = *p++;
396 if (*p == '?')
397 {
398 debug_flag = TRUE;
399 p++;
400 }
401
402 while ((*p == ' ' && *(p - 1) != '\\') || *p == '\t')
403 p++;
404 if (*p == '\0' || *p == '\n')
405 break;
406
407 debug_start = p;
408 p = test_condition (edit_widget, p, &condition);
409 debug_end = p;
410
411 debug_out (debug_start, debug_end, condition);
412
413 switch (operator)
414 {
415 case '+':
416 case '=':
417
418 *result = condition;
419 break;
420 case '&':
421 *result = *result && condition;
422 break;
423 case '|':
424 *result = *result || condition;
425 break;
426 default:
427 debug_error = TRUE;
428 break;
429 }
430
431 debug_out (&operator, NULL, *result);
432
433 }
434
435 debug_out (NULL, NULL, TRUE);
436
437 if (*p == '\0' || *p == '\n')
438 str_prev_char (&p);
439 return p;
440 }
441
442
443
444
445 static void
446 execute_menu_command (const Widget *edit_widget, const char *commands, gboolean show_prompt)
447 {
448 FILE *cmd_file;
449 int cmd_file_fd;
450 gboolean expand_prefix_found = FALSE;
451 char *parameter = NULL;
452 gboolean do_quote = FALSE;
453 char lc_prompt[80];
454 int col;
455 vfs_path_t *file_name_vpath;
456 gboolean run_view = FALSE;
457 char *cmd;
458
459
460 commands = strchr (commands, '\n');
461 if (commands == NULL)
462 return;
463
464 cmd_file_fd = mc_mkstemps (&file_name_vpath, "mcusr", SCRIPT_SUFFIX);
465
466 if (cmd_file_fd == -1)
467 {
468 file_error_message (_ ("Cannot create temporary command file"), NULL);
469 return;
470 }
471
472 cmd_file = fdopen (cmd_file_fd, "w");
473 fputs ("#! /bin/sh\n", cmd_file);
474 commands++;
475
476 for (col = 0; *commands != '\0'; commands++)
477 {
478 if (col == 0)
479 {
480 if (!whitespace (*commands))
481 break;
482 while (whitespace (*commands))
483 commands++;
484 if (*commands == '\0')
485 break;
486 }
487 col++;
488 if (*commands == '\n')
489 col = 0;
490 if (parameter != NULL)
491 {
492 if (*commands == '}')
493 {
494 *parameter = '\0';
495 parameter = input_dialog (
496 _ ("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, "",
497 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_HOSTNAMES
498 | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES);
499 if (parameter == NULL || *parameter == '\0')
500 {
501
502 g_free (parameter);
503 fclose (cmd_file);
504 mc_unlink (file_name_vpath);
505 vfs_path_free (file_name_vpath, TRUE);
506 return;
507 }
508 if (do_quote)
509 {
510 char *tmp;
511
512 tmp = name_quote (parameter, FALSE);
513 if (tmp != NULL)
514 {
515 fputs (tmp, cmd_file);
516 g_free (tmp);
517 }
518 }
519 else
520 fputs (parameter, cmd_file);
521
522 MC_PTR_FREE (parameter);
523 }
524 else if (parameter < lc_prompt + sizeof (lc_prompt) - 1)
525 *parameter++ = *commands;
526 }
527 else if (expand_prefix_found)
528 {
529 expand_prefix_found = FALSE;
530 if (g_ascii_isdigit ((gchar) *commands))
531 {
532 do_quote = (atoi (commands) != 0);
533 while (g_ascii_isdigit ((gchar) *commands))
534 commands++;
535 }
536 if (*commands == '{')
537 parameter = lc_prompt;
538 else
539 {
540 char *text;
541
542 text = expand_format (edit_widget, *commands, do_quote);
543 if (text != NULL)
544 {
545 fputs (text, cmd_file);
546 g_free (text);
547 }
548 }
549 }
550 else if (*commands == '%')
551 {
552 int i;
553
554 i = check_format_view (commands + 1);
555 if (i != 0)
556 {
557 commands += i;
558 run_view = TRUE;
559 }
560 else
561 {
562 do_quote = TRUE;
563 expand_prefix_found = TRUE;
564 }
565 }
566 else
567 fputc (*commands, cmd_file);
568 }
569
570 fclose (cmd_file);
571 mc_chmod (file_name_vpath, S_IRWXU);
572
573
574 cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (file_name_vpath), (char *) NULL);
575
576 if (run_view)
577 {
578 mcview_viewer (cmd, NULL, 0, 0, 0);
579 dialog_switch_process_pending ();
580 }
581 else if (show_prompt)
582 shell_execute (cmd, EXECUTE_HIDE);
583 else
584 {
585 gboolean ok;
586
587
588
589 tty_reset_shell_mode ();
590
591 ok = (system (cmd) != -1);
592
593
594 tty_raw_mode ();
595
596
597 tty_clear_screen ();
598 repaint_screen ();
599
600 if (!ok)
601 message (D_ERROR, MSG_ERROR, "%s", _ ("Error calling program"));
602 }
603
604 g_free (cmd);
605
606 mc_unlink (file_name_vpath);
607 vfs_path_free (file_name_vpath, TRUE);
608 }
609
610
611
612
613
614
615
616
617
618
619 static gboolean
620 menu_file_own (char *path)
621 {
622 struct stat st;
623
624 if (stat (path, &st) == 0 && (st.st_uid == 0 || (st.st_uid == geteuid ()) != 0)
625 && ((st.st_mode & (S_IWGRP | S_IWOTH)) == 0))
626 return TRUE;
627
628 if (verbose)
629 message (D_NORMAL, _ ("Warning -- ignoring file"),
630 _ ("File %s is not owned by root or you or is world writable.\n"
631 "Using it may compromise your security"),
632 path);
633
634 return FALSE;
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666 int
667 check_format_view (const char *p)
668 {
669 const char *q = p;
670
671 if (strncmp (p, "view", 4) == 0)
672 {
673 q += 4;
674 if (*q == '{')
675 {
676 for (q++; *q != '\0' && *q != '}'; q++)
677 {
678 if (strncmp (q, DEFAULT_CHARSET, 5) == 0)
679 {
680 mcview_global_flags.hex = FALSE;
681 q += 4;
682 }
683 else if (strncmp (q, "hex", 3) == 0)
684 {
685 mcview_global_flags.hex = TRUE;
686 q += 2;
687 }
688 else if (strncmp (q, "nroff", 5) == 0)
689 {
690 mcview_global_flags.nroff = TRUE;
691 q += 4;
692 }
693 else if (strncmp (q, "unform", 6) == 0)
694 {
695 mcview_global_flags.nroff = FALSE;
696 q += 5;
697 }
698 }
699 if (*q == '}')
700 q++;
701 }
702 return q - p;
703 }
704 return 0;
705 }
706
707
708
709 int
710 check_format_cd (const char *p)
711 {
712 return (strncmp (p, "cd", 2)) != 0 ? 0 : 3;
713 }
714
715
716
717
718
719
720 int
721 check_format_var (const char *p, char **v)
722 {
723 *v = NULL;
724
725 if (strncmp (p, "var{", 4) == 0)
726 {
727 const char *q = p;
728 const char *dots = NULL;
729 const char *value;
730 char *var_name;
731
732 for (q += 4; *q != '\0' && *q != '}'; q++)
733 {
734 if (*q == ':')
735 dots = q + 1;
736 }
737 if (*q == '\0')
738 return 0;
739
740 if (dots == NULL || dots == q + 5)
741 {
742 message (D_ERROR, _ ("Format error on file Extensions File"),
743 dots == NULL ? _ ("The %%var macro has no default")
744 : _ ("The %%var macro has no variable"));
745 return 0;
746 }
747
748
749 var_name = g_strndup (p + 4, dots - 2 - (p + 3));
750 value = getenv (var_name);
751 g_free (var_name);
752
753 if (value != NULL)
754 *v = g_strdup (value);
755 else
756 *v = g_strndup (dots, q - dots);
757
758 return q - p;
759 }
760 return 0;
761 }
762
763
764
765 char *
766 expand_format (const Widget *edit_widget, char c, gboolean do_quote)
767 {
768 WPanel *panel = NULL;
769 char *(*quote_func) (const char *, gboolean);
770 const char *fname = NULL;
771 char *result;
772 char c_lc;
773
774 #ifdef USE_INTERNAL_EDIT
775 const WEdit *e = CONST_EDIT (edit_widget);
776 #else
777 (void) edit_widget;
778 #endif
779
780 if (c == '%')
781 return g_strdup ("%");
782
783 switch (mc_global.mc_run_mode)
784 {
785 case MC_RUN_FULL:
786 #ifdef USE_INTERNAL_EDIT
787 if (e != NULL)
788 fname = edit_get_file_name (e);
789 else
790 #endif
791 {
792 const file_entry_t *fe;
793
794 if (g_ascii_islower ((gchar) c))
795 panel = current_panel;
796 else
797 {
798 if (get_other_type () != view_listing)
799 return NULL;
800 panel = other_panel;
801 }
802
803 fe = panel_current_entry (panel);
804 fname = fe == NULL ? NULL : fe->fname->str;
805 }
806 break;
807
808 #ifdef USE_INTERNAL_EDIT
809 case MC_RUN_EDITOR:
810 fname = edit_get_file_name (e);
811 break;
812 #endif
813
814 case MC_RUN_VIEWER:
815
816 fname = (const char *) mc_run_param0;
817 break;
818
819 default:
820
821 return NULL;
822 }
823
824 if (do_quote)
825 quote_func = name_quote;
826 else
827 quote_func = fake_name_quote;
828
829 c_lc = g_ascii_tolower ((gchar) c);
830
831 switch (c_lc)
832 {
833 case 'f':
834 case 'p':
835 result = quote_func (fname, FALSE);
836 goto ret;
837 case 'x':
838 result = quote_func (extension (fname), FALSE);
839 goto ret;
840 case 'd':
841 {
842 const char *cwd;
843
844 if (panel != NULL)
845 cwd = vfs_path_as_str (panel->cwd_vpath);
846 else
847 cwd = vfs_get_current_dir ();
848
849 result = quote_func (cwd, FALSE);
850 goto ret;
851 }
852 case 'c':
853 #ifdef USE_INTERNAL_EDIT
854 if (e != NULL)
855 {
856 result = g_strdup_printf ("%u", (unsigned int) edit_get_cursor_offset (e));
857 goto ret;
858 }
859 #endif
860 break;
861 case 'i':
862 #ifdef USE_INTERNAL_EDIT
863 if (e != NULL)
864 {
865 result = g_strnfill (edit_get_curs_col (e), ' ');
866 goto ret;
867 }
868 #endif
869 break;
870 case 'y':
871 #ifdef USE_INTERNAL_EDIT
872 if (e != NULL)
873 {
874 const char *syntax_type;
875
876 syntax_type = edit_get_syntax_type (e);
877 if (syntax_type != NULL)
878 {
879 result = g_strdup (syntax_type);
880 goto ret;
881 }
882 }
883 #endif
884 break;
885 case 'k':
886 case 'b':
887 #ifdef USE_INTERNAL_EDIT
888 if (e != NULL)
889 {
890 char *file;
891
892 file = mc_config_get_full_path (EDIT_HOME_BLOCK_FILE);
893 result = quote_func (file, FALSE);
894 g_free (file);
895 goto ret;
896 }
897 #endif
898 if (c_lc == 'b')
899 {
900 result = strip_ext (quote_func (fname, FALSE));
901 goto ret;
902 }
903 break;
904 case 'n':
905 #ifdef USE_INTERNAL_EDIT
906 if (e != NULL)
907 {
908 result = strip_ext (quote_func (fname, FALSE));
909 goto ret;
910 }
911 #endif
912 break;
913 case 'm':
914 if (menu != NULL)
915 {
916 result = quote_func (menu, FALSE);
917 goto ret;
918 }
919 break;
920 case 's':
921 if (panel == NULL || panel->marked == 0)
922 {
923 result = quote_func (fname, FALSE);
924 goto ret;
925 }
926
927 MC_FALLTHROUGH;
928
929 case 't':
930 case 'u':
931 {
932 GString *block = NULL;
933 int i;
934
935 if (panel == NULL)
936 {
937 result = NULL;
938 goto ret;
939 }
940
941 for (i = 0; i < panel->dir.len; i++)
942 if (panel->dir.list[i].f.marked != 0)
943 {
944 char *tmp;
945
946 tmp = quote_func (panel->dir.list[i].fname->str, FALSE);
947 if (tmp != NULL)
948 {
949 if (block == NULL)
950 block = g_string_new_take (tmp);
951 else
952 {
953 g_string_append (block, tmp);
954 g_free (tmp);
955 }
956 g_string_append_c (block, ' ');
957 }
958
959 if (c_lc == 'u')
960 do_file_mark (panel, i, 0);
961 }
962 result = block == NULL ? NULL : g_string_free (block, block->len == 0);
963 goto ret;
964 }
965 default:
966 break;
967 }
968
969 result = g_strdup ("% ");
970 result[1] = c;
971 ret:
972 return result;
973 }
974
975
976
977
978
979
980
981 gboolean
982 user_menu_cmd (const Widget *edit_widget, const char *menu_file, int selected_entry)
983 {
984 char *data, *p;
985 GPtrArray *entries = NULL;
986 int max_cols = 0;
987 int col = 0;
988 gboolean accept_entry = TRUE;
989 int selected = 0;
990 gboolean old_patterns;
991 gboolean res = FALSE;
992 gboolean interactive = TRUE;
993
994 if (!vfs_current_is_local ())
995 {
996 message (D_ERROR, MSG_ERROR, "%s", _ ("Cannot execute commands on non-local filesystems"));
997 return FALSE;
998 }
999
1000 menu = g_strdup (menu_file != NULL ? menu_file
1001 : edit_widget != NULL ? EDIT_LOCAL_MENU
1002 : MC_LOCAL_MENU);
1003
1004 if (!exist_file (menu) || !menu_file_own (menu))
1005 {
1006 if (menu_file != NULL)
1007 {
1008 file_error_message (_ ("Cannot open file\n%s"), menu);
1009 MC_PTR_FREE (menu);
1010 return FALSE;
1011 }
1012
1013 g_free (menu);
1014 menu = mc_config_get_full_path (edit_widget != NULL ? EDIT_HOME_MENU : MC_USERMENU_FILE);
1015 if (!exist_file (menu))
1016 {
1017 const char *global_menu;
1018
1019 global_menu = edit_widget != NULL ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU;
1020
1021 g_free (menu);
1022 menu = mc_build_filename (mc_config_get_home_dir (), global_menu, (char *) NULL);
1023 if (!exist_file (menu))
1024 {
1025 g_free (menu);
1026 menu = mc_build_filename (mc_global.sysconfig_dir, global_menu, (char *) NULL);
1027 if (!exist_file (menu))
1028 {
1029 g_free (menu);
1030 menu = mc_build_filename (mc_global.share_data_dir, global_menu, (char *) NULL);
1031 }
1032 }
1033 }
1034 }
1035
1036 if (!g_file_get_contents (menu, &data, NULL, NULL))
1037 {
1038 file_error_message (_ ("Cannot open file\n%s"), menu);
1039 MC_PTR_FREE (menu);
1040 return FALSE;
1041 }
1042
1043 old_patterns = easy_patterns;
1044
1045
1046 for (p = check_patterns (data); *p != '\0'; str_next_char (&p))
1047 {
1048 unsigned int menu_lines = entries == NULL ? 0 : entries->len;
1049
1050 if (col == 0 && (entries == NULL || menu_lines == entries->len))
1051 switch (*p)
1052 {
1053 case '#':
1054
1055 if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
1056 interactive = FALSE;
1057
1058 accept_entry = TRUE;
1059 break;
1060
1061 case '+':
1062 if (*(p + 1) == '=')
1063 {
1064
1065 p = test_line (edit_widget, p + 1, &accept_entry);
1066 if (selected == 0 && accept_entry)
1067 selected = menu_lines;
1068 }
1069 else
1070 {
1071
1072 p = test_line (edit_widget, p, &accept_entry);
1073 }
1074 break;
1075
1076 case '=':
1077 if (*(p + 1) == '+')
1078 {
1079
1080 p = test_line (edit_widget, p + 1, &accept_entry);
1081 if (selected == 0 && accept_entry)
1082 selected = menu_lines;
1083 }
1084 else
1085 {
1086
1087 gboolean ok = TRUE;
1088
1089 p = test_line (edit_widget, p, &ok);
1090 if (selected == 0 && ok)
1091 selected = menu_lines;
1092 }
1093 break;
1094
1095 default:
1096 if (!whitespace (*p) && str_isprint (p))
1097 {
1098
1099 if (accept_entry)
1100 {
1101 if (entries == NULL)
1102 entries = g_ptr_array_new ();
1103 g_ptr_array_add (entries, p);
1104 }
1105 else
1106 accept_entry = TRUE;
1107 }
1108 break;
1109 }
1110
1111 if (*p == '\n')
1112 {
1113 if (entries != NULL && entries->len > menu_lines)
1114 accept_entry = TRUE;
1115 max_cols = MAX (max_cols, col);
1116 col = 0;
1117 }
1118 else
1119 {
1120 if (*p == '\t')
1121 *p = ' ';
1122 col++;
1123 }
1124 }
1125
1126 if (entries == NULL)
1127 message (D_ERROR, MSG_ERROR, _ ("No suitable entries found in %s"), menu);
1128 else
1129 {
1130 if (selected_entry >= 0)
1131 selected = selected_entry;
1132 else
1133 {
1134 Listbox *listbox;
1135 unsigned int i;
1136
1137 max_cols = MIN (MAX (max_cols, col), MAX_ENTRY_LEN);
1138
1139
1140 listbox = listbox_window_new (entries->len, max_cols + 2, _ ("User menu"),
1141 "[Edit Menu File]");
1142
1143 for (i = 0; i < entries->len; i++)
1144 {
1145 p = g_ptr_array_index (entries, i);
1146 LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
1147 extract_line (p, p + MAX_ENTRY_LEN, NULL), p, FALSE);
1148 }
1149
1150 listbox_set_current (listbox->list, selected);
1151
1152 selected = listbox_run (listbox);
1153 }
1154
1155 if (selected >= 0)
1156 {
1157 execute_menu_command (edit_widget, g_ptr_array_index (entries, selected), interactive);
1158 res = TRUE;
1159 }
1160
1161 g_ptr_array_free (entries, TRUE);
1162
1163 do_refresh ();
1164 }
1165
1166 easy_patterns = old_patterns;
1167 MC_PTR_FREE (menu);
1168 g_free (data);
1169 return res;
1170 }
1171
1172