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. user_file_menu_cmd
  33. ftplink_cmd
  34. sftplink_cmd
  35. fishlink_cmd
  36. undelete_cmd
  37. quick_cd_cmd
  38. smart_dirsize_cmd
  39. single_dirsize_cmd
  40. dirsizes_cmd
  41. save_setup_cmd
  42. info_cmd_no_menu
  43. quick_cmd_no_menu
  44. listing_cmd
  45. setup_listing_format_cmd
  46. panel_tree_cmd
  47. info_cmd
  48. quick_view_cmd
  49. encoding_cmd

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

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