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

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