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

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