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 
 498     const char *name_cp_display =
 499         ((codepage_desc *) g_ptr_array_index (codepages, mc_global.display_codepage))->name;
 500 
 501     const char *name_cp_source = mc_global.source_codepage >= 0
 502         ? ((codepage_desc *) g_ptr_array_index (codepages, mc_global.source_codepage))->name
 503         : N_ ("No translation");
 504 
 505     label_cp_display =
 506         g_strdup_printf ("%s: %s", N_ ("Detected display codepage"), name_cp_display);
 507     label_cp_source =
 508         g_strdup_printf ("%s: %s", N_ ("Selected source (file I/O) codepage"), name_cp_source);
 509 
 510     quick_widget_t quick_widgets[] = {
 511         QUICK_LABEL (version, NULL),
 512         QUICK_SEPARATOR (TRUE),
 513         QUICK_LABEL (N_ ("Classic terminal file manager inspired by Norton Commander."), NULL),
 514         QUICK_SEPARATOR (FALSE),
 515         QUICK_LABEL (PACKAGE_COPYRIGHT, NULL),
 516         QUICK_SEPARATOR (TRUE),
 517         QUICK_LABEL (label_cp_display, NULL),
 518         QUICK_LABEL (label_cp_source, NULL),
 519         QUICK_START_BUTTONS (TRUE, TRUE),
 520         QUICK_BUTTON (N_ ("&OK"), B_ENTER, NULL, NULL),
 521         QUICK_END,
 522     };
 523 
 524     WRect r = { -1, -1, 0, 40 };
 525 
 526     quick_dialog_t qdlg = {
 527         .rect = r,
 528         .title = N_ ("About"),
 529         .help = "[Overview]",
 530         .widgets = quick_widgets,
 531         .callback = NULL,
 532         .mouse_callback = NULL,
 533     };
 534 
 535     quick_widgets[0].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 536     quick_widgets[2].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 537     quick_widgets[4].pos_flags = WPOS_KEEP_TOP | WPOS_CENTER_HORZ;
 538 
 539     (void) quick_dialog (&qdlg);
 540 
 541     g_free (version);
 542     g_free (label_cp_display);
 543     g_free (label_cp_source);
 544 }
 545 
 546 /* --------------------------------------------------------------------------------------------- */
 547 
 548 void
 549 configure_box (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 550 {
 551     const char *pause_options[] = {
 552         N_ ("&Never"),
 553         N_ ("On dum&b terminals"),
 554         N_ ("Alwa&ys"),
 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 (N_ ("File operations")),
 566                     QUICK_CHECKBOX (N_ ("&Verbose operation"), &verbose, NULL),
 567                     QUICK_CHECKBOX (N_ ("Compute tota&ls"), &file_op_compute_totals, NULL),
 568                     QUICK_CHECKBOX (N_ ("Classic pro&gressbar"), &classic_progressbar, NULL),
 569                     QUICK_CHECKBOX (N_ ("Mkdi&r autoname"), &auto_fill_mkdir_name, NULL),
 570                     QUICK_CHECKBOX (N_ ("&Preallocate space"), &mc_global.vfs.preallocate_space,
 571                                     NULL),
 572                 QUICK_STOP_GROUPBOX,
 573                 QUICK_START_GROUPBOX (N_ ("Esc key mode")),
 574                     QUICK_CHECKBOX (N_ ("S&ingle press"), &old_esc_mode, &configure_old_esc_mode_id),
 575                     QUICK_LABELED_INPUT (N_ ("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 (N_ ("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 (N_ ("Other options")),
 585                     QUICK_CHECKBOX (N_ ("Use internal edi&t"), &use_internal_edit, NULL),
 586                     QUICK_CHECKBOX (N_ ("Use internal vie&w"), &use_internal_view, NULL),
 587                     QUICK_CHECKBOX (N_ ("A&sk new file name"),
 588                                     &editor_ask_filename_before_edit, NULL),
 589                     QUICK_CHECKBOX (N_ ("Auto m&enus"), &auto_menu, NULL),
 590                     QUICK_CHECKBOX (N_ ("&Drop down menus"), &drop_menus, NULL),
 591                     QUICK_CHECKBOX (N_ ("S&hell patterns"), &easy_patterns, NULL),
 592                     QUICK_CHECKBOX (N_ ("Co&mplete: show all"),
 593                                     &mc_global.widget.show_all_if_ambiguous, NULL),
 594                     QUICK_CHECKBOX (N_ ("Rotating d&ash"), &nice_rotating_dash, NULL),
 595                     QUICK_CHECKBOX (N_ ("Cd follows lin&ks"), &mc_global.vfs.cd_symlinks, NULL),
 596                     QUICK_CHECKBOX (N_ ("Sa&fe delete"), &safe_delete, NULL),
 597                     QUICK_CHECKBOX (N_ ("Safe overwrite"), &safe_overwrite, NULL),       // w/o hotkey
 598                     QUICK_CHECKBOX (N_ ("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 = N_ ("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 (N_ ("Skin:"), NULL),
 660             QUICK_NEXT_COLUMN,
 661                 QUICK_BUTTON (str_fit_to_term (skin_name_to_label (current_skin_name), 20,
 662                               J_LEFT_FIT), B_USER, sel_skin_button, NULL),
 663             QUICK_STOP_COLUMNS,
 664             QUICK_SEPARATOR (TRUE),
 665             QUICK_CHECKBOX (N_ ("&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 = N_ ("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             N_ ("Case &insensitive"),
 708             N_ ("Cas&e sensitive"),
 709             N_ ("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 (N_ ("Main options")),
 716                     QUICK_CHECKBOX (N_ ("Show mi&ni-status"), &panels_options.show_mini_info, NULL),
 717                     QUICK_CHECKBOX (N_ ("Use SI si&ze units"), &panels_options.kilobyte_si, NULL),
 718                     QUICK_CHECKBOX (N_ ("Mi&x all files"), &panels_options.mix_all_files, NULL),
 719                     QUICK_CHECKBOX (N_ ("Show &backup files"), &panels_options.show_backups, NULL),
 720                     QUICK_CHECKBOX (N_ ("Show &hidden files"), &panels_options.show_dot_files, NULL),
 721                     QUICK_CHECKBOX (N_ ("&Fast dir reload"), &panels_options.fast_reload, NULL),
 722                     QUICK_CHECKBOX (N_ ("Ma&rk moves down"), &panels_options.mark_moves_down, NULL),
 723                     QUICK_CHECKBOX (N_ ("Re&verse files only"), &panels_options.reverse_files_only,
 724                                     NULL),
 725                     QUICK_CHECKBOX (N_ ("Simple s&wap"), &simple_swap, NULL),
 726                     QUICK_CHECKBOX (N_ ("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 (N_ ("Navigation")),
 734                     QUICK_CHECKBOX (N_ ("L&ynx-like motion"), &panels_options.navigate_with_arrows,
 735                                     NULL),
 736                     QUICK_CHECKBOX (N_ ("Pa&ge scrolling"), &panels_options.scroll_pages, NULL),
 737                     QUICK_CHECKBOX (N_ ("Center &scrolling"), &panels_options.scroll_center, NULL),
 738                     QUICK_CHECKBOX (N_ ("&Mouse page scrolling"), &panels_options.mouse_move_pages,
 739                                     NULL),
 740                 QUICK_STOP_GROUPBOX,
 741                 QUICK_START_GROUPBOX (N_ ("File highlight")),
 742                     QUICK_CHECKBOX (N_ ("File &types"), &panels_options.filetype_mode, NULL),
 743                     QUICK_CHECKBOX (N_ ("&Permissions"), &panels_options.permission_mode, NULL),
 744                 QUICK_STOP_GROUPBOX,
 745                 QUICK_START_GROUPBOX (N_ ("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 = N_ ("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             N_ ("&Full file list"),
 811             N_ ("&Brief file list:"),
 812             N_ ("&Long file list"),
 813             N_ ("&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 (N_ ("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 (N_ ("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 = N_ ("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 (N_ ("Executable &first"), &op->exec_first, NULL),
 924                 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &op->case_sensitive, NULL),
 925                 QUICK_CHECKBOX (N_ ("&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 = N_ ("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 = N_ ("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 (N_ ("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 (N_ ("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 (N_ ("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 (N_ ("&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 (N_ ("&Use ~/.netrc"), &ftpfs_use_netrc, NULL),
1072             QUICK_CHECKBOX (N_ ("Use &passive mode"), &ftpfs_use_passive_connections, NULL),
1073             QUICK_CHECKBOX (N_ ("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 = N_ ("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 (N_ ("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 = N_ ("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 (N_ ("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 (N_ ("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 = N_ ("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         { N_ ("&Stop"), NORMAL_BUTTON, B_STOP, 0, task_cb },
1206         { N_ ("&Resume"), NORMAL_BUTTON, B_RESUME, 0, task_cb },
1207         { N_ ("&Kill"), NORMAL_BUTTON, B_KILL, 0, task_cb },
1208         { N_ ("&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 #ifdef ENABLE_NLS
1223         job_but[i].name = _ (job_but[i].name);
1224 #endif
1225 
1226         job_but[i].len = str_term_width1 (job_but[i].name) + 3;
1227         if (job_but[i].flags == DEFPUSH_BUTTON)
1228             job_but[i].len += 2;
1229         x += job_but[i].len;
1230     }
1231 
1232     x += (int) n_but - 1;
1233     cols = MAX (cols, x + 6);
1234 
1235     jobs_dlg = dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, NULL, NULL,
1236                            "[Background jobs]", _ ("Background jobs"));
1237     g = GROUP (jobs_dlg);
1238 
1239     bg_list = listbox_new (2, 2, lines - 6, cols - 6, FALSE, NULL);
1240     jobs_fill_listbox (bg_list);
1241     group_add_widget (g, bg_list);
1242 
1243     group_add_widget (g, hline_new (lines - 4, -1, -1));
1244 
1245     x = (cols - x) / 2;
1246     for (i = 0; i < n_but; i++)
1247     {
1248         group_add_widget (g,
1249                           button_new (lines - 3, x, job_but[i].value, job_but[i].flags,
1250                                       job_but[i].name, job_but[i].callback));
1251         x += job_but[i].len + 1;
1252     }
1253 
1254     (void) dlg_run (jobs_dlg);
1255     widget_destroy (WIDGET (jobs_dlg));
1256 }
1257 #endif
1258 
1259 /* --------------------------------------------------------------------------------------------- */

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