root/src/filemanager/cmd.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. do_view_cmd
  2. do_edit
  3. set_panel_filter_to
  4. set_panel_filter
  5. compare_files
  6. compare_dir
  7. do_link
  8. nice_cd
  9. configure_panel_listing
  10. switch_to_listing
  11. view_file_at_line
  12. view_file
  13. view_cmd
  14. view_file_cmd
  15. view_raw_cmd
  16. view_filtered_cmd
  17. edit_file_at_line
  18. edit_cmd
  19. edit_cmd_force_internal
  20. edit_cmd_new
  21. copy_cmd
  22. rename_cmd
  23. copy_cmd_local
  24. rename_cmd_local
  25. mkdir_cmd
  26. delete_cmd
  27. delete_cmd_local
  28. filter_cmd
  29. reread_cmd
  30. ext_cmd
  31. edit_mc_menu_cmd
  32. edit_fhl_cmd
  33. hotlist_cmd
  34. vfs_list
  35. compare_dirs_cmd
  36. diff_view_cmd
  37. swap_cmd
  38. link_cmd
  39. edit_symlink_cmd
  40. help_cmd
  41. user_file_menu_cmd
  42. ftplink_cmd
  43. sftplink_cmd
  44. fishlink_cmd
  45. smblink_cmd
  46. undelete_cmd
  47. quick_cd_cmd
  48. smart_dirsize_cmd
  49. single_dirsize_cmd
  50. dirsizes_cmd
  51. save_setup_cmd
  52. info_cmd_no_menu
  53. quick_cmd_no_menu
  54. listing_cmd
  55. setup_listing_format_cmd
  56. panel_tree_cmd
  57. info_cmd
  58. quick_view_cmd
  59. encoding_cmd

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

/* [previous][next][first][last][top][bottom][index][help]  */