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