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
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698 int
699 check_format_view (const char *p)
700 {
701 const char *q = p;
702
703 if (strncmp (p, "view", 4) == 0)
704 {
705 q += 4;
706 if (*q == '{')
707 {
708 for (q++; *q != '\0' && *q != '}'; q++)
709 {
710 if (strncmp (q, DEFAULT_CHARSET, 5) == 0)
711 {
712 mcview_global_flags.hex = FALSE;
713 q += 4;
714 }
715 else if (strncmp (q, "hex", 3) == 0)
716 {
717 mcview_global_flags.hex = TRUE;
718 q += 2;
719 }
720 else if (strncmp (q, "nroff", 5) == 0)
721 {
722 mcview_global_flags.nroff = TRUE;
723 q += 4;
724 }
725 else if (strncmp (q, "unform", 6) == 0)
726 {
727 mcview_global_flags.nroff = FALSE;
728 q += 5;
729 }
730 }
731 if (*q == '}')
732 q++;
733 }
734 return q - p;
735 }
736 return 0;
737 }
738
739
740
741 int
742 check_format_cd (const char *p)
743 {
744 return (strncmp (p, "cd", 2)) != 0 ? 0 : 3;
745 }
746
747
748
749
750
751
752 int
753 check_format_var (const char *p, char **v)
754 {
755 *v = NULL;
756
757 if (strncmp (p, "var{", 4) == 0)
758 {
759 const char *q = p;
760 const char *dots = NULL;
761 const char *value;
762 char *var_name;
763
764 for (q += 4; *q != '\0' && *q != '}'; q++)
765 {
766 if (*q == ':')
767 dots = q + 1;
768 }
769 if (*q == '\0')
770 return 0;
771
772 if (dots == NULL || dots == q + 5)
773 {
774 message (D_ERROR, _ ("Format error on file Extensions File"),
775 dots == NULL ? _ ("The %%var macro has no default")
776 : _ ("The %%var macro has no variable"));
777 return 0;
778 }
779
780
781 var_name = g_strndup (p + 4, dots - 2 - (p + 3));
782 value = getenv (var_name);
783 g_free (var_name);
784
785 if (value != NULL)
786 *v = g_strdup (value);
787 else
788 *v = g_strndup (dots, q - dots);
789
790 return q - p;
791 }
792 return 0;
793 }
794
795
796
797 char *
798 expand_format (const Widget *edit_widget, char c, gboolean do_quote)
799 {
800 WPanel *panel = NULL;
801 char *(*quote_func) (const char *, gboolean);
802 const char *fname = NULL;
803 char *result;
804 char c_lc;
805
806 #ifdef USE_INTERNAL_EDIT
807 const WEdit *e = CONST_EDIT (edit_widget);
808 #else
809 (void) edit_widget;
810 #endif
811
812 if (c == '%')
813 return g_strdup ("%");
814
815 switch (mc_global.mc_run_mode)
816 {
817 case MC_RUN_FULL:
818 #ifdef USE_INTERNAL_EDIT
819 if (e != NULL)
820 fname = edit_get_file_name (e);
821 else
822 #endif
823 {
824 const file_entry_t *fe;
825
826 if (g_ascii_islower ((gchar) c))
827 panel = current_panel;
828 else
829 {
830 if (get_other_type () != view_listing)
831 return NULL;
832 panel = other_panel;
833 }
834
835 fe = panel_current_entry (panel);
836 fname = fe == NULL ? NULL : fe->fname->str;
837 }
838 break;
839
840 #ifdef USE_INTERNAL_EDIT
841 case MC_RUN_EDITOR:
842 fname = edit_get_file_name (e);
843 break;
844 #endif
845
846 case MC_RUN_VIEWER:
847
848 fname = (const char *) mc_run_param0;
849 break;
850
851 default:
852
853 return NULL;
854 }
855
856 if (do_quote)
857 quote_func = name_quote;
858 else
859 quote_func = fake_name_quote;
860
861 c_lc = g_ascii_tolower ((gchar) c);
862
863 switch (c_lc)
864 {
865 case 'f':
866 case 'p':
867 result = quote_func (fname, FALSE);
868 goto ret;
869 case 'x':
870 result = quote_func (extension (fname), FALSE);
871 goto ret;
872 case 'n':
873 result = strip_ext (quote_func (fname, FALSE));
874 goto ret;
875 case 'd':
876 {
877 const char *cwd;
878
879 if (panel != NULL)
880 cwd = vfs_path_as_str (panel->cwd_vpath);
881 else
882 cwd = vfs_get_current_dir ();
883
884 result = quote_func (cwd, FALSE);
885 goto ret;
886 }
887 case 'c':
888 #ifdef USE_INTERNAL_EDIT
889 if (e != NULL)
890 {
891 result = g_strdup_printf ("%u", (unsigned int) edit_get_cursor_offset (e));
892 goto ret;
893 }
894 #endif
895 break;
896 case 'i':
897 #ifdef USE_INTERNAL_EDIT
898 if (e != NULL)
899 {
900 result = g_strnfill (edit_get_curs_col (e), ' ');
901 goto ret;
902 }
903 #endif
904 break;
905 case 'y':
906 #ifdef USE_INTERNAL_EDIT
907 if (e != NULL)
908 {
909 const char *syntax_type;
910
911 syntax_type = edit_get_syntax_type (e);
912 if (syntax_type != NULL)
913 {
914 result = g_strdup (syntax_type);
915 goto ret;
916 }
917 }
918 #endif
919 break;
920 case 'b':
921 #ifdef USE_INTERNAL_EDIT
922 if (e != NULL)
923 {
924 char *file;
925
926 file = mc_config_get_full_path (EDIT_HOME_BLOCK_FILE);
927 result = quote_func (file, FALSE);
928 g_free (file);
929 goto ret;
930 }
931 #endif
932 break;
933 case 'm':
934 if (menu != NULL)
935 {
936 result = quote_func (menu, FALSE);
937 goto ret;
938 }
939 break;
940 case 's':
941 if (panel == NULL || panel->marked == 0)
942 {
943 result = quote_func (fname, FALSE);
944 goto ret;
945 }
946
947 MC_FALLTHROUGH;
948
949 case 't':
950 case 'u':
951 {
952 GString *block = NULL;
953 int i;
954
955 if (panel == NULL)
956 {
957 result = NULL;
958 goto ret;
959 }
960
961 for (i = 0; i < panel->dir.len; i++)
962 if (panel->dir.list[i].f.marked != 0)
963 {
964 char *tmp;
965
966 tmp = quote_func (panel->dir.list[i].fname->str, FALSE);
967 if (tmp != NULL)
968 {
969 if (block == NULL)
970 block = g_string_new_take (tmp);
971 else
972 {
973 g_string_append (block, tmp);
974 g_free (tmp);
975 }
976 g_string_append_c (block, ' ');
977 }
978
979 if (c_lc == 'u')
980 do_file_mark (panel, i, 0);
981 }
982 result = block == NULL ? NULL : g_string_free (block, block->len == 0);
983 goto ret;
984 }
985 default:
986 break;
987 }
988
989 result = g_strdup ("% ");
990 result[1] = c;
991 ret:
992 return result;
993 }
994
995
996
997
998
999
1000
1001 gboolean
1002 user_menu_cmd (const Widget *edit_widget, const char *menu_file, int selected_entry)
1003 {
1004 char *data, *p;
1005 GPtrArray *entries = NULL;
1006 int max_cols = 0;
1007 int col = 0;
1008 gboolean accept_entry = TRUE;
1009 int selected = -1;
1010 gboolean old_patterns;
1011 gboolean res = FALSE;
1012 gboolean interactive = TRUE;
1013
1014 if (!vfs_current_is_local ())
1015 {
1016 message (D_ERROR, MSG_ERROR, "%s", _ ("Cannot execute commands on non-local filesystems"));
1017 return FALSE;
1018 }
1019
1020 menu = g_strdup (menu_file != NULL ? menu_file
1021 : edit_widget != NULL ? EDIT_LOCAL_MENU
1022 : MC_LOCAL_MENU);
1023
1024 if (!exist_file (menu) || !menu_file_own (menu))
1025 {
1026 if (menu_file != NULL)
1027 {
1028 file_error_message (_ ("Cannot open file\n%s"), menu);
1029 MC_PTR_FREE (menu);
1030 return FALSE;
1031 }
1032
1033 g_free (menu);
1034 menu = mc_config_get_full_path (edit_widget != NULL ? EDIT_HOME_MENU : MC_USERMENU_FILE);
1035 if (!exist_file (menu))
1036 {
1037 const char *global_menu;
1038
1039 global_menu = edit_widget != NULL ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU;
1040
1041 g_free (menu);
1042 menu = mc_build_filename (mc_config_get_home_dir (), global_menu, (char *) NULL);
1043 if (!exist_file (menu))
1044 {
1045 g_free (menu);
1046 menu = mc_build_filename (mc_global.sysconfig_dir, global_menu, (char *) NULL);
1047 if (!exist_file (menu))
1048 {
1049 g_free (menu);
1050 menu = mc_build_filename (mc_global.share_data_dir, global_menu, (char *) NULL);
1051 }
1052 }
1053 }
1054 }
1055
1056 if (!g_file_get_contents (menu, &data, NULL, NULL))
1057 {
1058 file_error_message (_ ("Cannot open file\n%s"), menu);
1059 MC_PTR_FREE (menu);
1060 return FALSE;
1061 }
1062
1063 old_patterns = easy_patterns;
1064
1065
1066 for (p = check_patterns (data); *p != '\0'; str_next_char (&p))
1067 {
1068 unsigned int menu_lines = entries == NULL ? 0 : entries->len;
1069
1070 if (col == 0 && (entries == NULL || menu_lines == entries->len))
1071 switch (*p)
1072 {
1073 case '#':
1074
1075 if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
1076 interactive = FALSE;
1077
1078 accept_entry = TRUE;
1079 break;
1080
1081 case '+':
1082 if (*(p + 1) == '=')
1083 {
1084
1085 p = test_line (edit_widget, p + 1, &accept_entry);
1086 if (selected < 0 && accept_entry)
1087 selected = menu_lines;
1088 }
1089 else
1090 {
1091
1092 p = test_line (edit_widget, p, &accept_entry);
1093 }
1094 break;
1095
1096 case '=':
1097 if (*(p + 1) == '+')
1098 {
1099
1100 p = test_line (edit_widget, p + 1, &accept_entry);
1101 if (selected < 0 && accept_entry)
1102 selected = menu_lines;
1103 }
1104 else
1105 {
1106
1107 gboolean ok = TRUE;
1108
1109 p = test_line (edit_widget, p, &ok);
1110 if (selected < 0 && ok)
1111 selected = menu_lines;
1112 }
1113 break;
1114
1115 default:
1116 if (!whitespace (*p) && str_isprint (p))
1117 {
1118
1119 if (accept_entry)
1120 {
1121 if (entries == NULL)
1122 entries = g_ptr_array_new ();
1123 g_ptr_array_add (entries, p);
1124 }
1125 else
1126 accept_entry = TRUE;
1127 }
1128 break;
1129 }
1130
1131 if (*p == '\n')
1132 {
1133 if (entries != NULL && entries->len > menu_lines)
1134 accept_entry = TRUE;
1135 max_cols = MAX (max_cols, col);
1136 col = 0;
1137 }
1138 else
1139 {
1140 if (*p == '\t')
1141 *p = ' ';
1142 col++;
1143 }
1144 }
1145
1146 if (entries == NULL)
1147 message (D_ERROR, MSG_ERROR, _ ("No suitable entries found in %s"), menu);
1148 else
1149 {
1150 if (selected_entry >= 0)
1151 selected = selected_entry;
1152 else
1153 {
1154 Listbox *listbox;
1155 unsigned int i;
1156
1157 max_cols = MIN (MAX (max_cols, col), MAX_ENTRY_LEN);
1158
1159
1160 listbox = listbox_window_new (entries->len, max_cols + 2, _ ("User menu"),
1161 "[Edit Menu File]");
1162
1163 for (i = 0; i < entries->len; i++)
1164 {
1165 p = g_ptr_array_index (entries, i);
1166 LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
1167 extract_line (p, p + MAX_ENTRY_LEN, NULL), p, FALSE);
1168 }
1169
1170 listbox_set_current (listbox->list, selected);
1171
1172 selected = listbox_run (listbox);
1173 }
1174
1175 if (selected >= 0)
1176 {
1177 execute_menu_command (edit_widget, g_ptr_array_index (entries, selected), interactive);
1178 res = TRUE;
1179 }
1180
1181 g_ptr_array_free (entries, TRUE);
1182
1183 do_refresh ();
1184 }
1185
1186 easy_patterns = old_patterns;
1187 MC_PTR_FREE (menu);
1188 g_free (data);
1189 return res;
1190 }
1191
1192