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. compare_files
  4. compare_dir
  5. do_link
  6. nice_cd
  7. configure_panel_listing
  8. switch_to_listing
  9. view_file_at_line
  10. view_file
  11. view_cmd
  12. view_file_cmd
  13. view_raw_cmd
  14. view_filtered_cmd
  15. edit_file_at_line
  16. edit_cmd
  17. edit_cmd_force_internal
  18. edit_cmd_new
  19. mkdir_cmd
  20. reread_cmd
  21. ext_cmd
  22. edit_mc_menu_cmd
  23. edit_fhl_cmd
  24. hotlist_cmd
  25. vfs_list
  26. compare_dirs_cmd
  27. diff_view_cmd
  28. swap_cmd
  29. link_cmd
  30. edit_symlink_cmd
  31. help_cmd
  32. ftplink_cmd
  33. sftplink_cmd
  34. shelllink_cmd
  35. undelete_cmd
  36. quick_cd_cmd
  37. smart_dirsize_cmd
  38. single_dirsize_cmd
  39. dirsizes_cmd
  40. save_setup_cmd
  41. info_cmd_no_menu
  42. quick_cmd_no_menu
  43. listing_cmd
  44. setup_listing_format_cmd
  45. panel_tree_cmd
  46. info_cmd
  47. quick_view_cmd
  48. encoding_cmd

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

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