root/lib/widget/wtools.c

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

DEFINITIONS

This source file includes following definitions.
  1. query_default_callback
  2. do_create_message
  3. fg_message
  4. bg_message
  5. fg_input_dialog_help
  6. wtools_parent_call
  7. wtools_parent_call_string
  8. query_dialog
  9. query_set_sel
  10. create_message
  11. message
  12. mc_error_message
  13. input_dialog_help
  14. input_dialog
  15. input_expand_dialog
  16. status_msg_create
  17. status_msg_destroy
  18. status_msg_init
  19. status_msg_deinit
  20. status_msg_common_update
  21. simple_status_msg_init_cb

   1 /*
   2    Widget based utility functions.
   3 
   4    Copyright (C) 1994-2020
   5    Free Software Foundation, Inc.
   6 
   7    Authors:
   8    Miguel de Icaza, 1994, 1995, 1996
   9    Radek Doulik, 1994, 1995
  10    Jakub Jelinek, 1995
  11    Andrej Borsenkow, 1995
  12    Andrew Borodin <aborodin@vmail.ru>, 2009-2014
  13 
  14    This file is part of the Midnight Commander.
  15 
  16    The Midnight Commander is free software: you can redistribute it
  17    and/or modify it under the terms of the GNU General Public License as
  18    published by the Free Software Foundation, either version 3 of the License,
  19    or (at your option) any later version.
  20 
  21    The Midnight Commander is distributed in the hope that it will be useful,
  22    but WITHOUT ANY WARRANTY; without even the implied warranty of
  23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24    GNU General Public License for more details.
  25 
  26    You should have received a copy of the GNU General Public License
  27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  28  */
  29 
  30 /** \file wtools.c
  31  *  \brief Source: widget based utility functions
  32  */
  33 
  34 #include <config.h>
  35 
  36 #include <stdarg.h>
  37 #include <stdlib.h>
  38 
  39 #include "lib/global.h"
  40 #include "lib/tty/tty.h"
  41 #include "lib/tty/key.h"        /* tty_getch() */
  42 #include "lib/strutil.h"
  43 #include "lib/util.h"           /* tilde_expand() */
  44 #include "lib/widget.h"
  45 #include "lib/event.h"          /* mc_event_raise() */
  46 
  47 /*** global variables ****************************************************************************/
  48 
  49 /*** file scope macro definitions ****************************************************************/
  50 
  51 /*** file scope type declarations ****************************************************************/
  52 
  53 /*** file scope variables ************************************************************************/
  54 
  55 static WDialog *last_query_dlg;
  56 
  57 static int sel_pos = 0;
  58 
  59 /* --------------------------------------------------------------------------------------------- */
  60 /*** file scope functions ************************************************************************/
  61 /* --------------------------------------------------------------------------------------------- */
  62 
  63 /** default query callback, used to reposition query */
  64 
  65 static cb_ret_t
  66 query_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
  67 {
  68     WDialog *h = DIALOG (w);
  69 
  70     switch (msg)
  71     {
  72     case MSG_RESIZE:
  73         if ((w->pos_flags & WPOS_CENTER) == 0)
  74         {
  75             WDialog *prev_dlg = NULL;
  76             int ypos, xpos;
  77             WRect r;
  78 
  79             /* get dialog under h */
  80             if (top_dlg != NULL)
  81             {
  82                 if (top_dlg->data != (void *) h)
  83                     prev_dlg = DIALOG (top_dlg->data);
  84                 else
  85                 {
  86                     GList *p;
  87 
  88                     /* Top dialog is current if it is visible.
  89                        Get previous dialog in stack */
  90                     p = g_list_next (top_dlg);
  91                     if (p != NULL)
  92                         prev_dlg = DIALOG (p->data);
  93                 }
  94             }
  95 
  96             /* if previous dialog is not fullscreen'd -- overlap it */
  97             if (prev_dlg == NULL || (WIDGET (prev_dlg)->pos_flags & WPOS_FULLSCREEN) != 0)
  98                 ypos = LINES / 3 - (w->lines - 3) / 2;
  99             else
 100                 ypos = WIDGET (prev_dlg)->y + 2;
 101 
 102             xpos = COLS / 2 - w->cols / 2;
 103 
 104             /* set position */
 105             rect_init (&r, ypos, xpos, w->lines, w->cols);
 106 
 107             return dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
 108         }
 109         MC_FALLTHROUGH;
 110 
 111     default:
 112         return dlg_default_callback (w, sender, msg, parm, data);
 113     }
 114 }
 115 
 116 /* --------------------------------------------------------------------------------------------- */
 117 /** Create message dialog */
 118 
 119 static WDialog *
 120 do_create_message (int flags, const char *title, const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 121 {
 122     char *p;
 123     WDialog *d;
 124 
 125     /* Add empty lines before and after the message */
 126     p = g_strconcat ("\n", text, "\n", (char *) NULL);
 127     query_dialog (title, p, flags, 0);
 128     d = last_query_dlg;
 129 
 130     /* do resize before initing and running */
 131     send_message (d, NULL, MSG_RESIZE, 0, NULL);
 132 
 133     dlg_init (d);
 134     g_free (p);
 135 
 136     return d;
 137 }
 138 
 139 /* --------------------------------------------------------------------------------------------- */
 140 /**
 141  * Show message dialog.  Dismiss it when any key is pressed.
 142  * Not safe to call from background.
 143  */
 144 
 145 static void
 146 fg_message (int flags, const char *title, const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 147 {
 148     WDialog *d;
 149 
 150     d = do_create_message (flags, title, text);
 151     tty_getch ();
 152     dlg_run_done (d);
 153     dlg_destroy (d);
 154 }
 155 
 156 
 157 /* --------------------------------------------------------------------------------------------- */
 158 /** Show message box from background */
 159 
 160 #ifdef ENABLE_BACKGROUND
 161 static void
 162 bg_message (int dummy, int *flags, char *title, const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 163 {
 164     (void) dummy;
 165     title = g_strconcat (_("Background process:"), " ", title, (char *) NULL);
 166     fg_message (*flags, title, text);
 167     g_free (title);
 168 }
 169 #endif /* ENABLE_BACKGROUND */
 170 
 171 /* --------------------------------------------------------------------------------------------- */
 172 
 173 /**
 174  * Show dialog, not background safe.
 175  *
 176  * If the arguments "header" and "text" should be translated,
 177  * that MUST be done by the caller of fg_input_dialog_help().
 178  *
 179  * The argument "history_name" holds the name of a section
 180  * in the history file. Data entered in the input field of
 181  * the dialog box will be stored there.
 182  *
 183  */
 184 static char *
 185 fg_input_dialog_help (const char *header, const char *text, const char *help,
     /* [previous][next][first][last][top][bottom][index][help]  */
 186                       const char *history_name, const char *def_text, gboolean strip_password,
 187                       input_complete_t completion_flags)
 188 {
 189     char *p_text;
 190     char histname[64] = "inp|";
 191     gboolean is_passwd = FALSE;
 192     char *my_str;
 193     int ret;
 194 
 195     /* label text */
 196     p_text = g_strstrip (g_strdup (text));
 197 
 198     /* input history */
 199     if (history_name != NULL && *history_name != '\0')
 200         g_strlcpy (histname + 3, history_name, sizeof (histname) - 3);
 201 
 202     /* The special value of def_text is used to identify password boxes
 203        and hide characters with "*".  Don't save passwords in history! */
 204     if (def_text == INPUT_PASSWORD)
 205     {
 206         is_passwd = TRUE;
 207         histname[3] = '\0';
 208         def_text = "";
 209     }
 210 
 211     {
 212         quick_widget_t quick_widgets[] = {
 213             /* *INDENT-OFF* */
 214             QUICK_LABELED_INPUT (p_text, input_label_above, def_text, histname, &my_str,
 215                                  NULL, is_passwd, strip_password, completion_flags),
 216             QUICK_BUTTONS_OK_CANCEL,
 217             QUICK_END
 218             /* *INDENT-ON* */
 219         };
 220 
 221         quick_dialog_t qdlg = {
 222             -1, -1, COLS / 2, header,
 223             help, quick_widgets, NULL, NULL
 224         };
 225 
 226         ret = quick_dialog (&qdlg);
 227     }
 228 
 229     g_free (p_text);
 230 
 231     return (ret != B_CANCEL) ? my_str : NULL;
 232 }
 233 
 234 /* --------------------------------------------------------------------------------------------- */
 235 
 236 #ifdef ENABLE_BACKGROUND
 237 static int
 238 wtools_parent_call (void *routine, gpointer ctx, int argc, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 239 {
 240     ev_background_parent_call_t event_data;
 241 
 242     event_data.routine = routine;
 243     event_data.ctx = ctx;
 244     event_data.argc = argc;
 245     va_start (event_data.ap, argc);
 246     mc_event_raise (MCEVENT_GROUP_CORE, "background_parent_call", (gpointer) & event_data);
 247     va_end (event_data.ap);
 248     return event_data.ret.i;
 249 }
 250 
 251 /* --------------------------------------------------------------------------------------------- */
 252 
 253 static char *
 254 wtools_parent_call_string (void *routine, int argc, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 255 {
 256     ev_background_parent_call_t event_data;
 257 
 258     event_data.routine = routine;
 259     event_data.argc = argc;
 260     va_start (event_data.ap, argc);
 261     mc_event_raise (MCEVENT_GROUP_CORE, "background_parent_call_string", (gpointer) & event_data);
 262     va_end (event_data.ap);
 263     return event_data.ret.s;
 264 }
 265 #endif /* ENABLE_BACKGROUND */
 266 
 267 /* --------------------------------------------------------------------------------------------- */
 268 /*** public functions ****************************************************************************/
 269 /* --------------------------------------------------------------------------------------------- */
 270 
 271 /** Used to ask questions to the user */
 272 int
 273 query_dialog (const char *header, const char *text, int flags, int count, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 274 {
 275     va_list ap;
 276     WDialog *query_dlg;
 277     WGroup *g;
 278     WButton *button;
 279     int win_len = 0;
 280     int i;
 281     int result = -1;
 282     int cols, lines;
 283     const int *query_colors = (flags & D_ERROR) != 0 ? alarm_colors : dialog_colors;
 284     widget_pos_flags_t pos_flags =
 285         (flags & D_CENTER) != 0 ? (WPOS_CENTER | WPOS_TRYUP) : WPOS_KEEP_DEFAULT;
 286 
 287     if (header == MSG_ERROR)
 288         header = _("Error");
 289 
 290     if (count > 0)
 291     {
 292         va_start (ap, count);
 293         for (i = 0; i < count; i++)
 294         {
 295             char *cp = va_arg (ap, char *);
 296 
 297             win_len += str_term_width1 (cp) + 6;
 298             if (strchr (cp, '&') != NULL)
 299                 win_len--;
 300         }
 301         va_end (ap);
 302     }
 303 
 304     /* count coordinates */
 305     str_msg_term_size (text, &lines, &cols);
 306     cols = 6 + MAX (win_len, MAX (str_term_width1 (header), cols));
 307     lines += 4 + (count > 0 ? 2 : 0);
 308 
 309     /* prepare dialog */
 310     query_dlg =
 311         dlg_create (TRUE, 0, 0, lines, cols, pos_flags, FALSE, query_colors, query_default_callback,
 312                     NULL, "[QueryBox]", header);
 313     g = GROUP (query_dlg);
 314 
 315     if (count > 0)
 316     {
 317         WButton *defbutton = NULL;
 318 
 319         group_add_widget_autopos (g, label_new (2, 3, text), WPOS_KEEP_TOP | WPOS_CENTER_HORZ,
 320                                   NULL);
 321         group_add_widget (g, hline_new (lines - 4, -1, -1));
 322 
 323         cols = (cols - win_len - 2) / 2 + 2;
 324         va_start (ap, count);
 325         for (i = 0; i < count; i++)
 326         {
 327             int xpos;
 328             char *cur_name;
 329 
 330             cur_name = va_arg (ap, char *);
 331             xpos = str_term_width1 (cur_name) + 6;
 332             if (strchr (cur_name, '&') != NULL)
 333                 xpos--;
 334 
 335             button = button_new (lines - 3, cols, B_USER + i, NORMAL_BUTTON, cur_name, NULL);
 336             group_add_widget (g, button);
 337             cols += xpos;
 338             if (i == sel_pos)
 339                 defbutton = button;
 340         }
 341         va_end (ap);
 342 
 343         /* do resize before running and selecting any widget */
 344         send_message (query_dlg, NULL, MSG_RESIZE, 0, NULL);
 345 
 346         if (defbutton != NULL)
 347             widget_select (WIDGET (defbutton));
 348 
 349         /* run dialog and make result */
 350         switch (dlg_run (query_dlg))
 351         {
 352         case B_CANCEL:
 353             break;
 354         default:
 355             result = query_dlg->ret_value - B_USER;
 356         }
 357 
 358         /* free used memory */
 359         dlg_destroy (query_dlg);
 360     }
 361     else
 362     {
 363         group_add_widget_autopos (g, label_new (2, 3, text), WPOS_KEEP_TOP | WPOS_CENTER_HORZ,
 364                                   NULL);
 365         group_add_widget (g, button_new (0, 0, 0, HIDDEN_BUTTON, "-", NULL));
 366         last_query_dlg = query_dlg;
 367     }
 368     sel_pos = 0;
 369     return result;
 370 }
 371 
 372 /* --------------------------------------------------------------------------------------------- */
 373 
 374 void
 375 query_set_sel (int new_sel)
     /* [previous][next][first][last][top][bottom][index][help]  */
 376 {
 377     sel_pos = new_sel;
 378 }
 379 
 380 /* --------------------------------------------------------------------------------------------- */
 381 /**
 382  * Create message dialog.  The caller must call dlg_run_done() and
 383  * dlg_destroy() to dismiss it.  Not safe to call from background.
 384  */
 385 
 386 WDialog *
 387 create_message (int flags, const char *title, const char *text, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 388 {
 389     va_list args;
 390     WDialog *d;
 391     char *p;
 392 
 393     va_start (args, text);
 394     p = g_strdup_vprintf (text, args);
 395     va_end (args);
 396 
 397     d = do_create_message (flags, title, p);
 398     g_free (p);
 399 
 400     return d;
 401 }
 402 
 403 /* --------------------------------------------------------------------------------------------- */
 404 /** Show message box, background safe */
 405 
 406 void
 407 message (int flags, const char *title, const char *text, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 408 {
 409     char *p;
 410     va_list ap;
 411 
 412     va_start (ap, text);
 413     p = g_strdup_vprintf (text, ap);
 414     va_end (ap);
 415 
 416     if (title == MSG_ERROR)
 417         title = _("Error");
 418 
 419 #ifdef ENABLE_BACKGROUND
 420     if (mc_global.we_are_background)
 421     {
 422         union
 423         {
 424             void *p;
 425             void (*f) (int, int *, char *, const char *);
 426         } func;
 427         func.f = bg_message;
 428 
 429         wtools_parent_call (func.p, NULL, 3, sizeof (flags), &flags, strlen (title), title,
 430                             strlen (p), p);
 431     }
 432     else
 433 #endif /* ENABLE_BACKGROUND */
 434         fg_message (flags, title, p);
 435 
 436     g_free (p);
 437 }
 438 
 439 /* --------------------------------------------------------------------------------------------- */
 440 /** Show error message box */
 441 
 442 gboolean
 443 mc_error_message (GError ** mcerror, int *code)
     /* [previous][next][first][last][top][bottom][index][help]  */
 444 {
 445     if (mcerror == NULL || *mcerror == NULL)
 446         return FALSE;
 447 
 448     if ((*mcerror)->code == 0)
 449         message (D_ERROR, MSG_ERROR, "%s", (*mcerror)->message);
 450     else
 451         message (D_ERROR, MSG_ERROR, _("%s (%d)"), (*mcerror)->message, (*mcerror)->code);
 452 
 453     if (code != NULL)
 454         *code = (*mcerror)->code;
 455 
 456     g_error_free (*mcerror);
 457     *mcerror = NULL;
 458 
 459     return TRUE;
 460 }
 461 
 462 /* --------------------------------------------------------------------------------------------- */
 463 /**
 464  * Show input dialog, background safe.
 465  *
 466  * If the arguments "header" and "text" should be translated,
 467  * that MUST be done by the caller of these wrappers.
 468  */
 469 
 470 char *
 471 input_dialog_help (const char *header, const char *text, const char *help,
     /* [previous][next][first][last][top][bottom][index][help]  */
 472                    const char *history_name, const char *def_text, gboolean strip_password,
 473                    input_complete_t completion_flags)
 474 {
 475 #ifdef ENABLE_BACKGROUND
 476     if (mc_global.we_are_background)
 477     {
 478         union
 479         {
 480             void *p;
 481             char *(*f) (const char *, const char *, const char *, const char *, const char *,
 482                         gboolean, input_complete_t);
 483         } func;
 484         func.f = fg_input_dialog_help;
 485         return wtools_parent_call_string (func.p, 7,
 486                                           strlen (header), header, strlen (text),
 487                                           text, strlen (help), help,
 488                                           strlen (history_name), history_name,
 489                                           strlen (def_text), def_text,
 490                                           sizeof (gboolean), strip_password,
 491                                           sizeof (input_complete_t), completion_flags);
 492     }
 493     else
 494 #endif /* ENABLE_BACKGROUND */
 495         return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password,
 496                                      completion_flags);
 497 }
 498 
 499 /* --------------------------------------------------------------------------------------------- */
 500 /** Show input dialog with default help, background safe */
 501 
 502 char *
 503 input_dialog (const char *header, const char *text, const char *history_name, const char *def_text,
     /* [previous][next][first][last][top][bottom][index][help]  */
 504               input_complete_t completion_flags)
 505 {
 506     return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE,
 507                               completion_flags);
 508 }
 509 
 510 /* --------------------------------------------------------------------------------------------- */
 511 
 512 char *
 513 input_expand_dialog (const char *header, const char *text,
     /* [previous][next][first][last][top][bottom][index][help]  */
 514                      const char *history_name, const char *def_text,
 515                      input_complete_t completion_flags)
 516 {
 517     char *result;
 518 
 519     result = input_dialog (header, text, history_name, def_text, completion_flags);
 520     if (result)
 521     {
 522         char *expanded;
 523 
 524         expanded = tilde_expand (result);
 525         g_free (result);
 526         return expanded;
 527     }
 528     return result;
 529 }
 530 
 531 /* --------------------------------------------------------------------------------------------- */
 532 /**
 533  * Create status message window object and initialize it
 534  *
 535  * @param title window title
 536  * @param delay initial delay to raise window in seconds
 537  * @param init_cb callback to initialize user-defined part of status message
 538  * @param update_cb callback to update of status message
 539  * @param deinit_cb callback to deinitialize user-defined part of status message
 540  *
 541  * @return newly allocate status message window
 542  */
 543 
 544 status_msg_t *
 545 status_msg_create (const char *title, double delay, status_msg_cb init_cb,
     /* [previous][next][first][last][top][bottom][index][help]  */
 546                    status_msg_update_cb update_cb, status_msg_cb deinit_cb)
 547 {
 548     status_msg_t *sm;
 549 
 550     sm = g_try_new (status_msg_t, 1);
 551     status_msg_init (sm, title, delay, init_cb, update_cb, deinit_cb);
 552 
 553     return sm;
 554 }
 555 
 556 /* --------------------------------------------------------------------------------------------- */
 557 /**
 558  * Destroy status message window object
 559  *
 560  * @param sm status message window object
 561  */
 562 
 563 void
 564 status_msg_destroy (status_msg_t * sm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 565 {
 566     status_msg_deinit (sm);
 567     g_free (sm);
 568 }
 569 
 570 /* --------------------------------------------------------------------------------------------- */
 571 /**
 572  * Initialize already created status message window object
 573  *
 574  * @param sm status message window object
 575  * @param title window title
 576  * @param delay initial delay to raise window in seconds
 577  * @param init_cb callback to initialize user-defined part of status message
 578  * @param update_cb callback to update of status message
 579  * @param deinit_cb callback to deinitialize user-defined part of status message
 580  */
 581 
 582 void
 583 status_msg_init (status_msg_t * sm, const char *title, double delay, status_msg_cb init_cb,
     /* [previous][next][first][last][top][bottom][index][help]  */
 584                  status_msg_update_cb update_cb, status_msg_cb deinit_cb)
 585 {
 586     guint64 start;
 587 
 588     /* repaint screen to remove previous finished dialog */
 589     mc_refresh ();
 590 
 591     start = mc_timer_elapsed (mc_global.timer);
 592 
 593     sm->dlg = dlg_create (TRUE, 0, 0, 7, MIN (MAX (40, COLS / 2), COLS), WPOS_CENTER, FALSE,
 594                           dialog_colors, NULL, NULL, NULL, title);
 595     sm->start = start;
 596     sm->delay = (guint64) (delay * G_USEC_PER_SEC);
 597     sm->block = FALSE;
 598 
 599     sm->init = init_cb;
 600     sm->update = update_cb;
 601     sm->deinit = deinit_cb;
 602 
 603     if (sm->init != NULL)
 604         sm->init (sm);
 605 
 606     if (mc_time_elapsed (&start, sm->delay))
 607     {
 608         /* We will manage the dialog without any help, that's why we have to call dlg_init */
 609         dlg_init (sm->dlg);
 610     }
 611 }
 612 
 613 /* --------------------------------------------------------------------------------------------- */
 614 /**
 615  * Deinitialize status message window object
 616  *
 617  * @param sm status message window object
 618  */
 619 
 620 void
 621 status_msg_deinit (status_msg_t * sm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 622 {
 623     if (sm == NULL)
 624         return;
 625 
 626     if (sm->deinit != NULL)
 627         sm->deinit (sm);
 628 
 629     /* close and destroy dialog */
 630     dlg_run_done (sm->dlg);
 631     dlg_destroy (sm->dlg);
 632 }
 633 
 634 /* --------------------------------------------------------------------------------------------- */
 635 /**
 636  * Update status message window
 637  *
 638  * @param sm status message window object
 639  *
 640  * @return value of pressed key
 641  */
 642 
 643 int
 644 status_msg_common_update (status_msg_t * sm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 645 {
 646     int c;
 647     Gpm_Event event;
 648 
 649     if (sm == NULL)
 650         return B_ENTER;
 651 
 652     /* This should not happen, but... */
 653     if (sm->dlg == NULL)
 654         return B_ENTER;
 655 
 656     if (widget_get_state (WIDGET (sm->dlg), WST_CONSTRUCT))
 657     {
 658         /* dialog is not shown yet */
 659 
 660         /* do not change sm->start */
 661         guint64 start = sm->start;
 662 
 663         if (mc_time_elapsed (&start, sm->delay))
 664             dlg_init (sm->dlg);
 665 
 666         return B_ENTER;
 667     }
 668 
 669     event.x = -1;               /* Don't show the GPM cursor */
 670     c = tty_get_event (&event, FALSE, sm->block);
 671     if (c == EV_NONE)
 672         return B_ENTER;
 673 
 674     /* Reinitialize by non-B_CANCEL value to avoid old values
 675        after events other than selecting a button */
 676     sm->dlg->ret_value = B_ENTER;
 677     dlg_process_event (sm->dlg, c, &event);
 678 
 679     return sm->dlg->ret_value;
 680 }
 681 
 682 /* --------------------------------------------------------------------------------------------- */
 683 /**
 684  * Callback to initialize already created simple status message window object
 685  *
 686  * @param sm status message window object
 687  */
 688 
 689 void
 690 simple_status_msg_init_cb (status_msg_t * sm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 691 {
 692     simple_status_msg_t *ssm = SIMPLE_STATUS_MSG (sm);
 693     Widget *wd = WIDGET (sm->dlg);
 694     WGroup *wg = GROUP (sm->dlg);
 695 
 696     const char *b_name = N_("&Abort");
 697     int b_width;
 698     int wd_width, y;
 699     Widget *b;
 700 
 701 #ifdef ENABLE_NLS
 702     b_name = _(b_name);
 703 #endif
 704 
 705     b_width = str_term_width1 (b_name) + 4;
 706     wd_width = MAX (wd->cols, b_width + 6);
 707 
 708     y = 2;
 709     ssm->label = label_new (y++, 3, "");
 710     group_add_widget_autopos (wg, ssm->label, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, NULL);
 711     group_add_widget (wg, hline_new (y++, -1, -1));
 712     b = WIDGET (button_new (y++, 3, B_CANCEL, NORMAL_BUTTON, b_name, NULL));
 713     group_add_widget_autopos (wg, b, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, NULL);
 714 
 715     widget_set_size (wd, wd->y, wd->x, y + 2, wd_width);
 716 }
 717 
 718 /* --------------------------------------------------------------------------------------------- */

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