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