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