root/src/filemanager/midnight.c

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

DEFINITIONS

This source file includes following definitions.
  1. stop_dialogs
  2. treebox_cmd
  3. listmode_cmd
  4. create_panel_menu
  5. create_file_menu
  6. create_command_menu
  7. create_options_menu
  8. init_menu
  9. menu_last_selected_cmd
  10. menu_cmd
  11. sort_cmd
  12. midnight_get_shortcut
  13. midnight_get_title
  14. toggle_panels_split
  15. check_panel_timestamp
  16. check_current_panel_timestamp
  17. check_other_panel_timestamp
  18. print_vfs_message
  19. create_panels
  20. midnight_put_panel_path
  21. put_link
  22. put_current_link
  23. put_other_link
  24. put_current_selected
  25. put_tagged
  26. put_current_tagged
  27. put_other_tagged
  28. ctl_x_cmd
  29. setup_mc
  30. setup_dummy_mc
  31. done_mc
  32. create_file_manager
  33. prepend_cwd_on_local
  34. mc_maybe_editor_or_viewer
  35. show_editor_viewer_history
  36. quit_cmd_internal
  37. quit_cmd
  38. update_dirty_panels
  39. toggle_show_hidden
  40. midnight_execute_cmd
  41. is_cmdline_mute
  42. handle_cmdline_enter
  43. midnight_callback
  44. update_menu
  45. midnight_set_buttonbar
  46. get_random_hint
  47. load_hint
  48. change_panel
  49. save_cwds_stat
  50. quiet_quit_cmd
  51. do_nc

   1 /*
   2    Main dialog (file panels) of the Midnight Commander
   3 
   4    Copyright (C) 1994-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Miguel de Icaza, 1994, 1995, 1996, 1997
   9    Janne Kukonlehto, 1994, 1995
  10    Norbert Warmuth, 1997
  11    Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2012, 2013
  12    Slava Zanko <slavazanko@gmail.com>, 2013
  13 
  14    This file is part of the Midnight Commander.
  15 
  16    The Midnight Commander is free software: you can redistribute it
  17    and/or modify it under the terms of the GNU General Public License as
  18    published by the Free Software Foundation, either version 3 of the License,
  19    or (at your option) any later version.
  20 
  21    The Midnight Commander is distributed in the hope that it will be useful,
  22    but WITHOUT ANY WARRANTY; without even the implied warranty of
  23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24    GNU General Public License for more details.
  25 
  26    You should have received a copy of the GNU General Public License
  27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  28  */
  29 
  30 /** \file main.c
  31  *  \brief Source: main dialog (file panels) of the Midnight Commander
  32  */
  33 
  34 #include <config.h>
  35 
  36 #include <ctype.h>
  37 #include <errno.h>
  38 #include <locale.h>
  39 #include <stdio.h>
  40 #include <stdlib.h>
  41 #include <string.h>
  42 #include <sys/types.h>
  43 #include <sys/stat.h>
  44 #include <sys/wait.h>
  45 #include <pwd.h>                /* for username in xterm title */
  46 
  47 #include "lib/global.h"
  48 #include "lib/fileloc.h"        /* MC_HINT */
  49 
  50 #include "lib/tty/tty.h"
  51 #include "lib/tty/key.h"        /* KEY_M_* masks */
  52 #include "lib/skin.h"
  53 #include "lib/util.h"
  54 
  55 #include "lib/vfs/vfs.h"
  56 
  57 #include "src/args.h"
  58 #ifdef ENABLE_SUBSHELL
  59 #include "src/subshell/subshell.h"
  60 #endif
  61 #include "src/execute.h"        /* toggle_subshell */
  62 #include "src/setup.h"          /* variables */
  63 #include "src/learn.h"          /* learn_keys() */
  64 #include "src/keybind-defaults.h"
  65 #include "lib/fileloc.h"        /* MC_FILEPOS_FILE */
  66 #include "lib/keybind.h"
  67 #include "lib/event.h"
  68 
  69 #include "tree.h"
  70 #include "boxes.h"              /* sort_box(), tree_box() */
  71 #include "layout.h"
  72 #include "cmd.h"                /* commands */
  73 #include "hotlist.h"
  74 #include "panelize.h"
  75 #include "command.h"            /* cmdline */
  76 #include "dir.h"                /* dir_list_clean() */
  77 
  78 #include "chmod.h"
  79 #include "chown.h"
  80 #include "achown.h"
  81 
  82 #ifdef USE_INTERNAL_EDIT
  83 #include "src/editor/edit.h"
  84 #endif
  85 
  86 #ifdef USE_DIFF_VIEW
  87 #include "src/diffviewer/ydiff.h"
  88 #endif
  89 
  90 #include "src/consaver/cons.saver.h"    /* show_console_contents */
  91 #include "src/file_history.h"   /* show_file_history() */
  92 
  93 #include "midnight.h"
  94 
  95 /*** global variables ****************************************************************************/
  96 
  97 /* When the modes are active, left_panel, right_panel and tree_panel */
  98 /* point to a proper data structure.  You should check with the functions */
  99 /* get_current_type and get_other_type the types of the panels before using */
 100 /* this pointer variables */
 101 
 102 /* The structures for the panels */
 103 WPanel *left_panel = NULL;
 104 WPanel *right_panel = NULL;
 105 /* Pointer to the selected and unselected panel */
 106 WPanel *current_panel = NULL;
 107 
 108 /* The Menubar */
 109 WMenuBar *the_menubar = NULL;
 110 /* The widget where we draw the prompt */
 111 WLabel *the_prompt;
 112 /* The hint bar */
 113 WLabel *the_hint;
 114 /* The button bar */
 115 WButtonBar *the_bar;
 116 
 117 /* The prompt */
 118 const char *mc_prompt = NULL;
 119 
 120 /*** file scope macro definitions ****************************************************************/
 121 
 122 #ifdef HAVE_CHARSET
 123 /*
 124  * Don't restrict the output on the screen manager level,
 125  * the translation tables take care of it.
 126  */
 127 #endif /* !HAVE_CHARSET */
 128 
 129 /*** file scope type declarations ****************************************************************/
 130 
 131 /*** file scope variables ************************************************************************/
 132 
 133 static menu_t *left_menu, *right_menu;
 134 
 135 static gboolean ctl_x_map_enabled = FALSE;
 136 
 137 /*** file scope functions ************************************************************************/
 138 
 139 /** Stop MC main dialog and the current dialog if it exists.
 140   * Needed to provide fast exit from MC viewer or editor on shell exit */
 141 static void
 142 stop_dialogs (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 143 {
 144     dlg_stop (midnight_dlg);
 145 
 146     if (top_dlg != NULL)
 147         dlg_stop (DIALOG (top_dlg->data));
 148 }
 149 
 150 /* --------------------------------------------------------------------------------------------- */
 151 
 152 static void
 153 treebox_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 154 {
 155     char *sel_dir;
 156 
 157     sel_dir = tree_box (selection (current_panel)->fname);
 158     if (sel_dir != NULL)
 159     {
 160         vfs_path_t *sel_vdir;
 161 
 162         sel_vdir = vfs_path_from_str (sel_dir);
 163         do_cd (sel_vdir, cd_exact);
 164         vfs_path_free (sel_vdir);
 165         g_free (sel_dir);
 166     }
 167 }
 168 
 169 /* --------------------------------------------------------------------------------------------- */
 170 
 171 #ifdef LISTMODE_EDITOR
 172 static void
 173 listmode_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 174 {
 175     char *newmode;
 176 
 177     if (get_current_type () != view_listing)
 178         return;
 179 
 180     newmode = listmode_edit (current_panel->user_format);
 181     if (!newmode)
 182         return;
 183 
 184     g_free (current_panel->user_format);
 185     current_panel->list_format = list_user;
 186     current_panel->user_format = newmode;
 187     set_panel_formats (current_panel);
 188 
 189     do_refresh ();
 190 }
 191 #endif /* LISTMODE_EDITOR */
 192 
 193 /* --------------------------------------------------------------------------------------------- */
 194 
 195 static GList *
 196 create_panel_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 197 {
 198     GList *entries = NULL;
 199 
 200     entries = g_list_prepend (entries, menu_entry_create (_("File listin&g"), CK_PanelListing));
 201     entries = g_list_prepend (entries, menu_entry_create (_("&Quick view"), CK_PanelQuickView));
 202     entries = g_list_prepend (entries, menu_entry_create (_("&Info"), CK_PanelInfo));
 203     entries = g_list_prepend (entries, menu_entry_create (_("&Tree"), CK_PanelTree));
 204     entries = g_list_prepend (entries, menu_separator_create ());
 205     entries =
 206         g_list_prepend (entries,
 207                         menu_entry_create (_("&Listing format..."), CK_SetupListingFormat));
 208     entries = g_list_prepend (entries, menu_entry_create (_("&Sort order..."), CK_Sort));
 209     entries = g_list_prepend (entries, menu_entry_create (_("&Filter..."), CK_Filter));
 210 #ifdef HAVE_CHARSET
 211     entries = g_list_prepend (entries, menu_entry_create (_("&Encoding..."), CK_SelectCodepage));
 212 #endif
 213     entries = g_list_prepend (entries, menu_separator_create ());
 214 #ifdef ENABLE_VFS_FTP
 215     entries = g_list_prepend (entries, menu_entry_create (_("FT&P link..."), CK_ConnectFtp));
 216 #endif
 217 #ifdef ENABLE_VFS_FISH
 218     entries = g_list_prepend (entries, menu_entry_create (_("S&hell link..."), CK_ConnectFish));
 219 #endif
 220 #ifdef ENABLE_VFS_SFTP
 221     entries = g_list_prepend (entries, menu_entry_create (_("S&FTP link..."), CK_ConnectSftp));
 222 #endif
 223 #ifdef ENABLE_VFS_SMB
 224     entries = g_list_prepend (entries, menu_entry_create (_("SM&B link..."), CK_ConnectSmb));
 225 #endif
 226     entries = g_list_prepend (entries, menu_entry_create (_("Paneli&ze"), CK_Panelize));
 227     entries = g_list_prepend (entries, menu_separator_create ());
 228     entries = g_list_prepend (entries, menu_entry_create (_("&Rescan"), CK_Reread));
 229 
 230     return g_list_reverse (entries);
 231 }
 232 
 233 /* --------------------------------------------------------------------------------------------- */
 234 
 235 static GList *
 236 create_file_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 237 {
 238     GList *entries = NULL;
 239 
 240     entries = g_list_prepend (entries, menu_entry_create (_("&View"), CK_View));
 241     entries = g_list_prepend (entries, menu_entry_create (_("Vie&w file..."), CK_ViewFile));
 242     entries = g_list_prepend (entries, menu_entry_create (_("&Filtered view"), CK_ViewFiltered));
 243     entries = g_list_prepend (entries, menu_entry_create (_("&Edit"), CK_Edit));
 244     entries = g_list_prepend (entries, menu_entry_create (_("&Copy"), CK_Copy));
 245     entries = g_list_prepend (entries, menu_entry_create (_("C&hmod"), CK_ChangeMode));
 246     entries = g_list_prepend (entries, menu_entry_create (_("&Link"), CK_Link));
 247     entries = g_list_prepend (entries, menu_entry_create (_("&Symlink"), CK_LinkSymbolic));
 248     entries =
 249         g_list_prepend (entries,
 250                         menu_entry_create (_("Relative symlin&k"), CK_LinkSymbolicRelative));
 251     entries = g_list_prepend (entries, menu_entry_create (_("Edit s&ymlink"), CK_LinkSymbolicEdit));
 252     entries = g_list_prepend (entries, menu_entry_create (_("Ch&own"), CK_ChangeOwn));
 253     entries =
 254         g_list_prepend (entries, menu_entry_create (_("&Advanced chown"), CK_ChangeOwnAdvanced));
 255     entries = g_list_prepend (entries, menu_entry_create (_("&Rename/Move"), CK_Move));
 256     entries = g_list_prepend (entries, menu_entry_create (_("&Mkdir"), CK_MakeDir));
 257     entries = g_list_prepend (entries, menu_entry_create (_("&Delete"), CK_Delete));
 258     entries = g_list_prepend (entries, menu_entry_create (_("&Quick cd"), CK_CdQuick));
 259     entries = g_list_prepend (entries, menu_separator_create ());
 260     entries = g_list_prepend (entries, menu_entry_create (_("Select &group"), CK_Select));
 261     entries = g_list_prepend (entries, menu_entry_create (_("U&nselect group"), CK_Unselect));
 262     entries = g_list_prepend (entries, menu_entry_create (_("&Invert selection"), CK_SelectInvert));
 263     entries = g_list_prepend (entries, menu_separator_create ());
 264     entries = g_list_prepend (entries, menu_entry_create (_("E&xit"), CK_Quit));
 265 
 266     return g_list_reverse (entries);
 267 }
 268 
 269 /* --------------------------------------------------------------------------------------------- */
 270 
 271 static GList *
 272 create_command_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 273 {
 274     /* I know, I'm lazy, but the tree widget when it's not running
 275      * as a panel still has some problems, I have not yet finished
 276      * the WTree widget port, sorry.
 277      */
 278     GList *entries = NULL;
 279 
 280     entries = g_list_prepend (entries, menu_entry_create (_("&User menu"), CK_UserMenu));
 281     entries = g_list_prepend (entries, menu_entry_create (_("&Directory tree"), CK_Tree));
 282     entries = g_list_prepend (entries, menu_entry_create (_("&Find file"), CK_Find));
 283     entries = g_list_prepend (entries, menu_entry_create (_("S&wap panels"), CK_Swap));
 284     entries = g_list_prepend (entries, menu_entry_create (_("Switch &panels on/off"), CK_Shell));
 285     entries =
 286         g_list_prepend (entries, menu_entry_create (_("&Compare directories"), CK_CompareDirs));
 287 #ifdef USE_DIFF_VIEW
 288     entries = g_list_prepend (entries, menu_entry_create (_("C&ompare files"), CK_CompareFiles));
 289 #endif
 290     entries =
 291         g_list_prepend (entries, menu_entry_create (_("E&xternal panelize"), CK_ExternalPanelize));
 292     entries = g_list_prepend (entries, menu_entry_create (_("Show directory s&izes"), CK_DirSize));
 293     entries = g_list_prepend (entries, menu_separator_create ());
 294     entries = g_list_prepend (entries, menu_entry_create (_("Command &history"), CK_History));
 295     entries =
 296         g_list_prepend (entries,
 297                         menu_entry_create (_("Viewed/edited files hi&story"),
 298                                            CK_EditorViewerHistory));
 299     entries = g_list_prepend (entries, menu_entry_create (_("Di&rectory hotlist"), CK_HotList));
 300 #ifdef ENABLE_VFS
 301     entries = g_list_prepend (entries, menu_entry_create (_("&Active VFS list"), CK_VfsList));
 302 #endif
 303 #ifdef ENABLE_BACKGROUND
 304     entries = g_list_prepend (entries, menu_entry_create (_("&Background jobs"), CK_Jobs));
 305 #endif
 306     entries = g_list_prepend (entries, menu_entry_create (_("Screen lis&t"), CK_ScreenList));
 307     entries = g_list_prepend (entries, menu_separator_create ());
 308 #ifdef ENABLE_VFS_UNDELFS
 309     entries =
 310         g_list_prepend (entries,
 311                         menu_entry_create (_("&Undelete files (ext2fs only)"), CK_Undelete));
 312 #endif
 313 #ifdef LISTMODE_EDITOR
 314     entries = g_list_prepend (entries, menu_entry_create (_("&Listing format edit"), CK_ListMode));
 315 #endif
 316 #if defined (ENABLE_VFS_UNDELFS) || defined (LISTMODE_EDITOR)
 317     entries = g_list_prepend (entries, menu_separator_create ());
 318 #endif
 319     entries =
 320         g_list_prepend (entries,
 321                         menu_entry_create (_("Edit &extension file"), CK_EditExtensionsFile));
 322     entries = g_list_prepend (entries, menu_entry_create (_("Edit &menu file"), CK_EditUserMenu));
 323     entries =
 324         g_list_prepend (entries,
 325                         menu_entry_create (_("Edit hi&ghlighting group file"),
 326                                            CK_EditFileHighlightFile));
 327 
 328     return g_list_reverse (entries);
 329 }
 330 
 331 /* --------------------------------------------------------------------------------------------- */
 332 
 333 static GList *
 334 create_options_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 335 {
 336     GList *entries = NULL;
 337 
 338     entries = g_list_prepend (entries, menu_entry_create (_("&Configuration..."), CK_Options));
 339     entries = g_list_prepend (entries, menu_entry_create (_("&Layout..."), CK_OptionsLayout));
 340     entries = g_list_prepend (entries, menu_entry_create (_("&Panel options..."), CK_OptionsPanel));
 341     entries =
 342         g_list_prepend (entries, menu_entry_create (_("C&onfirmation..."), CK_OptionsConfirm));
 343     entries =
 344         g_list_prepend (entries, menu_entry_create (_("&Appearance..."), CK_OptionsAppearance));
 345     entries =
 346         g_list_prepend (entries, menu_entry_create (_("&Display bits..."), CK_OptionsDisplayBits));
 347     entries = g_list_prepend (entries, menu_entry_create (_("Learn &keys..."), CK_LearnKeys));
 348 #ifdef ENABLE_VFS
 349     entries = g_list_prepend (entries, menu_entry_create (_("&Virtual FS..."), CK_OptionsVfs));
 350 #endif
 351     entries = g_list_prepend (entries, menu_separator_create ());
 352     entries = g_list_prepend (entries, menu_entry_create (_("&Save setup"), CK_SaveSetup));
 353 
 354     return g_list_reverse (entries);
 355 }
 356 
 357 /* --------------------------------------------------------------------------------------------- */
 358 
 359 static void
 360 init_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 361 {
 362     left_menu = create_menu ("", create_panel_menu (), "[Left and Right Menus]");
 363     menubar_add_menu (the_menubar, left_menu);
 364     menubar_add_menu (the_menubar, create_menu (_("&File"), create_file_menu (), "[File Menu]"));
 365     menubar_add_menu (the_menubar,
 366                       create_menu (_("&Command"), create_command_menu (), "[Command Menu]"));
 367     menubar_add_menu (the_menubar,
 368                       create_menu (_("&Options"), create_options_menu (), "[Options Menu]"));
 369     right_menu = create_menu ("", create_panel_menu (), "[Left and Right Menus]");
 370     menubar_add_menu (the_menubar, right_menu);
 371     update_menu ();
 372 }
 373 
 374 /* --------------------------------------------------------------------------------------------- */
 375 
 376 static void
 377 menu_last_selected_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 378 {
 379     menubar_activate (the_menubar, drop_menus, -1);
 380 }
 381 
 382 /* --------------------------------------------------------------------------------------------- */
 383 
 384 static void
 385 menu_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 386 {
 387     int selected;
 388 
 389     if ((get_current_index () == 0) == (current_panel->active != 0))
 390         selected = 0;
 391     else
 392         selected = g_list_length (the_menubar->menu) - 1;
 393 
 394     menubar_activate (the_menubar, drop_menus, selected);
 395 }
 396 
 397 /* --------------------------------------------------------------------------------------------- */
 398 
 399 static void
 400 sort_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 401 {
 402     WPanel *p;
 403     const panel_field_t *sort_order;
 404 
 405     if (!SELECTED_IS_PANEL)
 406         return;
 407 
 408     p = MENU_PANEL;
 409     sort_order = sort_box (&p->sort_info, p->sort_field);
 410     panel_set_sort_order (p, sort_order);
 411 }
 412 
 413 /* --------------------------------------------------------------------------------------------- */
 414 
 415 static char *
 416 midnight_get_shortcut (long command)
     /* [previous][next][first][last][top][bottom][index][help]  */
 417 {
 418     const char *ext_map;
 419     const char *shortcut = NULL;
 420 
 421     shortcut = keybind_lookup_keymap_shortcut (main_map, command);
 422     if (shortcut != NULL)
 423         return g_strdup (shortcut);
 424 
 425     shortcut = keybind_lookup_keymap_shortcut (panel_map, command);
 426     if (shortcut != NULL)
 427         return g_strdup (shortcut);
 428 
 429     ext_map = keybind_lookup_keymap_shortcut (main_map, CK_ExtendedKeyMap);
 430     if (ext_map != NULL)
 431         shortcut = keybind_lookup_keymap_shortcut (main_x_map, command);
 432     if (shortcut != NULL)
 433         return g_strdup_printf ("%s %s", ext_map, shortcut);
 434 
 435     return NULL;
 436 }
 437 
 438 /* --------------------------------------------------------------------------------------------- */
 439 
 440 static char *
 441 midnight_get_title (const WDialog * h, size_t len)
     /* [previous][next][first][last][top][bottom][index][help]  */
 442 {
 443     char *path;
 444     char *login;
 445     char *p;
 446 
 447     (void) h;
 448 
 449     title_path_prepare (&path, &login);
 450 
 451     p = g_strdup_printf ("%s [%s]:%s", _("Panels:"), login, path);
 452     g_free (path);
 453     g_free (login);
 454     path = g_strdup (str_trunc (p, len - 4));
 455     g_free (p);
 456 
 457     return path;
 458 }
 459 
 460 /* --------------------------------------------------------------------------------------------- */
 461 
 462 static void
 463 toggle_panels_split (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 464 {
 465     panels_layout.horizontal_split = !panels_layout.horizontal_split;
 466     layout_change ();
 467     do_refresh ();
 468 }
 469 
 470 /* --------------------------------------------------------------------------------------------- */
 471 
 472 #ifdef ENABLE_VFS
 473 /* event helper */
 474 static gboolean
 475 check_panel_timestamp (const WPanel * panel, panel_view_mode_t mode, struct vfs_class *vclass,
     /* [previous][next][first][last][top][bottom][index][help]  */
 476                        vfsid id)
 477 {
 478     if (mode == view_listing)
 479     {
 480         const vfs_path_element_t *path_element;
 481 
 482         path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
 483 
 484         if (path_element->class != vclass)
 485             return FALSE;
 486 
 487         if (vfs_getid (panel->cwd_vpath) != id)
 488             return FALSE;
 489     }
 490     return TRUE;
 491 }
 492 
 493 /* --------------------------------------------------------------------------------------------- */
 494 
 495 /* event callback */
 496 static gboolean
 497 check_current_panel_timestamp (const gchar * event_group_name, const gchar * event_name,
     /* [previous][next][first][last][top][bottom][index][help]  */
 498                                gpointer init_data, gpointer data)
 499 {
 500     ev_vfs_stamp_create_t *event_data = (ev_vfs_stamp_create_t *) data;
 501 
 502     (void) event_group_name;
 503     (void) event_name;
 504     (void) init_data;
 505 
 506     event_data->ret =
 507         check_panel_timestamp (current_panel, get_current_type (), event_data->vclass,
 508                                event_data->id);
 509     return !event_data->ret;
 510 }
 511 
 512 /* --------------------------------------------------------------------------------------------- */
 513 
 514 /* event callback */
 515 static gboolean
 516 check_other_panel_timestamp (const gchar * event_group_name, const gchar * event_name,
     /* [previous][next][first][last][top][bottom][index][help]  */
 517                              gpointer init_data, gpointer data)
 518 {
 519     ev_vfs_stamp_create_t *event_data = (ev_vfs_stamp_create_t *) data;
 520 
 521     (void) event_group_name;
 522     (void) event_name;
 523     (void) init_data;
 524 
 525     event_data->ret =
 526         check_panel_timestamp (other_panel, get_other_type (), event_data->vclass, event_data->id);
 527     return !event_data->ret;
 528 }
 529 #endif /* ENABLE_VFS */
 530 
 531 /* --------------------------------------------------------------------------------------------- */
 532 
 533 /* event callback */
 534 static gboolean
 535 print_vfs_message (const gchar * event_group_name, const gchar * event_name,
     /* [previous][next][first][last][top][bottom][index][help]  */
 536                    gpointer init_data, gpointer data)
 537 {
 538     ev_vfs_print_message_t *event_data = (ev_vfs_print_message_t *) data;
 539 
 540     (void) event_group_name;
 541     (void) event_name;
 542     (void) init_data;
 543 
 544     if (mc_global.midnight_shutdown)
 545         goto ret;
 546 
 547     if (!mc_global.message_visible || the_hint == NULL || WIDGET (the_hint)->owner == NULL)
 548     {
 549         int col, row;
 550 
 551         if (!nice_rotating_dash || (ok_to_refresh <= 0))
 552             goto ret;
 553 
 554         /* Preserve current cursor position */
 555         tty_getyx (&row, &col);
 556 
 557         tty_gotoyx (0, 0);
 558         tty_setcolor (NORMAL_COLOR);
 559         tty_print_string (str_fit_to_term (event_data->msg, COLS - 1, J_LEFT));
 560 
 561         /* Restore cursor position */
 562         tty_gotoyx (row, col);
 563         mc_refresh ();
 564         goto ret;
 565     }
 566 
 567     if (mc_global.message_visible)
 568         set_hintbar (event_data->msg);
 569 
 570   ret:
 571     MC_PTR_FREE (event_data->msg);
 572     return TRUE;
 573 }
 574 
 575 /* --------------------------------------------------------------------------------------------- */
 576 
 577 static void
 578 create_panels (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 579 {
 580     int current_index, other_index;
 581     panel_view_mode_t current_mode, other_mode;
 582     char *current_dir, *other_dir;
 583     vfs_path_t *original_dir;
 584 
 585     /*
 586      * Following cases from command line are possible:
 587      * 'mc' (no arguments):            mc_run_param0 == NULL, mc_run_param1 == NULL
 588      *                                 active panel uses current directory
 589      *                                 passive panel uses "other_dir" from panels.ini
 590      *
 591      * 'mc dir1 dir2' (two arguments): mc_run_param0 != NULL, mc_run_param1 != NULL
 592      *                                 active panel uses mc_run_param0
 593      *                                 passive panel uses mc_run_param1
 594      *
 595      * 'mc dir1' (single argument):    mc_run_param0 != NULL, mc_run_param1 == NULL
 596      *                                 active panel uses mc_run_param0
 597      *                                 passive panel uses "other_dir" from panels.ini
 598      */
 599 
 600     /* Set up panel directories */
 601     if (boot_current_is_left)
 602     {
 603         /* left panel is active */
 604         current_index = 0;
 605         other_index = 1;
 606         current_mode = startup_left_mode;
 607         other_mode = startup_right_mode;
 608 
 609         if (mc_run_param0 == NULL && mc_run_param1 == NULL)
 610         {
 611             /* no arguments */
 612             current_dir = NULL; /* assume current dir */
 613             other_dir = saved_other_dir;        /* from ini */
 614         }
 615         else if (mc_run_param0 != NULL && mc_run_param1 != NULL)
 616         {
 617             /* two arguments */
 618             current_dir = (char *) mc_run_param0;
 619             other_dir = mc_run_param1;
 620         }
 621         else                    /* mc_run_param0 != NULL && mc_run_param1 == NULL */
 622         {
 623             /* one argument */
 624             current_dir = (char *) mc_run_param0;
 625             other_dir = saved_other_dir;        /* from ini */
 626         }
 627     }
 628     else
 629     {
 630         /* right panel is active */
 631         current_index = 1;
 632         other_index = 0;
 633         current_mode = startup_right_mode;
 634         other_mode = startup_left_mode;
 635 
 636         if (mc_run_param0 == NULL && mc_run_param1 == NULL)
 637         {
 638             /* no arguments */
 639             current_dir = NULL; /* assume current dir */
 640             other_dir = saved_other_dir;        /* from ini */
 641         }
 642         else if (mc_run_param0 != NULL && mc_run_param1 != NULL)
 643         {
 644             /* two arguments */
 645             current_dir = (char *) mc_run_param0;
 646             other_dir = mc_run_param1;
 647         }
 648         else                    /* mc_run_param0 != NULL && mc_run_param1 == NULL */
 649         {
 650             /* one argument */
 651             current_dir = (char *) mc_run_param0;
 652             other_dir = saved_other_dir;        /* from ini */
 653         }
 654     }
 655 
 656     /* 1. Get current dir */
 657     original_dir = vfs_path_clone (vfs_get_raw_current_dir ());
 658 
 659     /* 2. Create passive panel */
 660     if (other_dir != NULL)
 661     {
 662         vfs_path_t *vpath;
 663 
 664         if (g_path_is_absolute (other_dir))
 665             vpath = vfs_path_from_str (other_dir);
 666         else
 667             vpath = vfs_path_append_new (original_dir, other_dir, (char *) NULL);
 668         mc_chdir (vpath);
 669         vfs_path_free (vpath);
 670     }
 671     create_panel (other_index, other_mode);
 672 
 673     /* 3. Create active panel */
 674     if (current_dir == NULL)
 675         mc_chdir (original_dir);
 676     else
 677     {
 678         vfs_path_t *vpath;
 679 
 680         if (g_path_is_absolute (current_dir))
 681             vpath = vfs_path_from_str (current_dir);
 682         else
 683             vpath = vfs_path_append_new (original_dir, current_dir, (char *) NULL);
 684         mc_chdir (vpath);
 685         vfs_path_free (vpath);
 686     }
 687     create_panel (current_index, current_mode);
 688 
 689     if (startup_left_mode == view_listing)
 690         current_panel = left_panel;
 691     else if (right_panel != NULL)
 692         current_panel = right_panel;
 693     else
 694         current_panel = left_panel;
 695 
 696     vfs_path_free (original_dir);
 697 
 698 #ifdef ENABLE_VFS
 699     mc_event_add (MCEVENT_GROUP_CORE, "vfs_timestamp", check_other_panel_timestamp, NULL, NULL);
 700     mc_event_add (MCEVENT_GROUP_CORE, "vfs_timestamp", check_current_panel_timestamp, NULL, NULL);
 701 #endif /* ENABLE_VFS */
 702 
 703     mc_event_add (MCEVENT_GROUP_CORE, "vfs_print_message", print_vfs_message, NULL, NULL);
 704 }
 705 
 706 /* --------------------------------------------------------------------------------------------- */
 707 
 708 static void
 709 midnight_put_panel_path (WPanel * panel)
     /* [previous][next][first][last][top][bottom][index][help]  */
 710 {
 711     vfs_path_t *cwd_vpath;
 712     const char *cwd_vpath_str;
 713 
 714     if (!command_prompt)
 715         return;
 716 
 717 #ifdef HAVE_CHARSET
 718     cwd_vpath = remove_encoding_from_path (panel->cwd_vpath);
 719 #else
 720     cwd_vpath = vfs_path_clone (panel->cwd_vpath);
 721 #endif
 722 
 723     cwd_vpath_str = vfs_path_as_str (cwd_vpath);
 724 
 725     command_insert (cmdline, cwd_vpath_str, FALSE);
 726 
 727     if (!IS_PATH_SEP (cwd_vpath_str[strlen (cwd_vpath_str) - 1]))
 728         command_insert (cmdline, PATH_SEP_STR, FALSE);
 729 
 730     vfs_path_free (cwd_vpath);
 731 }
 732 
 733 /* --------------------------------------------------------------------------------------------- */
 734 
 735 static void
 736 put_link (WPanel * panel)
     /* [previous][next][first][last][top][bottom][index][help]  */
 737 {
 738     if (!command_prompt)
 739         return;
 740     if (S_ISLNK (selection (panel)->st.st_mode))
 741     {
 742         char buffer[MC_MAXPATHLEN];
 743         vfs_path_t *vpath;
 744         int i;
 745 
 746         vpath = vfs_path_append_new (panel->cwd_vpath, selection (panel)->fname, (char *) NULL);
 747         i = mc_readlink (vpath, buffer, sizeof (buffer) - 1);
 748         vfs_path_free (vpath);
 749 
 750         if (i > 0)
 751         {
 752             buffer[i] = '\0';
 753             command_insert (cmdline, buffer, TRUE);
 754         }
 755     }
 756 }
 757 
 758 /* --------------------------------------------------------------------------------------------- */
 759 
 760 static void
 761 put_current_link (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 762 {
 763     put_link (current_panel);
 764 }
 765 
 766 /* --------------------------------------------------------------------------------------------- */
 767 
 768 static void
 769 put_other_link (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 770 {
 771     if (get_other_type () == view_listing)
 772         put_link (other_panel);
 773 }
 774 
 775 /* --------------------------------------------------------------------------------------------- */
 776 
 777 /** Insert the selected file name into the input line */
 778 static void
 779 put_current_selected (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 780 {
 781     const char *tmp;
 782 
 783     if (!command_prompt)
 784         return;
 785 
 786     if (get_current_type () == view_tree)
 787     {
 788         WTree *tree;
 789         const vfs_path_t *selected_name;
 790 
 791         tree = (WTree *) get_panel_widget (get_current_index ());
 792         selected_name = tree_selected_name (tree);
 793         tmp = vfs_path_as_str (selected_name);
 794     }
 795     else
 796         tmp = selection (current_panel)->fname;
 797 
 798     command_insert (cmdline, tmp, TRUE);
 799 }
 800 
 801 /* --------------------------------------------------------------------------------------------- */
 802 
 803 static void
 804 put_tagged (WPanel * panel)
     /* [previous][next][first][last][top][bottom][index][help]  */
 805 {
 806     if (!command_prompt)
 807         return;
 808     input_disable_update (cmdline);
 809     if (panel->marked)
 810     {
 811         int i;
 812 
 813         for (i = 0; i < panel->dir.len; i++)
 814         {
 815             if (panel->dir.list[i].f.marked)
 816                 command_insert (cmdline, panel->dir.list[i].fname, TRUE);
 817         }
 818     }
 819     else
 820     {
 821         command_insert (cmdline, panel->dir.list[panel->selected].fname, TRUE);
 822     }
 823     input_enable_update (cmdline);
 824 }
 825 
 826 /* --------------------------------------------------------------------------------------------- */
 827 
 828 static void
 829 put_current_tagged (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 830 {
 831     put_tagged (current_panel);
 832 }
 833 
 834 /* --------------------------------------------------------------------------------------------- */
 835 
 836 static void
 837 put_other_tagged (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 838 {
 839     if (get_other_type () == view_listing)
 840         put_tagged (other_panel);
 841 }
 842 
 843 /* --------------------------------------------------------------------------------------------- */
 844 
 845 static void
 846 ctl_x_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 847 {
 848     ctl_x_map_enabled = TRUE;
 849 }
 850 
 851 /* --------------------------------------------------------------------------------------------- */
 852 
 853 static void
 854 setup_mc (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 855 {
 856 #ifdef HAVE_SLANG
 857 #ifdef HAVE_CHARSET
 858     tty_display_8bit (TRUE);
 859 #else
 860     tty_display_8bit (mc_global.full_eight_bits);
 861 #endif /* HAVE_CHARSET */
 862 
 863 #else /* HAVE_SLANG */
 864 
 865 #ifdef HAVE_CHARSET
 866     tty_display_8bit (TRUE);
 867 #else
 868     tty_display_8bit (mc_global.eight_bit_clean);
 869 #endif /* HAVE_CHARSET */
 870 #endif /* HAVE_SLANG */
 871 
 872 #ifdef ENABLE_SUBSHELL
 873     if (mc_global.tty.use_subshell)
 874         add_select_channel (mc_global.tty.subshell_pty, load_prompt, NULL);
 875 #endif /* !ENABLE_SUBSHELL */
 876 
 877     if ((tty_baudrate () < 9600) || mc_global.tty.slow_terminal)
 878         verbose = FALSE;
 879 }
 880 
 881 /* --------------------------------------------------------------------------------------------- */
 882 
 883 static void
 884 setup_dummy_mc (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 885 {
 886     vfs_path_t *vpath;
 887     char *d;
 888     int ret;
 889 
 890     d = _vfs_get_cwd ();
 891     setup_mc ();
 892     vpath = vfs_path_from_str (d);
 893     ret = mc_chdir (vpath);
 894     (void) ret;
 895     vfs_path_free (vpath);
 896     g_free (d);
 897 }
 898 
 899 /* --------------------------------------------------------------------------------------------- */
 900 
 901 static void
 902 done_mc (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 903 {
 904     /* Setup shutdown
 905      *
 906      * We sync the profiles since the hotlist may have changed, while
 907      * we only change the setup data if we have the auto save feature set
 908      */
 909 
 910     save_setup (auto_save_setup, panels_options.auto_save_setup);
 911 
 912     vfs_stamp_path (vfs_get_raw_current_dir ());
 913 }
 914 
 915 /* --------------------------------------------------------------------------------------------- */
 916 
 917 static void
 918 create_file_manager (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 919 {
 920     midnight_dlg->get_shortcut = midnight_get_shortcut;
 921     midnight_dlg->get_title = midnight_get_title;
 922     /* allow rebind tab */
 923     widget_want_tab (WIDGET (midnight_dlg), TRUE);
 924 
 925     the_menubar = menubar_new (NULL, menubar_visible);
 926     add_widget (midnight_dlg, the_menubar);
 927     init_menu ();
 928 
 929     create_panels ();
 930     add_widget (midnight_dlg, get_panel_widget (0));
 931     add_widget (midnight_dlg, get_panel_widget (1));
 932 
 933     the_hint = label_new (0, 0, 0);
 934     the_hint->transparent = TRUE;
 935     the_hint->auto_adjust_cols = 0;
 936     WIDGET (the_hint)->cols = COLS;
 937     add_widget (midnight_dlg, the_hint);
 938 
 939     cmdline = command_new (0, 0, 0);
 940     add_widget (midnight_dlg, cmdline);
 941 
 942     the_prompt = label_new (0, 0, mc_prompt);
 943     the_prompt->transparent = TRUE;
 944     add_widget (midnight_dlg, the_prompt);
 945 
 946     the_bar = buttonbar_new (mc_global.keybar_visible);
 947     add_widget (midnight_dlg, the_bar);
 948     midnight_set_buttonbar (the_bar);
 949 }
 950 
 951 /* --------------------------------------------------------------------------------------------- */
 952 
 953 /** result must be free'd (I think this should go in util.c) */
 954 static vfs_path_t *
 955 prepend_cwd_on_local (const char *filename)
     /* [previous][next][first][last][top][bottom][index][help]  */
 956 {
 957     vfs_path_t *vpath;
 958 
 959     vpath = vfs_path_from_str (filename);
 960     if (!vfs_file_is_local (vpath) || g_path_is_absolute (filename))
 961         return vpath;
 962 
 963     vfs_path_free (vpath);
 964 
 965     return vfs_path_append_new (vfs_get_raw_current_dir (), filename, (char *) NULL);
 966 }
 967 
 968 /* --------------------------------------------------------------------------------------------- */
 969 
 970 /** Invoke the internal view/edit routine with:
 971  * the default processing and forcing the internal viewer/editor
 972  */
 973 static gboolean
 974 mc_maybe_editor_or_viewer (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 975 {
 976     gboolean ret;
 977 
 978     switch (mc_global.mc_run_mode)
 979     {
 980 #ifdef USE_INTERNAL_EDIT
 981     case MC_RUN_EDITOR:
 982         ret = edit_files ((GList *) mc_run_param0);
 983         break;
 984 #endif /* USE_INTERNAL_EDIT */
 985     case MC_RUN_VIEWER:
 986         {
 987             vfs_path_t *vpath = NULL;
 988 
 989             if (mc_run_param0 != NULL && *(char *) mc_run_param0 != '\0')
 990                 vpath = prepend_cwd_on_local ((char *) mc_run_param0);
 991 
 992             ret = view_file (vpath, FALSE, TRUE);
 993             vfs_path_free (vpath);
 994             break;
 995         }
 996 #ifdef USE_DIFF_VIEW
 997     case MC_RUN_DIFFVIEWER:
 998         ret = dview_diff_cmd (mc_run_param0, mc_run_param1);
 999         break;
1000 #endif /* USE_DIFF_VIEW */
1001     default:
1002         ret = FALSE;
1003     }
1004 
1005     return ret;
1006 }
1007 
1008 /* --------------------------------------------------------------------------------------------- */
1009 
1010 static void
1011 show_editor_viewer_history (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1012 {
1013     char *s;
1014     int act;
1015 
1016     s = show_file_history (WIDGET (midnight_dlg), &act);
1017     if (s != NULL)
1018     {
1019         vfs_path_t *s_vpath;
1020 
1021         switch (act)
1022         {
1023         case CK_Edit:
1024             s_vpath = vfs_path_from_str (s);
1025             edit_file_at_line (s_vpath, use_internal_edit, 0);
1026             break;
1027 
1028         case CK_View:
1029             s_vpath = vfs_path_from_str (s);
1030             view_file (s_vpath, use_internal_view, 0);
1031             break;
1032 
1033         default:
1034             {
1035                 char *d;
1036 
1037                 d = g_path_get_dirname (s);
1038                 s_vpath = vfs_path_from_str (d);
1039                 do_cd (s_vpath, cd_exact);
1040                 try_to_select (current_panel, s);
1041                 g_free (d);
1042             }
1043         }
1044 
1045         g_free (s);
1046         vfs_path_free (s_vpath);
1047     }
1048 }
1049 
1050 /* --------------------------------------------------------------------------------------------- */
1051 
1052 static gboolean
1053 quit_cmd_internal (int quiet)
     /* [previous][next][first][last][top][bottom][index][help]  */
1054 {
1055     int q = quit;
1056     size_t n;
1057 
1058     n = dialog_switch_num () - 1;
1059     if (n != 0)
1060     {
1061         char msg[BUF_MEDIUM];
1062 
1063         g_snprintf (msg, sizeof (msg),
1064                     ngettext ("You have %zu opened screen. Quit anyway?",
1065                               "You have %zu opened screens. Quit anyway?", n), n);
1066 
1067         if (query_dialog (_("The Midnight Commander"), msg, D_NORMAL, 2, _("&Yes"), _("&No")) != 0)
1068             return FALSE;
1069         q = 1;
1070     }
1071     else if (quiet || !confirm_exit)
1072         q = 1;
1073     else if (query_dialog (_("The Midnight Commander"),
1074                            _("Do you really want to quit the Midnight Commander?"),
1075                            D_NORMAL, 2, _("&Yes"), _("&No")) == 0)
1076         q = 1;
1077 
1078     if (q != 0)
1079     {
1080 #ifdef ENABLE_SUBSHELL
1081         if (!mc_global.tty.use_subshell)
1082             stop_dialogs ();
1083         else if ((q = exit_subshell ()? 1 : 0) != 0)
1084 #endif
1085             stop_dialogs ();
1086     }
1087 
1088     if (q != 0)
1089         quit |= 1;
1090     return (quit != 0);
1091 }
1092 
1093 /* --------------------------------------------------------------------------------------------- */
1094 
1095 static gboolean
1096 quit_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1097 {
1098     return quit_cmd_internal (0);
1099 }
1100 
1101 /* --------------------------------------------------------------------------------------------- */
1102 
1103 /**
1104  * Repaint the contents of the panels without frames.  To schedule panel
1105  * for repainting, set panel->dirty to 1.  There are many reasons why
1106  * the panels need to be repainted, and this is a costly operation, so
1107  * it's done once per event.
1108  */
1109 
1110 static void
1111 update_dirty_panels (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1112 {
1113     if (get_current_type () == view_listing && current_panel->dirty)
1114         widget_redraw (WIDGET (current_panel));
1115 
1116     if (get_other_type () == view_listing && other_panel->dirty)
1117         widget_redraw (WIDGET (other_panel));
1118 }
1119 
1120 /* --------------------------------------------------------------------------------------------- */
1121 
1122 static void
1123 toggle_show_hidden (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1124 {
1125     panels_options.show_dot_files = !panels_options.show_dot_files;
1126     update_panels (UP_RELOAD, UP_KEEPSEL);
1127     /* redraw panels forced */
1128     update_dirty_panels ();
1129 }
1130 
1131 /* --------------------------------------------------------------------------------------------- */
1132 
1133 static cb_ret_t
1134 midnight_execute_cmd (Widget * sender, long command)
     /* [previous][next][first][last][top][bottom][index][help]  */
1135 {
1136     cb_ret_t res = MSG_HANDLED;
1137 
1138     (void) sender;
1139 
1140     /* stop quick search before executing any command */
1141     send_message (current_panel, NULL, MSG_ACTION, CK_SearchStop, NULL);
1142 
1143     switch (command)
1144     {
1145     case CK_ChangePanel:
1146         change_panel ();
1147         break;
1148     case CK_HotListAdd:
1149         add2hotlist_cmd ();
1150         break;
1151     case CK_SetupListingFormat:
1152         setup_listing_format_cmd ();
1153         break;
1154     case CK_ChangeMode:
1155         chmod_cmd ();
1156         break;
1157     case CK_ChangeOwn:
1158         chown_cmd ();
1159         break;
1160     case CK_ChangeOwnAdvanced:
1161         advanced_chown_cmd ();
1162         break;
1163     case CK_CompareDirs:
1164         compare_dirs_cmd ();
1165         break;
1166     case CK_Options:
1167         configure_box ();
1168         break;
1169 #ifdef ENABLE_VFS
1170     case CK_OptionsVfs:
1171         configure_vfs_box ();
1172         break;
1173 #endif
1174     case CK_OptionsConfirm:
1175         confirm_box ();
1176         break;
1177     case CK_Copy:
1178         copy_cmd ();
1179         break;
1180     case CK_PutCurrentPath:
1181         midnight_put_panel_path (current_panel);
1182         break;
1183     case CK_PutCurrentSelected:
1184         put_current_selected ();
1185         break;
1186     case CK_PutCurrentFullSelected:
1187         midnight_put_panel_path (current_panel);
1188         put_current_selected ();
1189         break;
1190     case CK_PutCurrentLink:
1191         put_current_link ();
1192         break;
1193     case CK_PutCurrentTagged:
1194         put_current_tagged ();
1195         break;
1196     case CK_PutOtherPath:
1197         if (get_other_type () == view_listing)
1198             midnight_put_panel_path (other_panel);
1199         break;
1200     case CK_PutOtherLink:
1201         put_other_link ();
1202         break;
1203     case CK_PutOtherTagged:
1204         put_other_tagged ();
1205         break;
1206     case CK_Delete:
1207         delete_cmd ();
1208         break;
1209     case CK_ScreenList:
1210         dialog_switch_list ();
1211         break;
1212 #ifdef USE_DIFF_VIEW
1213     case CK_CompareFiles:
1214         diff_view_cmd ();
1215         break;
1216 #endif
1217     case CK_OptionsDisplayBits:
1218         display_bits_box ();
1219         break;
1220     case CK_Edit:
1221         edit_cmd ();
1222         break;
1223 #ifdef USE_INTERNAL_EDIT
1224     case CK_EditForceInternal:
1225         edit_cmd_force_internal ();
1226         break;
1227 #endif
1228     case CK_EditExtensionsFile:
1229         ext_cmd ();
1230         break;
1231     case CK_EditFileHighlightFile:
1232         edit_fhl_cmd ();
1233         break;
1234     case CK_EditUserMenu:
1235         edit_mc_menu_cmd ();
1236         break;
1237     case CK_LinkSymbolicEdit:
1238         edit_symlink_cmd ();
1239         break;
1240     case CK_ExternalPanelize:
1241         external_panelize ();
1242         break;
1243     case CK_Filter:
1244         filter_cmd ();
1245         break;
1246     case CK_ViewFiltered:
1247         view_filtered_cmd ();
1248         break;
1249     case CK_Find:
1250         find_cmd ();
1251         break;
1252 #ifdef ENABLE_VFS_FISH
1253     case CK_ConnectFish:
1254         fishlink_cmd ();
1255         break;
1256 #endif
1257 #ifdef ENABLE_VFS_FTP
1258     case CK_ConnectFtp:
1259         ftplink_cmd ();
1260         break;
1261 #endif
1262 #ifdef ENABLE_VFS_SFTP
1263     case CK_ConnectSftp:
1264         sftplink_cmd ();
1265         break;
1266 #endif
1267 #ifdef ENABLE_VFS_SMB
1268     case CK_ConnectSmb:
1269         smblink_cmd ();
1270         break;
1271 #endif /* ENABLE_VFS_SMB */
1272     case CK_Panelize:
1273         cd_panelize_cmd ();
1274         break;
1275     case CK_Help:
1276         help_cmd ();
1277         break;
1278     case CK_History:
1279         /* show the history of command line widget */
1280         send_message (cmdline, NULL, MSG_ACTION, CK_History, NULL);
1281         break;
1282     case CK_PanelInfo:
1283         if (sender == WIDGET (the_menubar))
1284             info_cmd ();        /* menu */
1285         else
1286             info_cmd_no_menu ();        /* shortcut or buttonbar */
1287         break;
1288 #ifdef ENABLE_BACKGROUND
1289     case CK_Jobs:
1290         jobs_box ();
1291         break;
1292 #endif
1293     case CK_OptionsLayout:
1294         layout_box ();
1295         break;
1296     case CK_OptionsAppearance:
1297         appearance_box ();
1298         break;
1299     case CK_LearnKeys:
1300         learn_keys ();
1301         break;
1302     case CK_Link:
1303         link_cmd (LINK_HARDLINK);
1304         break;
1305     case CK_PanelListing:
1306         listing_cmd ();
1307         break;
1308 #ifdef LISTMODE_EDITOR
1309     case CK_ListMode:
1310         listmode_cmd ();
1311         break;
1312 #endif
1313     case CK_Menu:
1314         menu_cmd ();
1315         break;
1316     case CK_MenuLastSelected:
1317         menu_last_selected_cmd ();
1318         break;
1319     case CK_MakeDir:
1320         mkdir_cmd ();
1321         break;
1322     case CK_OptionsPanel:
1323         panel_options_box ();
1324         break;
1325 #ifdef HAVE_CHARSET
1326     case CK_SelectCodepage:
1327         encoding_cmd ();
1328         break;
1329 #endif
1330     case CK_CdQuick:
1331         quick_cd_cmd ();
1332         break;
1333     case CK_HotList:
1334         hotlist_cmd ();
1335         break;
1336     case CK_PanelQuickView:
1337         if (sender == WIDGET (the_menubar))
1338             quick_view_cmd ();  /* menu */
1339         else
1340             quick_cmd_no_menu ();       /* shortcut or buttonabr */
1341         break;
1342     case CK_QuitQuiet:
1343         quiet_quit_cmd ();
1344         break;
1345     case CK_Quit:
1346         quit_cmd ();
1347         break;
1348     case CK_LinkSymbolicRelative:
1349         link_cmd (LINK_SYMLINK_RELATIVE);
1350         break;
1351     case CK_Move:
1352         rename_cmd ();
1353         break;
1354     case CK_Reread:
1355         reread_cmd ();
1356         break;
1357 #ifdef ENABLE_VFS
1358     case CK_VfsList:
1359         vfs_list ();
1360         break;
1361 #endif
1362     case CK_SaveSetup:
1363         save_setup_cmd ();
1364         break;
1365     case CK_Select:
1366     case CK_Unselect:
1367     case CK_SelectInvert:
1368         res = send_message (current_panel, midnight_dlg, MSG_ACTION, command, NULL);
1369         break;
1370     case CK_Shell:
1371         toggle_subshell ();
1372         break;
1373     case CK_DirSize:
1374         smart_dirsize_cmd ();
1375         break;
1376     case CK_Sort:
1377         sort_cmd ();
1378         break;
1379     case CK_ExtendedKeyMap:
1380         ctl_x_cmd ();
1381         break;
1382     case CK_Suspend:
1383         mc_event_raise (MCEVENT_GROUP_CORE, "suspend", NULL);
1384         break;
1385     case CK_Swap:
1386         swap_cmd ();
1387         break;
1388     case CK_LinkSymbolic:
1389         link_cmd (LINK_SYMLINK_ABSOLUTE);
1390         break;
1391     case CK_ShowHidden:
1392         toggle_show_hidden ();
1393         break;
1394     case CK_SplitVertHoriz:
1395         toggle_panels_split ();
1396         break;
1397     case CK_SplitEqual:
1398         panels_split_equal ();
1399         break;
1400     case CK_SplitMore:
1401         panels_split_more ();
1402         break;
1403     case CK_SplitLess:
1404         panels_split_less ();
1405         break;
1406     case CK_PanelTree:
1407         panel_tree_cmd ();
1408         break;
1409     case CK_Tree:
1410         treebox_cmd ();
1411         break;
1412 #ifdef ENABLE_VFS_UNDELFS
1413     case CK_Undelete:
1414         undelete_cmd ();
1415         break;
1416 #endif
1417     case CK_UserMenu:
1418         user_file_menu_cmd ();
1419         break;
1420     case CK_View:
1421         view_cmd ();
1422         break;
1423     case CK_ViewFile:
1424         view_file_cmd ();
1425         break;
1426     case CK_EditorViewerHistory:
1427         show_editor_viewer_history ();
1428         break;
1429     case CK_Cancel:
1430         /* don't close panels due to SIGINT */
1431         break;
1432     default:
1433         res = MSG_NOT_HANDLED;
1434     }
1435 
1436     return res;
1437 }
1438 
1439 /* --------------------------------------------------------------------------------------------- */
1440 
1441 /**
1442  * Whether the command-line should not respond to key events.
1443  *
1444  * This is TRUE if a QuickView or TreeView have the focus, as they're going
1445  * to consume some keys and there's no sense in passing to the command-line
1446  * just the leftovers.
1447  */
1448 static gboolean
1449 is_cmdline_mute (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1450 {
1451     /* When one of panels is other than view_listing,
1452        current_panel points to view_listing panel all time independently of
1453        it's activity. Thus, we can't use get_current_type() here.
1454        current_panel should point to actualy current active panel
1455        independently of it's type. */
1456     return (current_panel->active == 0
1457             && (get_other_type () == view_quick || get_other_type () == view_tree));
1458 }
1459 
1460 /* --------------------------------------------------------------------------------------------- */
1461 
1462 /**
1463  * Handles the Enter key on the command-line.
1464  *
1465  * Returns TRUE if non-whitespace was indeed processed.
1466  */
1467 static gboolean
1468 handle_cmdline_enter (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1469 {
1470     size_t i;
1471 
1472     for (i = 0; cmdline->buffer[i] != '\0' && whitespace (cmdline->buffer[i]); i++)
1473         ;
1474 
1475     if (cmdline->buffer[i] != '\0')
1476     {
1477         send_message (cmdline, NULL, MSG_KEY, '\n', NULL);
1478         return TRUE;
1479     }
1480 
1481     input_insert (cmdline, "", FALSE);
1482     cmdline->point = 0;
1483 
1484     return FALSE;
1485 }
1486 
1487 /* --------------------------------------------------------------------------------------------- */
1488 
1489 static cb_ret_t
1490 midnight_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
1491 {
1492     long command;
1493 
1494     switch (msg)
1495     {
1496     case MSG_INIT:
1497         panel_init ();
1498         setup_panels ();
1499         return MSG_HANDLED;
1500 
1501     case MSG_DRAW:
1502         load_hint (TRUE);
1503         /* We handle the special case of the output lines */
1504         if (mc_global.tty.console_flag != '\0' && output_lines)
1505             show_console_contents (output_start_y,
1506                                    LINES - output_lines - mc_global.keybar_visible -
1507                                    1, LINES - mc_global.keybar_visible - 1);
1508         return MSG_HANDLED;
1509 
1510     case MSG_RESIZE:
1511         widget_adjust_position (w->pos_flags, &w->y, &w->x, &w->lines, &w->cols);
1512         setup_panels ();
1513         menubar_arrange (the_menubar);
1514         return MSG_HANDLED;
1515 
1516     case MSG_IDLE:
1517         /* We only need the first idle event to show user menu after start */
1518         widget_idle (w, FALSE);
1519 
1520         if (boot_current_is_left)
1521             widget_select (get_panel_widget (0));
1522         else
1523             widget_select (get_panel_widget (1));
1524 
1525         if (auto_menu)
1526             midnight_execute_cmd (NULL, CK_UserMenu);
1527         return MSG_HANDLED;
1528 
1529     case MSG_KEY:
1530         if (ctl_x_map_enabled)
1531         {
1532             ctl_x_map_enabled = FALSE;
1533             command = keybind_lookup_keymap_command (main_x_map, parm);
1534             if (command != CK_IgnoreKey)
1535                 return midnight_execute_cmd (NULL, command);
1536         }
1537 
1538         /* FIXME: should handle all menu shortcuts before this point */
1539         if (widget_get_state (WIDGET (the_menubar), WST_FOCUSED))
1540             return MSG_NOT_HANDLED;
1541 
1542         if (parm == '\n' && !is_cmdline_mute ())
1543         {
1544             if (handle_cmdline_enter ())
1545                 return MSG_HANDLED;
1546             /* Else: the panel will handle it. */
1547         }
1548 
1549         if ((!mc_global.tty.alternate_plus_minus
1550              || !(mc_global.tty.console_flag != '\0' || mc_global.tty.xterm_flag)) && !quote
1551             && !current_panel->searching)
1552         {
1553             if (!only_leading_plus_minus)
1554             {
1555                 /* Special treatement, since the input line will eat them */
1556                 if (parm == '+')
1557                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_Select, NULL);
1558 
1559                 if (parm == '\\' || parm == '-')
1560                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_Unselect,
1561                                          NULL);
1562 
1563                 if (parm == '*')
1564                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_SelectInvert,
1565                                          NULL);
1566             }
1567             else if (!command_prompt || input_is_empty (cmdline))
1568             {
1569                 /* Special treatement '+', '-', '\', '*' only when this is
1570                  * first char on input line
1571                  */
1572                 if (parm == '+')
1573                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_Select, NULL);
1574 
1575                 if (parm == '\\' || parm == '-')
1576                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_Unselect,
1577                                          NULL);
1578 
1579                 if (parm == '*')
1580                     return send_message (current_panel, midnight_dlg, MSG_ACTION, CK_SelectInvert,
1581                                          NULL);
1582             }
1583         }
1584         return MSG_NOT_HANDLED;
1585 
1586     case MSG_HOTKEY_HANDLED:
1587         if ((get_current_type () == view_listing) && current_panel->searching)
1588         {
1589             current_panel->dirty = 1;   /* FIXME: unneeded? */
1590             send_message (current_panel, NULL, MSG_ACTION, CK_SearchStop, NULL);
1591         }
1592         return MSG_HANDLED;
1593 
1594     case MSG_UNHANDLED_KEY:
1595         {
1596             cb_ret_t v = MSG_NOT_HANDLED;
1597 
1598             if (ctl_x_map_enabled)
1599             {
1600                 ctl_x_map_enabled = FALSE;
1601                 command = keybind_lookup_keymap_command (main_x_map, parm);
1602             }
1603             else
1604                 command = keybind_lookup_keymap_command (main_map, parm);
1605 
1606             if (command != CK_IgnoreKey)
1607                 v = midnight_execute_cmd (NULL, command);
1608 
1609             if (v == MSG_NOT_HANDLED && command_prompt && !is_cmdline_mute ())
1610                 v = send_message (cmdline, NULL, MSG_KEY, parm, NULL);
1611 
1612             return v;
1613         }
1614 
1615     case MSG_POST_KEY:
1616         if (!widget_get_state (WIDGET (the_menubar), WST_FOCUSED))
1617             update_dirty_panels ();
1618         return MSG_HANDLED;
1619 
1620     case MSG_ACTION:
1621         /* Handle shortcuts, menu, and buttonbar. */
1622         return midnight_execute_cmd (sender, parm);
1623 
1624     case MSG_END:
1625         panel_deinit ();
1626         return MSG_HANDLED;
1627 
1628     default:
1629         return dlg_default_callback (w, sender, msg, parm, data);
1630     }
1631 }
1632 
1633 /* --------------------------------------------------------------------------------------------- */
1634 /*** public functions ****************************************************************************/
1635 /* --------------------------------------------------------------------------------------------- */
1636 
1637 void
1638 update_menu (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1639 {
1640     menu_set_name (left_menu, panels_layout.horizontal_split ? _("&Above") : _("&Left"));
1641     menu_set_name (right_menu, panels_layout.horizontal_split ? _("&Below") : _("&Right"));
1642     menubar_arrange (the_menubar);
1643     menubar_set_visible (the_menubar, menubar_visible);
1644 }
1645 
1646 /* --------------------------------------------------------------------------------------------- */
1647 
1648 void
1649 midnight_set_buttonbar (WButtonBar * b)
     /* [previous][next][first][last][top][bottom][index][help]  */
1650 {
1651     buttonbar_set_label (b, 1, Q_ ("ButtonBar|Help"), main_map, NULL);
1652     buttonbar_set_label (b, 2, Q_ ("ButtonBar|Menu"), main_map, NULL);
1653     buttonbar_set_label (b, 3, Q_ ("ButtonBar|View"), main_map, NULL);
1654     buttonbar_set_label (b, 4, Q_ ("ButtonBar|Edit"), main_map, NULL);
1655     buttonbar_set_label (b, 5, Q_ ("ButtonBar|Copy"), main_map, NULL);
1656     buttonbar_set_label (b, 6, Q_ ("ButtonBar|RenMov"), main_map, NULL);
1657     buttonbar_set_label (b, 7, Q_ ("ButtonBar|Mkdir"), main_map, NULL);
1658     buttonbar_set_label (b, 8, Q_ ("ButtonBar|Delete"), main_map, NULL);
1659     buttonbar_set_label (b, 9, Q_ ("ButtonBar|PullDn"), main_map, NULL);
1660     buttonbar_set_label (b, 10, Q_ ("ButtonBar|Quit"), main_map, NULL);
1661 }
1662 
1663 /* --------------------------------------------------------------------------------------------- */
1664 /**
1665  * Return a random hint.  If force is TRUE, ignore the timeout.
1666  */
1667 
1668 char *
1669 get_random_hint (gboolean force)
     /* [previous][next][first][last][top][bottom][index][help]  */
1670 {
1671     static const guint64 update_period = 60 * G_USEC_PER_SEC;
1672     static guint64 tv = 0;
1673 
1674     char *data, *result = NULL, *eop;
1675     size_t len, start;
1676     GIConv conv;
1677 
1678     /* Do not change hints more often than one minute */
1679     if (!force && !mc_time_elapsed (&tv, update_period))
1680         return g_strdup ("");
1681 
1682     data = load_mc_home_file (mc_global.share_data_dir, MC_HINT, NULL, &len);
1683     if (data == NULL)
1684         return NULL;
1685 
1686     /* get a random entry */
1687     srand ((unsigned int) (tv / G_USEC_PER_SEC));
1688     start = ((size_t) rand ()) % (len - 1);
1689 
1690     /* Search the start of paragraph */
1691     for (; start != 0; start--)
1692         if (data[start] == '\n' && data[start + 1] == '\n')
1693         {
1694             start += 2;
1695             break;
1696         }
1697 
1698     /* Search the end of paragraph */
1699     for (eop = data + start; *eop != '\0'; eop++)
1700     {
1701         if (*eop == '\n' && *(eop + 1) == '\n')
1702         {
1703             *eop = '\0';
1704             break;
1705         }
1706         if (*eop == '\n')
1707             *eop = ' ';
1708     }
1709 
1710     /* hint files are stored in utf-8 */
1711     /* try convert hint file from utf-8 to terminal encoding */
1712     conv = str_crt_conv_from ("UTF-8");
1713     if (conv != INVALID_CONV)
1714     {
1715         GString *buffer;
1716 
1717         buffer = g_string_sized_new (len - start);
1718         if (str_convert (conv, &data[start], buffer) != ESTR_FAILURE)
1719             result = g_string_free (buffer, FALSE);
1720         else
1721             g_string_free (buffer, TRUE);
1722         str_close_conv (conv);
1723     }
1724     else
1725         result = g_strndup (data + start, len - start);
1726 
1727     g_free (data);
1728     return result;
1729 }
1730 
1731 
1732 /* --------------------------------------------------------------------------------------------- */
1733 /**
1734  * Load new hint and display it.
1735  * IF force is not 0, ignore the timeout.
1736  */
1737 
1738 void
1739 load_hint (gboolean force)
     /* [previous][next][first][last][top][bottom][index][help]  */
1740 {
1741     char *hint;
1742 
1743     if (WIDGET (the_hint)->owner == NULL)
1744         return;
1745 
1746     if (!mc_global.message_visible)
1747     {
1748         label_set_text (the_hint, NULL);
1749         return;
1750     }
1751 
1752     hint = get_random_hint (force);
1753 
1754     if (hint != NULL)
1755     {
1756         if (*hint != '\0')
1757             set_hintbar (hint);
1758         g_free (hint);
1759     }
1760     else
1761     {
1762         char text[BUF_SMALL];
1763 
1764         g_snprintf (text, sizeof (text), _("GNU Midnight Commander %s\n"), VERSION);
1765         set_hintbar (text);
1766     }
1767 }
1768 
1769 /* --------------------------------------------------------------------------------------------- */
1770 
1771 void
1772 change_panel (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1773 {
1774     input_free_completions (cmdline);
1775     dlg_select_next_widget (midnight_dlg);
1776 }
1777 
1778 /* --------------------------------------------------------------------------------------------- */
1779 
1780 /** Save current stat of directories to avoid reloading the panels
1781  * when no modifications have taken place
1782  */
1783 void
1784 save_cwds_stat (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1785 {
1786     if (panels_options.fast_reload)
1787     {
1788         mc_stat (current_panel->cwd_vpath, &(current_panel->dir_stat));
1789         if (get_other_type () == view_listing)
1790             mc_stat (other_panel->cwd_vpath, &(other_panel->dir_stat));
1791     }
1792 }
1793 
1794 /* --------------------------------------------------------------------------------------------- */
1795 
1796 gboolean
1797 quiet_quit_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1798 {
1799     print_last_revert = TRUE;
1800     return quit_cmd_internal (1);
1801 }
1802 
1803 /* --------------------------------------------------------------------------------------------- */
1804 
1805 /** Run the main dialog that occupies the whole screen */
1806 gboolean
1807 do_nc (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1808 {
1809     gboolean ret;
1810 
1811 #ifdef USE_INTERNAL_EDIT
1812     edit_stack_init ();
1813 #endif
1814 
1815     midnight_dlg = dlg_create (FALSE, 0, 0, 1, 1, WPOS_FULLSCREEN, FALSE, dialog_colors,
1816                                midnight_callback, NULL, "[main]", NULL);
1817 
1818     /* Check if we were invoked as an editor or file viewer */
1819     if (mc_global.mc_run_mode != MC_RUN_FULL)
1820     {
1821         setup_dummy_mc ();
1822         ret = mc_maybe_editor_or_viewer ();
1823     }
1824     else
1825     {
1826         /* We only need the first idle event to show user menu after start */
1827         widget_idle (WIDGET (midnight_dlg), TRUE);
1828 
1829         setup_mc ();
1830         mc_filehighlight = mc_fhl_new (TRUE);
1831 
1832         create_file_manager ();
1833         (void) dlg_run (midnight_dlg);
1834 
1835         mc_fhl_free (&mc_filehighlight);
1836 
1837         ret = TRUE;
1838 
1839         /* dlg_destroy destroys even current_panel->cwd_vpath, so we have to save a copy :) */
1840         if (mc_args__last_wd_file != NULL && vfs_current_is_local ())
1841             last_wd_string = g_strdup (vfs_path_as_str (current_panel->cwd_vpath));
1842 
1843         /* don't handle VFS timestamps for dirs opened in panels */
1844         mc_event_destroy (MCEVENT_GROUP_CORE, "vfs_timestamp");
1845 
1846         dir_list_free_list (&panelized_panel.list);
1847     }
1848 
1849     /* Program end */
1850     mc_global.midnight_shutdown = TRUE;
1851     dialog_switch_shutdown ();
1852     done_mc ();
1853     dlg_destroy (midnight_dlg);
1854     current_panel = NULL;
1855 
1856 #ifdef USE_INTERNAL_EDIT
1857     edit_stack_free ();
1858 #endif
1859 
1860     if ((quit & SUBSHELL_EXIT) == 0)
1861         clr_scr ();
1862 
1863     return ret;
1864 }
1865 
1866 /* --------------------------------------------------------------------------------------------- */

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