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