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. setup_mc
  29. setup_dummy_mc
  30. done_mc
  31. create_file_manager
  32. prepend_cwd_on_local
  33. mc_maybe_editor_or_viewer
  34. show_editor_viewer_history
  35. quit_cmd_internal
  36. quit_cmd
  37. update_dirty_panels
  38. toggle_show_hidden
  39. midnight_execute_cmd
  40. is_cmdline_mute
  41. handle_cmdline_enter
  42. midnight_callback
  43. update_menu
  44. midnight_set_buttonbar
  45. get_random_hint
  46. load_hint
  47. change_panel
  48. save_cwds_stat
  49. quiet_quit_cmd
  50. do_nc

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

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