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 = 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 message (D_ERROR, MSG_ERROR, _ ("Cannot create temporary command file\n%s"),
469 unix_error_string (errno));
470 return;
471 }
472
473 cmd_file = fdopen (cmd_file_fd, "w");
474 fputs ("#! /bin/sh\n", cmd_file);
475 commands++;
476
477 for (col = 0; *commands != '\0'; commands++)
478 {
479 if (col == 0)
480 {
481 if (!whitespace (*commands))
482 break;
483 while (whitespace (*commands))
484 commands++;
485 if (*commands == '\0')
486 break;
487 }
488 col++;
489 if (*commands == '\n')
490 col = 0;
491 if (parameter != NULL)
492 {
493 if (*commands == '}')
494 {
495 *parameter = '\0';
496 parameter = input_dialog (
497 _ ("Parameter"), lc_prompt, MC_HISTORY_FM_MENU_EXEC_PARAM, "",
498 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_HOSTNAMES
499 | INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES);
500 if (parameter == NULL || *parameter == '\0')
501 {
502
503 g_free (parameter);
504 fclose (cmd_file);
505 mc_unlink (file_name_vpath);
506 vfs_path_free (file_name_vpath, TRUE);
507 return;
508 }
509 if (do_quote)
510 {
511 char *tmp;
512
513 tmp = name_quote (parameter, FALSE);
514 if (tmp != NULL)
515 {
516 fputs (tmp, cmd_file);
517 g_free (tmp);
518 }
519 }
520 else
521 fputs (parameter, cmd_file);
522
523 MC_PTR_FREE (parameter);
524 }
525 else if (parameter < lc_prompt + sizeof (lc_prompt) - 1)
526 *parameter++ = *commands;
527 }
528 else if (expand_prefix_found)
529 {
530 expand_prefix_found = FALSE;
531 if (g_ascii_isdigit ((gchar) *commands))
532 {
533 do_quote = (atoi (commands) != 0);
534 while (g_ascii_isdigit ((gchar) *commands))
535 commands++;
536 }
537 if (*commands == '{')
538 parameter = lc_prompt;
539 else
540 {
541 char *text;
542
543 text = expand_format (edit_widget, *commands, do_quote);
544 if (text != NULL)
545 {
546 fputs (text, cmd_file);
547 g_free (text);
548 }
549 }
550 }
551 else if (*commands == '%')
552 {
553 int i;
554
555 i = check_format_view (commands + 1);
556 if (i != 0)
557 {
558 commands += i;
559 run_view = TRUE;
560 }
561 else
562 {
563 do_quote = TRUE;
564 expand_prefix_found = TRUE;
565 }
566 }
567 else
568 fputc (*commands, cmd_file);
569 }
570
571 fclose (cmd_file);
572 mc_chmod (file_name_vpath, S_IRWXU);
573
574
575 cmd = g_strconcat ("/bin/sh ", vfs_path_as_str (file_name_vpath), (char *) NULL);
576
577 if (run_view)
578 {
579 mcview_viewer (cmd, NULL, 0, 0, 0);
580 dialog_switch_process_pending ();
581 }
582 else if (show_prompt)
583 shell_execute (cmd, EXECUTE_HIDE);
584 else
585 {
586 gboolean ok;
587
588
589
590 tty_reset_shell_mode ();
591
592 ok = (system (cmd) != -1);
593
594
595 tty_raw_mode ();
596
597
598 tty_clear_screen ();
599 repaint_screen ();
600
601 if (!ok)
602 message (D_ERROR, MSG_ERROR, "%s", _ ("Error calling program"));
603 }
604
605 g_free (cmd);
606
607 mc_unlink (file_name_vpath);
608 vfs_path_free (file_name_vpath, TRUE);
609 }
610
611
612
613
614
615
616
617
618
619
620 static gboolean
621 menu_file_own (char *path)
622 {
623 struct stat st;
624
625 if (stat (path, &st) == 0 && (st.st_uid == 0 || (st.st_uid == geteuid ()) != 0)
626 && ((st.st_mode & (S_IWGRP | S_IWOTH)) == 0))
627 return TRUE;
628
629 if (verbose)
630 message (D_NORMAL, _ ("Warning -- ignoring file"),
631 _ ("File %s is not owned by root or you or is world writable.\n"
632 "Using it may compromise your security"),
633 path);
634
635 return FALSE;
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 int
668 check_format_view (const char *p)
669 {
670 const char *q = p;
671
672 if (strncmp (p, "view", 4) == 0)
673 {
674 q += 4;
675 if (*q == '{')
676 {
677 for (q++; *q != '\0' && *q != '}'; q++)
678 {
679 if (strncmp (q, DEFAULT_CHARSET, 5) == 0)
680 {
681 mcview_global_flags.hex = FALSE;
682 q += 4;
683 }
684 else if (strncmp (q, "hex", 3) == 0)
685 {
686 mcview_global_flags.hex = TRUE;
687 q += 2;
688 }
689 else if (strncmp (q, "nroff", 5) == 0)
690 {
691 mcview_global_flags.nroff = TRUE;
692 q += 4;
693 }
694 else if (strncmp (q, "unform", 6) == 0)
695 {
696 mcview_global_flags.nroff = FALSE;
697 q += 5;
698 }
699 }
700 if (*q == '}')
701 q++;
702 }
703 return q - p;
704 }
705 return 0;
706 }
707
708
709
710 int
711 check_format_cd (const char *p)
712 {
713 return (strncmp (p, "cd", 2)) != 0 ? 0 : 3;
714 }
715
716
717
718
719
720
721 int
722 check_format_var (const char *p, char **v)
723 {
724 *v = NULL;
725
726 if (strncmp (p, "var{", 4) == 0)
727 {
728 const char *q = p;
729 const char *dots = NULL;
730 const char *value;
731 char *var_name;
732
733 for (q += 4; *q != '\0' && *q != '}'; q++)
734 {
735 if (*q == ':')
736 dots = q + 1;
737 }
738 if (*q == '\0')
739 return 0;
740
741 if (dots == NULL || dots == q + 5)
742 {
743 message (D_ERROR, _ ("Format error on file Extensions File"),
744 dots == NULL ? _ ("The %%var macro has no default")
745 : _ ("The %%var macro has no variable"));
746 return 0;
747 }
748
749
750 var_name = g_strndup (p + 4, dots - 2 - (p + 3));
751 value = getenv (var_name);
752 g_free (var_name);
753
754 if (value != NULL)
755 *v = g_strdup (value);
756 else
757 *v = g_strndup (dots, q - dots);
758
759 return q - p;
760 }
761 return 0;
762 }
763
764
765
766 char *
767 expand_format (const Widget *edit_widget, char c, gboolean do_quote)
768 {
769 WPanel *panel = NULL;
770 char *(*quote_func) (const char *, gboolean);
771 const char *fname = NULL;
772 char *result;
773 char c_lc;
774
775 #ifdef USE_INTERNAL_EDIT
776 const WEdit *e = CONST_EDIT (edit_widget);
777 #else
778 (void) edit_widget;
779 #endif
780
781 if (c == '%')
782 return g_strdup ("%");
783
784 switch (mc_global.mc_run_mode)
785 {
786 case MC_RUN_FULL:
787 #ifdef USE_INTERNAL_EDIT
788 if (e != NULL)
789 fname = edit_get_file_name (e);
790 else
791 #endif
792 {
793 const file_entry_t *fe;
794
795 if (g_ascii_islower ((gchar) c))
796 panel = current_panel;
797 else
798 {
799 if (get_other_type () != view_listing)
800 return NULL;
801 panel = other_panel;
802 }
803
804 fe = panel_current_entry (panel);
805 fname = fe == NULL ? NULL : fe->fname->str;
806 }
807 break;
808
809 #ifdef USE_INTERNAL_EDIT
810 case MC_RUN_EDITOR:
811 fname = edit_get_file_name (e);
812 break;
813 #endif
814
815 case MC_RUN_VIEWER:
816
817 fname = (const char *) mc_run_param0;
818 break;
819
820 default:
821
822 return NULL;
823 }
824
825 if (do_quote)
826 quote_func = name_quote;
827 else
828 quote_func = fake_name_quote;
829
830 c_lc = g_ascii_tolower ((gchar) c);
831
832 switch (c_lc)
833 {
834 case 'f':
835 case 'p':
836 result = quote_func (fname, FALSE);
837 goto ret;
838 case 'x':
839 result = quote_func (extension (fname), FALSE);
840 goto ret;
841 case 'd':
842 {
843 const char *cwd;
844
845 if (panel != NULL)
846 cwd = vfs_path_as_str (panel->cwd_vpath);
847 else
848 cwd = vfs_get_current_dir ();
849
850 result = quote_func (cwd, FALSE);
851 goto ret;
852 }
853 case 'c':
854 #ifdef USE_INTERNAL_EDIT
855 if (e != NULL)
856 {
857 result = g_strdup_printf ("%u", (unsigned int) edit_get_cursor_offset (e));
858 goto ret;
859 }
860 #endif
861 break;
862 case 'i':
863 #ifdef USE_INTERNAL_EDIT
864 if (e != NULL)
865 {
866 result = g_strnfill (edit_get_curs_col (e), ' ');
867 goto ret;
868 }
869 #endif
870 break;
871 case 'y':
872 #ifdef USE_INTERNAL_EDIT
873 if (e != NULL)
874 {
875 const char *syntax_type;
876
877 syntax_type = edit_get_syntax_type (e);
878 if (syntax_type != NULL)
879 {
880 result = g_strdup (syntax_type);
881 goto ret;
882 }
883 }
884 #endif
885 break;
886 case 'k':
887 case 'b':
888 #ifdef USE_INTERNAL_EDIT
889 if (e != NULL)
890 {
891 char *file;
892
893 file = mc_config_get_full_path (EDIT_HOME_BLOCK_FILE);
894 result = quote_func (file, FALSE);
895 g_free (file);
896 goto ret;
897 }
898 #endif
899 if (c_lc == 'b')
900 {
901 result = strip_ext (quote_func (fname, FALSE));
902 goto ret;
903 }
904 break;
905 case 'n':
906 #ifdef USE_INTERNAL_EDIT
907 if (e != NULL)
908 {
909 result = strip_ext (quote_func (fname, FALSE));
910 goto ret;
911 }
912 #endif
913 break;
914 case 'm':
915 if (menu != NULL)
916 {
917 result = quote_func (menu, FALSE);
918 goto ret;
919 }
920 break;
921 case 's':
922 if (panel == NULL || panel->marked == 0)
923 {
924 result = quote_func (fname, FALSE);
925 goto ret;
926 }
927
928 MC_FALLTHROUGH;
929
930 case 't':
931 case 'u':
932 {
933 GString *block = NULL;
934 int i;
935
936 if (panel == NULL)
937 {
938 result = NULL;
939 goto ret;
940 }
941
942 for (i = 0; i < panel->dir.len; i++)
943 if (panel->dir.list[i].f.marked != 0)
944 {
945 char *tmp;
946
947 tmp = quote_func (panel->dir.list[i].fname->str, FALSE);
948 if (tmp != NULL)
949 {
950 if (block == NULL)
951 block = g_string_new_take (tmp);
952 else
953 {
954 g_string_append (block, tmp);
955 g_free (tmp);
956 }
957 g_string_append_c (block, ' ');
958 }
959
960 if (c_lc == 'u')
961 do_file_mark (panel, i, 0);
962 }
963 result = block == NULL ? NULL : g_string_free (block, block->len == 0);
964 goto ret;
965 }
966 default:
967 break;
968 }
969
970 result = g_strdup ("% ");
971 result[1] = c;
972 ret:
973 return result;
974 }
975
976
977
978
979
980
981
982 gboolean
983 user_menu_cmd (const Widget *edit_widget, const char *menu_file, int selected_entry)
984 {
985 char *data, *p;
986 GPtrArray *entries = NULL;
987 int max_cols = 0;
988 int col = 0;
989 gboolean accept_entry = TRUE;
990 int selected = 0;
991 gboolean old_patterns;
992 gboolean res = FALSE;
993 gboolean interactive = TRUE;
994
995 if (!vfs_current_is_local ())
996 {
997 message (D_ERROR, MSG_ERROR, "%s", _ ("Cannot execute commands on non-local filesystems"));
998 return FALSE;
999 }
1000
1001 menu = g_strdup (menu_file != NULL ? menu_file
1002 : edit_widget != NULL ? EDIT_LOCAL_MENU
1003 : MC_LOCAL_MENU);
1004
1005 if (!exist_file (menu) || !menu_file_own (menu))
1006 {
1007 if (menu_file != NULL)
1008 {
1009 message (D_ERROR, MSG_ERROR, _ ("Cannot open file %s\n%s"), menu,
1010 unix_error_string (errno));
1011 MC_PTR_FREE (menu);
1012 return FALSE;
1013 }
1014
1015 g_free (menu);
1016 menu = mc_config_get_full_path (edit_widget != NULL ? EDIT_HOME_MENU : MC_USERMENU_FILE);
1017 if (!exist_file (menu))
1018 {
1019 const char *global_menu;
1020
1021 global_menu = edit_widget != NULL ? EDIT_GLOBAL_MENU : MC_GLOBAL_MENU;
1022
1023 g_free (menu);
1024 menu = mc_build_filename (mc_config_get_home_dir (), global_menu, (char *) NULL);
1025 if (!exist_file (menu))
1026 {
1027 g_free (menu);
1028 menu = mc_build_filename (mc_global.sysconfig_dir, global_menu, (char *) NULL);
1029 if (!exist_file (menu))
1030 {
1031 g_free (menu);
1032 menu = mc_build_filename (mc_global.share_data_dir, global_menu, (char *) NULL);
1033 }
1034 }
1035 }
1036 }
1037
1038 if (!g_file_get_contents (menu, &data, NULL, NULL))
1039 {
1040 message (D_ERROR, MSG_ERROR, _ ("Cannot open file %s\n%s"), menu,
1041 unix_error_string (errno));
1042 MC_PTR_FREE (menu);
1043 return FALSE;
1044 }
1045
1046 old_patterns = easy_patterns;
1047
1048
1049 for (p = check_patterns (data); *p != '\0'; str_next_char (&p))
1050 {
1051 unsigned int menu_lines = entries == NULL ? 0 : entries->len;
1052
1053 if (col == 0 && (entries == NULL || menu_lines == entries->len))
1054 switch (*p)
1055 {
1056 case '#':
1057
1058 if (selected_entry >= 0 && strncmp (p, "#silent", 7) == 0)
1059 interactive = FALSE;
1060
1061 accept_entry = TRUE;
1062 break;
1063
1064 case '+':
1065 if (*(p + 1) == '=')
1066 {
1067
1068 p = test_line (edit_widget, p + 1, &accept_entry);
1069 if (selected == 0 && accept_entry)
1070 selected = menu_lines;
1071 }
1072 else
1073 {
1074
1075 p = test_line (edit_widget, p, &accept_entry);
1076 }
1077 break;
1078
1079 case '=':
1080 if (*(p + 1) == '+')
1081 {
1082
1083 p = test_line (edit_widget, p + 1, &accept_entry);
1084 if (selected == 0 && accept_entry)
1085 selected = menu_lines;
1086 }
1087 else
1088 {
1089
1090 gboolean ok = TRUE;
1091
1092 p = test_line (edit_widget, p, &ok);
1093 if (selected == 0 && ok)
1094 selected = menu_lines;
1095 }
1096 break;
1097
1098 default:
1099 if (!whitespace (*p) && str_isprint (p))
1100 {
1101
1102 if (accept_entry)
1103 {
1104 if (entries == NULL)
1105 entries = g_ptr_array_new ();
1106 g_ptr_array_add (entries, p);
1107 }
1108 else
1109 accept_entry = TRUE;
1110 }
1111 break;
1112 }
1113
1114 if (*p == '\n')
1115 {
1116 if (entries != NULL && entries->len > menu_lines)
1117 accept_entry = TRUE;
1118 max_cols = MAX (max_cols, col);
1119 col = 0;
1120 }
1121 else
1122 {
1123 if (*p == '\t')
1124 *p = ' ';
1125 col++;
1126 }
1127 }
1128
1129 if (entries == NULL)
1130 message (D_ERROR, MSG_ERROR, _ ("No suitable entries found in %s"), menu);
1131 else
1132 {
1133 if (selected_entry >= 0)
1134 selected = selected_entry;
1135 else
1136 {
1137 Listbox *listbox;
1138 unsigned int i;
1139
1140 max_cols = MIN (MAX (max_cols, col), MAX_ENTRY_LEN);
1141
1142
1143 listbox = listbox_window_new (entries->len, max_cols + 2, _ ("User menu"),
1144 "[Edit Menu File]");
1145
1146 for (i = 0; i < entries->len; i++)
1147 {
1148 p = g_ptr_array_index (entries, i);
1149 LISTBOX_APPEND_TEXT (listbox, (unsigned char) p[0],
1150 extract_line (p, p + MAX_ENTRY_LEN, NULL), p, FALSE);
1151 }
1152
1153 listbox_set_current (listbox->list, selected);
1154
1155 selected = listbox_run (listbox);
1156 }
1157
1158 if (selected >= 0)
1159 {
1160 execute_menu_command (edit_widget, g_ptr_array_index (entries, selected), interactive);
1161 res = TRUE;
1162 }
1163
1164 g_ptr_array_free (entries, TRUE);
1165
1166 do_refresh ();
1167 }
1168
1169 easy_patterns = old_patterns;
1170 MC_PTR_FREE (menu);
1171 g_free (data);
1172 return res;
1173 }
1174
1175