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 <errno.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "lib/global.h"
40 #include "lib/fileloc.h"
41 #include "lib/tty/tty.h"
42 #include "lib/skin.h"
43 #include "lib/search.h"
44 #include "lib/vfs/vfs.h"
45 #include "lib/strutil.h"
46 #include "lib/util.h"
47
48 #ifdef USE_INTERNAL_EDIT
49 # include "src/editor/edit.h"
50 #endif
51 #include "src/viewer/mcviewer.h"
52
53 #include "src/args.h"
54 #include "src/execute.h"
55 #include "src/setup.h"
56 #include "src/history.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;
269
270 edit_filename = edit_get_file_name (e);
271 *condition = mc_search (arg, DEFAULT_CHARSET, edit_filename, search_type);
272 }
273 else
274 #endif
275 {
276 if (panel == NULL)
277 *condition = FALSE;
278 else
279 {
280 const file_entry_t *fe;
281
282 fe = panel_current_entry (panel);
283 *condition =
284 fe != NULL && mc_search (arg, DEFAULT_CHARSET, fe->fname->str, search_type);
285 }
286 }
287 break;
288 case 'y':
289 #ifdef USE_INTERNAL_EDIT
290 if (e != NULL)
291 {
292 const char *syntax_type;
293
294 syntax_type = edit_get_syntax_type (e);
295 if (syntax_type != NULL)
296 {
297 p = extract_arg (p, arg, sizeof (arg));
298 *condition = mc_search (arg, DEFAULT_CHARSET, syntax_type, MC_SEARCH_T_NORMAL);
299 }
300 }
301 #endif
302 break;
303 case 'd':
304 p = extract_arg (p, arg, sizeof (arg));
305 *condition = panel != NULL
306 && mc_search (arg, DEFAULT_CHARSET, vfs_path_as_str (panel->cwd_vpath),
307 search_type);
308 break;
309 case 't':
310 p = extract_arg (p, arg, sizeof (arg));
311 *condition = panel != NULL && test_type (panel, arg);
312 break;
313 case 'x':
314 {
315 struct stat status;
316
317 p = extract_arg (p, arg, sizeof (arg));
318 *condition = stat (arg, &status) == 0 && is_exe (status.st_mode);
319 break;
320 }
321 default:
322 debug_error = TRUE;
323 break;
324 }
325 }
326 return p;
327 }
328
329
330
331
332 static void
333 debug_out (char *start, char *end, gboolean condition)
334 {
335 static char *msg = NULL;
336
337 if (start == NULL && end == NULL)
338 {
339
340 if (debug_flag && msg != NULL)
341 {
342 size_t len;
343
344 len = strlen (msg);
345 if (len != 0)
346 msg[len - 1] = '\0';
347 message (D_NORMAL, _ ("Debug"), "%s", msg);
348 }
349 debug_flag = FALSE;
350 MC_PTR_FREE (msg);
351 }
352 else
353 {
354 const char *type;
355 char *p;
356
357
358 if (!debug_flag)
359 return;
360
361 if (debug_error)
362 {
363 type = _ ("ERROR:");
364 debug_error = FALSE;
365 }
366 else if (condition)
367 type = _ ("True:");
368 else
369 type = _ ("False:");
370
371 if (end == NULL)
372 p = g_strdup_printf ("%s %s %c \n", msg ? msg : "", type, *start);
373 else
374 p = g_strdup_printf ("%s %s %.*s \n", msg ? msg : "", type, (int) (end - start), start);
375 g_free (msg);
376 msg = p;
377 }
378 }
379
380
381
382
383
384 static char *
385 test_line (const Widget *edit_widget, char *p, gboolean *result)
386 {
387 char operator;
388
389
390 while (*p != '\0' && *p != '\n')
391 {
392 char *debug_start, *debug_end;
393 gboolean condition = TRUE;
394
395
396 while ((*p == ' ' && *(p - 1) != '\\') || *p == '\t')
397 p++;
398 if (*p == '\0' || *p == '\n')
399 break;
400 operator= * p++;
401 if (*p == '?')
402 {
403 debug_flag = TRUE;
404 p++;
405 }
406
407 while ((*p == ' ' && *(p - 1) != '\\') || *p == '\t')
408 p++;
409 if (*p == '\0' || *p == '\n')
410 break;
411
412 debug_start = p;
413 p = test_condition (edit_widget, p, &condition);
414 debug_end = p;
415
416 debug_out (debug_start, debug_end, condition);
417
418 switch (operator)
419 {
420 case '+':
421 case '=':
422
423 *result = condition;
424 break;
425 case '&':
426 *result = *result && condition;
427 break;
428 case '|':
429 *result = *result || condition;
430 break;
431 default:
432 debug_error = TRUE;
433 break;
434 }
435
436 debug_out (&operator, NULL, *result);
437
438 }
439
440 debug_out (NULL, NULL, TRUE);
441
442 if (*p == '\0' || *p == '\n')
443 str_prev_char (&p);
444 return p;
445 }
446
447
448
449
450 static void
451 execute_menu_command (const Widget *edit_widget, const char *commands, gboolean show_prompt)
452 {
453 FILE *cmd_file;
454 int cmd_file_fd;
455 gboolean expand_prefix_found = FALSE;
456 char *parameter = NULL;
457 gboolean do_quote = FALSE;
458 char lc_prompt[80];
459 int col;
460 vfs_path_t *file_name_vpath;
461 gboolean run_view = FALSE;
462 char *cmd;
463
464
465 commands = strchr (commands, '\n');
466 if (commands == NULL)
467 return;
468
469 cmd_file_fd = mc_mkstemps (&file_name_vpath, "mcusr", SCRIPT_SUFFIX);
470
471 if (cmd_file_fd == -1)
472 {
473 message (D_ERROR, MSG_ERROR, _ ("Cannot create temporary command file\n%s"),
474 unix_error_string (errno));
475 return;
476 }
477
478 cmd_file = fdopen (cmd_file_fd, "w");
479 fputs ("#! /bin/sh\n", cmd_file);
480 commands++;
481
482 for (col = 0; *commands != '\0'; commands++)
483 {
484 if (col == 0)
485 {
486 if (!whitespace (*commands))
487 break;
488 while (whitespace (*commands))
489 commands++;
490 if (*commands == '\0')
491 break;
492 }
493 col++;
494 if (*commands == '\n')
495 col = 0;
496 if (parameter != NULL)
497 {
498 if (*commands == '}')
499 {
500 *parameter = '\0';
501 parameter = input_dialog (
502 _ ("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, "",
503 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_HOSTNAMES
504 | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES);
505 if (parameter == NULL || *parameter == '\0')
506 {
507
508 g_free (parameter);
509 fclose (cmd_file);
510 mc_unlink (file_name_vpath);
511 vfs_path_free (file_name_vpath, TRUE);
512 return;
513 }
514 if (do_quote)
515 {
516 char *tmp;
517
518 tmp = name_quote (parameter, FALSE);
519 if (tmp != NULL)
520 {
521 fputs (tmp, cmd_file);
522 g_free (tmp);
523 }
524 }
525 else
526 fputs (parameter, cmd_file);
527
528 MC_PTR_FREE (parameter);
529 }
530 else if (parameter < lc_prompt + sizeof (lc_prompt) - 1)
531 *parameter++ = *commands;
532 }
533 else if (expand_prefix_found)
534 {
535 expand_prefix_found = FALSE;
536 if (g_ascii_isdigit ((gchar) *commands))
537 {
538 do_quote = (atoi (commands) != 0);
539 while (g_ascii_isdigit ((gchar) *commands))
540 commands++;
541 }
542 if (*commands == '{')
543 parameter = lc_prompt;
544 else
545 {
546 char *text;
547
548 text = expand_format (edit_widget, *commands, do_quote);
549 if (text != NULL)
550 {
551 fputs (text, cmd_file);
552 g_free (text);
553 }
554 }
555 }
556 else if (*commands == '%')
557 {
558 int i;
559
560 i = check_format_view (commands + 1);
561 if (i != 0)
562 {
563 commands += i;
564 run_view = TRUE;
565 }
566 else
567 {
568 do_quote = TRUE;
569 expand_prefix_found = TRUE;
570 }
571 }
572 else
573 fputc (*commands, cmd_file);
574 }
575
576 fclose (cmd_file);
577 mc_chmod (file_name_vpath, S_IRWXU);
578
579
580 cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (file_name_vpath), (char *) NULL);
581
582 if (run_view)
583 {
584 mcview_viewer (cmd, NULL, 0, 0, 0);
585 dialog_switch_process_pending ();
586 }
587 else if (show_prompt)
588 shell_execute (cmd, EXECUTE_HIDE);
589 else
590 {
591 gboolean ok;
592
593
594
595 tty_reset_shell_mode ();
596
597 ok = (system (cmd) != -1);
598
599
600 tty_raw_mode ();
601
602
603 tty_clear_screen ();
604 repaint_screen ();
605
606 if (!ok)
607 message (D_ERROR, MSG_ERROR, "%s", _ ("Error calling program"));
608 }
609
610 g_free (cmd);
611
612 mc_unlink (file_name_vpath);
613 vfs_path_free (file_name_vpath, TRUE);
614 }
615
616
617
618
619
620
621
622
623
624
625 static gboolean
626 menu_file_own (char *path)
627 {
628 struct stat st;
629
630 if (stat (path, &st) == 0 && (st.st_uid == 0 || (st.st_uid == geteuid ()) != 0)
631 && ((st.st_mode & (S_IWGRP | S_IWOTH)) == 0))
632 return TRUE;
633
634 if (verbose)
635 message (D_NORMAL, _ ("Warning -- ignoring file"),
636 _ ("File %s is not owned by root or you or is world writable.\n"
637 "Using it may compromise your security"),
638 path);
639
640 return FALSE;
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 int
673 check_format_view (const char *p)
674 {
675 const char *q = p;
676
677 if (strncmp (p, "view", 4) == 0)
678 {
679 q += 4;
680 if (*q == '{')
681 {
682 for (q++; *q != '\0' && *q != '}'; q++)
683 {
684 if (strncmp (q, DEFAULT_CHARSET, 5) == 0)
685 {
686 mcview_global_flags.hex = FALSE;
687 q += 4;
688 }
689 else if (strncmp (q, "hex", 3) == 0)
690 {
691 mcview_global_flags.hex = TRUE;
692 q += 2;
693 }
694 else if (strncmp (q, "nroff", 5) == 0)
695 {
696 mcview_global_flags.nroff = TRUE;
697 q += 4;
698 }
699 else if (strncmp (q, "unform", 6) == 0)
700 {
701 mcview_global_flags.nroff = FALSE;
702 q += 5;
703 }
704 }
705 if (*q == '}')
706 q++;
707 }
708 return q - p;
709 }
710 return 0;
711 }
712
713
714
715 int
716 check_format_cd (const char *p)
717 {
718 return (strncmp (p, "cd", 2)) != 0 ? 0 : 3;
719 }
720
721
722
723
724
725
726 int
727 check_format_var (const char *p, char **v)
728 {
729 *v = NULL;
730
731 if (strncmp (p, "var{", 4) == 0)
732 {
733 const char *q = p;
734 const char *dots = NULL;
735 const char *value;
736 char *var_name;
737
738 for (q += 4; *q != '\0' && *q != '}'; q++)
739 {
740 if (*q == ':')
741 dots = q + 1;
742 }
743 if (*q == '\0')
744 return 0;
745
746 if (dots == NULL || dots == q + 5)
747 {
748 message (D_ERROR, _ ("Format error on file Extensions File"),
749 dots == NULL ? _ ("The %%var macro has no default")
750 : _ ("The %%var macro has no variable"));
751 return 0;
752 }
753
754
755 var_name = g_strndup (p + 4, dots - 2 - (p + 3));
756 value = getenv (var_name);
757 g_free (var_name);
758
759 if (value != NULL)
760 *v = g_strdup (value);
761 else
762 *v = g_strndup (dots, q - dots);
763
764 return q - p;
765 }
766 return 0;
767 }
768
769
770
771 char *
772 expand_format (const Widget *edit_widget, char c, gboolean do_quote)
773 {
774 WPanel *panel = NULL;
775 char *(*quote_func) (const char *, gboolean);
776 const char *fname = NULL;
777 char *result;
778 char c_lc;
779
780 #ifdef USE_INTERNAL_EDIT
781 const WEdit *e = CONST_EDIT (edit_widget);
782 #else
783 (void) edit_widget;
784 #endif
785
786 if (c == '%')
787 return g_strdup ("%");
788
789 switch (mc_global.mc_run_mode)
790 {
791 case MC_RUN_FULL:
792 #ifdef USE_INTERNAL_EDIT
793 if (e != NULL)
794 fname = edit_get_file_name (e);
795 else
796 #endif
797 {
798 const file_entry_t *fe;
799
800 if (g_ascii_islower ((gchar) c))
801 panel = current_panel;
802 else
803 {
804 if (get_other_type () != view_listing)
805 return NULL;
806 panel = other_panel;
807 }
808
809 fe = panel_current_entry (panel);
810 fname = fe == NULL ? NULL : fe->fname->str;
811 }
812 break;
813
814 #ifdef USE_INTERNAL_EDIT
815 case MC_RUN_EDITOR:
816 fname = edit_get_file_name (e);
817 break;
818 #endif
819
820 case MC_RUN_VIEWER:
821
822 fname = (const char *) mc_run_param0;
823 break;
824
825 default:
826
827 return NULL;
828 }
829
830 if (do_quote)
831 quote_func = name_quote;
832 else
833 quote_func = fake_name_quote;
834
835 c_lc = g_ascii_tolower ((gchar) c);
836
837 switch (c_lc)
838 {
839 case 'f':
840 case 'p':
841 result = quote_func (fname, FALSE);
842 goto ret;
843 case 'x':
844 result = quote_func (extension (fname), FALSE);
845 goto ret;
846 case 'd':
847 {
848 const char *cwd;
849
850 if (panel != NULL)
851 cwd = vfs_path_as_str (panel->cwd_vpath);
852 else
853 cwd = vfs_get_current_dir ();
854
855 result = quote_func (cwd, FALSE);
856 goto ret;
857 }
858 case 'c':
859 #ifdef USE_INTERNAL_EDIT
860 if (e != NULL)
861 {
862 result = g_strdup_printf ("%u", (unsigned int) edit_get_cursor_offset (e));
863 goto ret;
864 }
865 #endif
866 break;
867 case 'i':
868 #ifdef USE_INTERNAL_EDIT
869 if (e != NULL)
870 {
871 result = g_strnfill (edit_get_curs_col (e), ' ');
872 goto ret;
873 }
874 #endif
875 break;
876 case 'y':
877 #ifdef USE_INTERNAL_EDIT
878 if (e != NULL)
879 {
880 const char *syntax_type;
881
882 syntax_type = edit_get_syntax_type (e);
883 if (syntax_type != NULL)
884 {
885 result = g_strdup (syntax_type);
886 goto ret;
887 }
888 }
889 #endif
890 break;
891 case 'k':
892 case 'b':
893 #ifdef USE_INTERNAL_EDIT
894 if (e != NULL)
895 {
896 char *file;
897
898 file = mc_config_get_full_path (EDIT_HOME_BLOCK_FILE);
899 result = quote_func (file, FALSE);
900 g_free (file);
901 goto ret;
902 }
903 #endif
904 if (c_lc == 'b')
905 {
906 result = strip_ext (quote_func (fname, FALSE));
907 goto ret;
908 }
909 break;
910 case 'n':
911 #ifdef USE_INTERNAL_EDIT
912 if (e != NULL)
913 {
914 result = strip_ext (quote_func (fname, FALSE));
915 goto ret;
916 }
917 #endif
918 break;
919 case 'm':
920 if (menu != NULL)
921 {
922 result = quote_func (menu, FALSE);
923 goto ret;
924 }
925 break;
926 case 's':
927 if (panel == NULL || panel->marked == 0)
928 {
929 result = quote_func (fname, FALSE);
930 goto ret;
931 }
932
933 MC_FALLTHROUGH;
934
935 case 't':
936 case 'u':
937 {
938 GString *block = NULL;
939 int i;
940
941 if (panel == NULL)
942 {
943 result = NULL;
944 goto ret;
945 }
946
947 for (i = 0; i < panel->dir.len; i++)
948 if (panel->dir.list[i].f.marked != 0)
949 {
950 char *tmp;
951
952 tmp = quote_func (panel->dir.list[i].fname->str, FALSE);
953 if (tmp != NULL)
954 {
955 if (block == NULL)
956 block = g_string_new_take (tmp);
957 else
958 {
959 g_string_append (block, tmp);
960 g_free (tmp);
961 }
962 g_string_append_c (block, ' ');
963 }
964
965 if (c_lc == 'u')
966 do_file_mark (panel, i, 0);
967 }
968 result = block == NULL ? NULL : g_string_free (block, block->len == 0);
969 goto ret;
970 }
971 default:
972 break;
973 }
974
975 result = g_strdup ("% ");
976 result[1] = c;
977 ret:
978 return result;
979 }
980
981
982
983
984
985
986
987 gboolean
988 user_menu_cmd (const Widget *edit_widget, const char *menu_file, int selected_entry)
989 {
990 char *data, *p;
991 GPtrArray *entries = NULL;
992 int max_cols = 0;
993 int col = 0;
994 gboolean accept_entry = TRUE;
995 int selected = 0;
996 gboolean old_patterns;
997 gboolean res = FALSE;
998 gboolean interactive = TRUE;
999
1000 if (!vfs_current_is_local ())
1001 {
1002 message (D_ERROR, MSG_ERROR, "%s", _ ("Cannot execute commands on non-local filesystems"));
1003 return FALSE;
1004 }
1005
1006 menu = g_strdup (menu_file != NULL ? menu_file
1007 : edit_widget != NULL ? EDIT_LOCAL_MENU
1008 : MC_LOCAL_MENU);
1009
1010 if (!exist_file (menu) || !menu_file_own (menu))
1011 {
1012 if (menu_file != NULL)
1013 {
1014 message (D_ERROR, MSG_ERROR, _ ("Cannot open file %s\n%s"), menu,
1015 unix_error_string (errno));
1016 MC_PTR_FREE (menu);
1017 return FALSE;
1018 }
1019
1020 g_free (menu);
1021 menu = mc_config_get_full_path (edit_widget != NULL ? EDIT_HOME_MENU : MC_USERMENU_FILE);
1022 if (!exist_file (menu))
1023 {
1024 const char *global_menu;
1025
1026 global_menu = edit_widget != NULL ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU;
1027
1028 g_free (menu);
1029 menu = mc_build_filename (mc_config_get_home_dir (), global_menu, (char *) NULL);
1030 if (!exist_file (menu))
1031 {
1032 g_free (menu);
1033 menu = mc_build_filename (mc_global.sysconfig_dir, global_menu, (char *) NULL);
1034 if (!exist_file (menu))
1035 {
1036 g_free (menu);
1037 menu = mc_build_filename (mc_global.share_data_dir, global_menu, (char *) NULL);
1038 }
1039 }
1040 }
1041 }
1042
1043 if (!g_file_get_contents (menu, &data, NULL, NULL))
1044 {
1045 message (D_ERROR, MSG_ERROR, _ ("Cannot open file %s\n%s"), menu,
1046 unix_error_string (errno));
1047 MC_PTR_FREE (menu);
1048 return FALSE;
1049 }
1050
1051 old_patterns = easy_patterns;
1052
1053
1054 for (p = check_patterns (data); *p != '\0'; str_next_char (&p))
1055 {
1056 unsigned int menu_lines = entries == NULL ? 0 : entries->len;
1057
1058 if (col == 0 && (entries == NULL || menu_lines == entries->len))
1059 switch (*p)
1060 {
1061 case '#':
1062
1063 if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
1064 interactive = FALSE;
1065
1066 accept_entry = TRUE;
1067 break;
1068
1069 case '+':
1070 if (*(p + 1) == '=')
1071 {
1072
1073 p = test_line (edit_widget, p + 1, &accept_entry);
1074 if (selected == 0 && accept_entry)
1075 selected = menu_lines;
1076 }
1077 else
1078 {
1079
1080 p = test_line (edit_widget, p, &accept_entry);
1081 }
1082 break;
1083
1084 case '=':
1085 if (*(p + 1) == '+')
1086 {
1087
1088 p = test_line (edit_widget, p + 1, &accept_entry);
1089 if (selected == 0 && accept_entry)
1090 selected = menu_lines;
1091 }
1092 else
1093 {
1094
1095 gboolean ok = TRUE;
1096
1097 p = test_line (edit_widget, p, &ok);
1098 if (selected == 0 && ok)
1099 selected = menu_lines;
1100 }
1101 break;
1102
1103 default:
1104 if (!whitespace (*p) && str_isprint (p))
1105 {
1106
1107 if (accept_entry)
1108 {
1109 if (entries == NULL)
1110 entries = g_ptr_array_new ();
1111 g_ptr_array_add (entries, p);
1112 }
1113 else
1114 accept_entry = TRUE;
1115 }
1116 break;
1117 }
1118
1119 if (*p == '\n')
1120 {
1121 if (entries != NULL && entries->len > menu_lines)
1122 accept_entry = TRUE;
1123 max_cols = MAX (max_cols, col);
1124 col = 0;
1125 }
1126 else
1127 {
1128 if (*p == '\t')
1129 *p = ' ';
1130 col++;
1131 }
1132 }
1133
1134 if (entries == NULL)
1135 message (D_ERROR, MSG_ERROR, _ ("No suitable entries found in %s"), menu);
1136 else
1137 {
1138 if (selected_entry >= 0)
1139 selected = selected_entry;
1140 else
1141 {
1142 Listbox *listbox;
1143 unsigned int i;
1144
1145 max_cols = MIN (MAX (max_cols, col), MAX_ENTRY_LEN);
1146
1147
1148 listbox = listbox_window_new (entries->len, max_cols + 2, _ ("User menu"),
1149 "[Edit Menu File]");
1150
1151 for (i = 0; i < entries->len; i++)
1152 {
1153 p = g_ptr_array_index (entries, i);
1154 LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
1155 extract_line (p, p + MAX_ENTRY_LEN, NULL), p, FALSE);
1156 }
1157
1158 listbox_set_current (listbox->list, selected);
1159
1160 selected = listbox_run (listbox);
1161 }
1162
1163 if (selected >= 0)
1164 {
1165 execute_menu_command (edit_widget, g_ptr_array_index (entries, selected), interactive);
1166 res = TRUE;
1167 }
1168
1169 g_ptr_array_free (entries, TRUE);
1170
1171 do_refresh ();
1172 }
1173
1174 easy_patterns = old_patterns;
1175 MC_PTR_FREE (menu);
1176 g_free (data);
1177 return res;
1178 }
1179
1180