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