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

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