2010-04-18 14:58:18 +04:00
|
|
|
/*
|
2011-10-15 14:56:47 +04:00
|
|
|
Support of multiply editors and viewers.
|
|
|
|
|
|
|
|
Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
|
|
|
|
|
2020-01-18 19:54:37 +03:00
|
|
|
Copyright (C) 2009-2020
|
2014-04-07 16:15:46 +04:00
|
|
|
Free Software Foundation, Inc.
|
2011-10-15 14:56:47 +04:00
|
|
|
|
|
|
|
Written by:
|
|
|
|
Daniel Borca <dborca@yahoo.com>, 2007
|
2013-06-24 11:40:53 +04:00
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2010, 2013
|
2011-10-15 14:56:47 +04:00
|
|
|
|
|
|
|
This file is part of the Midnight Commander.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
|
|
|
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
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2010-04-18 14:58:18 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file dialog-switch.c
|
|
|
|
* \brief Source: support of multiply editors and viewers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "lib/global.h"
|
|
|
|
#include "lib/tty/tty.h" /* LINES, COLS */
|
2011-02-16 19:11:19 +03:00
|
|
|
#include "lib/tty/color.h" /* tty_set_normal_attrs() */
|
2010-11-12 11:03:57 +03:00
|
|
|
#include "lib/widget.h"
|
2011-02-16 19:11:19 +03:00
|
|
|
#include "lib/event.h"
|
2010-11-10 22:45:56 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
2010-04-18 14:58:18 +04:00
|
|
|
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *midnight_dlg = NULL;
|
2011-02-16 19:11:19 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope macro definitions ****************************************************************/
|
|
|
|
|
|
|
|
/*** file scope type declarations ****************************************************************/
|
|
|
|
|
|
|
|
/*** file scope variables ************************************************************************/
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
/* List of dialogs: filemanagers, editors, viewers */
|
|
|
|
static GList *mc_dialogs = NULL;
|
|
|
|
/* Currently active dialog */
|
|
|
|
static GList *mc_current = NULL;
|
|
|
|
/* Is there any dialogs that we have to run after returning to the manager from another dialog */
|
|
|
|
static gboolean dialog_switch_pending = FALSE;
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
static unsigned char
|
|
|
|
get_hotkey (int n)
|
|
|
|
{
|
|
|
|
return (n <= 9) ? '0' + n : 'a' + n - 10;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-11-30 14:17:07 +04:00
|
|
|
static void
|
|
|
|
dialog_switch_suspend (void *data, void *user_data)
|
|
|
|
{
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
if (data != mc_current->data)
|
2016-04-10 20:02:59 +03:00
|
|
|
widget_set_state (WIDGET (data), WST_SUSPENDED, TRUE);
|
2011-11-30 14:17:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
static void
|
2010-11-10 14:09:42 +03:00
|
|
|
dialog_switch_goto (GList * dlg)
|
2010-04-18 14:58:18 +04:00
|
|
|
{
|
|
|
|
if (mc_current != dlg)
|
|
|
|
{
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *old = DIALOG (mc_current->data);
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
mc_current = dlg;
|
|
|
|
|
|
|
|
if (old == midnight_dlg)
|
|
|
|
{
|
|
|
|
/* switch from panels to another dialog (editor, viewer, etc) */
|
|
|
|
dialog_switch_pending = TRUE;
|
|
|
|
dialog_switch_process_pending ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* switch from editor, viewer, etc to another dialog */
|
2016-04-10 20:02:59 +03:00
|
|
|
widget_set_state (WIDGET (old), WST_SUSPENDED, TRUE);
|
2010-04-18 14:58:18 +04:00
|
|
|
|
2012-09-28 11:18:45 +04:00
|
|
|
if (DIALOG (dlg->data) != midnight_dlg)
|
2010-04-18 14:58:18 +04:00
|
|
|
/* switch to another editor, viewer, etc */
|
|
|
|
/* return to panels before run the required dialog */
|
|
|
|
dialog_switch_pending = TRUE;
|
|
|
|
else
|
2011-11-30 14:17:07 +04:00
|
|
|
{
|
2010-04-18 14:58:18 +04:00
|
|
|
/* switch to panels */
|
2016-04-10 20:02:59 +03:00
|
|
|
widget_set_state (WIDGET (midnight_dlg), WST_ACTIVE, TRUE);
|
2010-04-18 14:58:18 +04:00
|
|
|
do_refresh ();
|
2011-11-30 14:17:07 +04:00
|
|
|
}
|
2010-04-18 14:58:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-18 14:30:15 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static void
|
2016-11-08 14:10:24 +03:00
|
|
|
dialog_switch_resize (WDialog * d)
|
2011-02-18 14:30:15 +03:00
|
|
|
{
|
2016-04-10 20:02:59 +03:00
|
|
|
if (widget_get_state (WIDGET (d), WST_ACTIVE))
|
2012-09-28 15:05:43 +04:00
|
|
|
send_message (d, NULL, MSG_RESIZE, 0, NULL);
|
2011-11-30 14:17:07 +04:00
|
|
|
else
|
2016-09-27 14:08:42 +03:00
|
|
|
GROUP (d)->winch_pending = TRUE;
|
2011-02-18 14:30:15 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
void
|
2012-09-28 11:18:45 +04:00
|
|
|
dialog_switch_add (WDialog * h)
|
2010-04-18 14:58:18 +04:00
|
|
|
{
|
|
|
|
GList *dlg;
|
|
|
|
|
|
|
|
dlg = g_list_find (mc_dialogs, h);
|
|
|
|
|
|
|
|
if (dlg != NULL)
|
|
|
|
mc_current = dlg;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mc_dialogs = g_list_prepend (mc_dialogs, h);
|
|
|
|
mc_current = mc_dialogs;
|
|
|
|
}
|
2011-11-30 14:17:07 +04:00
|
|
|
|
|
|
|
/* suspend forced all other screens */
|
|
|
|
g_list_foreach (mc_dialogs, dialog_switch_suspend, NULL);
|
2010-04-18 14:58:18 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
void
|
2012-09-28 11:18:45 +04:00
|
|
|
dialog_switch_remove (WDialog * h)
|
2010-04-18 14:58:18 +04:00
|
|
|
{
|
|
|
|
GList *this;
|
|
|
|
|
2012-09-28 11:18:45 +04:00
|
|
|
if (DIALOG (mc_current->data) == h)
|
2010-04-18 14:58:18 +04:00
|
|
|
this = mc_current;
|
|
|
|
else
|
|
|
|
this = g_list_find (mc_dialogs, h);
|
|
|
|
|
2010-09-20 13:58:17 +04:00
|
|
|
mc_dialogs = g_list_delete_link (mc_dialogs, this);
|
2010-04-18 14:58:18 +04:00
|
|
|
|
2010-09-20 13:58:17 +04:00
|
|
|
/* adjust current dialog */
|
|
|
|
if (top_dlg != NULL)
|
2012-09-28 11:18:45 +04:00
|
|
|
mc_current = g_list_find (mc_dialogs, DIALOG (top_dlg->data));
|
2010-09-20 13:58:17 +04:00
|
|
|
else
|
|
|
|
mc_current = mc_dialogs;
|
2011-11-30 14:17:07 +04:00
|
|
|
|
|
|
|
/* resume forced the current screen */
|
|
|
|
if (mc_current != NULL)
|
2016-04-10 20:02:59 +03:00
|
|
|
widget_set_state (WIDGET (mc_current->data), WST_ACTIVE, TRUE);
|
2010-04-18 14:58:18 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-06-18 14:35:27 +04:00
|
|
|
size_t
|
|
|
|
dialog_switch_num (void)
|
|
|
|
{
|
|
|
|
return g_list_length (mc_dialogs);
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
void
|
|
|
|
dialog_switch_next (void)
|
|
|
|
{
|
|
|
|
GList *next;
|
|
|
|
|
2012-01-28 14:13:32 +04:00
|
|
|
if (mc_global.midnight_shutdown || mc_current == NULL)
|
2010-04-18 14:58:18 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
next = g_list_next (mc_current);
|
|
|
|
if (next == NULL)
|
|
|
|
next = mc_dialogs;
|
|
|
|
|
|
|
|
dialog_switch_goto (next);
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
void
|
|
|
|
dialog_switch_prev (void)
|
|
|
|
{
|
|
|
|
GList *prev;
|
|
|
|
|
2012-01-28 14:13:32 +04:00
|
|
|
if (mc_global.midnight_shutdown || mc_current == NULL)
|
2010-04-18 14:58:18 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
prev = g_list_previous (mc_current);
|
|
|
|
if (prev == NULL)
|
|
|
|
prev = g_list_last (mc_dialogs);
|
|
|
|
|
|
|
|
dialog_switch_goto (prev);
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
void
|
|
|
|
dialog_switch_list (void)
|
|
|
|
{
|
|
|
|
const size_t dlg_num = g_list_length (mc_dialogs);
|
|
|
|
int lines, cols;
|
|
|
|
Listbox *listbox;
|
2017-01-25 16:53:49 +03:00
|
|
|
GList *h, *selected;
|
2010-04-18 14:58:18 +04:00
|
|
|
int i = 0;
|
|
|
|
|
2012-01-28 14:13:32 +04:00
|
|
|
if (mc_global.midnight_shutdown || mc_current == NULL)
|
2010-04-18 14:58:18 +04:00
|
|
|
return;
|
|
|
|
|
2016-04-07 10:52:04 +03:00
|
|
|
lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
|
2010-11-10 14:09:42 +03:00
|
|
|
cols = COLS * 2 / 3;
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
|
|
|
|
|
|
|
|
for (h = mc_dialogs; h != NULL; h = g_list_next (h))
|
|
|
|
{
|
2019-01-27 11:38:57 +03:00
|
|
|
WDialog *dlg = DIALOG (h->data);
|
2010-04-18 14:58:18 +04:00
|
|
|
char *title;
|
|
|
|
|
2019-01-27 11:38:57 +03:00
|
|
|
if (dlg->get_title != NULL)
|
2012-06-20 15:09:44 +04:00
|
|
|
title = dlg->get_title (dlg, WIDGET (listbox->list)->cols - 2);
|
2010-04-18 14:58:18 +04:00
|
|
|
else
|
|
|
|
title = g_strdup ("");
|
|
|
|
|
2017-01-25 16:53:49 +03:00
|
|
|
listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h, FALSE);
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
g_free (title);
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:53:49 +03:00
|
|
|
selected = run_listbox_with_data (listbox, mc_current);
|
|
|
|
if (selected != NULL)
|
|
|
|
dialog_switch_goto (selected);
|
2010-04-18 14:58:18 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
int
|
|
|
|
dialog_switch_process_pending (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
while (dialog_switch_pending)
|
|
|
|
{
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *h = DIALOG (mc_current->data);
|
2016-04-10 20:02:59 +03:00
|
|
|
Widget *wh = WIDGET (h);
|
2010-04-18 14:58:18 +04:00
|
|
|
|
|
|
|
dialog_switch_pending = FALSE;
|
2016-04-10 20:02:59 +03:00
|
|
|
widget_set_state (wh, WST_SUSPENDED, TRUE);
|
2013-06-24 11:40:53 +04:00
|
|
|
ret = dlg_run (h);
|
2016-04-10 20:02:59 +03:00
|
|
|
if (widget_get_state (wh, WST_CLOSED))
|
2010-04-18 14:58:18 +04:00
|
|
|
{
|
2013-06-24 11:40:53 +04:00
|
|
|
dlg_destroy (h);
|
2011-11-30 14:17:07 +04:00
|
|
|
|
2010-04-18 14:58:18 +04:00
|
|
|
/* return to panels */
|
2011-02-10 18:02:54 +03:00
|
|
|
if (mc_global.mc_run_mode == MC_RUN_FULL)
|
2010-04-18 14:58:18 +04:00
|
|
|
{
|
|
|
|
mc_current = g_list_find (mc_dialogs, midnight_dlg);
|
2011-02-16 19:11:19 +03:00
|
|
|
mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
|
2010-04-18 14:58:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
repaint_screen ();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2010-05-30 18:43:50 +04:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-06-05 18:48:06 +04:00
|
|
|
void
|
|
|
|
dialog_switch_got_winch (void)
|
|
|
|
{
|
|
|
|
GList *dlg;
|
|
|
|
|
|
|
|
for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
|
|
|
|
if (dlg != mc_current)
|
2016-09-27 14:08:42 +03:00
|
|
|
GROUP (dlg->data)->winch_pending = TRUE;
|
2010-06-05 18:48:06 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-05-30 18:43:50 +04:00
|
|
|
void
|
|
|
|
dialog_switch_shutdown (void)
|
|
|
|
{
|
|
|
|
while (mc_dialogs != NULL)
|
|
|
|
{
|
2012-09-28 11:18:45 +04:00
|
|
|
WDialog *dlg = DIALOG (mc_dialogs->data);
|
2010-05-30 18:43:50 +04:00
|
|
|
|
2013-06-24 11:40:53 +04:00
|
|
|
dlg_run (dlg);
|
|
|
|
dlg_destroy (dlg);
|
2010-05-30 18:43:50 +04:00
|
|
|
}
|
|
|
|
}
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-02-16 19:11:19 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
clr_scr (void)
|
|
|
|
{
|
|
|
|
tty_set_normal_attrs ();
|
|
|
|
tty_fill_region (0, 0, LINES, COLS, ' ');
|
|
|
|
tty_refresh ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void
|
|
|
|
repaint_screen (void)
|
|
|
|
{
|
|
|
|
do_refresh ();
|
|
|
|
tty_refresh ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2011-02-18 14:30:15 +03:00
|
|
|
|
2011-10-01 17:50:16 +04:00
|
|
|
void
|
|
|
|
mc_refresh (void)
|
|
|
|
{
|
2012-01-09 15:48:39 +04:00
|
|
|
#ifdef ENABLE_BACKGROUND
|
2011-10-01 17:50:16 +04:00
|
|
|
if (mc_global.we_are_background)
|
|
|
|
return;
|
2012-01-09 15:48:39 +04:00
|
|
|
#endif /* ENABLE_BACKGROUND */
|
2019-08-17 17:55:50 +03:00
|
|
|
|
|
|
|
if (!tty_got_winch ())
|
2011-10-01 17:50:16 +04:00
|
|
|
tty_refresh ();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* if winch was caugth, we should do not only redraw screen, but
|
|
|
|
reposition/resize all */
|
|
|
|
dialog_change_screen_size ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-02-18 14:30:15 +03:00
|
|
|
void
|
|
|
|
dialog_change_screen_size (void)
|
|
|
|
{
|
2016-11-08 14:10:24 +03:00
|
|
|
GList *d;
|
|
|
|
|
2019-09-21 20:44:51 +03:00
|
|
|
tty_flush_winch ();
|
2011-09-01 11:21:47 +04:00
|
|
|
tty_change_screen_size ();
|
2012-10-15 16:03:04 +04:00
|
|
|
|
2012-10-30 14:56:02 +04:00
|
|
|
#ifdef HAVE_SLANG
|
|
|
|
tty_keypad (TRUE);
|
|
|
|
tty_nodelay (FALSE);
|
2011-02-18 14:30:15 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Inform all suspending dialogs */
|
|
|
|
dialog_switch_got_winch ();
|
2016-11-08 14:10:24 +03:00
|
|
|
|
|
|
|
/* Inform all running dialogs from first to last */
|
|
|
|
for (d = g_list_last (top_dlg); d != NULL; d = g_list_previous (d))
|
|
|
|
dialog_switch_resize (DIALOG (d->data));
|
2011-02-18 14:30:15 +03:00
|
|
|
|
|
|
|
/* Now, force the redraw */
|
|
|
|
repaint_screen ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|