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-2026
   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"
  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 *version;
 492     char *package_copyright;
 493     char *label_cp_display;
 494     char *label_cp_source;
 495 
 496     version = g_strdup_printf ("%s %s", PACKAGE_NAME, mc_global.mc_version);
 497     package_copyright = mc_get_package_copyright ();
 498 
 499     const char *name_cp_display = get_codepage_name (mc_global.display_codepage);
 500     const char *name_cp_source = get_codepage_name (mc_global.source_codepage);
 501 
 502     label_cp_display = g_strdup_printf (_ ("Detected display codepage: %s"), name_cp_display);
 503     label_cp_source =
 504         g_strdup_printf (_ ("Selected source (file I/O) codepage: %s"), name_cp_source);
 505 
 506     {
 507         quick_widget_t quick_widgets[] = {
 508             QUICK_LABEL (version, NULL),
 509             QUICK_SEPARATOR (TRUE),
 510             QUICK_LABEL (_ ("Classic terminal file manager inspired by Norton Commander."), NULL),
 511             QUICK_SEPARATOR (FALSE),
 512             QUICK_LABEL (package_copyright, NULL),
 513             QUICK_SEPARATOR (TRUE),
 514             QUICK_LABEL (label_cp_display, NULL),
 515             QUICK_LABEL (label_cp_source, NULL),
 516             QUICK_START_BUTTONS (TRUE, TRUE),
 517             QUICK_BUTTON (_ ("&OK"), B_ENTER, NULL, NULL),
 518             QUICK_END,
 519         };
 520 
 521         WRect r = { -1, -1, 0, 40 };
 522 
 523         quick_dialog_t qdlg = {
 524             .rect = r,
 525             .title = _ ("About"),
 526             .help = "[Overview]",
 527             .widgets = quick_widgets,
 528             .callback = NULL,
 529             .mouse_callback = NULL,
 530         };
 531 
 532         quick_widgets[0].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 533         quick_widgets[2].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 534         quick_widgets[4].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 535 
 536         (void) quick_dialog (&qdlg);
 537     }
 538 
 539     g_free (label_cp_display);
 540     g_free (label_cp_source);
 541     g_free (version);
 542     g_free (package_copyright);
 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 
 556     const int pause_options_num = G_N_ELEMENTS (pause_options);
 557 
 558     {
 559         char time_out[BUF_TINY] = "";
 560         char *time_out_new = NULL;
 561 
 562         quick_widget_t quick_widgets[] = {
 563             // clang-format off
 564             QUICK_START_COLUMNS,
 565                 QUICK_START_GROUPBOX (_ ("File operations")),
 566                     QUICK_CHECKBOX (_ ("&Verbose operation"), &verbose, NULL),
 567                     QUICK_CHECKBOX (_ ("Compute tota&ls"), &file_op_compute_totals, NULL),
 568                     QUICK_CHECKBOX (_ ("Classic pro&gressbar"), &classic_progressbar, NULL),
 569                     QUICK_CHECKBOX (_ ("Mkdi&r autoname"), &auto_fill_mkdir_name, NULL),
 570                     QUICK_CHECKBOX (_ ("&Preallocate space"), &mc_global.vfs.preallocate_space,
 571                                     NULL),
 572                     QUICK_CHECKBOX (_ ("Use COW file cloning"), &mc_global.vfs.file_cloning, NULL),
 573                 QUICK_STOP_GROUPBOX,
 574                 QUICK_START_GROUPBOX (_ ("Esc key mode")),
 575                     QUICK_CHECKBOX (_ ("S&ingle press"), &old_esc_mode, &configure_old_esc_mode_id),
 576                     QUICK_LABELED_INPUT (_ ("Timeout:"), input_label_left,
 577                                          (const char *) time_out, MC_HISTORY_ESC_TIMEOUT,
 578                                          &time_out_new, &configure_time_out_id, FALSE, FALSE,
 579                                          INPUT_COMPLETE_NONE),
 580                 QUICK_STOP_GROUPBOX,
 581                 QUICK_START_GROUPBOX (_ ("Pause after run")),
 582                     QUICK_RADIO (pause_options_num, pause_options, &pause_after_run, NULL),
 583                 QUICK_STOP_GROUPBOX,
 584             QUICK_NEXT_COLUMN,
 585                 QUICK_START_GROUPBOX (_ ("Other options")),
 586                     QUICK_CHECKBOX (_ ("Use internal edi&t"), &use_internal_edit, NULL),
 587                     QUICK_CHECKBOX (_ ("Use internal vie&w"), &use_internal_view, NULL),
 588                     QUICK_CHECKBOX (_ ("A&sk new file name"),
 589                                     &editor_ask_filename_before_edit, NULL),
 590                     QUICK_CHECKBOX (_ ("Auto m&enus"), &auto_menu, NULL),
 591                     QUICK_CHECKBOX (_ ("&Drop down menus"), &drop_menus, NULL),
 592                     QUICK_CHECKBOX (_ ("S&hell patterns"), &easy_patterns, NULL),
 593                     QUICK_CHECKBOX (_ ("Co&mplete: show all"),
 594                                     &mc_global.widget.show_all_if_ambiguous, NULL),
 595                     QUICK_CHECKBOX (_ ("Rotating d&ash"), &nice_rotating_dash, NULL),
 596                     QUICK_CHECKBOX (_ ("Cd follows lin&ks"), &mc_global.vfs.cd_symlinks, NULL),
 597                     QUICK_CHECKBOX (_ ("Sa&fe delete"), &safe_delete, NULL),
 598                     QUICK_CHECKBOX (_ ("Safe overwrite"), &safe_overwrite, NULL),       // w/o hotkey
 599                     QUICK_CHECKBOX (_ ("A&uto save setup"), &auto_save_setup, NULL),
 600                     QUICK_SEPARATOR (FALSE),
 601                     QUICK_SEPARATOR (FALSE),
 602                 QUICK_STOP_GROUPBOX,
 603             QUICK_STOP_COLUMNS,
 604             QUICK_BUTTONS_OK_CANCEL,
 605             QUICK_END,
 606             // clang-format on
 607         };
 608 
 609         WRect r = { -1, -1, 0, 60 };
 610 
 611         quick_dialog_t qdlg = {
 612             .rect = r,
 613             .title = _ ("Configure options"),
 614             .help = "[Configuration]",
 615             .widgets = quick_widgets,
 616             .callback = configure_callback,
 617             .mouse_callback = NULL,
 618         };
 619 
 620         g_snprintf (time_out, sizeof (time_out), "%d", old_esc_mode_timeout);
 621 
 622 #ifndef USE_INTERNAL_EDIT
 623         quick_widgets[18].state = WST_DISABLED;
 624 #endif
 625 
 626         if (!old_esc_mode)
 627             quick_widgets[11].state = WST_DISABLED;
 628 
 629 #ifndef HAVE_POSIX_FALLOCATE
 630         mc_global.vfs.preallocate_space = FALSE;
 631         quick_widgets[6].state = WST_DISABLED;
 632 #endif
 633 
 634 #if !defined(HAVE_FILE_CLONING_BY_RANGE) && !defined(HAVE_FILE_CLONING_BY_PATH)
 635         mc_global.vfs.file_cloning = FALSE;
 636         quick_widgets[7].state = WST_DISABLED;
 637 #endif
 638 
 639         if (quick_dialog (&qdlg) == B_ENTER)
 640         {
 641             if (time_out_new[0] == '\0')
 642                 old_esc_mode_timeout = 0;
 643             else
 644                 old_esc_mode_timeout = atoi (time_out_new);
 645         }
 646 
 647         g_free (time_out_new);
 648     }
 649 }
 650 
 651 /* --------------------------------------------------------------------------------------------- */
 652 
 653 void
 654 appearance_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 655 {
 656     const gboolean shadows = mc_global.tty.shadows;
 657 
 658     current_skin_name = g_strdup (mc_skin__default.name);
 659     skin_names = mc_skin_list ();
 660 
 661     {
 662         quick_widget_t quick_widgets[] = {
 663             // clang-format off
 664             QUICK_START_COLUMNS,
 665                 QUICK_LABEL (_ ("Skin:"), NULL),
 666             QUICK_NEXT_COLUMN,
 667                 QUICK_BUTTON (str_fit_to_term (skin_name_to_label (current_skin_name), SKIN_NAME_DISPLAY_LEN,
 668                               J_LEFT_FIT), B_USER, sel_skin_button, NULL),
 669             QUICK_STOP_COLUMNS,
 670             QUICK_SEPARATOR (TRUE),
 671             QUICK_CHECKBOX (_ ("&Shadows"), &mc_global.tty.shadows, &shadows_id),
 672             QUICK_BUTTONS_OK_CANCEL,
 673             QUICK_END,
 674             // clang-format on
 675         };
 676 
 677         WRect r = { -1, -1, 0, 54 };
 678 
 679         quick_dialog_t qdlg = {
 680             .rect = r,
 681             .title = _ ("Appearance"),
 682             .help = "[Appearance]",
 683             .widgets = quick_widgets,
 684             .callback = appearance_box_callback,
 685             .mouse_callback = NULL,
 686         };
 687 
 688         if (quick_dialog (&qdlg) == B_ENTER)
 689             mc_config_set_string (mc_global.main_config, CONFIG_APP_SECTION, "skin",
 690                                   current_skin_name);
 691         else
 692         {
 693             skin_apply (NULL);
 694             mc_global.tty.shadows = shadows;
 695         }
 696     }
 697 
 698     g_free (current_skin_name);
 699     g_ptr_array_free (skin_names, TRUE);
 700 }
 701 
 702 /* --------------------------------------------------------------------------------------------- */
 703 
 704 void
 705 panel_options_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 706 {
 707     gboolean simple_swap;
 708 
 709     simple_swap =
 710         mc_config_get_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", FALSE);
 711     {
 712         const char *qsearch_options[] = {
 713             _ ("Case &insensitive"),
 714             _ ("Cas&e sensitive"),
 715             _ ("Use panel sort mo&de"),
 716         };
 717 
 718         quick_widget_t quick_widgets[] = {
 719             // clang-format off
 720             QUICK_START_COLUMNS,
 721                 QUICK_START_GROUPBOX (_ ("Main options")),
 722                     QUICK_CHECKBOX (_ ("Show mi&ni-status"), &panels_options.show_mini_info, NULL),
 723                     QUICK_CHECKBOX (_ ("Use SI si&ze units"), &panels_options.kilobyte_si, NULL),
 724                     QUICK_CHECKBOX (_ ("Mi&x all files"), &panels_options.mix_all_files, NULL),
 725                     QUICK_CHECKBOX (_ ("Show &backup files"), &panels_options.show_backups, NULL),
 726                     QUICK_CHECKBOX (_ ("Show &hidden files"), &panels_options.show_dot_files, NULL),
 727                     QUICK_CHECKBOX (_ ("&Fast dir reload"), &panels_options.fast_reload, NULL),
 728                     QUICK_CHECKBOX (_ ("Ma&rk moves down"), &panels_options.mark_moves_down, NULL),
 729                     QUICK_CHECKBOX (_ ("Re&verse files only"), &panels_options.reverse_files_only,
 730                                     NULL),
 731                     QUICK_CHECKBOX (_ ("Simple s&wap"), &simple_swap, NULL),
 732                     QUICK_CHECKBOX (_ ("A&uto save panels setup"), &panels_options.auto_save_setup,
 733                                     NULL),
 734                     QUICK_SEPARATOR (FALSE),
 735                     QUICK_SEPARATOR (FALSE),
 736                     QUICK_SEPARATOR (FALSE),
 737                 QUICK_STOP_GROUPBOX,
 738             QUICK_NEXT_COLUMN,
 739                 QUICK_START_GROUPBOX (_ ("Navigation")),
 740                     QUICK_CHECKBOX (_ ("L&ynx-like motion"), &panels_options.navigate_with_arrows,
 741                                     NULL),
 742                     QUICK_CHECKBOX (_ ("Pa&ge scrolling"), &panels_options.scroll_pages, NULL),
 743                     QUICK_CHECKBOX (_ ("Center &scrolling"), &panels_options.scroll_center, NULL),
 744                     QUICK_CHECKBOX (_ ("&Mouse page scrolling"), &panels_options.mouse_move_pages,
 745                                     NULL),
 746                 QUICK_STOP_GROUPBOX,
 747                 QUICK_START_GROUPBOX (_ ("File highlight")),
 748                     QUICK_CHECKBOX (_ ("File &types"), &panels_options.filetype_mode, NULL),
 749                     QUICK_CHECKBOX (_ ("&Permissions"), &panels_options.permission_mode, NULL),
 750                 QUICK_STOP_GROUPBOX,
 751                 QUICK_START_GROUPBOX (_ ("Quick search")),
 752                     QUICK_RADIO (QSEARCH_NUM, qsearch_options, (int *) &panels_options.qsearch_mode,
 753                                  NULL),
 754                 QUICK_STOP_GROUPBOX,
 755             QUICK_STOP_COLUMNS,
 756             QUICK_BUTTONS_OK_CANCEL,
 757             QUICK_END,
 758             // clang-format on
 759         };
 760 
 761         WRect r = { -1, -1, 0, 60 };
 762 
 763         quick_dialog_t qdlg = {
 764             .rect = r,
 765             .title = _ ("Panel options"),
 766             .help = "[Panel options]",
 767             .widgets = quick_widgets,
 768             .callback = NULL,
 769             .mouse_callback = NULL,
 770         };
 771 
 772         if (quick_dialog (&qdlg) != B_ENTER)
 773             return;
 774     }
 775 
 776     mc_config_set_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", simple_swap);
 777 
 778     if (!panels_options.fast_reload_msg_shown && panels_options.fast_reload)
 779     {
 780         message (D_NORMAL, _ ("Information"),
 781                  _ ("Using the fast reload option may not reflect the exact\n"
 782                     "directory contents. In this case you'll need to do a\n"
 783                     "manual reload of the directory. See the man page for\n"
 784                     "the details."));
 785         panels_options.fast_reload_msg_shown = TRUE;
 786     }
 787 
 788     update_panels (UP_RELOAD, UP_KEEPSEL);
 789 }
 790 
 791 /* --------------------------------------------------------------------------------------------- */
 792 
 793 /* return list type */
 794 int
 795 panel_listing_box (WPanel *panel, int num, char **userp, char **minip, gboolean *use_msformat,
     /* [previous][next][first][last][top][bottom][index][help]  */
 796                    int *brief_cols)
 797 {
 798     int result = -1;
 799     const char *p = NULL;
 800 
 801     if (panel == NULL)
 802     {
 803         p = get_nth_panel_name (num);
 804         panel = panel_empty_new (p);
 805     }
 806 
 807     {
 808         gboolean user_mini_status;
 809         char panel_brief_cols_in[BUF_TINY];
 810         char *panel_brief_cols_out = NULL;
 811         char *panel_user_format = NULL;
 812         char *mini_user_format = NULL;
 813 
 814         // Controls whether the array strings have been translated
 815         const char *list_formats[LIST_FORMATS] = {
 816             _ ("&Full file list"),
 817             _ ("&Brief file list:"),
 818             _ ("&Long file list"),
 819             _ ("&User defined:"),
 820         };
 821 
 822         quick_widget_t quick_widgets[] = {
 823             // clang-format off
 824             QUICK_START_COLUMNS,
 825                 QUICK_RADIO (LIST_FORMATS, list_formats, &result, &panel_list_formats_id),
 826             QUICK_NEXT_COLUMN,
 827                 QUICK_SEPARATOR (FALSE),
 828                 QUICK_LABELED_INPUT (_ ("columns"), input_label_right, panel_brief_cols_in,
 829                                      "panel-brief-cols-input", &panel_brief_cols_out,
 830                                      &panel_brief_cols_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 831             QUICK_STOP_COLUMNS,
 832             QUICK_INPUT (panel->user_format, "user-fmt-input", &panel_user_format,
 833                          &panel_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 834             QUICK_SEPARATOR (TRUE),
 835             QUICK_CHECKBOX (_ ("User &mini status"), &user_mini_status, &user_mini_status_id),
 836             QUICK_INPUT (panel->user_status_format[panel->list_format], "mini_input",
 837                          &mini_user_format, &mini_user_format_id, FALSE, FALSE, INPUT_COMPLETE_NONE),
 838             QUICK_BUTTONS_OK_CANCEL,
 839             QUICK_END,
 840             // clang-format on
 841         };
 842 
 843         WRect r = { -1, -1, 0, 48 };
 844 
 845         quick_dialog_t qdlg = {
 846             .rect = r,
 847             .title = _ ("Listing format"),
 848             .help = "[Listing Format...]",
 849             .widgets = quick_widgets,
 850             .callback = panel_listing_callback,
 851             .mouse_callback = NULL,
 852         };
 853 
 854         user_mini_status = panel->user_mini_status;
 855         result = panel->list_format;
 856         status_format = panel->user_status_format;
 857 
 858         g_snprintf (panel_brief_cols_in, sizeof (panel_brief_cols_in), "%d", panel->brief_cols);
 859 
 860         if ((int) panel->list_format != panel_list_brief_idx)
 861             quick_widgets[4].state = WST_DISABLED;
 862 
 863         if ((int) panel->list_format != panel_list_user_idx)
 864             quick_widgets[6].state = WST_DISABLED;
 865 
 866         if (!user_mini_status)
 867             quick_widgets[9].state = WST_DISABLED;
 868 
 869         if (quick_dialog (&qdlg) == B_CANCEL)
 870             result = -1;
 871         else
 872         {
 873             int cols;
 874             char *error = NULL;
 875 
 876             *userp = panel_user_format;
 877             *minip = mini_user_format;
 878             *use_msformat = user_mini_status;
 879 
 880             cols = strtol (panel_brief_cols_out, &error, 10);
 881             if (*error == '\0')
 882                 *brief_cols = cols;
 883             else
 884                 *brief_cols = panel->brief_cols;
 885 
 886             g_free (panel_brief_cols_out);
 887         }
 888     }
 889 
 890     if (p != NULL)
 891     {
 892         int i;
 893 
 894         g_free (panel->user_format);
 895         for (i = 0; i < LIST_FORMATS; i++)
 896             g_free (panel->user_status_format[i]);
 897         g_free (panel);
 898     }
 899 
 900     return result;
 901 }
 902 
 903 /* --------------------------------------------------------------------------------------------- */
 904 
 905 const panel_field_t *
 906 sort_box (dir_sort_options_t *op, const panel_field_t *sort_field)
     /* [previous][next][first][last][top][bottom][index][help]  */
 907 {
 908     char **sort_orders_names;
 909     gsize i;
 910     gsize sort_names_num = 0;
 911     int sort_idx = 0;
 912     const panel_field_t *result = NULL;
 913 
 914     sort_orders_names = panel_get_sortable_fields (&sort_names_num);
 915 
 916     for (i = 0; i < sort_names_num; i++)
 917         if (strcmp (sort_orders_names[i], _ (sort_field->title_hotkey)) == 0)
 918         {
 919             sort_idx = i;
 920             break;
 921         }
 922 
 923     {
 924         quick_widget_t quick_widgets[] = {
 925             // clang-format off
 926             QUICK_START_COLUMNS,
 927                 QUICK_RADIO (sort_names_num, (const char **) sort_orders_names, &sort_idx, NULL),
 928             QUICK_NEXT_COLUMN,
 929                 QUICK_CHECKBOX (_ ("Executable &first"), &op->exec_first, NULL),
 930                 QUICK_CHECKBOX (_ ("Cas&e sensitive"), &op->case_sensitive, NULL),
 931                 QUICK_CHECKBOX (_ ("&Reverse"), &op->reverse, NULL),
 932             QUICK_STOP_COLUMNS,
 933             QUICK_BUTTONS_OK_CANCEL,
 934             QUICK_END,
 935             // clang-format on
 936         };
 937 
 938         WRect r = { -1, -1, 0, 40 };
 939 
 940         quick_dialog_t qdlg = {
 941             .rect = r,
 942             .title = _ ("Sort order"),
 943             .help = "[Sort Order...]",
 944             .widgets = quick_widgets,
 945             .callback = NULL,
 946             .mouse_callback = NULL,
 947         };
 948 
 949         if (quick_dialog (&qdlg) != B_CANCEL)
 950             result = panel_get_field_by_title_hotkey (sort_orders_names[sort_idx]);
 951 
 952         if (result == NULL)
 953             result = sort_field;
 954     }
 955 
 956     g_strfreev (sort_orders_names);
 957 
 958     return result;
 959 }
 960 
 961 /* --------------------------------------------------------------------------------------------- */
 962 
 963 void
 964 confirm_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 965 {
 966     quick_widget_t quick_widgets[] = {
 967         // TRANSLATORS: no need to translate 'Confirmation', it's just a context prefix
 968         QUICK_CHECKBOX (Q_ ("Confirmation|&Delete"), &confirm_delete, NULL),
 969         QUICK_CHECKBOX (Q_ ("Confirmation|O&verwrite"), &confirm_overwrite, NULL),
 970         QUICK_CHECKBOX (Q_ ("Confirmation|&Execute"), &confirm_execute, NULL),
 971         QUICK_CHECKBOX (Q_ ("Confirmation|E&xit"), &confirm_exit, NULL),
 972         QUICK_CHECKBOX (Q_ ("Confirmation|Di&rectory hotlist delete"),
 973                         &confirm_directory_hotlist_delete, NULL),
 974         QUICK_CHECKBOX (Q_ ("Confirmation|&History cleanup"),
 975                         &mc_global.widget.confirm_history_cleanup, NULL),
 976         QUICK_BUTTONS_OK_CANCEL,
 977         QUICK_END,
 978     };
 979 
 980     WRect r = { -1, -1, 0, 46 };
 981 
 982     quick_dialog_t qdlg = {
 983         .rect = r,
 984         .title = _ ("Confirmation"),
 985         .help = "[Confirmation]",
 986         .widgets = quick_widgets,
 987         .callback = NULL,
 988         .mouse_callback = NULL,
 989     };
 990 
 991     (void) quick_dialog (&qdlg);
 992 }
 993 
 994 /* --------------------------------------------------------------------------------------------- */
 995 /** Show tree in a box, not on a panel */
 996 
 997 char *
 998 tree_box (const char *current_dir)
     /* [previous][next][first][last][top][bottom][index][help]  */
 999 {
1000     WTree *mytree;
1001     WRect r;
1002     WDialog *dlg;
1003     WGroup *g;
1004     Widget *wd;
1005     char *val = NULL;
1006     WButtonBar *bar;
1007 
1008     (void) current_dir;
1009 
1010     // Create the components
1011     dlg = dlg_create (TRUE, 0, 0, LINES - 9, COLS - 20, WPOS_CENTER, FALSE, dialog_colors,
1012                       tree_callback, NULL, "[Directory Tree]", _ ("Directory tree"));
1013     g = GROUP (dlg);
1014     wd = WIDGET (dlg);
1015 
1016     rect_init (&r, 2, 2, wd->rect.lines - 6, wd->rect.cols - 5);
1017     mytree = tree_new (&r, FALSE);
1018     group_add_widget_autopos (g, mytree, WPOS_KEEP_ALL, NULL);
1019     group_add_widget_autopos (g, hline_new (wd->rect.lines - 4, 1, -1), WPOS_KEEP_BOTTOM, NULL);
1020     bar = buttonbar_new ();
1021     group_add_widget (g, bar);
1022     // restore ButtonBar coordinates after add_widget()
1023     WIDGET (bar)->rect.x = 0;
1024     WIDGET (bar)->rect.y = LINES - 1;
1025 
1026     if (dlg_run (dlg) == B_ENTER)
1027     {
1028         const vfs_path_t *selected_name;
1029 
1030         selected_name = tree_selected_name (mytree);
1031         val = g_strdup (vfs_path_as_str (selected_name));
1032     }
1033 
1034     widget_destroy (wd);
1035     return val;
1036 }
1037 
1038 /* --------------------------------------------------------------------------------------------- */
1039 
1040 #ifdef ENABLE_VFS
1041 void
1042 configure_vfs_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1043 {
1044     char buffer2[BUF_TINY];
1045 #ifdef ENABLE_VFS_FTP
1046     char buffer3[BUF_TINY];
1047 
1048     g_snprintf (buffer3, sizeof (buffer3), "%i", ftpfs_directory_timeout);
1049 #endif
1050 
1051     g_snprintf (buffer2, sizeof (buffer2), "%i", vfs_timeout);
1052 
1053     {
1054         char *ret_timeout;
1055 #ifdef ENABLE_VFS_FTP
1056         char *ret_passwd;
1057         char *ret_ftp_proxy;
1058         char *ret_directory_timeout;
1059 #endif
1060 
1061         quick_widget_t quick_widgets[] = {
1062             QUICK_LABELED_INPUT (_ ("Timeout for freeing VFSs (sec):"), input_label_left, buffer2,
1063                                  "input-timo-vfs", &ret_timeout, NULL, FALSE, FALSE,
1064                                  INPUT_COMPLETE_NONE),
1065 #ifdef ENABLE_VFS_FTP
1066             QUICK_SEPARATOR (TRUE),
1067             QUICK_LABELED_INPUT (_ ("FTP anonymous password:"), input_label_left,
1068                                  ftpfs_anonymous_passwd, "input-passwd", &ret_passwd, NULL, FALSE,
1069                                  FALSE, INPUT_COMPLETE_NONE),
1070             QUICK_LABELED_INPUT (_ ("FTP directory cache timeout (sec):"), input_label_left,
1071                                  buffer3, "input-timeout", &ret_directory_timeout, NULL, FALSE,
1072                                  FALSE, INPUT_COMPLETE_NONE),
1073             QUICK_CHECKBOX (_ ("&Always use ftp proxy:"), &ftpfs_always_use_proxy,
1074                             &ftpfs_always_use_proxy_id),
1075             QUICK_INPUT (ftpfs_proxy_host, "input-ftp-proxy", &ret_ftp_proxy, &ftpfs_proxy_host_id,
1076                          FALSE, FALSE, INPUT_COMPLETE_HOSTNAMES),
1077             QUICK_CHECKBOX (_ ("&Use ~/.netrc"), &ftpfs_use_netrc, NULL),
1078             QUICK_CHECKBOX (_ ("Use &passive mode"), &ftpfs_use_passive_connections, NULL),
1079             QUICK_CHECKBOX (_ ("Use passive mode over pro&xy"),
1080                             &ftpfs_use_passive_connections_over_proxy, NULL),
1081 #endif
1082             QUICK_BUTTONS_OK_CANCEL,
1083             QUICK_END,
1084         };
1085 
1086         WRect r = { -1, -1, 0, 56 };
1087 
1088         quick_dialog_t qdlg = {
1089             .rect = r,
1090             .title = _ ("Virtual File System Setting"),
1091             .help = "[Virtual FS]",
1092             .widgets = quick_widgets,
1093 #ifdef ENABLE_VFS_FTP
1094             .callback = confvfs_callback,
1095 #else
1096             .callback = NULL,
1097 #endif
1098             .mouse_callback = NULL,
1099         };
1100 
1101 #ifdef ENABLE_VFS_FTP
1102         if (!ftpfs_always_use_proxy)
1103             quick_widgets[5].state = WST_DISABLED;
1104 #endif
1105 
1106         if (quick_dialog (&qdlg) != B_CANCEL)
1107         {
1108             if (ret_timeout[0] == '\0')
1109                 vfs_timeout = 0;
1110             else
1111                 vfs_timeout = atoi (ret_timeout);
1112             g_free (ret_timeout);
1113 
1114             if (vfs_timeout < 0 || vfs_timeout > 10000)
1115                 vfs_timeout = 10;
1116 #ifdef ENABLE_VFS_FTP
1117             g_free (ftpfs_anonymous_passwd);
1118             ftpfs_anonymous_passwd = ret_passwd;
1119             g_free (ftpfs_proxy_host);
1120             ftpfs_proxy_host = ret_ftp_proxy;
1121             if (ret_directory_timeout[0] == '\0')
1122                 ftpfs_directory_timeout = 0;
1123             else
1124                 ftpfs_directory_timeout = atoi (ret_directory_timeout);
1125             g_free (ret_directory_timeout);
1126 #endif
1127         }
1128     }
1129 }
1130 
1131 #endif
1132 
1133 /* --------------------------------------------------------------------------------------------- */
1134 
1135 char *
1136 cd_box (const WPanel *panel)
     /* [previous][next][first][last][top][bottom][index][help]  */
1137 {
1138     const Widget *w = CONST_WIDGET (panel);
1139     char *my_str = NULL;
1140 
1141     quick_widget_t quick_widgets[] = {
1142         QUICK_LABELED_INPUT (_ ("cd"), input_label_left, "", "input", &my_str, NULL, FALSE, TRUE,
1143                              INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD),
1144         QUICK_END,
1145     };
1146 
1147     WRect r = { w->rect.y + w->rect.lines - 6, w->rect.x, 0, w->rect.cols };
1148 
1149     quick_dialog_t qdlg = {
1150         .rect = r,
1151         .title = _ ("Quick cd"),
1152         .help = "[Quick cd]",
1153         .widgets = quick_widgets,
1154         .callback = NULL,
1155         .mouse_callback = NULL,
1156     };
1157 
1158     return (quick_dialog (&qdlg) != B_CANCEL) ? my_str : NULL;
1159 }
1160 
1161 /* --------------------------------------------------------------------------------------------- */
1162 
1163 void
1164 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]  */
1165              char **ret_new)
1166 {
1167     quick_widget_t quick_widgets[] = {
1168         QUICK_LABELED_INPUT (_ ("Existing filename (filename symlink will point to):"),
1169                              input_label_above, vfs_path_as_str (existing_vpath), "input-2",
1170                              ret_existing, NULL, FALSE, FALSE, INPUT_COMPLETE_FILENAMES),
1171         QUICK_SEPARATOR (FALSE),
1172         QUICK_LABELED_INPUT (_ ("Symbolic link filename:"), input_label_above,
1173                              vfs_path_as_str (new_vpath), "input-1", ret_new, NULL, FALSE, FALSE,
1174                              INPUT_COMPLETE_FILENAMES),
1175         QUICK_BUTTONS_OK_CANCEL,
1176         QUICK_END,
1177     };
1178 
1179     WRect r = { -1, -1, 0, 64 };
1180 
1181     quick_dialog_t qdlg = {
1182         .rect = r,
1183         .title = _ ("Symbolic link"),
1184         .help = "[File Menu]",
1185         .widgets = quick_widgets,
1186         .callback = NULL,
1187         .mouse_callback = NULL,
1188     };
1189 
1190     if (quick_dialog (&qdlg) == B_CANCEL)
1191     {
1192         *ret_new = NULL;
1193         *ret_existing = NULL;
1194     }
1195 }
1196 
1197 /* --------------------------------------------------------------------------------------------- */
1198 
1199 #ifdef ENABLE_BACKGROUND
1200 void
1201 jobs_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1202 {
1203     struct
1204     {
1205         const char *name;
1206         int flags;
1207         int value;
1208         int len;
1209         bcback_fn callback;
1210     } job_but[] = {
1211         { _ ("&Stop"), NORMAL_BUTTON, B_STOP, 0, task_cb },
1212         { _ ("&Resume"), NORMAL_BUTTON, B_RESUME, 0, task_cb },
1213         { _ ("&Kill"), NORMAL_BUTTON, B_KILL, 0, task_cb },
1214         { _ ("&OK"), DEFPUSH_BUTTON, B_CANCEL, 0, NULL },
1215     };
1216 
1217     size_t i;
1218     const size_t n_but = G_N_ELEMENTS (job_but);
1219 
1220     WDialog *jobs_dlg;
1221     WGroup *g;
1222     int cols = 60;
1223     int lines = 15;
1224     int x = 0;
1225 
1226     for (i = 0; i < n_but; i++)
1227     {
1228         job_but[i].len = str_term_width1 (job_but[i].name) + 3;
1229         if (job_but[i].flags == DEFPUSH_BUTTON)
1230             job_but[i].len += 2;
1231         x += job_but[i].len;
1232     }
1233 
1234     x += (int) n_but - 1;
1235     cols = MAX (cols, x + 6);
1236 
1237     jobs_dlg = dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, NULL, NULL,
1238                            "[Background jobs]", _ ("Background jobs"));
1239     g = GROUP (jobs_dlg);
1240 
1241     bg_list = listbox_new (2, 2, lines - 6, cols - 6, FALSE, NULL);
1242     jobs_fill_listbox (bg_list);
1243     group_add_widget (g, bg_list);
1244 
1245     group_add_widget (g, hline_new (lines - 4, -1, -1));
1246 
1247     x = (cols - x) / 2;
1248     for (i = 0; i < n_but; i++)
1249     {
1250         group_add_widget (g,
1251                           button_new (lines - 3, x, job_but[i].value, job_but[i].flags,
1252                                       job_but[i].name, job_but[i].callback));
1253         x += job_but[i].len + 1;
1254     }
1255 
1256     (void) dlg_run (jobs_dlg);
1257     widget_destroy (WIDGET (jobs_dlg));
1258 }
1259 #endif
1260 
1261 /* --------------------------------------------------------------------------------------------- */

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