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

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