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