Manual pages: mcmcdiffmceditmcview

root/src/filemanager/boxes.c

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

DEFINITIONS

This source file includes following definitions.
  1. configure_callback
  2. skin_apply
  3. skin_name_to_label
  4. skin_dlg_callback
  5. sel_skin_button
  6. appearance_box_callback
  7. panel_listing_callback
  8. sel_charset_button
  9. tree_callback
  10. confvfs_callback
  11. jobs_fill_listbox
  12. task_cb
  13. configure_box
  14. appearance_box
  15. panel_options_box
  16. panel_listing_box
  17. sort_box
  18. confirm_box
  19. display_bits_box
  20. tree_box
  21. configure_vfs_box
  22. cd_box
  23. symlink_box
  24. jobs_box

   1 /*
   2    Some misc dialog boxes for the program.
   3 
   4    Copyright (C) 1994-2025
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Miguel de Icaza, 1994, 1995
   9    Jakub Jelinek, 1995
  10    Andrew Borodin <aborodin@vmail.ru>, 2009-2022
  11 
  12    This file is part of the Midnight Commander.
  13 
  14    The Midnight Commander is free software: you can redistribute it
  15    and/or modify it under the terms of the GNU General Public License as
  16    published by the Free Software Foundation, either version 3 of the License,
  17    or (at your option) any later version.
  18 
  19    The Midnight Commander is distributed in the hope that it will be useful,
  20    but WITHOUT ANY WARRANTY; without even the implied warranty of
  21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22    GNU General Public License for more details.
  23 
  24    You should have received a copy of the GNU General Public License
  25    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  26  */
  27 
  28 /** \file boxes.c
  29  *  \brief Source: Some misc dialog boxes for the program
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <ctype.h>
  35 #include <signal.h>
  36 #include <stdio.h>
  37 #include <stdlib.h>
  38 #include <string.h>
  39 #include <sys/types.h>
  40 #include <sys/stat.h>
  41 
  42 #include "lib/global.h"
  43 
  44 #include "lib/tty/tty.h"
  45 #include "lib/tty/color.h"  // tty_use_colors()
  46 #include "lib/tty/key.h"    // XCTRL and ALT macros
  47 #include "lib/skin.h"       // INPUT_COLOR
  48 #include "lib/mcconfig.h"   // Load/save user formats
  49 #include "lib/strutil.h"
  50 
  51 #include "lib/vfs/vfs.h"
  52 #ifdef ENABLE_VFS_FTP
  53 #include "src/vfs/ftpfs/ftpfs.h"
  54 #endif
  55 
  56 #include "lib/util.h"  // Q_()
  57 #include "lib/widget.h"
  58 #include "lib/charsets.h"
  59 
  60 #include "src/setup.h"
  61 #include "src/history.h"  // MC_HISTORY_ESC_TIMEOUT
  62 #include "src/execute.h"  // pause_after_run
  63 #ifdef ENABLE_BACKGROUND
  64 #include "src/background.h"  // task_list
  65 #endif
  66 #include "src/selcodepage.h"
  67 
  68 #include "command.h"  // For cmdline
  69 #include "dir.h"
  70 #include "tree.h"
  71 #include "layout.h"  // for get_nth_panel_name proto
  72 #include "filemanager.h"
  73 
  74 #include "boxes.h"
  75 
  76 /*** global variables ****************************************************************************/
  77 
  78 /*** file scope macro definitions ****************************************************************/
  79 
  80 #ifdef ENABLE_BACKGROUND
  81 #define B_STOP   (B_USER + 1)
  82 #define B_RESUME (B_USER + 2)
  83 #define B_KILL   (B_USER + 3)
  84 #endif
  85 
  86 /*** file scope type declarations ****************************************************************/
  87 
  88 /*** forward declarations (file scope functions) *************************************************/
  89 
  90 /*** file scope variables ************************************************************************/
  91 
  92 static unsigned long configure_old_esc_mode_id, configure_time_out_id;
  93 
  94 /* Index in list_formats[] for "brief" */
  95 static const int panel_list_brief_idx = 1;
  96 /* Index in list_formats[] for "user defined" */
  97 static const int panel_list_user_idx = 3;
  98 
  99 static char **status_format;
 100 static unsigned long panel_list_formats_id, panel_user_format_id, panel_brief_cols_id;
 101 static unsigned long user_mini_status_id, mini_user_format_id;
 102 
 103 static int new_display_codepage;
 104 
 105 #if defined(ENABLE_VFS) && defined(ENABLE_VFS_FTP)
 106 static unsigned long ftpfs_always_use_proxy_id, ftpfs_proxy_host_id;
 107 #endif
 108 
 109 static GPtrArray *skin_names;
 110 static gchar *current_skin_name;
 111 
 112 #ifdef ENABLE_BACKGROUND
 113 static WListbox *bg_list = NULL;
 114 #endif
 115 
 116 static unsigned long shadows_id;
 117 
 118 /* --------------------------------------------------------------------------------------------- */
 119 /*** file scope functions ************************************************************************/
 120 /* --------------------------------------------------------------------------------------------- */
 121 
 122 static cb_ret_t
 123 configure_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 124 {
 125     switch (msg)
 126     {
 127     case MSG_NOTIFY:
 128         // message from "Single press" checkbutton
 129         if (sender != NULL && sender->id == configure_old_esc_mode_id)
 130         {
 131             const gboolean not_single = !CHECK (sender)->state;
 132             Widget *ww;
 133 
 134             // input line
 135             ww = widget_find_by_id (w, configure_time_out_id);
 136             widget_disable (ww, not_single);
 137 
 138             return MSG_HANDLED;
 139         }
 140         return MSG_NOT_HANDLED;
 141 
 142     default:
 143         return dlg_default_callback (w, sender, msg, parm, data);
 144     }
 145 }
 146 
 147 /* --------------------------------------------------------------------------------------------- */
 148 
 149 static void
 150 skin_apply (const gchar *skin_override)
     /* [previous][next][first][last][top][bottom][index][help]  */
 151 {
 152     GError *mcerror = NULL;
 153 
 154     mc_skin_deinit ();
 155     mc_skin_init (skin_override, &mcerror);
 156     mc_fhl_free (&mc_filehighlight);
 157     mc_filehighlight = mc_fhl_new (TRUE);
 158     dlg_set_default_colors ();
 159     input_set_default_colors ();
 160     if (mc_global.mc_run_mode == MC_RUN_FULL)
 161         command_set_default_colors ();
 162     panel_deinit ();
 163     panel_init ();
 164     repaint_screen ();
 165 
 166     mc_error_message (&mcerror, NULL);
 167 }
 168 
 169 /* --------------------------------------------------------------------------------------------- */
 170 
 171 static const gchar *
 172 skin_name_to_label (const gchar *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 173 {
 174     if (strcmp (name, "default") == 0)
 175         return _ ("< Default >");
 176     return name;
 177 }
 178 
 179 /* --------------------------------------------------------------------------------------------- */
 180 
 181 static cb_ret_t
 182 skin_dlg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 183 {
 184     switch (msg)
 185     {
 186     case MSG_RESIZE:
 187     {
 188         WDialog *d = DIALOG (w);
 189         const WRect *wd = &WIDGET (d->data.p)->rect;
 190         WRect r = w->rect;
 191 
 192         r.y = wd->y + (wd->lines - r.lines) / 2;
 193         r.x = wd->x + wd->cols / 2;
 194 
 195         return dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
 196     }
 197 
 198     default:
 199         return dlg_default_callback (w, sender, msg, parm, data);
 200     }
 201 }
 202 
 203 /* --------------------------------------------------------------------------------------------- */
 204 
 205 static int
 206 sel_skin_button (WButton *button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 207 {
 208     int result;
 209     WListbox *skin_list;
 210     WDialog *skin_dlg;
 211     const gchar *skin_name;
 212     unsigned int i;
 213     unsigned int pos = 1;
 214 
 215     (void) action;
 216 
 217     skin_dlg = dlg_create (TRUE, 0, 0, 13, 24, WPOS_KEEP_DEFAULT, TRUE, dialog_colors,
 218                            skin_dlg_callback, NULL, "[Appearance]", _ ("Skins"));
 219     // use Appearance dialog for positioning
 220     skin_dlg->data.p = WIDGET (button)->owner;
 221 
 222     // set dialog location before all
 223     send_message (skin_dlg, NULL, MSG_RESIZE, 0, NULL);
 224 
 225     skin_list = listbox_new (1, 1, 11, 22, FALSE, NULL);
 226     skin_name = "default";
 227     listbox_add_item (skin_list, LISTBOX_APPEND_AT_END, 0, skin_name_to_label (skin_name),
 228                       (void *) skin_name, FALSE);
 229 
 230     if (strcmp (skin_name, current_skin_name) == 0)
 231         listbox_set_current (skin_list, 0);
 232 
 233     for (i = 0; i < skin_names->len; i++)
 234     {
 235         skin_name = g_ptr_array_index (skin_names, i);
 236         if (strcmp (skin_name, "default") != 0)
 237         {
 238             listbox_add_item (skin_list, LISTBOX_APPEND_AT_END, 0, skin_name_to_label (skin_name),
 239                               (void *) skin_name, FALSE);
 240             if (strcmp (skin_name, current_skin_name) == 0)
 241                 listbox_set_current (skin_list, pos);
 242             pos++;
 243         }
 244     }
 245 
 246     // make list stick to all sides of dialog, effectively make it be resized with dialog
 247     group_add_widget_autopos (GROUP (skin_dlg), skin_list, WPOS_KEEP_ALL, NULL);
 248 
 249     result = dlg_run (skin_dlg);
 250     if (result == B_ENTER)
 251     {
 252         gchar *skin_label;
 253 
 254         listbox_get_current (skin_list, &skin_label, (void **) &skin_name);
 255         g_free (current_skin_name);
 256         current_skin_name = g_strdup (skin_name);
 257         skin_apply (skin_name);
 258 
 259         button_set_text (button, str_fit_to_term (skin_label, 20, J_LEFT_FIT));
 260     }
 261     widget_destroy (WIDGET (skin_dlg));
 262 
 263     return 0;
 264 }
 265 
 266 /* --------------------------------------------------------------------------------------------- */
 267 
 268 static cb_ret_t
 269 appearance_box_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 270 {
 271     switch (msg)
 272     {
 273     case MSG_INIT:
 274 #ifdef ENABLE_SHADOWS
 275         if (!tty_use_colors ())
 276 #endif
 277         {
 278             Widget *shadow;
 279 
 280             shadow = widget_find_by_id (w, shadows_id);
 281             CHECK (shadow)->state = FALSE;
 282             widget_disable (shadow, TRUE);
 283         }
 284         return MSG_HANDLED;
 285 
 286     case MSG_NOTIFY:
 287         if (sender != NULL && sender->id == shadows_id)
 288         {
 289             mc_global.tty.shadows = CHECK (sender)->state;
 290             repaint_screen ();
 291             return MSG_HANDLED;
 292         }
 293         return MSG_NOT_HANDLED;
 294 
 295     default:
 296         return dlg_default_callback (w, sender, msg, parm, data);
 297     }
 298 }
 299 
 300 /* --------------------------------------------------------------------------------------------- */
 301 
 302 static cb_ret_t
 303 panel_listing_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 304 {
 305     switch (msg)
 306     {
 307     case MSG_NOTIFY:
 308         if (sender != NULL && sender->id == panel_list_formats_id)
 309         {
 310             WCheck *ch;
 311             WInput *in1, *in2, *in3;
 312 
 313             in1 = INPUT (widget_find_by_id (w, panel_user_format_id));
 314             in2 = INPUT (widget_find_by_id (w, panel_brief_cols_id));
 315             ch = CHECK (widget_find_by_id (w, user_mini_status_id));
 316             in3 = INPUT (widget_find_by_id (w, mini_user_format_id));
 317 
 318             if (!ch->state)
 319                 input_assign_text (in3, status_format[RADIO (sender)->sel]);
 320             input_update (in1, FALSE);
 321             input_update (in2, FALSE);
 322             input_update (in3, FALSE);
 323             widget_disable (WIDGET (in1), RADIO (sender)->sel != panel_list_user_idx);
 324             widget_disable (WIDGET (in2), RADIO (sender)->sel != panel_list_brief_idx);
 325             return MSG_HANDLED;
 326         }
 327 
 328         if (sender != NULL && sender->id == user_mini_status_id)
 329         {
 330             WInput *in;
 331 
 332             in = INPUT (widget_find_by_id (w, mini_user_format_id));
 333 
 334             if (CHECK (sender)->state)
 335             {
 336                 widget_disable (WIDGET (in), FALSE);
 337                 input_assign_text (in, status_format[3]);
 338             }
 339             else
 340             {
 341                 WRadio *r;
 342 
 343                 r = RADIO (widget_find_by_id (w, panel_list_formats_id));
 344                 widget_disable (WIDGET (in), TRUE);
 345                 input_assign_text (in, status_format[r->sel]);
 346             }
 347             // input_update (in, FALSE);
 348             return MSG_HANDLED;
 349         }
 350 
 351         return MSG_NOT_HANDLED;
 352 
 353     default:
 354         return dlg_default_callback (w, sender, msg, parm, data);
 355     }
 356 }
 357 
 358 /* --------------------------------------------------------------------------------------------- */
 359 
 360 static int
 361 sel_charset_button (WButton *button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 362 {
 363     int new_dcp;
 364 
 365     (void) action;
 366 
 367     new_dcp = select_charset (-1, -1, new_display_codepage, TRUE);
 368 
 369     if (new_dcp != SELECT_CHARSET_CANCEL)
 370     {
 371         const char *cpname;
 372 
 373         new_display_codepage = new_dcp;
 374         cpname = (new_display_codepage == SELECT_CHARSET_OTHER_8BIT)
 375             ? _ ("Other 8 bit")
 376             : ((codepage_desc *) g_ptr_array_index (codepages, new_display_codepage))->name;
 377         if (cpname != NULL)
 378             mc_global.utf8_display = str_isutf8 (cpname);
 379         else
 380             cpname = _ ("7-bit ASCII");  // FIXME
 381 
 382         button_set_text (button, cpname);
 383         widget_draw (WIDGET (WIDGET (button)->owner));
 384     }
 385 
 386     return 0;
 387 }
 388 
 389 /* --------------------------------------------------------------------------------------------- */
 390 
 391 static cb_ret_t
 392 tree_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 393 {
 394     WDialog *h = DIALOG (w);
 395 
 396     switch (msg)
 397     {
 398     case MSG_RESIZE:
 399     {
 400         WRect r = w->rect;
 401         Widget *bar;
 402 
 403         r.lines = LINES - 9;
 404         r.cols = COLS - 20;
 405         dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
 406 
 407         bar = WIDGET (buttonbar_find (h));
 408         bar->rect.x = 0;
 409         bar->rect.y = LINES - 1;
 410         return MSG_HANDLED;
 411     }
 412 
 413     case MSG_ACTION:
 414         return send_message (find_tree (h), NULL, MSG_ACTION, parm, NULL);
 415 
 416     default:
 417         return dlg_default_callback (w, sender, msg, parm, data);
 418     }
 419 }
 420 
 421 /* --------------------------------------------------------------------------------------------- */
 422 
 423 #if defined(ENABLE_VFS) && defined(ENABLE_VFS_FTP)
 424 static cb_ret_t
 425 confvfs_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 426 {
 427     switch (msg)
 428     {
 429     case MSG_NOTIFY:
 430         // message from "Always use ftp proxy" checkbutton
 431         if (sender != NULL && sender->id == ftpfs_always_use_proxy_id)
 432         {
 433             const gboolean not_use = !CHECK (sender)->state;
 434             Widget *wi;
 435 
 436             // input
 437             wi = widget_find_by_id (w, ftpfs_proxy_host_id);
 438             widget_disable (wi, not_use);
 439             return MSG_HANDLED;
 440         }
 441         return MSG_NOT_HANDLED;
 442 
 443     default:
 444         return dlg_default_callback (w, sender, msg, parm, data);
 445     }
 446 }
 447 #endif
 448 
 449 /* --------------------------------------------------------------------------------------------- */
 450 
 451 #ifdef ENABLE_BACKGROUND
 452 static void
 453 jobs_fill_listbox (WListbox *list)
     /* [previous][next][first][last][top][bottom][index][help]  */
 454 {
 455     static const char *state_str[2] = { "", "" };
 456     TaskList *tl;
 457 
 458     if (state_str[0][0] == '\0')
 459     {
 460         state_str[0] = _ ("Running");
 461         state_str[1] = _ ("Stopped");
 462     }
 463 
 464     for (tl = task_list; tl != NULL; tl = tl->next)
 465     {
 466         char *s;
 467 
 468         s = g_strconcat (state_str[tl->state], " ", tl->info, (char *) NULL);
 469         listbox_add_item_take (list, LISTBOX_APPEND_AT_END, 0, s, (void *) tl, FALSE);
 470     }
 471 }
 472 
 473 /* --------------------------------------------------------------------------------------------- */
 474 
 475 static int
 476 task_cb (WButton *button, int action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 477 {
 478     TaskList *tl;
 479     int sig = 0;
 480 
 481     (void) button;
 482 
 483     if (bg_list->list == NULL)
 484         return 0;
 485 
 486     // Get this instance information
 487     listbox_get_current (bg_list, NULL, (void **) &tl);
 488 
 489 #ifdef SIGTSTP
 490     if (action == B_STOP)
 491     {
 492         sig = SIGSTOP;
 493         tl->state = Task_Stopped;
 494     }
 495     else if (action == B_RESUME)
 496     {
 497         sig = SIGCONT;
 498         tl->state = Task_Running;
 499     }
 500     else
 501 #endif
 502         if (action == B_KILL)
 503         sig = SIGKILL;
 504 
 505     if (sig == SIGKILL)
 506         unregister_task_running (tl->pid, tl->fd);
 507 
 508     kill (tl->pid, sig);
 509     listbox_remove_list (bg_list);
 510     jobs_fill_listbox (bg_list);
 511 
 512     // This can be optimized to just redraw this widget :-)
 513     widget_draw (WIDGET (WIDGET (button)->owner));
 514 
 515     return 0;
 516 }
 517 #endif
 518 
 519 /* --------------------------------------------------------------------------------------------- */
 520 /*** public functions ****************************************************************************/
 521 /* --------------------------------------------------------------------------------------------- */
 522 
 523 void
 524 configure_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 525 {
 526     const char *pause_options[] = {
 527         N_ ("&Never"),
 528         N_ ("On dum&b terminals"),
 529         N_ ("Alwa&ys"),
 530     };
 531     const int pause_options_num = G_N_ELEMENTS (pause_options);
 532 
 533     {
 534         char time_out[BUF_TINY] = "";
 535         char *time_out_new = NULL;
 536 
 537         quick_widget_t quick_widgets[] = {
 538             // clang-format off
 539             QUICK_START_COLUMNS,
 540                 QUICK_START_GROUPBOX (N_ ("File operations")),
 541                     QUICK_CHECKBOX (N_ ("&Verbose operation"), &verbose, NULL),
 542                     QUICK_CHECKBOX (N_ ("Compute tota&ls"), &file_op_compute_totals, NULL),
 543                     QUICK_CHECKBOX (N_ ("Classic pro&gressbar"), &classic_progressbar, NULL),
 544                     QUICK_CHECKBOX (N_ ("Mkdi&r autoname"), &auto_fill_mkdir_name, NULL),
 545                     QUICK_CHECKBOX (N_ ("&Preallocate space"), &mc_global.vfs.preallocate_space,
 546                                     NULL),
 547                 QUICK_STOP_GROUPBOX,
 548                 QUICK_START_GROUPBOX (N_ ("Esc key mode")),
 549                     QUICK_CHECKBOX (N_ ("S&ingle press"), &old_esc_mode, &configure_old_esc_mode_id),
 550                     QUICK_LABELED_INPUT (N_ ("Timeout:"), input_label_left,
 551                                          (const char *) time_out, MC_HISTORY_ESC_TIMEOUT,
 552                                          &time_out_new, &configure_time_out_id, FALSE, FALSE,
 553                                          INPUT_COMPLETE_NONE),
 554                 QUICK_STOP_GROUPBOX,
 555                 QUICK_START_GROUPBOX (N_ ("Pause after run")),
 556                     QUICK_RADIO (pause_options_num, pause_options, &pause_after_run, NULL),
 557                 QUICK_STOP_GROUPBOX,
 558             QUICK_NEXT_COLUMN,
 559                 QUICK_START_GROUPBOX (N_ ("Other options")),
 560                     QUICK_CHECKBOX (N_ ("Use internal edi&t"), &use_internal_edit, NULL),
 561                     QUICK_CHECKBOX (N_ ("Use internal vie&w"), &use_internal_view, NULL),
 562                     QUICK_CHECKBOX (N_ ("A&sk new file name"),
 563                                     &editor_ask_filename_before_edit, NULL),
 564                     QUICK_CHECKBOX (N_ ("Auto m&enus"), &auto_menu, NULL),
 565                     QUICK_CHECKBOX (N_ ("&Drop down menus"), &drop_menus, NULL),
 566                     QUICK_CHECKBOX (N_ ("S&hell patterns"), &easy_patterns, NULL),
 567                     QUICK_CHECKBOX (N_ ("Co&mplete: show all"),
 568                                     &mc_global.widget.show_all_if_ambiguous, NULL),
 569                     QUICK_CHECKBOX (N_ ("Rotating d&ash"), &nice_rotating_dash, NULL),
 570                     QUICK_CHECKBOX (N_ ("Cd follows lin&ks"), &mc_global.vfs.cd_symlinks, NULL),
 571                     QUICK_CHECKBOX (N_ ("Sa&fe delete"), &safe_delete, NULL),
 572                     QUICK_CHECKBOX (N_ ("Safe overwrite"), &safe_overwrite, NULL),       // w/o hotkey
 573                     QUICK_CHECKBOX (N_ ("A&uto save setup"), &auto_save_setup, NULL),
 574                     QUICK_SEPARATOR (FALSE),
 575                     QUICK_SEPARATOR (FALSE),
 576                 QUICK_STOP_GROUPBOX,
 577             QUICK_STOP_COLUMNS,
 578             QUICK_BUTTONS_OK_CANCEL,
 579             QUICK_END,
 580             // clang-format on
 581         };
 582 
 583         WRect r = { -1, -1, 0, 60 };
 584 
 585         quick_dialog_t qdlg = {
 586             .rect = r,
 587             .title = N_ ("Configure options"),
 588             .help = "[Configuration]",
 589             .widgets = quick_widgets,
 590             .callback = configure_callback,
 591             .mouse_callback = NULL,
 592         };
 593 
 594         g_snprintf (time_out, sizeof (time_out), "%d", old_esc_mode_timeout);
 595 
 596 #ifndef USE_INTERNAL_EDIT
 597         quick_widgets[17].state = WST_DISABLED;
 598 #endif
 599 
 600         if (!old_esc_mode)
 601             quick_widgets[10].state = quick_widgets[11].state = WST_DISABLED;
 602 
 603 #ifndef HAVE_POSIX_FALLOCATE
 604         mc_global.vfs.preallocate_space = FALSE;
 605         quick_widgets[7].state = WST_DISABLED;
 606 #endif
 607 
 608         if (quick_dialog (&qdlg) == B_ENTER)
 609         {
 610             if (time_out_new[0] == '\0')
 611                 old_esc_mode_timeout = 0;
 612             else
 613                 old_esc_mode_timeout = atoi (time_out_new);
 614         }
 615 
 616         g_free (time_out_new);
 617     }
 618 }
 619 
 620 /* --------------------------------------------------------------------------------------------- */
 621 
 622 void
 623 appearance_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 624 {
 625     gboolean shadows = mc_global.tty.shadows;
 626 
 627     current_skin_name = g_strdup (mc_skin__default.name);
 628     skin_names = mc_skin_list ();
 629 
 630     {
 631         quick_widget_t quick_widgets[] = {
 632             // clang-format off
 633             QUICK_START_COLUMNS,
 634                 QUICK_LABEL (N_ ("Skin:"), NULL),
 635             QUICK_NEXT_COLUMN,
 636                 QUICK_BUTTON (str_fit_to_term (skin_name_to_label (current_skin_name), 20,
 637                               J_LEFT_FIT), B_USER, sel_skin_button, NULL),
 638             QUICK_STOP_COLUMNS,
 639             QUICK_SEPARATOR (TRUE),
 640             QUICK_CHECKBOX (N_ ("&Shadows"), &mc_global.tty.shadows, &shadows_id),
 641             QUICK_BUTTONS_OK_CANCEL,
 642             QUICK_END,
 643             // clang-format on
 644         };
 645 
 646         WRect r = { -1, -1, 0, 54 };
 647 
 648         quick_dialog_t qdlg = {
 649             .rect = r,
 650             .title = N_ ("Appearance"),
 651             .help = "[Appearance]",
 652             .widgets = quick_widgets,
 653             .callback = appearance_box_callback,
 654             .mouse_callback = NULL,
 655         };
 656 
 657         if (quick_dialog (&qdlg) == B_ENTER)
 658             mc_config_set_string (mc_global.main_config, CONFIG_APP_SECTION, "skin",
 659                                   current_skin_name);
 660         else
 661         {
 662             skin_apply (NULL);
 663             mc_global.tty.shadows = shadows;
 664         }
 665     }
 666 
 667     g_free (current_skin_name);
 668     g_ptr_array_free (skin_names, TRUE);
 669 }
 670 
 671 /* --------------------------------------------------------------------------------------------- */
 672 
 673 void
 674 panel_options_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 675 {
 676     gboolean simple_swap;
 677 
 678     simple_swap =
 679         mc_config_get_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", FALSE);
 680     {
 681         const char *qsearch_options[] = {
 682             N_ ("Case &insensitive"),
 683             N_ ("Cas&e sensitive"),
 684             N_ ("Use panel sort mo&de"),
 685         };
 686 
 687         quick_widget_t quick_widgets[] = {
 688             // clang-format off
 689             QUICK_START_COLUMNS,
 690                 QUICK_START_GROUPBOX (N_ ("Main options")),
 691                     QUICK_CHECKBOX (N_ ("Show mi&ni-status"), &panels_options.show_mini_info, NULL),
 692                     QUICK_CHECKBOX (N_ ("Use SI si&ze units"), &panels_options.kilobyte_si, NULL),
 693                     QUICK_CHECKBOX (N_ ("Mi&x all files"), &panels_options.mix_all_files, NULL),
 694                     QUICK_CHECKBOX (N_ ("Show &backup files"), &panels_options.show_backups, NULL),
 695                     QUICK_CHECKBOX (N_ ("Show &hidden files"), &panels_options.show_dot_files, NULL),
 696                     QUICK_CHECKBOX (N_ ("&Fast dir reload"), &panels_options.fast_reload, NULL),
 697                     QUICK_CHECKBOX (N_ ("Ma&rk moves down"), &panels_options.mark_moves_down, NULL),
 698                     QUICK_CHECKBOX (N_ ("Re&verse files only"), &panels_options.reverse_files_only,
 699                                     NULL),
 700                     QUICK_CHECKBOX (N_ ("Simple s&wap"), &simple_swap, NULL),
 701                     QUICK_CHECKBOX (N_ ("A&uto save panels setup"), &panels_options.auto_save_setup,
 702                                     NULL),
 703                     QUICK_SEPARATOR (FALSE),
 704                     QUICK_SEPARATOR (FALSE),
 705                     QUICK_SEPARATOR (FALSE),
 706                 QUICK_STOP_GROUPBOX,
 707             QUICK_NEXT_COLUMN,
 708                 QUICK_START_GROUPBOX (N_ ("Navigation")),
 709                     QUICK_CHECKBOX (N_ ("L&ynx-like motion"), &panels_options.navigate_with_arrows,
 710                                     NULL),
 711                     QUICK_CHECKBOX (N_ ("Pa&ge scrolling"), &panels_options.scroll_pages, NULL),
 712                     QUICK_CHECKBOX (N_ ("Center &scrolling"), &panels_options.scroll_center, NULL),
 713                     QUICK_CHECKBOX (N_ ("&Mouse page scrolling"), &panels_options.mouse_move_pages,
 714                                     NULL),
 715                 QUICK_STOP_GROUPBOX,
 716                 QUICK_START_GROUPBOX (N_ ("File highlight")),
 717                     QUICK_CHECKBOX (N_ ("File &types"), &panels_options.filetype_mode, NULL),
 718                     QUICK_CHECKBOX (N_ ("&Permissions"), &panels_options.permission_mode, NULL),
 719                 QUICK_STOP_GROUPBOX,
 720                 QUICK_START_GROUPBOX (N_ ("Quick search")),
 721                     QUICK_RADIO (QSEARCH_NUM, qsearch_options, (int *) &panels_options.qsearch_mode,
 722                                  NULL),
 723                 QUICK_STOP_GROUPBOX,
 724             QUICK_STOP_COLUMNS,
 725             QUICK_BUTTONS_OK_CANCEL,
 726             QUICK_END,
 727             // clang-format on
 728         };
 729 
 730         WRect r = { -1, -1, 0, 60 };
 731 
 732         quick_dialog_t qdlg = {
 733             .rect = r,
 734             .title = N_ ("Panel options"),
 735             .help = "[Panel options]",
 736             .widgets = quick_widgets,
 737             .callback = NULL,
 738             .mouse_callback = NULL,
 739         };
 740 
 741         if (quick_dialog (&qdlg) != B_ENTER)
 742             return;
 743     }
 744 
 745     mc_config_set_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", simple_swap);
 746 
 747     if (!panels_options.fast_reload_msg_shown && panels_options.fast_reload)
 748     {
 749         message (D_NORMAL, _ ("Information"),
 750                  _ ("Using the fast reload option may not reflect the exact\n"
 751                     "directory contents. In this case you'll need to do a\n"
 752                     "manual reload of the directory. See the man page for\n"
 753                     "the details."));
 754         panels_options.fast_reload_msg_shown = TRUE;
 755     }
 756 
 757     update_panels (UP_RELOAD, UP_KEEPSEL);
 758 }
 759 
 760 /* --------------------------------------------------------------------------------------------- */
 761 
 762 /* return list type */
 763 int
 764 panel_listing_box (WPanel *panel, int num, char **userp, char **minip, gboolean *use_msformat,
     /* [previous][next][first][last][top][bottom][index][help]  */
 765                    int *brief_cols)
 766 {
 767     int result = -1;
 768     const char *p = NULL;
 769 
 770     if (panel == NULL)
 771     {
 772         p = get_nth_panel_name (num);
 773         panel = panel_empty_new (p);
 774     }
 775 
 776     {
 777         gboolean user_mini_status;
 778         char panel_brief_cols_in[BUF_TINY];
 779         char *panel_brief_cols_out = NULL;
 780         char *panel_user_format = NULL;
 781         char *mini_user_format = NULL;
 782 
 783         // Controls whether the array strings have been translated
 784         const char *list_formats[LIST_FORMATS] = {
 785             N_ ("&Full file list"),
 786             N_ ("&Brief file list:"),
 787             N_ ("&Long file list"),
 788             N_ ("&User defined:"),
 789         };
 790 
 791         quick_widget_t quick_widgets[] = {
 792             // clang-format off
 793             QUICK_START_COLUMNS,
 794                 QUICK_RADIO (LIST_FORMATS, list_formats, &result, &panel_list_formats_id),
 795             QUICK_NEXT_COLUMN,
 796                 QUICK_SEPARATOR (FALSE),
 797                 QUICK_LABELED_INPUT (N_ ("columns"), input_label_right, panel_brief_cols_in,
 798                                      "panel-brief-cols-input", &panel_brief_cols_out,
 799                                      &panel_brief_cols_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 800             QUICK_STOP_COLUMNS,
 801             QUICK_INPUT (panel->user_format, "user-fmt-input", &panel_user_format,
 802                          &panel_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 803             QUICK_SEPARATOR (TRUE),
 804             QUICK_CHECKBOX (N_ ("User &mini status"), &user_mini_status, &user_mini_status_id),
 805             QUICK_INPUT (panel->user_status_format[panel->list_format], "mini_input",
 806                          &mini_user_format, &mini_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 807             QUICK_BUTTONS_OK_CANCEL,
 808             QUICK_END,
 809             // clang-format on
 810         };
 811 
 812         WRect r = { -1, -1, 0, 48 };
 813 
 814         quick_dialog_t qdlg = {
 815             .rect = r,
 816             .title = N_ ("Listing format"),
 817             .help = "[Listing Format...]",
 818             .widgets = quick_widgets,
 819             .callback = panel_listing_callback,
 820             .mouse_callback = NULL,
 821         };
 822 
 823         user_mini_status = panel->user_mini_status;
 824         result = panel->list_format;
 825         status_format = panel->user_status_format;
 826 
 827         g_snprintf (panel_brief_cols_in, sizeof (panel_brief_cols_in), "%d", panel->brief_cols);
 828 
 829         if ((int) panel->list_format != panel_list_brief_idx)
 830             quick_widgets[4].state = WST_DISABLED;
 831 
 832         if ((int) panel->list_format != panel_list_user_idx)
 833             quick_widgets[6].state = WST_DISABLED;
 834 
 835         if (!user_mini_status)
 836             quick_widgets[9].state = WST_DISABLED;
 837 
 838         if (quick_dialog (&qdlg) == B_CANCEL)
 839             result = -1;
 840         else
 841         {
 842             int cols;
 843             char *error = NULL;
 844 
 845             *userp = panel_user_format;
 846             *minip = mini_user_format;
 847             *use_msformat = user_mini_status;
 848 
 849             cols = strtol (panel_brief_cols_out, &error, 10);
 850             if (*error == '\0')
 851                 *brief_cols = cols;
 852             else
 853                 *brief_cols = panel->brief_cols;
 854 
 855             g_free (panel_brief_cols_out);
 856         }
 857     }
 858 
 859     if (p != NULL)
 860     {
 861         int i;
 862 
 863         g_free (panel->user_format);
 864         for (i = 0; i < LIST_FORMATS; i++)
 865             g_free (panel->user_status_format[i]);
 866         g_free (panel);
 867     }
 868 
 869     return result;
 870 }
 871 
 872 /* --------------------------------------------------------------------------------------------- */
 873 
 874 const panel_field_t *
 875 sort_box (dir_sort_options_t *op, const panel_field_t *sort_field)
     /* [previous][next][first][last][top][bottom][index][help]  */
 876 {
 877     char **sort_orders_names;
 878     gsize i;
 879     gsize sort_names_num = 0;
 880     int sort_idx = 0;
 881     const panel_field_t *result = NULL;
 882 
 883     sort_orders_names = panel_get_sortable_fields (&sort_names_num);
 884 
 885     for (i = 0; i < sort_names_num; i++)
 886         if (strcmp (sort_orders_names[i], _ (sort_field->title_hotkey)) == 0)
 887         {
 888             sort_idx = i;
 889             break;
 890         }
 891 
 892     {
 893         quick_widget_t quick_widgets[] = {
 894             // clang-format off
 895             QUICK_START_COLUMNS,
 896                 QUICK_RADIO (sort_names_num, (const char **) sort_orders_names, &sort_idx, NULL),
 897             QUICK_NEXT_COLUMN,
 898                 QUICK_CHECKBOX (N_ ("Executable &first"), &op->exec_first, NULL),
 899                 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &op->case_sensitive, NULL),
 900                 QUICK_CHECKBOX (N_ ("&Reverse"), &op->reverse, NULL),
 901             QUICK_STOP_COLUMNS,
 902             QUICK_BUTTONS_OK_CANCEL,
 903             QUICK_END,
 904             // clang-format on
 905         };
 906 
 907         WRect r = { -1, -1, 0, 40 };
 908 
 909         quick_dialog_t qdlg = {
 910             .rect = r,
 911             .title = N_ ("Sort order"),
 912             .help = "[Sort Order...]",
 913             .widgets = quick_widgets,
 914             .callback = NULL,
 915             .mouse_callback = NULL,
 916         };
 917 
 918         if (quick_dialog (&qdlg) != B_CANCEL)
 919             result = panel_get_field_by_title_hotkey (sort_orders_names[sort_idx]);
 920 
 921         if (result == NULL)
 922             result = sort_field;
 923     }
 924 
 925     g_strfreev (sort_orders_names);
 926 
 927     return result;
 928 }
 929 
 930 /* --------------------------------------------------------------------------------------------- */
 931 
 932 void
 933 confirm_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 934 {
 935     quick_widget_t quick_widgets[] = {
 936         // TRANSLATORS: no need to translate 'Confirmation', it's just a context prefix
 937         QUICK_CHECKBOX (Q_ ("Confirmation|&Delete"), &confirm_delete, NULL),
 938         QUICK_CHECKBOX (Q_ ("Confirmation|O&verwrite"), &confirm_overwrite, NULL),
 939         QUICK_CHECKBOX (Q_ ("Confirmation|&Execute"), &confirm_execute, NULL),
 940         QUICK_CHECKBOX (Q_ ("Confirmation|E&xit"), &confirm_exit, NULL),
 941         QUICK_CHECKBOX (Q_ ("Confirmation|Di&rectory hotlist delete"),
 942                         &confirm_directory_hotlist_delete, NULL),
 943         QUICK_CHECKBOX (Q_ ("Confirmation|&History cleanup"),
 944                         &mc_global.widget.confirm_history_cleanup, NULL),
 945         QUICK_BUTTONS_OK_CANCEL,
 946         QUICK_END,
 947     };
 948 
 949     WRect r = { -1, -1, 0, 46 };
 950 
 951     quick_dialog_t qdlg = {
 952         .rect = r,
 953         .title = N_ ("Confirmation"),
 954         .help = "[Confirmation]",
 955         .widgets = quick_widgets,
 956         .callback = NULL,
 957         .mouse_callback = NULL,
 958     };
 959 
 960     (void) quick_dialog (&qdlg);
 961 }
 962 
 963 /* --------------------------------------------------------------------------------------------- */
 964 
 965 void
 966 display_bits_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 967 {
 968     const char *cpname;
 969 
 970     new_display_codepage = mc_global.display_codepage;
 971 
 972     cpname = (new_display_codepage < 0)
 973         ? _ ("Other 8 bit")
 974         : ((codepage_desc *) g_ptr_array_index (codepages, new_display_codepage))->name;
 975 
 976     {
 977         gboolean new_meta;
 978 
 979         quick_widget_t quick_widgets[] = {
 980             // clang-format off
 981             QUICK_START_COLUMNS,
 982                 QUICK_LABEL (N_ ("Input / display codepage:"), NULL),
 983             QUICK_NEXT_COLUMN,
 984                 QUICK_BUTTON (cpname, B_USER, sel_charset_button, NULL),
 985             QUICK_STOP_COLUMNS,
 986             QUICK_SEPARATOR (TRUE),
 987                 QUICK_CHECKBOX (N_ ("F&ull 8 bits input"), &new_meta, NULL),
 988             QUICK_BUTTONS_OK_CANCEL,
 989             QUICK_END,
 990             // clang-format on
 991         };
 992 
 993         WRect r = { -1, -1, 0, 46 };
 994 
 995         quick_dialog_t qdlg = {
 996             .rect = r,
 997             .title = N_ ("Display bits"),
 998             .help = "[Display bits]",
 999             .widgets = quick_widgets,
1000             .callback = NULL,
1001             .mouse_callback = NULL,
1002         };
1003 
1004         new_meta = !use_8th_bit_as_meta;
1005         application_keypad_mode ();
1006 
1007         if (quick_dialog (&qdlg) == B_ENTER)
1008         {
1009             char *errmsg;
1010 
1011             mc_global.display_codepage = new_display_codepage;
1012 
1013             errmsg = init_translation_table (mc_global.source_codepage, mc_global.display_codepage);
1014             if (errmsg != NULL)
1015             {
1016                 message (D_ERROR, MSG_ERROR, "%s", errmsg);
1017                 g_free (errmsg);
1018             }
1019 
1020 #ifdef HAVE_SLANG
1021             tty_display_8bit (mc_global.display_codepage != 0 && mc_global.display_codepage != 1);
1022 #else
1023             tty_display_8bit (mc_global.display_codepage != 0);
1024 #endif
1025             use_8th_bit_as_meta = !new_meta;
1026 
1027             repaint_screen ();
1028         }
1029     }
1030 }
1031 
1032 /* --------------------------------------------------------------------------------------------- */
1033 /** Show tree in a box, not on a panel */
1034 
1035 char *
1036 tree_box (const char *current_dir)
     /* [previous][next][first][last][top][bottom][index][help]  */
1037 {
1038     WTree *mytree;
1039     WRect r;
1040     WDialog *dlg;
1041     WGroup *g;
1042     Widget *wd;
1043     char *val = NULL;
1044     WButtonBar *bar;
1045 
1046     (void) current_dir;
1047 
1048     // Create the components
1049     dlg = dlg_create (TRUE, 0, 0, LINES - 9, COLS - 20, WPOS_CENTER, FALSE, dialog_colors,
1050                       tree_callback, NULL, "[Directory Tree]", _ ("Directory tree"));
1051     g = GROUP (dlg);
1052     wd = WIDGET (dlg);
1053 
1054     rect_init (&r, 2, 2, wd->rect.lines - 6, wd->rect.cols - 5);
1055     mytree = tree_new (&r, FALSE);
1056     group_add_widget_autopos (g, mytree, WPOS_KEEP_ALL, NULL);
1057     group_add_widget_autopos (g, hline_new (wd->rect.lines - 4, 1, -1), WPOS_KEEP_BOTTOM, NULL);
1058     bar = buttonbar_new ();
1059     group_add_widget (g, bar);
1060     // restore ButtonBar coordinates after add_widget()
1061     WIDGET (bar)->rect.x = 0;
1062     WIDGET (bar)->rect.y = LINES - 1;
1063 
1064     if (dlg_run (dlg) == B_ENTER)
1065     {
1066         const vfs_path_t *selected_name;
1067 
1068         selected_name = tree_selected_name (mytree);
1069         val = g_strdup (vfs_path_as_str (selected_name));
1070     }
1071 
1072     widget_destroy (wd);
1073     return val;
1074 }
1075 
1076 /* --------------------------------------------------------------------------------------------- */
1077 
1078 #ifdef ENABLE_VFS
1079 void
1080 configure_vfs_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1081 {
1082     char buffer2[BUF_TINY];
1083 #ifdef ENABLE_VFS_FTP
1084     char buffer3[BUF_TINY];
1085 
1086     g_snprintf (buffer3, sizeof (buffer3), "%i", ftpfs_directory_timeout);
1087 #endif
1088 
1089     g_snprintf (buffer2, sizeof (buffer2), "%i", vfs_timeout);
1090 
1091     {
1092         char *ret_timeout;
1093 #ifdef ENABLE_VFS_FTP
1094         char *ret_passwd;
1095         char *ret_ftp_proxy;
1096         char *ret_directory_timeout;
1097 #endif
1098 
1099         quick_widget_t quick_widgets[] = {
1100             QUICK_LABELED_INPUT (N_ ("Timeout for freeing VFSs (sec):"), input_label_left, buffer2,
1101                                  "input-timo-vfs", &ret_timeout, NULL, FALSE, FALSE,
1102                                  INPUT_COMPLETE_NONE),
1103 #ifdef ENABLE_VFS_FTP
1104             QUICK_SEPARATOR (TRUE),
1105             QUICK_LABELED_INPUT (N_ ("FTP anonymous password:"), input_label_left,
1106                                  ftpfs_anonymous_passwd, "input-passwd", &ret_passwd, NULL, FALSE,
1107                                  FALSE, INPUT_COMPLETE_NONE),
1108             QUICK_LABELED_INPUT (N_ ("FTP directory cache timeout (sec):"), input_label_left,
1109                                  buffer3, "input-timeout", &ret_directory_timeout, NULL, FALSE,
1110                                  FALSE, INPUT_COMPLETE_NONE),
1111             QUICK_CHECKBOX (N_ ("&Always use ftp proxy:"), &ftpfs_always_use_proxy,
1112                             &ftpfs_always_use_proxy_id),
1113             QUICK_INPUT (ftpfs_proxy_host, "input-ftp-proxy", &ret_ftp_proxy, &ftpfs_proxy_host_id,
1114                          FALSE, FALSE, INPUT_COMPLETE_HOSTNAMES),
1115             QUICK_CHECKBOX (N_ ("&Use ~/.netrc"), &ftpfs_use_netrc, NULL),
1116             QUICK_CHECKBOX (N_ ("Use &passive mode"), &ftpfs_use_passive_connections, NULL),
1117             QUICK_CHECKBOX (N_ ("Use passive mode over pro&xy"),
1118                             &ftpfs_use_passive_connections_over_proxy, NULL),
1119 #endif
1120             QUICK_BUTTONS_OK_CANCEL,
1121             QUICK_END,
1122         };
1123 
1124         WRect r = { -1, -1, 0, 56 };
1125 
1126         quick_dialog_t qdlg = {
1127             .rect = r,
1128             .title = N_ ("Virtual File System Setting"),
1129             .help = "[Virtual FS]",
1130             .widgets = quick_widgets,
1131 #ifdef ENABLE_VFS_FTP
1132             .callback = confvfs_callback,
1133 #else
1134             .callback = NULL,
1135 #endif
1136             .mouse_callback = NULL,
1137         };
1138 
1139 #ifdef ENABLE_VFS_FTP
1140         if (!ftpfs_always_use_proxy)
1141             quick_widgets[5].state = WST_DISABLED;
1142 #endif
1143 
1144         if (quick_dialog (&qdlg) != B_CANCEL)
1145         {
1146             // cppcheck-suppress uninitvar
1147             if (ret_timeout[0] == '\0')
1148                 vfs_timeout = 0;
1149             else
1150                 vfs_timeout = atoi (ret_timeout);
1151             g_free (ret_timeout);
1152 
1153             if (vfs_timeout < 0 || vfs_timeout > 10000)
1154                 vfs_timeout = 10;
1155 #ifdef ENABLE_VFS_FTP
1156             g_free (ftpfs_anonymous_passwd);
1157             // cppcheck-suppress uninitvar
1158             ftpfs_anonymous_passwd = ret_passwd;
1159             g_free (ftpfs_proxy_host);
1160             // cppcheck-suppress uninitvar
1161             ftpfs_proxy_host = ret_ftp_proxy;
1162             // cppcheck-suppress uninitvar
1163             if (ret_directory_timeout[0] == '\0')
1164                 ftpfs_directory_timeout = 0;
1165             else
1166                 ftpfs_directory_timeout = atoi (ret_directory_timeout);
1167             g_free (ret_directory_timeout);
1168 #endif
1169         }
1170     }
1171 }
1172 
1173 #endif
1174 
1175 /* --------------------------------------------------------------------------------------------- */
1176 
1177 char *
1178 cd_box (const WPanel *panel)
     /* [previous][next][first][last][top][bottom][index][help]  */
1179 {
1180     const Widget *w = CONST_WIDGET (panel);
1181     char *my_str = NULL;
1182 
1183     quick_widget_t quick_widgets[] = {
1184         QUICK_LABELED_INPUT (N_ ("cd"), input_label_left, "", "input", &my_str, NULL, FALSE, TRUE,
1185                              INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD),
1186         QUICK_END,
1187     };
1188 
1189     WRect r = { w->rect.y + w->rect.lines - 6, w->rect.x, 0, w->rect.cols };
1190 
1191     quick_dialog_t qdlg = {
1192         .rect = r,
1193         .title = N_ ("Quick cd"),
1194         .help = "[Quick cd]",
1195         .widgets = quick_widgets,
1196         .callback = NULL,
1197         .mouse_callback = NULL,
1198     };
1199 
1200     return (quick_dialog (&qdlg) != B_CANCEL) ? my_str : NULL;
1201 }
1202 
1203 /* --------------------------------------------------------------------------------------------- */
1204 
1205 void
1206 symlink_box (const vfs_path_t *existing_vpath, const vfs_path_t *new_vpath, char **ret_existing,
     /* [previous][next][first][last][top][bottom][index][help]  */
1207              char **ret_new)
1208 {
1209     quick_widget_t quick_widgets[] = {
1210         QUICK_LABELED_INPUT (N_ ("Existing filename (filename symlink will point to):"),
1211                              input_label_above, vfs_path_as_str (existing_vpath), "input-2",
1212                              ret_existing, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES),
1213         QUICK_SEPARATOR (FALSE),
1214         QUICK_LABELED_INPUT (N_ ("Symbolic link filename:"), input_label_above,
1215                              vfs_path_as_str (new_vpath), "input-1", ret_new, NULL, FALSE, FALSE,
1216                              INPUT_COMPLETE_FILENAMES),
1217         QUICK_BUTTONS_OK_CANCEL,
1218         QUICK_END,
1219     };
1220 
1221     WRect r = { -1, -1, 0, 64 };
1222 
1223     quick_dialog_t qdlg = {
1224         .rect = r,
1225         .title = N_ ("Symbolic link"),
1226         .help = "[File Menu]",
1227         .widgets = quick_widgets,
1228         .callback = NULL,
1229         .mouse_callback = NULL,
1230     };
1231 
1232     if (quick_dialog (&qdlg) == B_CANCEL)
1233     {
1234         *ret_new = NULL;
1235         *ret_existing = NULL;
1236     }
1237 }
1238 
1239 /* --------------------------------------------------------------------------------------------- */
1240 
1241 #ifdef ENABLE_BACKGROUND
1242 void
1243 jobs_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1244 {
1245     struct
1246     {
1247         const char *name;
1248         int flags;
1249         int value;
1250         int len;
1251         bcback_fn callback;
1252     } job_but[] = {
1253         { N_ ("&Stop"), NORMAL_BUTTON, B_STOP, 0, task_cb },
1254         { N_ ("&Resume"), NORMAL_BUTTON, B_RESUME, 0, task_cb },
1255         { N_ ("&Kill"), NORMAL_BUTTON, B_KILL, 0, task_cb },
1256         { N_ ("&OK"), DEFPUSH_BUTTON, B_CANCEL, 0, NULL },
1257     };
1258 
1259     size_t i;
1260     const size_t n_but = G_N_ELEMENTS (job_but);
1261 
1262     WDialog *jobs_dlg;
1263     WGroup *g;
1264     int cols = 60;
1265     int lines = 15;
1266     int x = 0;
1267 
1268     for (i = 0; i < n_but; i++)
1269     {
1270 #ifdef ENABLE_NLS
1271         job_but[i].name = _ (job_but[i].name);
1272 #endif
1273 
1274         job_but[i].len = str_term_width1 (job_but[i].name) + 3;
1275         if (job_but[i].flags == DEFPUSH_BUTTON)
1276             job_but[i].len += 2;
1277         x += job_but[i].len;
1278     }
1279 
1280     x += (int) n_but - 1;
1281     cols = MAX (cols, x + 6);
1282 
1283     jobs_dlg = dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, NULL, NULL,
1284                            "[Background jobs]", _ ("Background jobs"));
1285     g = GROUP (jobs_dlg);
1286 
1287     bg_list = listbox_new (2, 2, lines - 6, cols - 6, FALSE, NULL);
1288     jobs_fill_listbox (bg_list);
1289     group_add_widget (g, bg_list);
1290 
1291     group_add_widget (g, hline_new (lines - 4, -1, -1));
1292 
1293     x = (cols - x) / 2;
1294     for (i = 0; i < n_but; i++)
1295     {
1296         group_add_widget (g,
1297                           button_new (lines - 3, x, job_but[i].value, job_but[i].flags,
1298                                       job_but[i].name, job_but[i].callback));
1299         x += job_but[i].len + 1;
1300     }
1301 
1302     (void) dlg_run (jobs_dlg);
1303     widget_destroy (WIDGET (jobs_dlg));
1304 }
1305 #endif
1306 
1307 /* --------------------------------------------------------------------------------------------- */

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