This source file includes following definitions.
- do_view_cmd
- do_edit
- compare_files
- compare_dir
- do_link
- nice_cd
- configure_panel_listing
- switch_to_listing
- view_file_at_line
- view_file
- view_cmd
- view_file_cmd
- view_raw_cmd
- view_filtered_cmd
- edit_file_at_line
- edit_cmd
- edit_cmd_force_internal
- edit_cmd_new
- mkdir_cmd
- reread_cmd
- ext_cmd
- edit_mc_menu_cmd
- edit_fhl_cmd
- hotlist_cmd
- vfs_list
- compare_dirs_cmd
- diff_view_cmd
- swap_cmd
- link_cmd
- edit_symlink_cmd
- help_cmd
- user_file_menu_cmd
- ftplink_cmd
- sftplink_cmd
- shelllink_cmd
- undelete_cmd
- quick_cd_cmd
- smart_dirsize_cmd
- single_dirsize_cmd
- dirsizes_cmd
- save_setup_cmd
- info_cmd_no_menu
- quick_cmd_no_menu
- listing_cmd
- setup_listing_format_cmd
- panel_tree_cmd
- info_cmd
- quick_view_cmd
- encoding_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
32
33 #include <config.h>
34
35 #include <errno.h>
36 #include <stdio.h>
37 #include <string.h>
38
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #ifdef HAVE_MMAP
42 #include <sys/mman.h>
43 #endif
44 #ifdef ENABLE_VFS_NET
45 #include <netdb.h>
46 #endif
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <pwd.h>
50 #include <grp.h>
51
52 #include "lib/global.h"
53
54 #include "lib/tty/tty.h"
55 #include "lib/tty/key.h"
56 #include "lib/mcconfig.h"
57 #include "lib/filehighlight.h"
58 #include "lib/vfs/vfs.h"
59 #include "lib/fileloc.h"
60 #include "lib/strutil.h"
61 #include "lib/file-entry.h"
62 #include "lib/util.h"
63 #include "lib/widget.h"
64 #include "lib/keybind.h"
65 #include "lib/event.h"
66
67 #include "src/setup.h"
68 #include "src/execute.h"
69 #include "src/history.h"
70 #include "src/usermenu.h"
71 #include "src/util.h"
72
73 #include "src/viewer/mcviewer.h"
74
75 #ifdef USE_INTERNAL_EDIT
76 #include "src/editor/edit.h"
77 #endif
78
79 #ifdef USE_DIFF_VIEW
80 #include "src/diffviewer/ydiff.h"
81 #endif
82
83 #include "fileopctx.h"
84 #include "filenot.h"
85 #include "hotlist.h"
86 #include "tree.h"
87 #include "filemanager.h"
88 #include "command.h"
89 #include "layout.h"
90 #include "ext.h"
91 #include "boxes.h"
92 #include "dir.h"
93 #include "cd.h"
94
95 #include "cmd.h"
96
97
98
99
100
101 #ifdef HAVE_MMAP
102 #ifndef MAP_FILE
103 #define MAP_FILE 0
104 #endif
105 #endif
106
107
108
109 enum CompareMode
110 {
111 compare_quick = 0,
112 compare_size_only,
113 compare_thourough
114 };
115
116
117
118
119
120 #ifdef ENABLE_VFS_NET
121 static const char *machine_str = N_("Enter machine name (F1 for details):");
122 #endif
123
124
125
126
127
128
129
130
131 static void
132 do_view_cmd (WPanel * panel, gboolean plain_view)
133 {
134 const file_entry_t *fe;
135
136 fe = panel_current_entry (panel);
137
138
139 if (S_ISDIR (fe->st.st_mode) || link_isdir (fe))
140 {
141 vfs_path_t *fname_vpath;
142
143 if (confirm_view_dir && (panel->marked != 0 || panel->dirs_marked != 0) &&
144 query_dialog (_("Confirmation"), _("Files tagged, want to cd?"), D_NORMAL, 2,
145 _("&Yes"), _("&No")) != 0)
146 return;
147
148 fname_vpath = vfs_path_from_str (fe->fname->str);
149 if (!panel_cd (panel, fname_vpath, cd_exact))
150 cd_error_message (fe->fname->str);
151 vfs_path_free (fname_vpath, TRUE);
152 }
153 else
154 {
155 vfs_path_t *filename_vpath;
156
157 filename_vpath = vfs_path_from_str (fe->fname->str);
158 view_file (filename_vpath, plain_view, use_internal_view);
159 vfs_path_free (filename_vpath, TRUE);
160 }
161
162 repaint_screen ();
163 }
164
165
166
167 static inline void
168 do_edit (const vfs_path_t * what_vpath)
169 {
170 edit_file_at_line (what_vpath, use_internal_edit, 0);
171 }
172
173
174
175 static int
176 compare_files (const vfs_path_t * vpath1, const vfs_path_t * vpath2, off_t size)
177 {
178 int file1;
179 int result = -1;
180
181 if (size == 0)
182 return 0;
183
184 file1 = open (vfs_path_as_str (vpath1), O_RDONLY);
185 if (file1 >= 0)
186 {
187 int file2;
188
189 file2 = open (vfs_path_as_str (vpath2), O_RDONLY);
190 if (file2 >= 0)
191 {
192 #ifdef HAVE_MMAP
193 char *data1;
194
195
196 data1 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file1, 0);
197 if (data1 != (char *) -1)
198 {
199 char *data2;
200
201 data2 = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file2, 0);
202 if (data2 != (char *) -1)
203 {
204 rotate_dash (TRUE);
205 result = memcmp (data1, data2, size);
206 munmap (data2, size);
207 }
208 munmap (data1, size);
209 }
210 #else
211
212 char buf1[BUFSIZ], buf2[BUFSIZ];
213 int n1, n2;
214
215 rotate_dash (TRUE);
216 do
217 {
218 while ((n1 = read (file1, buf1, sizeof (buf1))) == -1 && errno == EINTR)
219 ;
220 while ((n2 = read (file2, buf2, sizeof (buf2))) == -1 && errno == EINTR)
221 ;
222 }
223 while (n1 == n2 && n1 == sizeof (buf1) && memcmp (buf1, buf2, sizeof (buf1)) == 0);
224 result = (n1 != n2) || memcmp (buf1, buf2, n1);
225 #endif
226 close (file2);
227 }
228 close (file1);
229 }
230 rotate_dash (FALSE);
231
232 return result;
233 }
234
235
236
237 static void
238 compare_dir (WPanel * panel, const WPanel * other, enum CompareMode mode)
239 {
240 int i, j;
241
242
243 panel->marked = 0;
244 panel->total = 0;
245 panel->dirs_marked = 0;
246
247
248 for (i = 0; i < panel->dir.len; i++)
249 {
250 file_entry_t *source = &panel->dir.list[i];
251 const char *source_fname;
252
253
254 file_mark (panel, i, 0);
255
256
257 if (S_ISDIR (source->st.st_mode))
258 continue;
259
260 source_fname = source->fname->str;
261 if (panel->is_panelized)
262 source_fname = x_basename (source_fname);
263
264
265 for (j = 0; j < other->dir.len; j++)
266 {
267 const char *other_fname;
268
269 other_fname = other->dir.list[j].fname->str;
270 if (other->is_panelized)
271 other_fname = x_basename (other_fname);
272
273 if (strcmp (source_fname, other_fname) == 0)
274 break;
275 }
276
277 if (j >= other->dir.len)
278
279 do_file_mark (panel, i, 1);
280 else
281 {
282
283 file_entry_t *target = &other->dir.list[j];
284
285 if (mode != compare_size_only)
286
287 if (source->st.st_mtime < target->st.st_mtime)
288 continue;
289
290
291 if (source->st.st_size != target->st.st_size)
292 {
293 do_file_mark (panel, i, 1);
294 continue;
295 }
296
297 if (mode == compare_size_only)
298 continue;
299
300 if (mode == compare_quick)
301 {
302
303
304 if (source->st.st_mtime > target->st.st_mtime)
305 do_file_mark (panel, i, 1);
306
307 continue;
308 }
309
310
311 {
312 vfs_path_t *src_name, *dst_name;
313
314 src_name =
315 vfs_path_append_new (panel->cwd_vpath, source->fname->str, (char *) NULL);
316 dst_name =
317 vfs_path_append_new (other->cwd_vpath, target->fname->str, (char *) NULL);
318 if (compare_files (src_name, dst_name, source->st.st_size))
319 do_file_mark (panel, i, 1);
320 vfs_path_free (src_name, TRUE);
321 vfs_path_free (dst_name, TRUE);
322 }
323 }
324 }
325 }
326
327
328
329 static void
330 do_link (link_type_t link_type, const char *fname)
331 {
332 char *dest = NULL, *src = NULL;
333 vfs_path_t *dest_vpath = NULL;
334
335 if (link_type == LINK_HARDLINK)
336 {
337 vfs_path_t *fname_vpath;
338
339 src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46));
340 dest =
341 input_expand_dialog (_("Link"), src, MC_HISTORY_FM_LINK, "", INPUT_COMPLETE_FILENAMES);
342 if (dest == NULL || *dest == '\0')
343 goto cleanup;
344
345 save_cwds_stat ();
346
347 fname_vpath = vfs_path_from_str (fname);
348 dest_vpath = vfs_path_from_str (dest);
349 if (mc_link (fname_vpath, dest_vpath) == -1)
350 message (D_ERROR, MSG_ERROR, _("link: %s"), unix_error_string (errno));
351 vfs_path_free (fname_vpath, TRUE);
352 }
353 else
354 {
355 vfs_path_t *s, *d;
356
357
358
359 s = vfs_path_append_new (current_panel->cwd_vpath, fname, (char *) NULL);
360
361 if (get_other_type () == view_listing)
362 d = vfs_path_append_new (other_panel->cwd_vpath, fname, (char *) NULL);
363 else
364 d = vfs_path_from_str (fname);
365
366 if (link_type == LINK_SYMLINK_RELATIVE)
367 {
368 char *s_str;
369
370 s_str = diff_two_paths (other_panel->cwd_vpath, s);
371 vfs_path_free (s, TRUE);
372 s = vfs_path_from_str_flags (s_str, VPF_NO_CANON);
373 g_free (s_str);
374 }
375
376 symlink_box (s, d, &dest, &src);
377 vfs_path_free (d, TRUE);
378 vfs_path_free (s, TRUE);
379
380 if (dest == NULL || *dest == '\0' || src == NULL || *src == '\0')
381 goto cleanup;
382
383 save_cwds_stat ();
384
385 dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON);
386
387 s = vfs_path_from_str (src);
388 if (mc_symlink (dest_vpath, s) == -1)
389 message (D_ERROR, MSG_ERROR, _("symlink: %s"), unix_error_string (errno));
390 vfs_path_free (s, TRUE);
391 }
392
393 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
394 repaint_screen ();
395
396 cleanup:
397 vfs_path_free (dest_vpath, TRUE);
398 g_free (src);
399 g_free (dest);
400 }
401
402
403
404 #if defined(ENABLE_VFS_UNDELFS) || defined(ENABLE_VFS_NET)
405 static void
406 nice_cd (const char *text, const char *xtext, const char *help,
407 const char *history_name, const char *prefix, int to_home, gboolean strip_password)
408 {
409 char *machine;
410 char *cd_path;
411
412 machine =
413 input_dialog_help (text, xtext, help, history_name, INPUT_LAST_TEXT, strip_password,
414 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD | INPUT_COMPLETE_HOSTNAMES |
415 INPUT_COMPLETE_USERNAMES);
416 if (machine == NULL)
417 return;
418
419 to_home = 0;
420
421
422 if (strncmp (prefix, machine, strlen (prefix)) == 0)
423 cd_path = g_strconcat (machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
424 else
425 cd_path = g_strconcat (prefix, machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
426
427 g_free (machine);
428
429 if (!IS_PATH_SEP (*cd_path))
430 {
431 char *tmp = cd_path;
432
433 cd_path = g_strconcat (PATH_SEP_STR, tmp, (char *) NULL);
434 g_free (tmp);
435 }
436
437 {
438 panel_view_mode_t save_type;
439 vfs_path_t *cd_vpath;
440
441 save_type = get_panel_type (MENU_PANEL_IDX);
442
443 if (save_type != view_listing)
444 create_panel (MENU_PANEL_IDX, view_listing);
445
446 cd_vpath = vfs_path_from_str_flags (cd_path, VPF_NO_CANON);
447 if (!panel_do_cd (MENU_PANEL, cd_vpath, cd_parse_command))
448 {
449 cd_error_message (cd_path);
450
451 if (save_type != view_listing)
452 create_panel (MENU_PANEL_IDX, save_type);
453 }
454 vfs_path_free (cd_vpath, TRUE);
455 }
456 g_free (cd_path);
457
458
459 if (MENU_PANEL != current_panel)
460 (void) mc_chdir (current_panel->cwd_vpath);
461 }
462 #endif
463
464
465
466 static void
467 configure_panel_listing (WPanel * p, int list_format, int brief_cols, gboolean use_msformat,
468 char **user, char **status)
469 {
470 p->user_mini_status = use_msformat;
471 p->list_format = list_format;
472
473 if (list_format == list_brief)
474 p->brief_cols = brief_cols;
475
476 if (list_format == list_user || use_msformat)
477 {
478 g_free (p->user_format);
479 p->user_format = *user;
480 *user = NULL;
481
482 g_free (p->user_status_format[list_format]);
483 p->user_status_format[list_format] = *status;
484 *status = NULL;
485
486 set_panel_formats (p);
487 }
488
489 set_panel_formats (p);
490 do_refresh ();
491 }
492
493
494
495 static void
496 switch_to_listing (int panel_index)
497 {
498 if (get_panel_type (panel_index) != view_listing)
499 create_panel (panel_index, view_listing);
500 }
501
502
503
504
505
506 gboolean
507 view_file_at_line (const vfs_path_t * filename_vpath, gboolean plain_view, gboolean internal,
508 long start_line, off_t search_start, off_t search_end)
509 {
510 gboolean ret = TRUE;
511
512 if (plain_view)
513 {
514 mcview_mode_flags_t changed_flags;
515
516 mcview_clear_mode_flags (&changed_flags);
517 mcview_altered_flags.hex = FALSE;
518 mcview_altered_flags.magic = FALSE;
519 mcview_altered_flags.nroff = FALSE;
520 if (mcview_global_flags.hex)
521 changed_flags.hex = TRUE;
522 if (mcview_global_flags.magic)
523 changed_flags.magic = TRUE;
524 if (mcview_global_flags.nroff)
525 changed_flags.nroff = TRUE;
526 mcview_global_flags.hex = FALSE;
527 mcview_global_flags.magic = FALSE;
528 mcview_global_flags.nroff = FALSE;
529
530 ret = mcview_viewer (NULL, filename_vpath, start_line, search_start, search_end);
531
532 if (changed_flags.hex && !mcview_altered_flags.hex)
533 mcview_global_flags.hex = TRUE;
534 if (changed_flags.magic && !mcview_altered_flags.magic)
535 mcview_global_flags.magic = TRUE;
536 if (changed_flags.nroff && !mcview_altered_flags.nroff)
537 mcview_global_flags.nroff = TRUE;
538
539 dialog_switch_process_pending ();
540 }
541 else if (internal)
542 {
543 char view_entry[BUF_TINY];
544
545 if (start_line > 0)
546 g_snprintf (view_entry, sizeof (view_entry), "View:%ld", start_line);
547 else
548 strcpy (view_entry, "View");
549
550 ret = (regex_command (filename_vpath, view_entry) == 0);
551 if (ret)
552 {
553 ret = mcview_viewer (NULL, filename_vpath, start_line, search_start, search_end);
554 dialog_switch_process_pending ();
555 }
556 }
557 else
558 {
559 static const char *viewer = NULL;
560
561 if (viewer == NULL)
562 {
563 viewer = getenv ("VIEWER");
564 if (viewer == NULL)
565 viewer = getenv ("PAGER");
566 if (viewer == NULL)
567 viewer = "view";
568 }
569
570 execute_external_editor_or_viewer (viewer, filename_vpath, start_line);
571 }
572
573 return ret;
574 }
575
576
577
578
579
580
581
582
583
584
585
586 gboolean
587 view_file (const vfs_path_t * filename_vpath, gboolean plain_view, gboolean internal)
588 {
589 return view_file_at_line (filename_vpath, plain_view, internal, 0, 0, 0);
590 }
591
592
593
594
595
596 void
597 view_cmd (WPanel * panel)
598 {
599 do_view_cmd (panel, FALSE);
600 }
601
602
603
604
605 void
606 view_file_cmd (const WPanel * panel)
607 {
608 char *filename;
609 vfs_path_t *vpath;
610
611 filename =
612 input_expand_dialog (_("View file"), _("Filename:"),
613 MC_HISTORY_FM_VIEW_FILE, panel_current_entry (panel)->fname->str,
614 INPUT_COMPLETE_FILENAMES);
615 if (filename == NULL)
616 return;
617
618 vpath = vfs_path_from_str (filename);
619 g_free (filename);
620 view_file (vpath, FALSE, use_internal_view);
621 vfs_path_free (vpath, TRUE);
622 }
623
624
625
626 void
627 view_raw_cmd (WPanel * panel)
628 {
629 do_view_cmd (panel, TRUE);
630 }
631
632
633
634 void
635 view_filtered_cmd (const WPanel * panel)
636 {
637 char *command;
638 const char *initial_command;
639
640 if (input_is_empty (cmdline))
641 initial_command = panel_current_entry (panel)->fname->str;
642 else
643 initial_command = input_get_ctext (cmdline);
644
645 command =
646 input_dialog (_("Filtered view"),
647 _("Filter command and arguments:"),
648 MC_HISTORY_FM_FILTERED_VIEW, initial_command,
649 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS);
650
651 if (command != NULL)
652 {
653 mcview_viewer (command, NULL, 0, 0, 0);
654 g_free (command);
655 dialog_switch_process_pending ();
656 }
657 }
658
659
660
661 void
662 edit_file_at_line (const vfs_path_t * what_vpath, gboolean internal, long start_line)
663 {
664
665 #ifdef USE_INTERNAL_EDIT
666 if (internal)
667 edit_file (what_vpath, start_line);
668 else
669 #endif
670 {
671 static const char *editor = NULL;
672
673 (void) internal;
674
675 if (editor == NULL)
676 {
677 editor = getenv ("EDITOR");
678 if (editor == NULL)
679 editor = get_default_editor ();
680 }
681
682 execute_external_editor_or_viewer (editor, what_vpath, start_line);
683 }
684
685 if (mc_global.mc_run_mode == MC_RUN_FULL)
686 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
687
688 #ifdef USE_INTERNAL_EDIT
689 if (use_internal_edit)
690 dialog_switch_process_pending ();
691 else
692 #endif
693 repaint_screen ();
694 }
695
696
697
698 void
699 edit_cmd (const WPanel * panel)
700 {
701 vfs_path_t *fname;
702
703 fname = vfs_path_from_str (panel_current_entry (panel)->fname->str);
704 if (regex_command (fname, "Edit") == 0)
705 do_edit (fname);
706 vfs_path_free (fname, TRUE);
707 }
708
709
710
711 #ifdef USE_INTERNAL_EDIT
712 void
713 edit_cmd_force_internal (const WPanel * panel)
714 {
715 vfs_path_t *fname;
716
717 fname = vfs_path_from_str (panel_current_entry (panel)->fname->str);
718 if (regex_command (fname, "Edit") == 0)
719 edit_file_at_line (fname, TRUE, 1);
720 vfs_path_free (fname, TRUE);
721 }
722 #endif
723
724
725
726 void
727 edit_cmd_new (void)
728 {
729 vfs_path_t *fname_vpath = NULL;
730
731 if (editor_ask_filename_before_edit)
732 {
733 char *fname;
734
735 fname = input_expand_dialog (_("Edit file"), _("Enter file name:"),
736 MC_HISTORY_EDIT_LOAD, "", INPUT_COMPLETE_FILENAMES);
737 if (fname == NULL)
738 return;
739
740 if (*fname != '\0')
741 fname_vpath = vfs_path_from_str (fname);
742
743 g_free (fname);
744 }
745
746 #ifdef HAVE_CHARSET
747 mc_global.source_codepage = default_source_codepage;
748 #endif
749 do_edit (fname_vpath);
750
751 vfs_path_free (fname_vpath, TRUE);
752 }
753
754
755
756 void
757 mkdir_cmd (WPanel * panel)
758 {
759 const file_entry_t *fe;
760 char *dir;
761 const char *name = "";
762
763 fe = panel_current_entry (panel);
764
765
766 if (auto_fill_mkdir_name && !DIR_IS_DOTDOT (fe->fname->str))
767 name = fe->fname->str;
768
769 dir =
770 input_expand_dialog (_("Create a new Directory"),
771 _("Enter directory name:"), MC_HISTORY_FM_MKDIR, name,
772 INPUT_COMPLETE_FILENAMES);
773
774 if (dir != NULL && *dir != '\0')
775 {
776 vfs_path_t *absdir;
777
778 if (IS_PATH_SEP (dir[0]) || dir[0] == '~')
779 absdir = vfs_path_from_str (dir);
780 else
781 {
782
783
784 char *tmpdir = dir;
785
786 if (dir[0] == '\\' && dir[1] == '~')
787 tmpdir = dir + 1;
788
789 absdir = vfs_path_append_new (panel->cwd_vpath, tmpdir, (char *) NULL);
790 }
791
792 save_cwds_stat ();
793
794 if (my_mkdir (absdir, 0777) != 0)
795 message (D_ERROR, MSG_ERROR, "%s", unix_error_string (errno));
796 else
797 {
798 update_panels (UP_OPTIMIZE, dir);
799 repaint_screen ();
800 select_item (panel);
801 }
802
803 vfs_path_free (absdir, TRUE);
804 }
805 g_free (dir);
806 }
807
808
809
810 void
811 reread_cmd (void)
812 {
813 panel_update_flags_t flag = UP_ONLY_CURRENT;
814
815 if (get_current_type () == view_listing && get_other_type () == view_listing &&
816 vfs_path_equal (current_panel->cwd_vpath, other_panel->cwd_vpath))
817 flag = UP_OPTIMIZE;
818
819 update_panels (UP_RELOAD | flag, UP_KEEPSEL);
820 repaint_screen ();
821 }
822
823
824
825 void
826 ext_cmd (void)
827 {
828 vfs_path_t *extdir_vpath;
829 int dir = 0;
830
831 if (geteuid () == 0)
832 dir = query_dialog (_("Extension file edit"),
833 _("Which extension file you want to edit?"), D_NORMAL, 2,
834 _("&User"), _("&System Wide"));
835
836 extdir_vpath = vfs_path_build_filename (mc_global.sysconfig_dir, MC_EXT_FILE, (char *) NULL);
837
838 if (dir == 0)
839 {
840 vfs_path_t *buffer_vpath;
841
842 buffer_vpath = mc_config_get_full_vpath (MC_EXT_FILE);
843 check_for_default (extdir_vpath, buffer_vpath);
844 do_edit (buffer_vpath);
845 vfs_path_free (buffer_vpath, TRUE);
846 }
847 else if (dir == 1)
848 {
849 if (!exist_file (vfs_path_get_last_path_str (extdir_vpath)))
850 {
851 vfs_path_free (extdir_vpath, TRUE);
852 extdir_vpath =
853 vfs_path_build_filename (mc_global.share_data_dir, MC_EXT_FILE, (char *) NULL);
854 }
855 do_edit (extdir_vpath);
856 }
857
858 vfs_path_free (extdir_vpath, TRUE);
859 flush_extension_file ();
860 }
861
862
863
864
865 void
866 edit_mc_menu_cmd (void)
867 {
868 vfs_path_t *buffer_vpath;
869 vfs_path_t *menufile_vpath;
870 int dir = 0;
871
872 query_set_sel (1);
873 dir = query_dialog (_("Menu edit"),
874 _("Which menu file do you want to edit?"),
875 D_NORMAL, geteuid ()? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
876
877 menufile_vpath =
878 vfs_path_build_filename (mc_global.sysconfig_dir, MC_GLOBAL_MENU, (char *) NULL);
879
880 if (!exist_file (vfs_path_get_last_path_str (menufile_vpath)))
881 {
882 vfs_path_free (menufile_vpath, TRUE);
883 menufile_vpath =
884 vfs_path_build_filename (mc_global.share_data_dir, MC_GLOBAL_MENU, (char *) NULL);
885 }
886
887 switch (dir)
888 {
889 case 0:
890 buffer_vpath = vfs_path_from_str (MC_LOCAL_MENU);
891 check_for_default (menufile_vpath, buffer_vpath);
892 chmod (vfs_path_get_last_path_str (buffer_vpath), 0600);
893 break;
894
895 case 1:
896 buffer_vpath = mc_config_get_full_vpath (MC_USERMENU_FILE);
897 check_for_default (menufile_vpath, buffer_vpath);
898 break;
899
900 case 2:
901 buffer_vpath =
902 vfs_path_build_filename (mc_global.sysconfig_dir, MC_GLOBAL_MENU, (char *) NULL);
903 if (!exist_file (vfs_path_get_last_path_str (buffer_vpath)))
904 {
905 vfs_path_free (buffer_vpath, TRUE);
906 buffer_vpath =
907 vfs_path_build_filename (mc_global.share_data_dir, MC_GLOBAL_MENU, (char *) NULL);
908 }
909 break;
910
911 default:
912 vfs_path_free (menufile_vpath, TRUE);
913 return;
914 }
915
916 do_edit (buffer_vpath);
917
918 vfs_path_free (buffer_vpath, TRUE);
919 vfs_path_free (menufile_vpath, TRUE);
920 }
921
922
923
924 void
925 edit_fhl_cmd (void)
926 {
927 vfs_path_t *fhlfile_vpath = NULL;
928 int dir = 0;
929
930 if (geteuid () == 0)
931 dir = query_dialog (_("Highlighting groups file edit"),
932 _("Which highlighting file you want to edit?"), D_NORMAL, 2,
933 _("&User"), _("&System Wide"));
934
935 fhlfile_vpath =
936 vfs_path_build_filename (mc_global.sysconfig_dir, MC_FHL_INI_FILE, (char *) NULL);
937
938 if (dir == 0)
939 {
940 vfs_path_t *buffer_vpath;
941
942 buffer_vpath = mc_config_get_full_vpath (MC_FHL_INI_FILE);
943 check_for_default (fhlfile_vpath, buffer_vpath);
944 do_edit (buffer_vpath);
945 vfs_path_free (buffer_vpath, TRUE);
946 }
947 else if (dir == 1)
948 {
949 if (!exist_file (vfs_path_get_last_path_str (fhlfile_vpath)))
950 {
951 vfs_path_free (fhlfile_vpath, TRUE);
952 fhlfile_vpath =
953 vfs_path_build_filename (mc_global.sysconfig_dir, MC_FHL_INI_FILE, (char *) NULL);
954 }
955 do_edit (fhlfile_vpath);
956 }
957
958 vfs_path_free (fhlfile_vpath, TRUE);
959
960 mc_fhl_free (&mc_filehighlight);
961 mc_filehighlight = mc_fhl_new (TRUE);
962 }
963
964
965
966 void
967 hotlist_cmd (WPanel * panel)
968 {
969 char *target;
970
971 target = hotlist_show (LIST_HOTLIST, panel);
972 if (target == NULL)
973 return;
974
975 if (get_current_type () == view_tree)
976 {
977 vfs_path_t *vpath;
978
979 vpath = vfs_path_from_str (target);
980 tree_chdir (the_tree, vpath);
981 vfs_path_free (vpath, TRUE);
982 }
983 else
984 {
985 vfs_path_t *deprecated_vpath;
986 const char *deprecated_path;
987
988 deprecated_vpath = vfs_path_from_str_flags (target, VPF_USE_DEPRECATED_PARSER);
989 deprecated_path = vfs_path_as_str (deprecated_vpath);
990 cd_to (deprecated_path);
991 vfs_path_free (deprecated_vpath, TRUE);
992 }
993
994 g_free (target);
995 }
996
997
998
999 #ifdef ENABLE_VFS
1000 void
1001 vfs_list (WPanel * panel)
1002 {
1003 char *target;
1004 vfs_path_t *target_vpath;
1005
1006 target = hotlist_show (LIST_VFSLIST, panel);
1007 if (target == NULL)
1008 return;
1009
1010 target_vpath = vfs_path_from_str (target);
1011 if (!panel_cd (current_panel, target_vpath, cd_exact))
1012 cd_error_message (target);
1013 vfs_path_free (target_vpath, TRUE);
1014 g_free (target);
1015 }
1016 #endif
1017
1018
1019
1020 void
1021 compare_dirs_cmd (void)
1022 {
1023 int choice;
1024 enum CompareMode thorough_flag;
1025
1026 choice =
1027 query_dialog (_("Compare directories"),
1028 _("Select compare method:"), D_NORMAL, 4,
1029 _("&Quick"), _("&Size only"), _("&Thorough"), _("&Cancel"));
1030
1031 if (choice < 0 || choice > 2)
1032 return;
1033
1034 thorough_flag = choice;
1035
1036 if (get_current_type () == view_listing && get_other_type () == view_listing)
1037 {
1038 compare_dir (current_panel, other_panel, thorough_flag);
1039 compare_dir (other_panel, current_panel, thorough_flag);
1040 }
1041 else
1042 message (D_ERROR, MSG_ERROR,
1043 _("Both panels should be in the listing mode\nto use this command"));
1044 }
1045
1046
1047
1048 #ifdef USE_DIFF_VIEW
1049 void
1050 diff_view_cmd (void)
1051 {
1052
1053 if (get_current_type () == view_listing && get_other_type () == view_listing)
1054 {
1055 if (get_current_index () == 0)
1056 dview_diff_cmd (current_panel, other_panel);
1057 else
1058 dview_diff_cmd (other_panel, current_panel);
1059
1060 if (mc_global.mc_run_mode == MC_RUN_FULL)
1061 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
1062
1063 dialog_switch_process_pending ();
1064 }
1065 }
1066 #endif
1067
1068
1069
1070 void
1071 swap_cmd (void)
1072 {
1073 swap_panels ();
1074 tty_touch_screen ();
1075 repaint_screen ();
1076 }
1077
1078
1079
1080 void
1081 link_cmd (link_type_t link_type)
1082 {
1083 const char *filename;
1084
1085 filename = panel_current_entry (current_panel)->fname->str;
1086 if (filename != NULL)
1087 do_link (link_type, filename);
1088 }
1089
1090
1091
1092 void
1093 edit_symlink_cmd (void)
1094 {
1095 const file_entry_t *fe;
1096 const char *p;
1097
1098 fe = panel_current_entry (current_panel);
1099 p = fe->fname->str;
1100
1101 if (!S_ISLNK (fe->st.st_mode))
1102 message (D_ERROR, MSG_ERROR, _("'%s' is not a symbolic link"), p);
1103 else
1104 {
1105 char buffer[MC_MAXPATHLEN];
1106 int i;
1107
1108 i = readlink (p, buffer, sizeof (buffer) - 1);
1109 if (i > 0)
1110 {
1111 char *q, *dest;
1112
1113 buffer[i] = '\0';
1114
1115 q = g_strdup_printf (_("Symlink '%s\' points to:"), str_trunc (p, 32));
1116 dest =
1117 input_expand_dialog (_("Edit symlink"), q, MC_HISTORY_FM_EDIT_LINK, buffer,
1118 INPUT_COMPLETE_FILENAMES);
1119 g_free (q);
1120
1121 if (dest != NULL && *dest != '\0' && strcmp (buffer, dest) != 0)
1122 {
1123 vfs_path_t *p_vpath;
1124
1125 p_vpath = vfs_path_from_str (p);
1126
1127 save_cwds_stat ();
1128
1129 if (mc_unlink (p_vpath) == -1)
1130 message (D_ERROR, MSG_ERROR, _("edit symlink, unable to remove %s: %s"), p,
1131 unix_error_string (errno));
1132 else
1133 {
1134 vfs_path_t *dest_vpath;
1135
1136 dest_vpath = vfs_path_from_str_flags (dest, VPF_NO_CANON);
1137 if (mc_symlink (dest_vpath, p_vpath) == -1)
1138 message (D_ERROR, MSG_ERROR, _("edit symlink: %s"),
1139 unix_error_string (errno));
1140 vfs_path_free (dest_vpath, TRUE);
1141 }
1142
1143 vfs_path_free (p_vpath, TRUE);
1144
1145 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
1146 repaint_screen ();
1147 }
1148
1149 g_free (dest);
1150 }
1151 }
1152 }
1153
1154
1155
1156 void
1157 help_cmd (void)
1158 {
1159 ev_help_t event_data = { NULL, NULL };
1160
1161 if (current_panel->quick_search.active)
1162 event_data.node = "[Quick search]";
1163 else
1164 event_data.node = "[main]";
1165
1166 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
1167 }
1168
1169
1170
1171 void
1172 user_file_menu_cmd (void)
1173 {
1174 (void) user_menu_cmd (NULL, NULL, -1);
1175 }
1176
1177
1178
1179 #ifdef ENABLE_VFS_FTP
1180 void
1181 ftplink_cmd (void)
1182 {
1183 nice_cd (_("FTP to machine"), _(machine_str),
1184 "[FTP File System]", ":ftplink_cmd: FTP to machine ", "ftp://", 1, TRUE);
1185 }
1186 #endif
1187
1188
1189
1190 #ifdef ENABLE_VFS_SFTP
1191 void
1192 sftplink_cmd (void)
1193 {
1194 nice_cd (_("SFTP to machine"), _(machine_str),
1195 "[SFTP (SSH File Transfer Protocol) filesystem]",
1196 ":sftplink_cmd: SFTP to machine ", "sftp://", 1, TRUE);
1197 }
1198 #endif
1199
1200
1201
1202 #ifdef ENABLE_VFS_SHELL
1203 void
1204 shelllink_cmd (void)
1205 {
1206 nice_cd (_("Shell link to machine"), _(machine_str),
1207 "[FIle transfer over SHell filesystem]", ":fishlink_cmd: Shell link to machine ",
1208 "sh://", 1, TRUE);
1209 }
1210 #endif
1211
1212
1213
1214 #ifdef ENABLE_VFS_UNDELFS
1215 void
1216 undelete_cmd (void)
1217 {
1218 nice_cd (_("Undelete files on an ext2 file system"),
1219 _("Enter device (without /dev/) to undelete\nfiles on: (F1 for details)"),
1220 "[Undelete File System]", ":undelete_cmd: Undel on ext2 fs ", "undel://", 0, FALSE);
1221 }
1222 #endif
1223
1224
1225
1226 void
1227 quick_cd_cmd (WPanel * panel)
1228 {
1229 char *p;
1230
1231 p = cd_box (panel);
1232 if (p != NULL && *p != '\0')
1233 cd_to (p);
1234 g_free (p);
1235 }
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248 void
1249 smart_dirsize_cmd (WPanel * panel)
1250 {
1251 const file_entry_t *entry;
1252
1253 entry = panel_current_entry (panel);
1254 if ((S_ISDIR (entry->st.st_mode) && DIR_IS_DOTDOT (entry->fname->str)) || panel->dirs_marked)
1255 dirsizes_cmd (panel);
1256 else
1257 single_dirsize_cmd (panel);
1258 }
1259
1260
1261
1262 void
1263 single_dirsize_cmd (WPanel * panel)
1264 {
1265 file_entry_t *entry;
1266
1267 entry = panel_current_entry (panel);
1268
1269 if (S_ISDIR (entry->st.st_mode) && !DIR_IS_DOTDOT (entry->fname->str))
1270 {
1271 size_t dir_count = 0;
1272 size_t count = 0;
1273 uintmax_t total = 0;
1274 dirsize_status_msg_t dsm;
1275 vfs_path_t *p;
1276
1277 p = vfs_path_from_str (entry->fname->str);
1278
1279 memset (&dsm, 0, sizeof (dsm));
1280 status_msg_init (STATUS_MSG (&dsm), _("Directory scanning"), 0, dirsize_status_init_cb,
1281 dirsize_status_update_cb, dirsize_status_deinit_cb);
1282
1283 if (compute_dir_size (p, &dsm, &dir_count, &count, &total, FALSE) == FILE_CONT)
1284 {
1285 entry->st.st_size = (off_t) total;
1286 entry->f.dir_size_computed = 1;
1287 }
1288
1289 vfs_path_free (p, TRUE);
1290
1291 status_msg_deinit (STATUS_MSG (&dsm));
1292 }
1293
1294 if (panels_options.mark_moves_down)
1295 send_message (panel, NULL, MSG_ACTION, CK_Down, NULL);
1296
1297 recalculate_panel_summary (panel);
1298
1299 if (panel->sort_field->sort_routine == (GCompareFunc) sort_size)
1300 panel_re_sort (panel);
1301
1302 panel->dirty = TRUE;
1303 }
1304
1305
1306
1307 void
1308 dirsizes_cmd (WPanel * panel)
1309 {
1310 int i;
1311 dirsize_status_msg_t dsm;
1312
1313 memset (&dsm, 0, sizeof (dsm));
1314 status_msg_init (STATUS_MSG (&dsm), _("Directory scanning"), 0, dirsize_status_init_cb,
1315 dirsize_status_update_cb, dirsize_status_deinit_cb);
1316
1317 for (i = 0; i < panel->dir.len; i++)
1318 if (S_ISDIR (panel->dir.list[i].st.st_mode)
1319 && ((panel->dirs_marked != 0 && panel->dir.list[i].f.marked != 0)
1320 || panel->dirs_marked == 0) && !DIR_IS_DOTDOT (panel->dir.list[i].fname->str))
1321 {
1322 vfs_path_t *p;
1323 size_t dir_count = 0;
1324 size_t count = 0;
1325 uintmax_t total = 0;
1326 gboolean ok;
1327
1328 p = vfs_path_from_str (panel->dir.list[i].fname->str);
1329 ok = compute_dir_size (p, &dsm, &dir_count, &count, &total, FALSE) != FILE_CONT;
1330 vfs_path_free (p, TRUE);
1331 if (ok)
1332 break;
1333
1334 panel->dir.list[i].st.st_size = (off_t) total;
1335 panel->dir.list[i].f.dir_size_computed = 1;
1336 }
1337
1338 status_msg_deinit (STATUS_MSG (&dsm));
1339
1340 recalculate_panel_summary (panel);
1341
1342 if (panel->sort_field->sort_routine == (GCompareFunc) sort_size)
1343 panel_re_sort (panel);
1344
1345 panel->dirty = TRUE;
1346 }
1347
1348
1349
1350 void
1351 save_setup_cmd (void)
1352 {
1353 vfs_path_t *vpath;
1354 const char *path;
1355
1356 vpath = vfs_path_from_str_flags (mc_config_get_path (), VPF_STRIP_HOME);
1357 path = vfs_path_as_str (vpath);
1358
1359 if (save_setup (TRUE, TRUE))
1360 message (D_NORMAL, _("Setup"), _("Setup saved to %s"), path);
1361 else
1362 message (D_ERROR, _("Setup"), _("Unable to save setup to %s"), path);
1363
1364 vfs_path_free (vpath, TRUE);
1365 }
1366
1367
1368
1369 void
1370 info_cmd_no_menu (void)
1371 {
1372 if (get_panel_type (0) == view_info)
1373 create_panel (0, view_listing);
1374 else if (get_panel_type (1) == view_info)
1375 create_panel (1, view_listing);
1376 else
1377 create_panel (current_panel == left_panel ? 1 : 0, view_info);
1378 }
1379
1380
1381
1382 void
1383 quick_cmd_no_menu (void)
1384 {
1385 if (get_panel_type (0) == view_quick)
1386 create_panel (0, view_listing);
1387 else if (get_panel_type (1) == view_quick)
1388 create_panel (1, view_listing);
1389 else
1390 create_panel (current_panel == left_panel ? 1 : 0, view_quick);
1391 }
1392
1393
1394
1395 void
1396 listing_cmd (void)
1397 {
1398 WPanel *p;
1399
1400 switch_to_listing (MENU_PANEL_IDX);
1401
1402 p = PANEL (get_panel_widget (MENU_PANEL_IDX));
1403
1404 p->is_panelized = FALSE;
1405 panel_set_filter (p, NULL);
1406 }
1407
1408
1409
1410 void
1411 setup_listing_format_cmd (void)
1412 {
1413 int list_format;
1414 gboolean use_msformat;
1415 int brief_cols;
1416 char *user, *status;
1417 WPanel *p = NULL;
1418
1419 if (SELECTED_IS_PANEL)
1420 p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
1421
1422 list_format = panel_listing_box (p, MENU_PANEL_IDX, &user, &status, &use_msformat, &brief_cols);
1423 if (list_format != -1)
1424 {
1425 switch_to_listing (MENU_PANEL_IDX);
1426 p = MENU_PANEL_IDX == 0 ? left_panel : right_panel;
1427 configure_panel_listing (p, list_format, brief_cols, use_msformat, &user, &status);
1428 g_free (user);
1429 g_free (status);
1430 }
1431 }
1432
1433
1434
1435 void
1436 panel_tree_cmd (void)
1437 {
1438 create_panel (MENU_PANEL_IDX, view_tree);
1439 }
1440
1441
1442
1443 void
1444 info_cmd (void)
1445 {
1446 create_panel (MENU_PANEL_IDX, view_info);
1447 }
1448
1449
1450
1451 void
1452 quick_view_cmd (void)
1453 {
1454 if (PANEL (get_panel_widget (MENU_PANEL_IDX)) == current_panel)
1455 (void) change_panel ();
1456 create_panel (MENU_PANEL_IDX, view_quick);
1457 }
1458
1459
1460
1461 #ifdef HAVE_CHARSET
1462 void
1463 encoding_cmd (void)
1464 {
1465 if (SELECTED_IS_PANEL)
1466 panel_change_encoding (MENU_PANEL);
1467 }
1468 #endif
1469
1470