Manual pages: mcmcdiffmceditmcview

root/src/filemanager/boxes.c

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

DEFINITIONS

This source file includes following definitions.
  1. configure_callback
  2. skin_apply
  3. skin_name_to_label
  4. skin_dlg_callback
  5. sel_skin_button
  6. appearance_box_callback
  7. panel_listing_callback
  8. tree_callback
  9. confvfs_callback
  10. jobs_fill_listbox
  11. task_cb
  12. about_box
  13. configure_box
  14. appearance_box
  15. panel_options_box
  16. panel_listing_box
  17. sort_box
  18. confirm_box
  19. tree_box
  20. configure_vfs_box
  21. cd_box
  22. symlink_box
  23. jobs_box

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

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