Manual pages: mc • mcdiff • mcedit • mcview

root/src/filemanager/boxes.c

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

DEFINITIONS

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

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

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