2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Widget based utility functions.
|
|
|
|
|
2024-01-01 09:46:17 +03:00
|
|
|
Copyright (C) 1994-2024
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
2011-10-15 14:56:47 +04:00
|
|
|
|
|
|
|
Authors:
|
|
|
|
Miguel de Icaza, 1994, 1995, 1996
|
|
|
|
Radek Doulik, 1994, 1995
|
|
|
|
Jakub Jelinek, 1995
|
|
|
|
Andrej Borsenkow, 1995
|
2022-05-01 10:39:14 +03:00
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2009-2022
|
2009-09-04 09:49:51 +04:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
This file is part of the Midnight Commander.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is free software: you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
1998-02-27 07:54:42 +03:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2011-10-15 14:56:47 +04:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1998-02-27 07:54:42 +03:00
|
|
|
*/
|
|
|
|
|
2009-02-05 21:28:18 +03:00
|
|
|
/** \file wtools.c
|
|
|
|
* \brief Source: widget based utility functions
|
|
|
|
*/
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <config.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <stdarg.h>
|
2010-11-12 11:03:57 +03:00
|
|
|
#include <stdlib.h>
|
2001-09-03 09:07:40 +04:00
|
|
|
|
2010-01-20 18:11:52 +03:00
|
|
|
#include "lib/global.h"
|
2010-01-08 17:47:19 +03:00
|
|
|
#include "lib/tty/tty.h"
|
2010-06-28 16:22:49 +04:00
|
|
|
#include "lib/tty/key.h" /* tty_getch() */
|
2010-01-21 15:17:26 +03:00
|
|
|
#include "lib/strutil.h"
|
2010-11-12 11:03:57 +03:00
|
|
|
#include "lib/util.h" /* tilde_expand() */
|
|
|
|
#include "lib/widget.h"
|
2011-02-18 15:50:30 +03:00
|
|
|
#include "lib/event.h" /* mc_event_raise() */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
|
|
|
|
|
|
|
/*** file scope macro definitions ****************************************************************/
|
|
|
|
|
|
|
|
/*** file scope type declarations ****************************************************************/
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/*** forward declarations (file scope functions) *************************************************/
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope variables ************************************************************************/
|
|
|
|
|
2012-09-28 11:18:45 +04:00
|
|
|
static WDialog *last_query_dlg;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
static int sel_pos = 0;
|
|
|
|
|
2013-03-10 14:31:33 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** default query callback, used to reposition query */
|
|
|
|
|
|
|
|
static cb_ret_t
|
2024-06-01 21:12:14 +03:00
|
|
|
query_default_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
2012-09-28 15:05:43 +04:00
|
|
|
WDialog *h = DIALOG (w);
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
switch (msg)
|
|
|
|
{
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_RESIZE:
|
2016-05-08 21:10:05 +03:00
|
|
|
if ((w->pos_flags & WPOS_CENTER) == 0)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *prev_dlg = NULL;
|
2011-08-09 11:37:41 +04:00
|
|
|
int ypos, xpos;
|
2016-10-14 15:28:00 +03:00
|
|
|
WRect r;
|
2011-08-09 11:37:41 +04:00
|
|
|
|
|
|
|
/* get dialog under h */
|
|
|
|
if (top_dlg != NULL)
|
|
|
|
{
|
|
|
|
if (top_dlg->data != (void *) h)
|
2012-09-28 11:18:45 +04:00
|
|
|
prev_dlg = DIALOG (top_dlg->data);
|
2011-08-09 11:37:41 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
GList *p;
|
|
|
|
|
|
|
|
/* Top dialog is current if it is visible.
|
|
|
|
Get previous dialog in stack */
|
|
|
|
p = g_list_next (top_dlg);
|
|
|
|
if (p != NULL)
|
2012-09-28 11:18:45 +04:00
|
|
|
prev_dlg = DIALOG (p->data);
|
2011-08-09 11:37:41 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if previous dialog is not fullscreen'd -- overlap it */
|
2016-05-08 21:10:05 +03:00
|
|
|
if (prev_dlg == NULL || (WIDGET (prev_dlg)->pos_flags & WPOS_FULLSCREEN) != 0)
|
2022-05-01 10:43:33 +03:00
|
|
|
ypos = LINES / 3 - (w->rect.lines - 3) / 2;
|
2011-08-09 11:37:41 +04:00
|
|
|
else
|
2022-05-01 10:43:33 +03:00
|
|
|
ypos = WIDGET (prev_dlg)->rect.y + 2;
|
2011-08-09 11:37:41 +04:00
|
|
|
|
2022-05-22 15:30:55 +03:00
|
|
|
/* if dialog is too high, place it centered */
|
2022-06-05 20:12:46 +03:00
|
|
|
if (ypos + w->rect.lines < LINES / 2)
|
2022-05-22 15:30:55 +03:00
|
|
|
w->pos_flags |= WPOS_CENTER;
|
|
|
|
|
2022-05-01 10:43:33 +03:00
|
|
|
xpos = COLS / 2 - w->rect.cols / 2;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
/* set position */
|
2022-05-01 10:43:33 +03:00
|
|
|
rect_init (&r, ypos, xpos, w->rect.lines, w->rect.cols);
|
2011-10-23 11:08:24 +04:00
|
|
|
|
2016-10-13 10:15:03 +03:00
|
|
|
return dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
|
2010-11-10 14:09:42 +03:00
|
|
|
}
|
2017-12-16 20:52:39 +03:00
|
|
|
MC_FALLTHROUGH;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
default:
|
2012-09-28 15:05:43 +04:00
|
|
|
return dlg_default_callback (w, sender, msg, parm, data);
|
2010-11-10 14:09:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Create message dialog */
|
|
|
|
|
2016-03-03 22:51:40 +03:00
|
|
|
static WDialog *
|
2010-11-10 14:09:42 +03:00
|
|
|
do_create_message (int flags, const char *title, const char *text)
|
|
|
|
{
|
|
|
|
char *p;
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *d;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
/* Add empty lines before and after the message */
|
|
|
|
p = g_strconcat ("\n", text, "\n", (char *) NULL);
|
|
|
|
query_dialog (title, p, flags, 0);
|
|
|
|
d = last_query_dlg;
|
|
|
|
|
|
|
|
/* do resize before initing and running */
|
2012-09-28 15:05:43 +04:00
|
|
|
send_message (d, NULL, MSG_RESIZE, 0, NULL);
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2013-06-24 11:40:53 +04:00
|
|
|
dlg_init (d);
|
2010-11-10 14:09:42 +03:00
|
|
|
g_free (p);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Show message dialog. Dismiss it when any key is pressed.
|
|
|
|
* Not safe to call from background.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
fg_message (int flags, const char *title, const char *text)
|
|
|
|
{
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *d;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
d = do_create_message (flags, title, text);
|
|
|
|
tty_getch ();
|
|
|
|
dlg_run_done (d);
|
2020-10-31 19:32:29 +03:00
|
|
|
widget_destroy (WIDGET (d));
|
2010-11-10 14:09:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Show message box from background */
|
|
|
|
|
2012-01-09 15:48:39 +04:00
|
|
|
#ifdef ENABLE_BACKGROUND
|
2010-11-10 14:09:42 +03:00
|
|
|
static void
|
|
|
|
bg_message (int dummy, int *flags, char *title, const char *text)
|
|
|
|
{
|
|
|
|
(void) dummy;
|
|
|
|
title = g_strconcat (_("Background process:"), " ", title, (char *) NULL);
|
|
|
|
fg_message (*flags, title, text);
|
|
|
|
g_free (title);
|
|
|
|
}
|
2012-01-09 15:48:39 +04:00
|
|
|
#endif /* ENABLE_BACKGROUND */
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show dialog, not background safe.
|
|
|
|
*
|
|
|
|
* If the arguments "header" and "text" should be translated,
|
|
|
|
* that MUST be done by the caller of fg_input_dialog_help().
|
|
|
|
*
|
|
|
|
* The argument "history_name" holds the name of a section
|
|
|
|
* in the history file. Data entered in the input field of
|
|
|
|
* the dialog box will be stored there.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
fg_input_dialog_help (const char *header, const char *text, const char *help,
|
2013-01-25 16:41:41 +04:00
|
|
|
const char *history_name, const char *def_text, gboolean strip_password,
|
|
|
|
input_complete_t completion_flags)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
|
|
|
char *p_text;
|
2012-09-07 14:48:29 +04:00
|
|
|
char histname[64] = "inp|";
|
2013-01-25 16:41:41 +04:00
|
|
|
gboolean is_passwd = FALSE;
|
2012-09-07 14:48:29 +04:00
|
|
|
char *my_str;
|
2010-11-10 14:09:42 +03:00
|
|
|
int ret;
|
|
|
|
|
2012-09-07 14:48:29 +04:00
|
|
|
/* label text */
|
|
|
|
p_text = g_strstrip (g_strdup (text));
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2012-09-07 14:48:29 +04:00
|
|
|
/* input history */
|
2010-11-10 14:09:42 +03:00
|
|
|
if (history_name != NULL && *history_name != '\0')
|
|
|
|
g_strlcpy (histname + 3, history_name, sizeof (histname) - 3);
|
|
|
|
|
|
|
|
/* The special value of def_text is used to identify password boxes
|
|
|
|
and hide characters with "*". Don't save passwords in history! */
|
|
|
|
if (def_text == INPUT_PASSWORD)
|
|
|
|
{
|
2013-01-25 16:41:41 +04:00
|
|
|
is_passwd = TRUE;
|
2010-11-10 14:09:42 +03:00
|
|
|
histname[3] = '\0';
|
2012-09-07 14:48:29 +04:00
|
|
|
def_text = "";
|
2010-11-10 14:09:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2012-09-07 14:48:29 +04:00
|
|
|
quick_widget_t quick_widgets[] = {
|
2012-09-25 10:20:18 +04:00
|
|
|
/* *INDENT-OFF* */
|
2013-01-25 16:41:41 +04:00
|
|
|
QUICK_LABELED_INPUT (p_text, input_label_above, def_text, histname, &my_str,
|
|
|
|
NULL, is_passwd, strip_password, completion_flags),
|
2012-09-25 10:20:18 +04:00
|
|
|
QUICK_BUTTONS_OK_CANCEL,
|
2012-09-16 12:54:19 +04:00
|
|
|
QUICK_END
|
2012-09-25 10:20:18 +04:00
|
|
|
/* *INDENT-ON* */
|
2010-11-10 14:09:42 +03:00
|
|
|
};
|
|
|
|
|
2022-05-01 10:39:14 +03:00
|
|
|
WRect r = { -1, -1, 0, COLS / 2 };
|
|
|
|
|
2012-09-07 14:48:29 +04:00
|
|
|
quick_dialog_t qdlg = {
|
2022-05-01 10:39:14 +03:00
|
|
|
r, header, help,
|
|
|
|
quick_widgets, NULL, NULL
|
2012-09-07 14:48:29 +04:00
|
|
|
};
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2012-09-16 12:54:19 +04:00
|
|
|
ret = quick_dialog (&qdlg);
|
2010-11-10 14:09:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (p_text);
|
|
|
|
|
|
|
|
return (ret != B_CANCEL) ? my_str : NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-18 15:50:30 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2012-01-09 15:48:39 +04:00
|
|
|
#ifdef ENABLE_BACKGROUND
|
2011-02-18 15:50:30 +03:00
|
|
|
static int
|
|
|
|
wtools_parent_call (void *routine, gpointer ctx, int argc, ...)
|
|
|
|
{
|
|
|
|
ev_background_parent_call_t event_data;
|
|
|
|
|
|
|
|
event_data.routine = routine;
|
|
|
|
event_data.ctx = ctx;
|
|
|
|
event_data.argc = argc;
|
|
|
|
va_start (event_data.ap, argc);
|
|
|
|
mc_event_raise (MCEVENT_GROUP_CORE, "background_parent_call", (gpointer) & event_data);
|
|
|
|
va_end (event_data.ap);
|
|
|
|
return event_data.ret.i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static char *
|
|
|
|
wtools_parent_call_string (void *routine, int argc, ...)
|
|
|
|
{
|
|
|
|
ev_background_parent_call_t event_data;
|
|
|
|
|
|
|
|
event_data.routine = routine;
|
|
|
|
event_data.argc = argc;
|
|
|
|
va_start (event_data.ap, argc);
|
|
|
|
mc_event_raise (MCEVENT_GROUP_CORE, "background_parent_call_string", (gpointer) & event_data);
|
|
|
|
va_end (event_data.ap);
|
|
|
|
return event_data.ret.s;
|
|
|
|
}
|
2012-01-09 15:48:39 +04:00
|
|
|
#endif /* ENABLE_BACKGROUND */
|
2011-02-18 15:50:30 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/** Used to ask questions to the user */
|
2003-09-01 06:07:02 +04:00
|
|
|
int
|
2003-10-26 01:12:05 +04:00
|
|
|
query_dialog (const char *header, const char *text, int flags, int count, ...)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *query_dlg;
|
2016-09-28 11:01:30 +03:00
|
|
|
WGroup *g;
|
2003-09-12 12:28:21 +04:00
|
|
|
WButton *button;
|
1998-02-27 07:54:42 +03:00
|
|
|
int win_len = 0;
|
|
|
|
int i;
|
|
|
|
int result = -1;
|
|
|
|
int cols, lines;
|
2011-10-23 11:08:24 +04:00
|
|
|
const int *query_colors = (flags & D_ERROR) != 0 ? alarm_colors : dialog_colors;
|
2016-05-08 21:10:05 +03:00
|
|
|
widget_pos_flags_t pos_flags =
|
|
|
|
(flags & D_CENTER) != 0 ? (WPOS_CENTER | WPOS_TRYUP) : WPOS_KEEP_DEFAULT;
|
2003-09-01 06:07:02 +04:00
|
|
|
|
1998-03-30 01:07:37 +04:00
|
|
|
if (header == MSG_ERROR)
|
2010-06-28 16:22:49 +04:00
|
|
|
header = _("Error");
|
|
|
|
|
|
|
|
if (count > 0)
|
|
|
|
{
|
|
|
|
va_start (ap, count);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
char *cp = va_arg (ap, char *);
|
2016-09-28 11:01:30 +03:00
|
|
|
|
2010-06-28 16:22:49 +04:00
|
|
|
win_len += str_term_width1 (cp) + 6;
|
|
|
|
if (strchr (cp, '&') != NULL)
|
|
|
|
win_len--;
|
|
|
|
}
|
|
|
|
va_end (ap);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* count coordinates */
|
2008-12-29 01:59:38 +03:00
|
|
|
str_msg_term_size (text, &lines, &cols);
|
2016-04-07 10:52:04 +03:00
|
|
|
cols = 6 + MAX (win_len, MAX (str_term_width1 (header), cols));
|
1998-02-27 07:54:42 +03:00
|
|
|
lines += 4 + (count > 0 ? 2 : 0);
|
|
|
|
|
|
|
|
/* prepare dialog */
|
2003-09-01 06:07:02 +04:00
|
|
|
query_dlg =
|
2016-05-08 21:10:05 +03:00
|
|
|
dlg_create (TRUE, 0, 0, lines, cols, pos_flags, FALSE, query_colors, query_default_callback,
|
|
|
|
NULL, "[QueryBox]", header);
|
2016-09-28 11:01:30 +03:00
|
|
|
g = GROUP (query_dlg);
|
2010-06-28 16:22:49 +04:00
|
|
|
|
|
|
|
if (count > 0)
|
|
|
|
{
|
2013-10-15 10:34:04 +04:00
|
|
|
WButton *defbutton = NULL;
|
|
|
|
|
2016-09-28 11:01:30 +03:00
|
|
|
group_add_widget_autopos (g, label_new (2, 3, text), WPOS_KEEP_TOP | WPOS_CENTER_HORZ,
|
|
|
|
NULL);
|
|
|
|
group_add_widget (g, hline_new (lines - 4, -1, -1));
|
2012-09-24 14:49:24 +04:00
|
|
|
|
2010-06-28 16:22:49 +04:00
|
|
|
cols = (cols - win_len - 2) / 2 + 2;
|
|
|
|
va_start (ap, count);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
int xpos;
|
2013-10-15 10:34:04 +04:00
|
|
|
char *cur_name;
|
2010-06-28 16:22:49 +04:00
|
|
|
|
|
|
|
cur_name = va_arg (ap, char *);
|
|
|
|
xpos = str_term_width1 (cur_name) + 6;
|
|
|
|
if (strchr (cur_name, '&') != NULL)
|
|
|
|
xpos--;
|
|
|
|
|
2012-09-26 15:20:03 +04:00
|
|
|
button = button_new (lines - 3, cols, B_USER + i, NORMAL_BUTTON, cur_name, NULL);
|
2016-09-28 11:01:30 +03:00
|
|
|
group_add_widget (g, button);
|
2010-06-28 16:22:49 +04:00
|
|
|
cols += xpos;
|
|
|
|
if (i == sel_pos)
|
|
|
|
defbutton = button;
|
|
|
|
}
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
/* do resize before running and selecting any widget */
|
2012-09-28 15:05:43 +04:00
|
|
|
send_message (query_dlg, NULL, MSG_RESIZE, 0, NULL);
|
2010-06-28 16:22:49 +04:00
|
|
|
|
2012-09-26 15:20:03 +04:00
|
|
|
if (defbutton != NULL)
|
2016-08-09 09:35:27 +03:00
|
|
|
widget_select (WIDGET (defbutton));
|
2010-06-28 16:22:49 +04:00
|
|
|
|
|
|
|
/* run dialog and make result */
|
2013-06-24 11:40:53 +04:00
|
|
|
switch (dlg_run (query_dlg))
|
2010-06-28 16:22:49 +04:00
|
|
|
{
|
|
|
|
case B_CANCEL:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = query_dlg->ret_value - B_USER;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free used memory */
|
2020-10-31 19:32:29 +03:00
|
|
|
widget_destroy (WIDGET (query_dlg));
|
2010-06-28 16:22:49 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-28 11:01:30 +03:00
|
|
|
group_add_widget_autopos (g, label_new (2, 3, text), WPOS_KEEP_TOP | WPOS_CENTER_HORZ,
|
|
|
|
NULL);
|
|
|
|
group_add_widget (g, button_new (0, 0, 0, HIDDEN_BUTTON, "-", NULL));
|
2010-06-28 16:22:49 +04:00
|
|
|
last_query_dlg = query_dlg;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
sel_pos = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-06-28 16:22:49 +04:00
|
|
|
void
|
|
|
|
query_set_sel (int new_sel)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
sel_pos = new_sel;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2003-10-26 01:12:05 +04:00
|
|
|
* Create message dialog. The caller must call dlg_run_done() and
|
2020-10-31 19:32:29 +03:00
|
|
|
* widget_destroy() to dismiss it. Not safe to call from background.
|
2003-10-26 01:12:05 +04:00
|
|
|
*/
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2016-03-03 22:51:40 +03:00
|
|
|
WDialog *
|
2003-10-26 01:12:05 +04:00
|
|
|
create_message (int flags, const char *title, const char *text, ...)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2003-10-26 01:12:05 +04:00
|
|
|
va_list args;
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *d;
|
2003-10-26 01:12:05 +04:00
|
|
|
char *p;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
va_start (args, text);
|
2003-10-26 01:12:05 +04:00
|
|
|
p = g_strdup_vprintf (text, args);
|
1998-02-27 07:54:42 +03:00
|
|
|
va_end (args);
|
1998-12-03 02:44:06 +03:00
|
|
|
|
2003-10-26 01:12:05 +04:00
|
|
|
d = do_create_message (flags, title, p);
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (p);
|
2003-10-26 01:12:05 +04:00
|
|
|
|
|
|
|
return d;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2003-10-26 01:12:05 +04:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Show message box, background safe */
|
2003-10-26 01:12:05 +04:00
|
|
|
|
2003-10-26 01:54:55 +04:00
|
|
|
void
|
2003-10-26 07:47:20 +03:00
|
|
|
message (int flags, const char *title, const char *text, ...)
|
2003-10-26 01:54:55 +04:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start (ap, text);
|
|
|
|
p = g_strdup_vprintf (text, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
2003-10-26 07:47:20 +03:00
|
|
|
if (title == MSG_ERROR)
|
2010-06-28 16:22:49 +04:00
|
|
|
title = _("Error");
|
2003-10-26 07:47:20 +03:00
|
|
|
|
2012-01-09 15:48:39 +04:00
|
|
|
#ifdef ENABLE_BACKGROUND
|
2011-02-10 18:02:54 +03:00
|
|
|
if (mc_global.we_are_background)
|
2010-06-28 16:22:49 +04:00
|
|
|
{
|
2011-02-18 15:50:30 +03:00
|
|
|
union
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
void (*f) (int, int *, char *, const char *);
|
|
|
|
} func;
|
2010-06-28 16:22:49 +04:00
|
|
|
func.f = bg_message;
|
2011-02-18 15:50:30 +03:00
|
|
|
|
|
|
|
wtools_parent_call (func.p, NULL, 3, sizeof (flags), &flags, strlen (title), title,
|
|
|
|
strlen (p), p);
|
2010-06-28 16:22:49 +04:00
|
|
|
}
|
|
|
|
else
|
2012-01-09 15:48:39 +04:00
|
|
|
#endif /* ENABLE_BACKGROUND */
|
2010-06-28 16:22:49 +04:00
|
|
|
fg_message (flags, title, p);
|
2003-10-26 01:54:55 +04:00
|
|
|
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (p);
|
2003-10-26 01:54:55 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 16:53:06 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Show error message box */
|
|
|
|
|
|
|
|
gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
mc_error_message (GError **mcerror, int *code)
|
2014-07-15 16:53:06 +04:00
|
|
|
{
|
|
|
|
if (mcerror == NULL || *mcerror == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-01-03 18:47:35 +03:00
|
|
|
if ((*mcerror)->code == 0)
|
|
|
|
message (D_ERROR, MSG_ERROR, "%s", (*mcerror)->message);
|
|
|
|
else
|
2016-02-27 09:52:56 +03:00
|
|
|
message (D_ERROR, MSG_ERROR, _("%s (%d)"), (*mcerror)->message, (*mcerror)->code);
|
2015-05-09 16:41:44 +03:00
|
|
|
|
|
|
|
if (code != NULL)
|
|
|
|
*code = (*mcerror)->code;
|
|
|
|
|
2014-07-15 16:53:06 +04:00
|
|
|
g_error_free (*mcerror);
|
|
|
|
*mcerror = NULL;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
2006-09-14 13:12:49 +04:00
|
|
|
* Show input dialog, background safe.
|
|
|
|
*
|
|
|
|
* If the arguments "header" and "text" should be translated,
|
|
|
|
* that MUST be done by the caller of these wrappers.
|
|
|
|
*/
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2003-10-26 01:54:55 +04:00
|
|
|
char *
|
2009-01-14 03:01:18 +03:00
|
|
|
input_dialog_help (const char *header, const char *text, const char *help,
|
2013-01-25 16:41:41 +04:00
|
|
|
const char *history_name, const char *def_text, gboolean strip_password,
|
|
|
|
input_complete_t completion_flags)
|
2003-10-26 01:54:55 +04:00
|
|
|
{
|
2012-01-09 15:48:39 +04:00
|
|
|
#ifdef ENABLE_BACKGROUND
|
2011-02-10 18:02:54 +03:00
|
|
|
if (mc_global.we_are_background)
|
2009-04-24 02:47:22 +04:00
|
|
|
{
|
2011-03-23 19:34:41 +03:00
|
|
|
union
|
|
|
|
{
|
|
|
|
void *p;
|
2012-04-05 13:51:06 +04:00
|
|
|
char *(*f) (const char *, const char *, const char *, const char *, const char *,
|
2013-01-25 16:41:41 +04:00
|
|
|
gboolean, input_complete_t);
|
2011-03-23 19:34:41 +03:00
|
|
|
} func;
|
2010-06-28 16:22:49 +04:00
|
|
|
func.f = fg_input_dialog_help;
|
2013-01-25 16:41:41 +04:00
|
|
|
return wtools_parent_call_string (func.p, 7,
|
2011-02-18 15:50:30 +03:00
|
|
|
strlen (header), header, strlen (text),
|
|
|
|
text, strlen (help), help,
|
|
|
|
strlen (history_name), history_name,
|
2012-04-05 13:51:06 +04:00
|
|
|
strlen (def_text), def_text,
|
2013-01-25 16:41:41 +04:00
|
|
|
sizeof (gboolean), strip_password,
|
|
|
|
sizeof (input_complete_t), completion_flags);
|
2009-04-24 02:47:22 +04:00
|
|
|
}
|
2003-10-26 01:54:55 +04:00
|
|
|
else
|
2012-01-09 15:48:39 +04:00
|
|
|
#endif /* ENABLE_BACKGROUND */
|
2013-01-25 16:41:41 +04:00
|
|
|
return fg_input_dialog_help (header, text, help, history_name, def_text, strip_password,
|
|
|
|
completion_flags);
|
2003-10-26 01:54:55 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Show input dialog with default help, background safe */
|
|
|
|
|
2010-06-28 16:22:49 +04:00
|
|
|
char *
|
2013-01-25 16:41:41 +04:00
|
|
|
input_dialog (const char *header, const char *text, const char *history_name, const char *def_text,
|
|
|
|
input_complete_t completion_flags)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2013-01-25 16:41:41 +04:00
|
|
|
return input_dialog_help (header, text, "[Input Line Keys]", history_name, def_text, FALSE,
|
|
|
|
completion_flags);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2003-11-27 12:45:22 +03:00
|
|
|
char *
|
2009-09-04 09:49:51 +04:00
|
|
|
input_expand_dialog (const char *header, const char *text,
|
2013-01-25 16:41:41 +04:00
|
|
|
const char *history_name, const char *def_text,
|
|
|
|
input_complete_t completion_flags)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
|
2013-01-25 16:41:41 +04:00
|
|
|
result = input_dialog (header, text, history_name, def_text, completion_flags);
|
2010-06-28 16:22:49 +04:00
|
|
|
if (result)
|
|
|
|
{
|
2013-10-15 10:34:04 +04:00
|
|
|
char *expanded;
|
|
|
|
|
2010-06-28 16:22:49 +04:00
|
|
|
expanded = tilde_expand (result);
|
|
|
|
g_free (result);
|
|
|
|
return expanded;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2013-03-10 14:31:33 +04:00
|
|
|
/**
|
|
|
|
* Create status message window object and initialize it
|
|
|
|
*
|
|
|
|
* @param title window title
|
|
|
|
* @param delay initial delay to raise window in seconds
|
|
|
|
* @param init_cb callback to initialize user-defined part of status message
|
|
|
|
* @param update_cb callback to update of status message
|
|
|
|
* @param deinit_cb callback to deinitialize user-defined part of status message
|
|
|
|
*
|
|
|
|
* @return newly allocate status message window
|
|
|
|
*/
|
|
|
|
|
|
|
|
status_msg_t *
|
|
|
|
status_msg_create (const char *title, double delay, status_msg_cb init_cb,
|
|
|
|
status_msg_update_cb update_cb, status_msg_cb deinit_cb)
|
|
|
|
{
|
|
|
|
status_msg_t *sm;
|
|
|
|
|
|
|
|
sm = g_try_new (status_msg_t, 1);
|
|
|
|
status_msg_init (sm, title, delay, init_cb, update_cb, deinit_cb);
|
|
|
|
|
|
|
|
return sm;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Destroy status message window object
|
|
|
|
*
|
|
|
|
* @param sm status message window object
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
status_msg_destroy (status_msg_t *sm)
|
2013-03-10 14:31:33 +04:00
|
|
|
{
|
|
|
|
status_msg_deinit (sm);
|
|
|
|
g_free (sm);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Initialize already created status message window object
|
|
|
|
*
|
|
|
|
* @param sm status message window object
|
|
|
|
* @param title window title
|
|
|
|
* @param delay initial delay to raise window in seconds
|
|
|
|
* @param init_cb callback to initialize user-defined part of status message
|
|
|
|
* @param update_cb callback to update of status message
|
|
|
|
* @param deinit_cb callback to deinitialize user-defined part of status message
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
status_msg_init (status_msg_t *sm, const char *title, double delay, status_msg_cb init_cb,
|
2013-03-10 14:31:33 +04:00
|
|
|
status_msg_update_cb update_cb, status_msg_cb deinit_cb)
|
|
|
|
{
|
2020-11-22 15:40:18 +03:00
|
|
|
gint64 start;
|
2014-09-10 09:59:32 +04:00
|
|
|
|
2014-09-10 10:58:14 +04:00
|
|
|
/* repaint screen to remove previous finished dialog */
|
|
|
|
mc_refresh ();
|
|
|
|
|
2021-10-03 17:12:42 +03:00
|
|
|
start = g_get_monotonic_time ();
|
2014-09-10 09:59:32 +04:00
|
|
|
|
2016-05-08 21:10:05 +03:00
|
|
|
sm->dlg = dlg_create (TRUE, 0, 0, 7, MIN (MAX (40, COLS / 2), COLS), WPOS_CENTER, FALSE,
|
|
|
|
dialog_colors, NULL, NULL, NULL, title);
|
2014-09-10 09:59:32 +04:00
|
|
|
sm->start = start;
|
2020-11-22 15:40:18 +03:00
|
|
|
sm->delay = (gint64) (delay * G_USEC_PER_SEC);
|
2013-03-10 14:31:33 +04:00
|
|
|
sm->block = FALSE;
|
|
|
|
|
|
|
|
sm->init = init_cb;
|
|
|
|
sm->update = update_cb;
|
|
|
|
sm->deinit = deinit_cb;
|
|
|
|
|
|
|
|
if (sm->init != NULL)
|
|
|
|
sm->init (sm);
|
|
|
|
|
2014-09-10 09:59:32 +04:00
|
|
|
if (mc_time_elapsed (&start, sm->delay))
|
2013-03-10 14:31:33 +04:00
|
|
|
{
|
2015-10-25 07:40:34 +03:00
|
|
|
/* We will manage the dialog without any help, that's why we have to call dlg_init */
|
2013-03-10 14:31:33 +04:00
|
|
|
dlg_init (sm->dlg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Deinitialize status message window object
|
|
|
|
*
|
|
|
|
* @param sm status message window object
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
status_msg_deinit (status_msg_t *sm)
|
2013-03-10 14:31:33 +04:00
|
|
|
{
|
|
|
|
if (sm == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (sm->deinit != NULL)
|
|
|
|
sm->deinit (sm);
|
|
|
|
|
|
|
|
/* close and destroy dialog */
|
|
|
|
dlg_run_done (sm->dlg);
|
2020-10-31 19:32:29 +03:00
|
|
|
widget_destroy (WIDGET (sm->dlg));
|
2013-03-10 14:31:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
|
|
* Update status message window
|
|
|
|
*
|
|
|
|
* @param sm status message window object
|
|
|
|
*
|
|
|
|
* @return value of pressed key
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2024-06-01 21:12:14 +03:00
|
|
|
status_msg_common_update (status_msg_t *sm)
|
2013-03-10 14:31:33 +04:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
Gpm_Event event;
|
|
|
|
|
|
|
|
if (sm == NULL)
|
|
|
|
return B_ENTER;
|
|
|
|
|
2014-09-10 09:59:32 +04:00
|
|
|
/* This should not happen, but... */
|
|
|
|
if (sm->dlg == NULL)
|
|
|
|
return B_ENTER;
|
|
|
|
|
2016-04-10 20:02:59 +03:00
|
|
|
if (widget_get_state (WIDGET (sm->dlg), WST_CONSTRUCT))
|
2013-03-10 14:31:33 +04:00
|
|
|
{
|
2014-09-10 09:59:32 +04:00
|
|
|
/* dialog is not shown yet */
|
2013-03-10 14:31:33 +04:00
|
|
|
|
2014-09-10 09:59:32 +04:00
|
|
|
/* do not change sm->start */
|
2020-11-22 15:40:18 +03:00
|
|
|
gint64 start = sm->start;
|
2013-03-10 14:31:33 +04:00
|
|
|
|
2014-09-10 09:59:32 +04:00
|
|
|
if (mc_time_elapsed (&start, sm->delay))
|
|
|
|
dlg_init (sm->dlg);
|
2013-03-10 14:31:33 +04:00
|
|
|
|
|
|
|
return B_ENTER;
|
2014-09-10 09:59:32 +04:00
|
|
|
}
|
2013-03-10 14:31:33 +04:00
|
|
|
|
|
|
|
event.x = -1; /* Don't show the GPM cursor */
|
|
|
|
c = tty_get_event (&event, FALSE, sm->block);
|
|
|
|
if (c == EV_NONE)
|
|
|
|
return B_ENTER;
|
|
|
|
|
|
|
|
/* Reinitialize by non-B_CANCEL value to avoid old values
|
|
|
|
after events other than selecting a button */
|
|
|
|
sm->dlg->ret_value = B_ENTER;
|
|
|
|
dlg_process_event (sm->dlg, c, &event);
|
|
|
|
|
|
|
|
return sm->dlg->ret_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2013-03-10 16:20:33 +04:00
|
|
|
/**
|
|
|
|
* Callback to initialize already created simple status message window object
|
|
|
|
*
|
|
|
|
* @param sm status message window object
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
simple_status_msg_init_cb (status_msg_t *sm)
|
2013-03-10 16:20:33 +04:00
|
|
|
{
|
|
|
|
simple_status_msg_t *ssm = SIMPLE_STATUS_MSG (sm);
|
|
|
|
Widget *wd = WIDGET (sm->dlg);
|
2016-09-28 11:01:30 +03:00
|
|
|
WGroup *wg = GROUP (sm->dlg);
|
2022-05-01 10:43:33 +03:00
|
|
|
WRect r;
|
2013-03-10 16:20:33 +04:00
|
|
|
|
|
|
|
const char *b_name = N_("&Abort");
|
|
|
|
int b_width;
|
|
|
|
int wd_width, y;
|
|
|
|
Widget *b;
|
|
|
|
|
|
|
|
#ifdef ENABLE_NLS
|
|
|
|
b_name = _(b_name);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
b_width = str_term_width1 (b_name) + 4;
|
2022-05-01 10:43:33 +03:00
|
|
|
wd_width = MAX (wd->rect.cols, b_width + 6);
|
2013-03-10 16:20:33 +04:00
|
|
|
|
|
|
|
y = 2;
|
2023-02-23 11:37:32 +03:00
|
|
|
ssm->label = label_new (y++, 3, NULL);
|
2016-09-28 11:01:30 +03:00
|
|
|
group_add_widget_autopos (wg, ssm->label, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, NULL);
|
|
|
|
group_add_widget (wg, hline_new (y++, -1, -1));
|
2013-03-10 16:20:33 +04:00
|
|
|
b = WIDGET (button_new (y++, 3, B_CANCEL, NORMAL_BUTTON, b_name, NULL));
|
2016-09-28 11:01:30 +03:00
|
|
|
group_add_widget_autopos (wg, b, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, NULL);
|
2013-03-10 16:20:33 +04:00
|
|
|
|
2022-05-01 10:43:33 +03:00
|
|
|
r = wd->rect;
|
|
|
|
r.lines = y + 2;
|
|
|
|
r.cols = wd_width;
|
|
|
|
widget_set_size_rect (wd, &r);
|
2013-03-10 16:20:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|