root/src/filemanager/layout.c

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

DEFINITIONS

This source file includes following definitions.
  1. max
  2. check_split
  3. update_split
  4. b_left_right_cback
  5. bplus_cback
  6. bminus_cback
  7. layout_callback
  8. layout_dlg_create
  9. panel_do_cols
  10. restore_into_right_dir_panel
  11. layout_change
  12. layout_box
  13. panel_update_cols
  14. setup_panels
  15. panels_split_equal
  16. panels_split_more
  17. panels_split_less
  18. setup_cmdline
  19. use_dash
  20. set_hintbar
  21. rotate_dash
  22. get_nth_panel_name
  23. create_panel
  24. swap_panels
  25. get_panel_type
  26. get_panel_widget
  27. get_current_index
  28. get_other_index
  29. get_other_panel
  30. get_current_type
  31. get_other_type
  32. save_panel_dir
  33. get_panel_dir_for
  34. do_load_prompt
  35. load_prompt
  36. title_path_prepare
  37. update_xterm_title_path

   1 /*
   2    Panel layout module for the Midnight Commander
   3 
   4    Copyright (C) 1995-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Janne Kukonlehto, 1995
   9    Miguel de Icaza, 1995
  10    Andrew Borodin <aborodin@vmail.ru>, 2011, 2012, 2013
  11    Slava Zanko <slavazanko@gmail.com>, 2013
  12    Avi Kelman <patcherton.fixesthings@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 layout.c
  31  *  \brief Source: panel layout module
  32  */
  33 
  34 #include <config.h>
  35 
  36 #include <pwd.h>                /* for username in xterm title */
  37 #include <stdlib.h>
  38 #include <stdio.h>
  39 #include <string.h>
  40 #include <sys/types.h>
  41 #include <unistd.h>
  42 
  43 #include "lib/global.h"
  44 #include "lib/tty/tty.h"
  45 #include "lib/skin.h"
  46 #include "lib/tty/key.h"
  47 #include "lib/tty/mouse.h"
  48 #include "lib/mcconfig.h"
  49 #include "lib/vfs/vfs.h"        /* For _vfs_get_cwd () */
  50 #include "lib/strutil.h"
  51 #include "lib/widget.h"
  52 #include "lib/event.h"
  53 #include "lib/util.h"           /* mc_time_elapsed() */
  54 
  55 #include "src/consaver/cons.saver.h"
  56 #include "src/viewer/mcviewer.h"        /* The view widget */
  57 #include "src/setup.h"
  58 #ifdef ENABLE_SUBSHELL
  59 #include "src/subshell/subshell.h"
  60 #endif
  61 
  62 #include "command.h"
  63 #include "midnight.h"
  64 #include "tree.h"
  65 /* Needed for the extern declarations of integer parameters */
  66 #include "dir.h"
  67 #include "layout.h"
  68 #include "info.h"               /* The Info widget */
  69 
  70 /*** global variables ****************************************************************************/
  71 
  72 panels_layout_t panels_layout = {
  73     /* Set if the panels are split horizontally */
  74     .horizontal_split = FALSE,
  75 
  76     /* vertical split */
  77     .vertical_equal = TRUE,
  78     .left_panel_size = 0,
  79 
  80     /* horizontal split */
  81     .horizontal_equal = TRUE,
  82     .top_panel_size = 0
  83 };
  84 
  85 /* Controls the display of the rotating dash on the verbose mode */
  86 gboolean nice_rotating_dash = TRUE;
  87 
  88 /* The number of output lines shown (if available) */
  89 int output_lines = 0;
  90 
  91 /* Set if the command prompt is to be displayed */
  92 gboolean command_prompt = TRUE;
  93 
  94 /* Set if the main menu is visible */
  95 gboolean menubar_visible = TRUE;
  96 
  97 /* Set to show current working dir in xterm window title */
  98 gboolean xterm_title = TRUE;
  99 
 100 /* Set to show free space on device assigned to current directory */
 101 gboolean free_space = TRUE;
 102 
 103 /* The starting line for the output of the subprogram */
 104 int output_start_y = 0;
 105 
 106 int ok_to_refresh = 1;
 107 
 108 /*** file scope macro definitions ****************************************************************/
 109 
 110 /* The maximum number of views managed by the create_panel routine */
 111 /* Must be at least two (for current and other).  Please note that until */
 112 /* Janne gets around this, we will only manage two of them :-) */
 113 #define MAX_VIEWS 2
 114 
 115 /* Width 12 for a wee Quick (Hex) View */
 116 #define MINWIDTH 12
 117 #define MINHEIGHT 5
 118 
 119 #define B_2LEFT B_USER
 120 #define B_2RIGHT (B_USER + 1)
 121 #define B_PLUS (B_USER + 2)
 122 #define B_MINUS (B_USER + 3)
 123 
 124 #define LAYOUT_OPTIONS_COUNT  G_N_ELEMENTS (check_options)
 125 
 126 /*** file scope type declarations ****************************************************************/
 127 
 128 /*** file scope variables ************************************************************************/
 129 
 130 static struct
 131 {
 132     panel_view_mode_t type;
 133     Widget *widget;
 134     char *last_saved_dir;       /* last view_list working directory */
 135 } panels[MAX_VIEWS] =
 136 {
 137     /* *INDENT-OFF* */
 138     /* init MAX_VIEWS items */
 139     { view_listing, NULL, NULL},
 140     { view_listing, NULL, NULL}
 141     /* *INDENT-ON* */
 142 };
 143 
 144 /* These variables are used to avoid updating the information unless */
 145 /* we need it */
 146 static panels_layout_t old_layout;
 147 static int old_output_lines;
 148 
 149 /* Internal variables */
 150 static int equal_split;
 151 static int _output_lines;
 152 
 153 static int height;
 154 
 155 static WRadio *radio_widget;
 156 
 157 static struct
 158 {
 159     const char *text;
 160     gboolean *variable;
 161     WCheck *widget;
 162 } check_options[] =
 163 {
 164     /* *INDENT-OFF* */
 165     { N_("&Equal split"), &equal_split, NULL },
 166     { N_("&Menubar visible"), &menubar_visible, NULL },
 167     { N_("Command &prompt"), &command_prompt, NULL },
 168     { N_("&Keybar visible"), &mc_global.keybar_visible, NULL },
 169     { N_("H&intbar visible"), &mc_global.message_visible, NULL },
 170     { N_("&XTerm window title"), &xterm_title, NULL },
 171     { N_("&Show free space"), &free_space, NULL }
 172     /* *INDENT-ON* */
 173 };
 174 
 175 static const char *output_lines_label = NULL;
 176 static int output_lines_label_len;
 177 
 178 static WButton *bleft_widget, *bright_widget;
 179 
 180 /*** file scope functions ************************************************************************/
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 /* don't use max() macro to avoid double call of str_term_width1() in widget width calculation */
 184 #undef max
 185 
 186 static int
 187 max (int a, int b)
     /* [previous][next][first][last][top][bottom][index][help]  */
 188 {
 189     return a > b ? a : b;
 190 }
 191 
 192 /* --------------------------------------------------------------------------------------------- */
 193 
 194 static void
 195 check_split (panels_layout_t * layout)
     /* [previous][next][first][last][top][bottom][index][help]  */
 196 {
 197     if (layout->horizontal_split)
 198     {
 199         if (layout->horizontal_equal)
 200             layout->top_panel_size = height / 2;
 201         else if (layout->top_panel_size < MINHEIGHT)
 202             layout->top_panel_size = MINHEIGHT;
 203         else if (layout->top_panel_size > height - MINHEIGHT)
 204             layout->top_panel_size = height - MINHEIGHT;
 205     }
 206     else
 207     {
 208         int md_cols = CONST_WIDGET (midnight_dlg)->cols;
 209 
 210         if (layout->vertical_equal)
 211             layout->left_panel_size = md_cols / 2;
 212         else if (layout->left_panel_size < MINWIDTH)
 213             layout->left_panel_size = MINWIDTH;
 214         else if (layout->left_panel_size > md_cols - MINWIDTH)
 215             layout->left_panel_size = md_cols - MINWIDTH;
 216     }
 217 }
 218 
 219 /* --------------------------------------------------------------------------------------------- */
 220 
 221 static void
 222 update_split (const WDialog * h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 223 {
 224     /* Check split has to be done before testing if it changed, since
 225        it can change due to calling check_split() as well */
 226     check_split (&panels_layout);
 227 
 228     if (panels_layout.horizontal_split)
 229         check_options[0].widget->state = panels_layout.horizontal_equal;
 230     else
 231         check_options[0].widget->state = panels_layout.vertical_equal;
 232     widget_draw (WIDGET (check_options[0].widget));
 233 
 234     tty_setcolor (check_options[0].widget->state ? DISABLED_COLOR : COLOR_NORMAL);
 235 
 236     widget_gotoyx (h, 6, 5);
 237     if (panels_layout.horizontal_split)
 238         tty_printf ("%03d", panels_layout.top_panel_size);
 239     else
 240         tty_printf ("%03d", panels_layout.left_panel_size);
 241 
 242     widget_gotoyx (h, 6, 17);
 243     if (panels_layout.horizontal_split)
 244         tty_printf ("%03d", height - panels_layout.top_panel_size);
 245     else
 246         tty_printf ("%03d", CONST_WIDGET (midnight_dlg)->cols - panels_layout.left_panel_size);
 247 
 248     widget_gotoyx (h, 6, 12);
 249     tty_print_char ('=');
 250 }
 251 
 252 /* --------------------------------------------------------------------------------------------- */
 253 
 254 static int
 255 b_left_right_cback (WButton * button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 256 {
 257     (void) action;
 258 
 259     if (button == bright_widget)
 260     {
 261         if (panels_layout.horizontal_split)
 262             panels_layout.top_panel_size++;
 263         else
 264             panels_layout.left_panel_size++;
 265     }
 266     else
 267     {
 268         if (panels_layout.horizontal_split)
 269             panels_layout.top_panel_size--;
 270         else
 271             panels_layout.left_panel_size--;
 272     }
 273 
 274     update_split (WIDGET (button)->owner);
 275     layout_change ();
 276     do_refresh ();
 277     return 0;
 278 }
 279 
 280 /* --------------------------------------------------------------------------------------------- */
 281 
 282 static int
 283 bplus_cback (WButton * button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 284 {
 285     (void) button;
 286     (void) action;
 287 
 288     if (_output_lines < 99)
 289         _output_lines++;
 290     return 0;
 291 }
 292 
 293 /* --------------------------------------------------------------------------------------------- */
 294 
 295 static int
 296 bminus_cback (WButton * button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 297 {
 298     (void) button;
 299     (void) action;
 300 
 301     if (_output_lines > 0)
 302         _output_lines--;
 303     return 0;
 304 }
 305 
 306 /* --------------------------------------------------------------------------------------------- */
 307 
 308 static cb_ret_t
 309 layout_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 310 {
 311     WDialog *h = DIALOG (w);
 312 
 313     switch (msg)
 314     {
 315     case MSG_DRAW:
 316         /* When repainting the whole dialog (e.g. with C-l) we have to
 317            update everything */
 318         dlg_default_repaint (h);
 319 
 320         old_output_lines = -1;
 321 
 322         update_split (h);
 323 
 324         if (old_output_lines != _output_lines)
 325         {
 326             old_output_lines = _output_lines;
 327             tty_setcolor (mc_global.tty.console_flag != '\0' ? COLOR_NORMAL : DISABLED_COLOR);
 328             widget_gotoyx (h, 9, 5);
 329             tty_print_string (output_lines_label);
 330             widget_gotoyx (h, 9, 5 + 3 + output_lines_label_len);
 331             tty_printf ("%02d", _output_lines);
 332         }
 333         return MSG_HANDLED;
 334 
 335     case MSG_POST_KEY:
 336         {
 337             const Widget *mw = CONST_WIDGET (midnight_dlg);
 338             gboolean _menubar_visible, _command_prompt, _keybar_visible, _message_visible;
 339 
 340             _menubar_visible = check_options[1].widget->state;
 341             _command_prompt = check_options[2].widget->state;
 342             _keybar_visible = check_options[3].widget->state;
 343             _message_visible = check_options[4].widget->state;
 344 
 345             if (mc_global.tty.console_flag == '\0')
 346                 height =
 347                     mw->lines - (_keybar_visible ? 1 : 0) - (_command_prompt ? 1 : 0) -
 348                     (_menubar_visible ? 1 : 0) - _output_lines - (_message_visible ? 1 : 0);
 349             else
 350             {
 351                 int minimum;
 352 
 353                 if (_output_lines < 0)
 354                     _output_lines = 0;
 355                 height =
 356                     mw->lines - (_keybar_visible ? 1 : 0) - (_command_prompt ? 1 : 0) -
 357                     (_menubar_visible ? 1 : 0) - _output_lines - (_message_visible ? 1 : 0);
 358                 minimum = MINHEIGHT * (1 + (panels_layout.horizontal_split ? 1 : 0));
 359                 if (height < minimum)
 360                 {
 361                     _output_lines -= minimum - height;
 362                     height = minimum;
 363                 }
 364             }
 365 
 366             if (old_output_lines != _output_lines)
 367             {
 368                 old_output_lines = _output_lines;
 369                 tty_setcolor (mc_global.tty.console_flag != '\0' ? COLOR_NORMAL : DISABLED_COLOR);
 370                 widget_gotoyx (h, 9, 5 + 3 + output_lines_label_len);
 371                 tty_printf ("%02d", _output_lines);
 372             }
 373         }
 374         return MSG_HANDLED;
 375 
 376     case MSG_NOTIFY:
 377         if (sender == WIDGET (radio_widget))
 378         {
 379             if ((panels_layout.horizontal_split ? 1 : 0) == radio_widget->sel)
 380                 update_split (h);
 381             else
 382             {
 383                 int eq;
 384 
 385                 panels_layout.horizontal_split = radio_widget->sel != 0;
 386 
 387                 if (panels_layout.horizontal_split)
 388                 {
 389                     eq = panels_layout.horizontal_equal;
 390                     if (eq)
 391                         panels_layout.top_panel_size = height / 2;
 392                 }
 393                 else
 394                 {
 395                     eq = panels_layout.vertical_equal;
 396                     if (eq)
 397                         panels_layout.left_panel_size = CONST_WIDGET (midnight_dlg)->cols / 2;
 398                 }
 399 
 400                 widget_disable (WIDGET (bleft_widget), eq);
 401                 widget_disable (WIDGET (bright_widget), eq);
 402 
 403                 update_split (h);
 404                 layout_change ();
 405                 do_refresh ();
 406             }
 407 
 408             return MSG_HANDLED;
 409         }
 410 
 411         if (sender == WIDGET (check_options[0].widget))
 412         {
 413             gboolean eq;
 414 
 415             if (panels_layout.horizontal_split)
 416             {
 417                 panels_layout.horizontal_equal = check_options[0].widget->state;
 418                 eq = panels_layout.horizontal_equal;
 419             }
 420             else
 421             {
 422                 panels_layout.vertical_equal = check_options[0].widget->state;
 423                 eq = panels_layout.vertical_equal;
 424             }
 425 
 426             widget_disable (WIDGET (bleft_widget), eq);
 427             widget_disable (WIDGET (bright_widget), eq);
 428 
 429             update_split (h);
 430             layout_change ();
 431             do_refresh ();
 432 
 433             return MSG_HANDLED;
 434         }
 435 
 436         return MSG_NOT_HANDLED;
 437 
 438     default:
 439         return dlg_default_callback (w, sender, msg, parm, data);
 440     }
 441 }
 442 
 443 /* --------------------------------------------------------------------------------------------- */
 444 
 445 static WDialog *
 446 layout_dlg_create (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 447 {
 448     WDialog *layout_dlg;
 449     int l1 = 0, width;
 450     int b1, b2, b;
 451     size_t i;
 452 
 453     const char *title1 = N_("Panel split");
 454     const char *title2 = N_("Console output");
 455     const char *title3 = N_("Other options");
 456 
 457     const char *s_split_direction[2] = {
 458         N_("&Vertical"),
 459         N_("&Horizontal")
 460     };
 461 
 462     const char *ok_button = N_("&OK");
 463     const char *cancel_button = N_("&Cancel");
 464 
 465     output_lines_label = _("Output lines:");
 466 
 467     /* save old params */
 468     old_output_lines = -1;
 469     _output_lines = output_lines;
 470 
 471 #ifdef ENABLE_NLS
 472     {
 473         static gboolean i18n = FALSE;
 474 
 475         title1 = _(title1);
 476         title2 = _(title2);
 477         title3 = _(title3);
 478 
 479         i = G_N_ELEMENTS (s_split_direction);
 480         while (i-- != 0)
 481             s_split_direction[i] = _(s_split_direction[i]);
 482 
 483         if (!i18n)
 484         {
 485             for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
 486                 check_options[i].text = _(check_options[i].text);
 487             i18n = TRUE;
 488         }
 489 
 490         ok_button = _(ok_button);
 491         cancel_button = _(cancel_button);
 492     }
 493 #endif
 494 
 495     /* radiobuttons */
 496     i = G_N_ELEMENTS (s_split_direction);
 497     while (i-- != 0)
 498         l1 = max (l1, str_term_width1 (s_split_direction[i]) + 7);
 499     /* checkboxes */
 500     for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
 501         l1 = max (l1, str_term_width1 (check_options[i].text) + 7);
 502     /* groupboxes */
 503     l1 = max (l1, str_term_width1 (title1) + 4);
 504     l1 = max (l1, str_term_width1 (title2) + 4);
 505     l1 = max (l1, str_term_width1 (title3) + 4);
 506     /* label + "+"/"-" buttons */
 507     output_lines_label_len = str_term_width1 (output_lines_label);
 508     l1 = max (l1, output_lines_label_len + 12);
 509     /* buttons */
 510     b1 = str_term_width1 (ok_button) + 5;       /* default button */
 511     b2 = str_term_width1 (cancel_button) + 3;
 512     b = b1 + b2 + 1;
 513     /* dialog width */
 514     width = max (l1 * 2 + 7, b);
 515 
 516     layout_dlg =
 517         dlg_create (TRUE, 0, 0, 15, width, WPOS_CENTER, FALSE, dialog_colors, layout_callback, NULL,
 518                     "[Layout]", _("Layout"));
 519 
 520 #define XTRACT(i) (*check_options[i].variable != 0), check_options[i].text
 521 
 522     /* "Panel split" groupbox */
 523     add_widget (layout_dlg, groupbox_new (2, 3, 6, l1, title1));
 524 
 525     radio_widget = radio_new (3, 5, 2, s_split_direction);
 526     radio_widget->sel = panels_layout.horizontal_split ? 1 : 0;
 527     add_widget (layout_dlg, radio_widget);
 528 
 529     check_options[0].widget = check_new (5, 5, XTRACT (0));
 530     add_widget (layout_dlg, check_options[0].widget);
 531 
 532     equal_split = panels_layout.horizontal_split ?
 533         panels_layout.horizontal_equal : panels_layout.vertical_equal;
 534 
 535     bleft_widget = button_new (6, 8, B_2LEFT, NARROW_BUTTON, "&<", b_left_right_cback);
 536     widget_disable (WIDGET (bleft_widget), equal_split);
 537     add_widget (layout_dlg, bleft_widget);
 538 
 539     bright_widget = button_new (6, 14, B_2RIGHT, NARROW_BUTTON, "&>", b_left_right_cback);
 540     widget_disable (WIDGET (bright_widget), equal_split);
 541     add_widget (layout_dlg, bright_widget);
 542 
 543     /* "Console output" groupbox */
 544     {
 545         widget_state_t disabled;
 546         Widget *w;
 547 
 548         disabled = mc_global.tty.console_flag != '\0' ? 0 : WST_DISABLED;
 549 
 550         w = WIDGET (groupbox_new (8, 3, 3, l1, title2));
 551         w->state |= disabled;
 552         add_widget (layout_dlg, w);
 553 
 554         w = WIDGET (button_new (9, output_lines_label_len + 5, B_PLUS,
 555                                 NARROW_BUTTON, "&+", bplus_cback));
 556         w->state |= disabled;
 557         add_widget (layout_dlg, w);
 558 
 559         w = WIDGET (button_new (9, output_lines_label_len + 5 + 5, B_MINUS,
 560                                 NARROW_BUTTON, "&-", bminus_cback));
 561         w->state |= disabled;
 562         add_widget (layout_dlg, w);
 563     }
 564 
 565     /* "Other options" groupbox */
 566     add_widget (layout_dlg, groupbox_new (2, 4 + l1, 9, l1, title3));
 567 
 568     for (i = 1; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
 569     {
 570         check_options[i].widget = check_new (i + 2, 6 + l1, XTRACT (i));
 571         add_widget (layout_dlg, check_options[i].widget);
 572     }
 573 
 574 #undef XTRACT
 575 
 576     add_widget (layout_dlg, hline_new (11, -1, -1));
 577     /* buttons */
 578     add_widget (layout_dlg,
 579                 button_new (12, (width - b) / 2, B_ENTER, DEFPUSH_BUTTON, ok_button, 0));
 580     add_widget (layout_dlg,
 581                 button_new (12, (width - b) / 2 + b1 + 1, B_CANCEL, NORMAL_BUTTON,
 582                             cancel_button, 0));
 583 
 584     widget_select (WIDGET (radio_widget));
 585 
 586     return layout_dlg;
 587 }
 588 
 589 /* --------------------------------------------------------------------------------------------- */
 590 
 591 static void
 592 panel_do_cols (int idx)
     /* [previous][next][first][last][top][bottom][index][help]  */
 593 {
 594     if (get_panel_type (idx) == view_listing)
 595         set_panel_formats (PANEL (panels[idx].widget));
 596     else
 597         panel_update_cols (panels[idx].widget, frame_half);
 598 }
 599 
 600 /* --------------------------------------------------------------------------------------------- */
 601 /** Save current list_view widget directory into panel */
 602 
 603 static Widget *
 604 restore_into_right_dir_panel (int idx, gboolean last_was_panel, int y, int x, int lines, int cols)
     /* [previous][next][first][last][top][bottom][index][help]  */
 605 {
 606     WPanel *new_widget;
 607     const char *p_name;
 608 
 609     p_name = get_nth_panel_name (idx);
 610 
 611     if (last_was_panel)
 612     {
 613         vfs_path_t *saved_dir_vpath;
 614 
 615         saved_dir_vpath = vfs_path_from_str (panels[idx].last_saved_dir);
 616         new_widget = panel_sized_with_dir_new (p_name, y, x, lines, cols, saved_dir_vpath);
 617         vfs_path_free (saved_dir_vpath);
 618     }
 619     else
 620         new_widget = panel_sized_new (p_name, y, x, lines, cols);
 621 
 622     return WIDGET (new_widget);
 623 }
 624 
 625 /* --------------------------------------------------------------------------------------------- */
 626 /*** public functions ****************************************************************************/
 627 /* --------------------------------------------------------------------------------------------- */
 628 
 629 void
 630 layout_change (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 631 {
 632     setup_panels ();
 633     /* update the main menu, because perhaps there was a change in the way
 634        how the panel are split (horizontal/vertical),
 635        and a change of menu visibility. */
 636     update_menu ();
 637     load_hint (TRUE);
 638 }
 639 
 640 /* --------------------------------------------------------------------------------------------- */
 641 
 642 void
 643 layout_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 644 {
 645     WDialog *layout_dlg;
 646 
 647     old_layout = panels_layout;
 648     old_output_lines = output_lines;
 649     layout_dlg = layout_dlg_create ();
 650 
 651     if (dlg_run (layout_dlg) == B_ENTER)
 652     {
 653         size_t i;
 654 
 655         for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
 656             if (check_options[i].widget != NULL)
 657                 *check_options[i].variable = check_options[i].widget->state;
 658 
 659         output_lines = _output_lines;
 660     }
 661     else
 662     {
 663         /* restore layout */
 664         panels_layout = old_layout;
 665         output_lines = old_output_lines;
 666         check_split (&panels_layout);   /* FIXME: is it really needed? */
 667     }
 668 
 669     dlg_destroy (layout_dlg);
 670     layout_change ();
 671     do_refresh ();
 672 }
 673 
 674 /* --------------------------------------------------------------------------------------------- */
 675 
 676 void
 677 panel_update_cols (Widget * widget, panel_display_t frame_size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 678 {
 679     const Widget *mw = CONST_WIDGET (midnight_dlg);
 680     int cols, x;
 681 
 682     /* don't touch panel if it is not in dialog yet */
 683     /* if panel is not in dialog it is not in widgets list
 684        and cannot be compared with get_panel_widget() result */
 685     if (widget->owner == NULL)
 686         return;
 687 
 688     if (panels_layout.horizontal_split)
 689     {
 690         widget->cols = mw->cols;
 691         return;
 692     }
 693 
 694     if (frame_size == frame_full)
 695     {
 696         cols = mw->cols;
 697         x = mw->x;
 698     }
 699     else if (widget == get_panel_widget (0))
 700     {
 701         cols = panels_layout.left_panel_size;
 702         x = mw->x;
 703     }
 704     else
 705     {
 706         cols = mw->cols - panels_layout.left_panel_size;
 707         x = mw->x + panels_layout.left_panel_size;
 708     }
 709 
 710     widget->cols = cols;
 711     widget->x = x;
 712 }
 713 
 714 /* --------------------------------------------------------------------------------------------- */
 715 
 716 void
 717 setup_panels (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 718 {
 719     /* File manager screen layout:
 720      *
 721      * +---------------------------------------------------------------+
 722      * | Menu bar                                                      |
 723      * +-------------------------------+-------------------------------+
 724      * |                               |                               |
 725      * |                               |                               |
 726      * |                               |                               |
 727      * |                               |                               |
 728      * |         Left panel            |         Right panel           |
 729      * |                               |                               |
 730      * |                               |                               |
 731      * |                               |                               |
 732      * |                               |                               |
 733      * +-------------------------------+-------------------------------+
 734      * | Hint (message) bar                                            |
 735      * +---------------------------------------------------------------+
 736      * |                                                               |
 737      * |                        Console content                        |
 738      * |                                                               |
 739      * +--------+------------------------------------------------------+
 740      * | Prompt | Command line                                         |
 741      * | Key (button) bar                                              |
 742      * +--------+------------------------------------------------------+
 743      */
 744 
 745     const Widget *mw = CONST_WIDGET (midnight_dlg);
 746     int start_y;
 747 
 748     /* iniitial height of panels */
 749     height =
 750         mw->lines - (menubar_visible ? 1 : 0) - (mc_global.message_visible ? 1 : 0) -
 751         (command_prompt ? 1 : 0) - (mc_global.keybar_visible ? 1 : 0);
 752 
 753     if (mc_global.tty.console_flag != '\0')
 754     {
 755         int minimum;
 756 
 757         if (output_lines < 0)
 758             output_lines = 0;
 759         else
 760             height -= output_lines;
 761         minimum = MINHEIGHT * (1 + (panels_layout.horizontal_split ? 1 : 0));
 762         if (height < minimum)
 763         {
 764             output_lines -= minimum - height;
 765             height = minimum;
 766         }
 767     }
 768 
 769     widget_set_size (WIDGET (the_menubar), mw->y, mw->x, 1, mw->cols);
 770     menubar_set_visible (the_menubar, menubar_visible);
 771 
 772     check_split (&panels_layout);
 773     start_y = mw->y + (menubar_visible ? 1 : 0);
 774 
 775     /* update columns first... */
 776     panel_do_cols (0);
 777     panel_do_cols (1);
 778 
 779     /* ...then rows and origin */
 780     if (panels_layout.horizontal_split)
 781     {
 782         widget_set_size (panels[0].widget, start_y, mw->x, panels_layout.top_panel_size,
 783                          panels[0].widget->cols);
 784         widget_set_size (panels[1].widget, start_y + panels_layout.top_panel_size, mw->x,
 785                          height - panels_layout.top_panel_size, panels[1].widget->cols);
 786     }
 787     else
 788     {
 789         widget_set_size (panels[0].widget, start_y, mw->x, height, panels[0].widget->cols);
 790         widget_set_size (panels[1].widget, start_y, panels[1].widget->x, height,
 791                          panels[1].widget->cols);
 792     }
 793 
 794     if (mc_global.message_visible)
 795         widget_set_size (WIDGET (the_hint), height + start_y, mw->x, 1, mw->cols);
 796     else
 797         /* make invisible */
 798         widget_set_size (WIDGET (the_hint), 0, 0, 0, 0);
 799 
 800     /* Output window */
 801     if (mc_global.tty.console_flag != '\0' && output_lines != 0)
 802     {
 803         unsigned char end_line;
 804 
 805         end_line = mw->lines - (mc_global.keybar_visible ? 1 : 0) - 1;
 806         output_start_y = end_line - (command_prompt ? 1 : 0) - output_lines + 1;
 807         show_console_contents (output_start_y, end_line - output_lines, end_line);
 808     }
 809 
 810     if (command_prompt)
 811     {
 812 #ifdef ENABLE_SUBSHELL
 813         if (!mc_global.tty.use_subshell || !do_load_prompt ())
 814 #endif
 815             setup_cmdline ();
 816     }
 817     else
 818     {
 819         /* make invisible */
 820         widget_set_size (WIDGET (cmdline), 0, 0, 0, 0);
 821         widget_set_size (WIDGET (the_prompt), mw->lines, mw->cols, 0, 0);
 822     }
 823 
 824     widget_set_size (WIDGET (the_bar), mw->lines - 1, mw->x, mc_global.keybar_visible ? 1 : 0,
 825                      mw->cols);
 826     buttonbar_set_visible (the_bar, mc_global.keybar_visible);
 827 
 828     update_xterm_title_path ();
 829 }
 830 
 831 /* --------------------------------------------------------------------------------------------- */
 832 
 833 void
 834 panels_split_equal (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 835 {
 836     if (panels_layout.horizontal_split)
 837         panels_layout.horizontal_equal = TRUE;
 838     else
 839         panels_layout.vertical_equal = TRUE;
 840 
 841     layout_change ();
 842     do_refresh ();
 843 }
 844 
 845 /* --------------------------------------------------------------------------------------------- */
 846 
 847 void
 848 panels_split_more (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 849 {
 850     if (panels_layout.horizontal_split)
 851     {
 852         panels_layout.horizontal_equal = FALSE;
 853         panels_layout.top_panel_size++;
 854     }
 855     else
 856     {
 857         panels_layout.vertical_equal = FALSE;
 858         panels_layout.left_panel_size++;
 859     }
 860 
 861     layout_change ();
 862 }
 863 
 864 /* --------------------------------------------------------------------------------------------- */
 865 
 866 void
 867 panels_split_less (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 868 {
 869     if (panels_layout.horizontal_split)
 870     {
 871         panels_layout.horizontal_equal = FALSE;
 872         panels_layout.top_panel_size--;
 873     }
 874     else
 875     {
 876         panels_layout.vertical_equal = FALSE;
 877         panels_layout.left_panel_size--;
 878     }
 879 
 880     layout_change ();
 881 }
 882 
 883 /* --------------------------------------------------------------------------------------------- */
 884 
 885 
 886 void
 887 setup_cmdline (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 888 {
 889     const Widget *mw = CONST_WIDGET (midnight_dlg);
 890     int prompt_width;
 891     int y;
 892     char *tmp_prompt = (char *) mc_prompt;
 893 
 894 #ifdef ENABLE_SUBSHELL
 895     if (mc_global.tty.use_subshell)
 896     {
 897         tmp_prompt = g_string_free (subshell_prompt, FALSE);
 898         (void) strip_ctrl_codes (tmp_prompt);
 899     }
 900 #endif
 901 
 902     prompt_width = str_term_width1 (tmp_prompt);
 903 
 904     /* Check for prompts too big */
 905     if (mw->cols > 8 && prompt_width > mw->cols - 8)
 906     {
 907         int prompt_len;
 908 
 909         prompt_width = mw->cols - 8;
 910         prompt_len = str_offset_to_pos (tmp_prompt, prompt_width);
 911         tmp_prompt[prompt_len] = '\0';
 912     }
 913 
 914 #ifdef ENABLE_SUBSHELL
 915     if (mc_global.tty.use_subshell)
 916     {
 917         subshell_prompt = g_string_new (tmp_prompt);
 918         g_free (tmp_prompt);
 919         mc_prompt = subshell_prompt->str;
 920     }
 921 #endif
 922 
 923     y = mw->lines - 1 - (mc_global.keybar_visible ? 1 : 0);
 924 
 925     widget_set_size (WIDGET (the_prompt), y, mw->x, 1, prompt_width);
 926     label_set_text (the_prompt, mc_prompt);
 927     widget_set_size (WIDGET (cmdline), y, mw->x + prompt_width, 1, mw->cols - prompt_width);
 928 }
 929 
 930 /* --------------------------------------------------------------------------------------------- */
 931 
 932 void
 933 use_dash (gboolean flag)
     /* [previous][next][first][last][top][bottom][index][help]  */
 934 {
 935     if (flag)
 936         ok_to_refresh++;
 937     else
 938         ok_to_refresh--;
 939 }
 940 
 941 /* --------------------------------------------------------------------------------------------- */
 942 
 943 void
 944 set_hintbar (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 945 {
 946     label_set_text (the_hint, str);
 947     if (ok_to_refresh > 0)
 948         mc_refresh ();
 949 }
 950 
 951 /* --------------------------------------------------------------------------------------------- */
 952 
 953 void
 954 rotate_dash (gboolean show)
     /* [previous][next][first][last][top][bottom][index][help]  */
 955 {
 956     static guint64 timestamp = 0;
 957     /* update with 10 FPS rate */
 958     static const guint64 delay = G_USEC_PER_SEC / 10;
 959 
 960     const Widget *w = CONST_WIDGET (midnight_dlg);
 961 
 962     if (!nice_rotating_dash || (ok_to_refresh <= 0))
 963         return;
 964 
 965     if (show && !mc_time_elapsed (&timestamp, delay))
 966         return;
 967 
 968     widget_gotoyx (w, menubar_visible != 0 ? 1 : 0, w->cols - 1);
 969     tty_setcolor (NORMAL_COLOR);
 970 
 971     if (!show)
 972         tty_print_alt_char (ACS_URCORNER, FALSE);
 973     else
 974     {
 975         static const char rotating_dash[4] = "|/-\\";
 976         static size_t pos = 0;
 977 
 978         tty_print_char (rotating_dash[pos]);
 979         pos = (pos + 1) % sizeof (rotating_dash);
 980     }
 981 
 982     mc_refresh ();
 983 }
 984 
 985 /* --------------------------------------------------------------------------------------------- */
 986 
 987 const char *
 988 get_nth_panel_name (int num)
     /* [previous][next][first][last][top][bottom][index][help]  */
 989 {
 990     if (num == 0)
 991         return "New Left Panel";
 992 
 993     if (num == 1)
 994         return "New Right Panel";
 995 
 996     {
 997         static char buffer[BUF_SMALL];
 998 
 999         g_snprintf (buffer, sizeof (buffer), "%ith Panel", num);
1000         return buffer;
1001     }
1002 }
1003 
1004 /* --------------------------------------------------------------------------------------------- */
1005 /* I wonder if I should start to use the folding mode than Dugan uses */
1006 /*                                                                     */
1007 /* This is the centralized managing of the panel display types         */
1008 /* This routine takes care of destroying and creating new widgets      */
1009 /* Please note that it could manage MAX_VIEWS, not just left and right */
1010 /* Currently nothing in the code takes advantage of this and has hard- */
1011 /* coded values for two panels only                                    */
1012 
1013 /* Set the num-th panel to the view type: type */
1014 /* This routine also keeps at least one WPanel object in the screen */
1015 /* since a lot of routines depend on the current_panel variable */
1016 
1017 void
1018 create_panel (int num, panel_view_mode_t type)
     /* [previous][next][first][last][top][bottom][index][help]  */
1019 {
1020     int x = 0, y = 0, cols = 0, lines = 0;
1021     unsigned int the_other = 0; /* Index to the other panel */
1022     const char *file_name = NULL;       /* For Quick view */
1023     Widget *new_widget = NULL, *old_widget = NULL;
1024     panel_view_mode_t old_type = view_listing;
1025     WPanel *the_other_panel = NULL;
1026 
1027     if (num >= MAX_VIEWS)
1028     {
1029         fprintf (stderr, "Cannot allocate more that %d views\n", MAX_VIEWS);
1030         abort ();
1031     }
1032     /* Check that we will have a WPanel * at least */
1033     if (type != view_listing)
1034     {
1035         the_other = num == 0 ? 1 : 0;
1036 
1037         if (panels[the_other].type != view_listing)
1038             return;
1039     }
1040 
1041     /* Get rid of it */
1042     if (panels[num].widget != NULL)
1043     {
1044         Widget *w = panels[num].widget;
1045         WPanel *panel = PANEL (w);
1046 
1047         x = w->x;
1048         y = w->y;
1049         cols = w->cols;
1050         lines = w->lines;
1051         old_widget = w;
1052         old_type = panels[num].type;
1053 
1054         if (old_type == view_listing && panel->frame_size == frame_full && type != view_listing)
1055         {
1056             int md_cols = CONST_WIDGET (midnight_dlg)->cols;
1057 
1058             if (panels_layout.horizontal_split)
1059             {
1060                 cols = md_cols;
1061                 x = 0;
1062             }
1063             else
1064             {
1065                 cols = md_cols - panels_layout.left_panel_size;
1066                 if (num == 1)
1067                     x = panels_layout.left_panel_size;
1068             }
1069         }
1070     }
1071 
1072     /* Restoring saved path from panels.ini for nonlist panel */
1073     /* when it's first creation (for example view_info) */
1074     if (old_widget == NULL && type != view_listing)
1075         panels[num].last_saved_dir = _vfs_get_cwd ();
1076 
1077     switch (type)
1078     {
1079     case view_nothing:
1080     case view_listing:
1081         {
1082             gboolean last_was_panel;
1083 
1084             last_was_panel = old_widget != NULL && get_panel_type (num) != view_listing;
1085             new_widget = restore_into_right_dir_panel (num, last_was_panel, y, x, lines, cols);
1086             break;
1087         }
1088 
1089     case view_info:
1090         new_widget = WIDGET (info_new (y, x, lines, cols));
1091         break;
1092 
1093     case view_tree:
1094         new_widget = WIDGET (tree_new (y, x, lines, cols, TRUE));
1095         break;
1096 
1097     case view_quick:
1098         new_widget = WIDGET (mcview_new (y, x, lines, cols, TRUE));
1099         the_other_panel = PANEL (panels[the_other].widget);
1100         if (the_other_panel != NULL)
1101             file_name = the_other_panel->dir.list[the_other_panel->selected].fname;
1102         else
1103             file_name = "";
1104 
1105         mcview_load ((WView *) new_widget, 0, file_name, 0, 0, 0);
1106         break;
1107 
1108     default:
1109         break;
1110     }
1111 
1112     if (type != view_listing)
1113         /* Must save dir, for restoring after change type to */
1114         /* view_listing */
1115         save_panel_dir (num);
1116 
1117     panels[num].type = type;
1118     panels[num].widget = new_widget;
1119 
1120     /* We use replace to keep the circular list of the dialog in the */
1121     /* same state.  Maybe we could just kill it and then replace it  */
1122     if ((midnight_dlg != NULL) && (old_widget != NULL))
1123     {
1124         if (old_type == view_listing)
1125         {
1126             /* save and write directory history of panel
1127              * ... and other histories of midnight_dlg  */
1128             dlg_save_history (midnight_dlg);
1129         }
1130 
1131         widget_replace (old_widget, new_widget);
1132     }
1133 
1134     if (type == view_listing)
1135     {
1136         WPanel *panel = PANEL (new_widget);
1137 
1138         /* if existing panel changed type to view_listing, then load history */
1139         if (old_widget != NULL)
1140         {
1141             ev_history_load_save_t event_data = { NULL, new_widget };
1142 
1143             mc_event_raise (midnight_dlg->event_group, MCEVENT_HISTORY_LOAD, &event_data);
1144         }
1145 
1146         if (num == 0)
1147             left_panel = panel;
1148         else
1149             right_panel = panel;
1150 
1151         /* forced update format after set new sizes */
1152         set_panel_formats (panel);
1153     }
1154 
1155     if (type == view_tree)
1156         the_tree = (WTree *) new_widget;
1157 
1158     /* Prevent current_panel's value from becoming invalid.
1159      * It's just a quick hack to prevent segfaults. Comment out and
1160      * try following:
1161      * - select left panel
1162      * - invoke menue left/tree
1163      * - as long as you stay in the left panel almost everything that uses
1164      *   current_panel causes segfault, e.g. C-Enter, C-x c, ...
1165      */
1166     if ((type != view_listing) && (current_panel == PANEL (old_widget)))
1167         current_panel = num == 0 ? right_panel : left_panel;
1168 
1169     g_free (old_widget);
1170 }
1171 
1172 /* --------------------------------------------------------------------------------------------- */
1173 /** This routine is deeply sticked to the two panels idea.
1174    What should it do in more panels. ANSWER - don't use it
1175    in any multiple panels environment. */
1176 
1177 void
1178 swap_panels (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1179 {
1180     WPanel *panel1, *panel2;
1181     Widget *tmp_widget;
1182 
1183     panel1 = PANEL (panels[0].widget);
1184     panel2 = PANEL (panels[1].widget);
1185 
1186     if (panels[0].type == view_listing && panels[1].type == view_listing &&
1187         !mc_config_get_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", FALSE))
1188     {
1189         WPanel panel;
1190 
1191 #define panelswap(x) panel.x = panel1->x; panel1->x = panel2->x; panel2->x = panel.x;
1192         /* Change content and related stuff */
1193         panelswap (dir);
1194         panelswap (active);
1195         panelswap (cwd_vpath);
1196         panelswap (lwd_vpath);
1197         panelswap (marked);
1198         panelswap (dirs_marked);
1199         panelswap (total);
1200         panelswap (top_file);
1201         panelswap (selected);
1202         panelswap (is_panelized);
1203         panelswap (dir_stat);
1204 #undef panelswap
1205 
1206         panel1->searching = FALSE;
1207         panel2->searching = FALSE;
1208 
1209         if (current_panel == panel1)
1210             current_panel = panel2;
1211         else
1212             current_panel = panel1;
1213 
1214         /* if sort options are different -> resort panels */
1215         if (memcmp (&panel1->sort_info, &panel2->sort_info, sizeof (dir_sort_options_t)) != 0)
1216         {
1217             panel_re_sort (other_panel);
1218             panel_re_sort (current_panel);
1219         }
1220 
1221         if (widget_is_active (panels[0].widget))
1222             widget_select (panels[1].widget);
1223         else if (widget_is_active (panels[1].widget))
1224             widget_select (panels[0].widget);
1225     }
1226     else
1227     {
1228         WPanel *tmp_panel;
1229         int x, y, cols, lines;
1230         int tmp_type;
1231 
1232         tmp_panel = right_panel;
1233         right_panel = left_panel;
1234         left_panel = tmp_panel;
1235 
1236         if (panels[0].type == view_listing)
1237         {
1238             if (strcmp (panel1->panel_name, get_nth_panel_name (0)) == 0)
1239             {
1240                 g_free (panel1->panel_name);
1241                 panel1->panel_name = g_strdup (get_nth_panel_name (1));
1242             }
1243         }
1244         if (panels[1].type == view_listing)
1245         {
1246             if (strcmp (panel2->panel_name, get_nth_panel_name (1)) == 0)
1247             {
1248                 g_free (panel2->panel_name);
1249                 panel2->panel_name = g_strdup (get_nth_panel_name (0));
1250             }
1251         }
1252 
1253         x = panels[0].widget->x;
1254         y = panels[0].widget->y;
1255         cols = panels[0].widget->cols;
1256         lines = panels[0].widget->lines;
1257 
1258         panels[0].widget->x = panels[1].widget->x;
1259         panels[0].widget->y = panels[1].widget->y;
1260         panels[0].widget->cols = panels[1].widget->cols;
1261         panels[0].widget->lines = panels[1].widget->lines;
1262 
1263         panels[1].widget->x = x;
1264         panels[1].widget->y = y;
1265         panels[1].widget->cols = cols;
1266         panels[1].widget->lines = lines;
1267 
1268         tmp_widget = panels[0].widget;
1269         panels[0].widget = panels[1].widget;
1270         panels[1].widget = tmp_widget;
1271         tmp_type = panels[0].type;
1272         panels[0].type = panels[1].type;
1273         panels[1].type = tmp_type;
1274 
1275         /* force update formats because of possible changed sizes */
1276         if (panels[0].type == view_listing)
1277             set_panel_formats (PANEL (panels[0].widget));
1278         if (panels[1].type == view_listing)
1279             set_panel_formats (PANEL (panels[1].widget));
1280     }
1281 }
1282 
1283 /* --------------------------------------------------------------------------------------------- */
1284 
1285 panel_view_mode_t
1286 get_panel_type (int idx)
     /* [previous][next][first][last][top][bottom][index][help]  */
1287 {
1288     return panels[idx].type;
1289 }
1290 
1291 /* --------------------------------------------------------------------------------------------- */
1292 
1293 Widget *
1294 get_panel_widget (int idx)
     /* [previous][next][first][last][top][bottom][index][help]  */
1295 {
1296     return panels[idx].widget;
1297 }
1298 
1299 /* --------------------------------------------------------------------------------------------- */
1300 
1301 int
1302 get_current_index (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1303 {
1304     return (panels[0].widget == WIDGET (current_panel) ? 0 : 1);
1305 }
1306 
1307 /* --------------------------------------------------------------------------------------------- */
1308 
1309 int
1310 get_other_index (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1311 {
1312     return (get_current_index () == 0 ? 1 : 0);
1313 }
1314 
1315 /* --------------------------------------------------------------------------------------------- */
1316 
1317 WPanel *
1318 get_other_panel (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1319 {
1320     return PANEL (get_panel_widget (get_other_index ()));
1321 }
1322 
1323 /* --------------------------------------------------------------------------------------------- */
1324 /** Returns the view type for the current panel/view */
1325 
1326 panel_view_mode_t
1327 get_current_type (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1328 {
1329     return (panels[0].widget == WIDGET (current_panel) ? panels[0].type : panels[1].type);
1330 }
1331 
1332 /* --------------------------------------------------------------------------------------------- */
1333 /** Returns the view type of the unselected panel */
1334 
1335 panel_view_mode_t
1336 get_other_type (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1337 {
1338     return (panels[0].widget == WIDGET (current_panel) ? panels[1].type : panels[0].type);
1339 }
1340 
1341 /* --------------------------------------------------------------------------------------------- */
1342 /** Save current list_view widget directory into panel */
1343 
1344 void
1345 save_panel_dir (int idx)
     /* [previous][next][first][last][top][bottom][index][help]  */
1346 {
1347     panel_view_mode_t type;
1348 
1349     type = get_panel_type (idx);
1350     if (type == view_listing)
1351     {
1352         WPanel *p;
1353 
1354         p = PANEL (get_panel_widget (idx));
1355         if (p != NULL)
1356         {
1357             g_free (panels[idx].last_saved_dir);        /* last path no needed */
1358             /* Because path can be nonlocal */
1359             panels[idx].last_saved_dir = g_strdup (vfs_path_as_str (p->cwd_vpath));
1360         }
1361     }
1362 }
1363 
1364 /* --------------------------------------------------------------------------------------------- */
1365 /** Return working dir, if it's view_listing - cwd,
1366    but for other types - last_saved_dir */
1367 
1368 char *
1369 get_panel_dir_for (const WPanel * widget)
     /* [previous][next][first][last][top][bottom][index][help]  */
1370 {
1371     int i;
1372 
1373     for (i = 0; i < MAX_VIEWS; i++)
1374         if (PANEL (get_panel_widget (i)) == widget)
1375             break;
1376 
1377     if (i >= MAX_VIEWS)
1378         return g_strdup (".");
1379 
1380     if (get_panel_type (i) == view_listing)
1381     {
1382         vfs_path_t *cwd_vpath;
1383 
1384         cwd_vpath = PANEL (get_panel_widget (i))->cwd_vpath;
1385         return g_strdup (vfs_path_as_str (cwd_vpath));
1386     }
1387 
1388     return g_strdup (panels[i].last_saved_dir);
1389 }
1390 
1391 /* --------------------------------------------------------------------------------------------- */
1392 
1393 #ifdef ENABLE_SUBSHELL
1394 gboolean
1395 do_load_prompt (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1396 {
1397     gboolean ret = FALSE;
1398 
1399     if (!read_subshell_prompt ())
1400         return ret;
1401 
1402     /* Don't actually change the prompt if it's invisible */
1403     if (top_dlg != NULL && DIALOG (top_dlg->data) == midnight_dlg && command_prompt)
1404     {
1405         setup_cmdline ();
1406 
1407         /* since the prompt has changed, and we are called from one of the
1408          * tty_get_event channels, the prompt updating does not take place
1409          * automatically: force a cursor update and a screen refresh
1410          */
1411         update_cursor (midnight_dlg);
1412         mc_refresh ();
1413         ret = TRUE;
1414     }
1415     update_subshell_prompt = TRUE;
1416     return ret;
1417 }
1418 
1419 /* --------------------------------------------------------------------------------------------- */
1420 
1421 int
1422 load_prompt (int fd, void *unused)
     /* [previous][next][first][last][top][bottom][index][help]  */
1423 {
1424     (void) fd;
1425     (void) unused;
1426 
1427     do_load_prompt ();
1428     return 0;
1429 }
1430 #endif /* ENABLE_SUBSHELL */
1431 
1432 /* --------------------------------------------------------------------------------------------- */
1433 
1434 void
1435 title_path_prepare (char **path, char **login)
     /* [previous][next][first][last][top][bottom][index][help]  */
1436 {
1437     char host[BUF_TINY];
1438     struct passwd *pw = NULL;
1439     int res = 0;
1440 
1441     *path =
1442         vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD);
1443 
1444     res = gethostname (host, sizeof (host));
1445     if (res != 0)
1446         host[0] = '\0';
1447     else
1448         host[sizeof (host) - 1] = '\0';
1449 
1450     pw = getpwuid (getuid ());
1451     if (pw != NULL)
1452         *login = g_strdup_printf ("%s@%s", pw->pw_name, host);
1453     else
1454         *login = g_strdup (host);
1455 }
1456 
1457 /* --------------------------------------------------------------------------------------------- */
1458 
1459 /** Show current directory in the xterm title */
1460 void
1461 update_xterm_title_path (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1462 {
1463     if (mc_global.tty.xterm_flag && xterm_title)
1464     {
1465         char *p;
1466         char *path;
1467         char *login;
1468 
1469         title_path_prepare (&path, &login);
1470 
1471         p = g_strdup_printf ("mc [%s]:%s", login, path);
1472         g_free (login);
1473         g_free (path);
1474 
1475         fprintf (stdout, "\33]0;%s\7", str_term_form (p));
1476         g_free (p);
1477 
1478         if (!mc_global.tty.alternate_plus_minus)
1479             numeric_keypad_mode ();
1480         (void) fflush (stdout);
1481     }
1482 }
1483 
1484 /* --------------------------------------------------------------------------------------------- */

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