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. find_cmd
  29. filter_cmd
  30. reread_cmd
  31. ext_cmd
  32. edit_mc_menu_cmd
  33. edit_fhl_cmd
  34. hotlist_cmd
  35. vfs_list
  36. compare_dirs_cmd
  37. diff_view_cmd
  38. swap_cmd
  39. link_cmd
  40. edit_symlink_cmd
  41. help_cmd
  42. user_file_menu_cmd
  43. ftplink_cmd
  44. sftplink_cmd
  45. fishlink_cmd
  46. smblink_cmd
  47. undelete_cmd
  48. quick_cd_cmd
  49. smart_dirsize_cmd
  50. single_dirsize_cmd
  51. dirsizes_cmd
  52. save_setup_cmd
  53. info_cmd_no_menu
  54. quick_cmd_no_menu
  55. listing_cmd
  56. setup_listing_format_cmd
  57. panel_tree_cmd
  58. info_cmd
  59. quick_view_cmd
  60. encoding_cmd

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

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