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