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

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