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

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