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

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