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

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