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 case 'v':
952 {
953 GString *block = NULL;
954 int i;
955 char *qcwd = NULL;
956
957 if (panel == NULL)
958 {
959 result = NULL;
960 goto ret;
961 }
962
963 if (c_lc == 'v')
964 {
965 const char *cwd = vfs_path_as_str (panel->cwd_vpath);
966
967 qcwd = quote_func (cwd, FALSE);
968 }
969
970 block = g_string_sized_new (64);
971
972 for (i = 0; i < panel->dir.len; i++)
973 if (panel->dir.list[i].f.marked != 0)
974 {
975 char *tmp;
976
977 if (qcwd != NULL)
978 {
979 g_string_append (block, qcwd);
980 g_string_append (block, PATH_SEP_STR);
981 }
982
983 tmp = quote_func (panel->dir.list[i].fname->str, FALSE);
984
985 if (tmp != NULL)
986 {
987 g_string_append (block, tmp);
988 g_free (tmp);
989 g_string_append_c (block, ' ');
990 }
991
992 if (c_lc == 'u')
993 do_file_mark (panel, i, 0);
994 }
995 g_free (qcwd);
996 result = g_string_free (block, block->len == 0);
997 goto ret;
998 }
999 default:
1000 break;
1001 }
1002
1003 result = g_strdup ("% ");
1004 result[1] = c;
1005 ret:
1006 return result;
1007 }
1008
1009
1010
1011
1012
1013
1014
1015 gboolean
1016 user_menu_cmd (const Widget *edit_widget, const char *menu_file, int selected_entry)
1017 {
1018 char *data, *p;
1019 GPtrArray *entries = NULL;
1020 int max_cols = 0;
1021 int col = 0;
1022 gboolean accept_entry = TRUE;
1023 int selected = -1;
1024 gboolean old_patterns;
1025 gboolean res = FALSE;
1026 gboolean interactive = TRUE;
1027
1028 if (!vfs_current_is_local ())
1029 {
1030 message (D_ERROR, MSG_ERROR, "%s", _ ("Cannot execute commands on non-local filesystems"));
1031 return FALSE;
1032 }
1033
1034 menu = g_strdup (menu_file != NULL ? menu_file
1035 : edit_widget != NULL ? EDIT_LOCAL_MENU
1036 : MC_LOCAL_MENU);
1037
1038 if (!exist_file (menu) || !menu_file_own (menu))
1039 {
1040 if (menu_file != NULL)
1041 {
1042 file_error_message (_ ("Cannot open file\n%s"), menu);
1043 MC_PTR_FREE (menu);
1044 return FALSE;
1045 }
1046
1047 g_free (menu);
1048 menu = mc_config_get_full_path (edit_widget != NULL ? EDIT_HOME_MENU : MC_USERMENU_FILE);
1049 if (!exist_file (menu))
1050 {
1051 const char *global_menu;
1052
1053 global_menu = edit_widget != NULL ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU;
1054
1055 g_free (menu);
1056 menu = mc_build_filename (mc_config_get_home_dir (), global_menu, (char *) NULL);
1057 if (!exist_file (menu))
1058 {
1059 g_free (menu);
1060 menu = mc_build_filename (mc_global.sysconfig_dir, global_menu, (char *) NULL);
1061 if (!exist_file (menu))
1062 {
1063 g_free (menu);
1064 menu = mc_build_filename (mc_global.share_data_dir, global_menu, (char *) NULL);
1065 }
1066 }
1067 }
1068 }
1069
1070 if (!g_file_get_contents (menu, &data, NULL, NULL))
1071 {
1072 file_error_message (_ ("Cannot open file\n%s"), menu);
1073 MC_PTR_FREE (menu);
1074 return FALSE;
1075 }
1076
1077 old_patterns = easy_patterns;
1078
1079
1080 for (p = check_patterns (data); *p != '\0'; str_next_char (&p))
1081 {
1082 unsigned int menu_lines = entries == NULL ? 0 : entries->len;
1083
1084 if (col == 0 && (entries == NULL || menu_lines == entries->len))
1085 switch (*p)
1086 {
1087 case '#':
1088
1089 if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
1090 interactive = FALSE;
1091
1092 accept_entry = TRUE;
1093 break;
1094
1095 case '+':
1096 if (*(p + 1) == '=')
1097 {
1098
1099 p = test_line (edit_widget, p + 1, &accept_entry);
1100 if (selected < 0 && accept_entry)
1101 selected = menu_lines;
1102 }
1103 else
1104 {
1105
1106 p = test_line (edit_widget, p, &accept_entry);
1107 }
1108 break;
1109
1110 case '=':
1111 if (*(p + 1) == '+')
1112 {
1113
1114 p = test_line (edit_widget, p + 1, &accept_entry);
1115 if (selected < 0 && accept_entry)
1116 selected = menu_lines;
1117 }
1118 else
1119 {
1120
1121 gboolean ok = TRUE;
1122
1123 p = test_line (edit_widget, p, &ok);
1124 if (selected < 0 && ok)
1125 selected = menu_lines;
1126 }
1127 break;
1128
1129 default:
1130 if (!whitespace (*p) && str_isprint (p))
1131 {
1132
1133 if (accept_entry)
1134 {
1135 if (entries == NULL)
1136 entries = g_ptr_array_new ();
1137 g_ptr_array_add (entries, p);
1138 }
1139 else
1140 accept_entry = TRUE;
1141 }
1142 break;
1143 }
1144
1145 if (*p == '\n')
1146 {
1147 if (entries != NULL && entries->len > menu_lines)
1148 accept_entry = TRUE;
1149 max_cols = MAX (max_cols, col);
1150 col = 0;
1151 }
1152 else
1153 {
1154 if (*p == '\t')
1155 *p = ' ';
1156 col++;
1157 }
1158 }
1159
1160 if (entries == NULL)
1161 message (D_ERROR, MSG_ERROR, _ ("No suitable entries found in %s"), menu);
1162 else
1163 {
1164 if (selected_entry >= 0)
1165 selected = selected_entry;
1166 else
1167 {
1168 Listbox *listbox;
1169 unsigned int i;
1170
1171 max_cols = MIN (MAX (max_cols, col), MAX_ENTRY_LEN);
1172
1173
1174 listbox = listbox_window_new (entries->len, max_cols + 2, _ ("User menu"),
1175 "[Edit Menu File]");
1176
1177 for (i = 0; i < entries->len; i++)
1178 {
1179 p = g_ptr_array_index (entries, i);
1180 LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
1181 extract_line (p, p + MAX_ENTRY_LEN, NULL), p, FALSE);
1182 }
1183
1184 listbox_set_current (listbox->list, selected);
1185
1186 selected = listbox_run (listbox);
1187 }
1188
1189 if (selected >= 0)
1190 {
1191 execute_menu_command (edit_widget, g_ptr_array_index (entries, selected), interactive);
1192 res = TRUE;
1193 }
1194
1195 g_ptr_array_free (entries, TRUE);
1196
1197 do_refresh ();
1198 }
1199
1200 easy_patterns = old_patterns;
1201 MC_PTR_FREE (menu);
1202 g_free (data);
1203 return res;
1204 }
1205
1206