123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- /*
- Support of multiply editors and viewers.
- Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
- Copyright (C) 2009-2024
- Free Software Foundation, Inc.
- Written by:
- Daniel Borca <dborca@yahoo.com>, 2007
- Andrew Borodin <aborodin@vmail.ru>, 2010-2022
- 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/>.
- */
- /** \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 */
- #include "lib/tty/color.h" /* tty_set_normal_attrs() */
- #include "lib/widget.h"
- #include "lib/event.h"
- /*** global variables ****************************************************************************/
- /* Primitive way to check if the the current dialog is our dialog */
- /* This is needed by async routines like load_prompt */
- GList *top_dlg = NULL;
- /* If set then dialogs just clean the screen when refreshing, else */
- /* they do a complete refresh, refreshing all the parts of the program */
- gboolean fast_refresh = FALSE;
- WDialog *filemanager = NULL;
- /*** file scope macro definitions ****************************************************************/
- /*** file scope type declarations ****************************************************************/
- /*** forward declarations (file scope functions) *************************************************/
- /*** file scope variables ************************************************************************/
- /* 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;
- /* --------------------------------------------------------------------------------------------- */
- /*** file scope functions ************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- static unsigned char
- get_hotkey (int n)
- {
- return (n <= 9) ? '0' + n : 'a' + n - 10;
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- dialog_switch_suspend (void *data, void *user_data)
- {
- (void) user_data;
- if (data != mc_current->data)
- widget_set_state (WIDGET (data), WST_SUSPENDED, TRUE);
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- dialog_switch_goto (GList *dlg)
- {
- if (mc_current != dlg)
- {
- WDialog *old = DIALOG (mc_current->data);
- mc_current = dlg;
- if (old == filemanager)
- {
- /* 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 */
- widget_set_state (WIDGET (old), WST_SUSPENDED, TRUE);
- if (DIALOG (dlg->data) != filemanager)
- /* switch to another editor, viewer, etc */
- /* return to panels before run the required dialog */
- dialog_switch_pending = TRUE;
- else
- {
- /* switch to panels */
- widget_set_state (WIDGET (filemanager), WST_ACTIVE, TRUE);
- do_refresh ();
- }
- }
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- dialog_switch_resize (WDialog *d)
- {
- if (widget_get_state (WIDGET (d), WST_ACTIVE))
- send_message (d, NULL, MSG_RESIZE, 0, NULL);
- else
- GROUP (d)->winch_pending = TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- /*** public functions ****************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_add (WDialog *h)
- {
- 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;
- }
- /* suspend forced all other screens */
- g_list_foreach (mc_dialogs, dialog_switch_suspend, NULL);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_remove (WDialog *h)
- {
- GList *this;
- if (DIALOG (mc_current->data) == h)
- this = mc_current;
- else
- this = g_list_find (mc_dialogs, h);
- mc_dialogs = g_list_delete_link (mc_dialogs, this);
- /* adjust current dialog */
- if (top_dlg != NULL)
- mc_current = g_list_find (mc_dialogs, DIALOG (top_dlg->data));
- else
- mc_current = mc_dialogs;
- /* resume forced the current screen */
- if (mc_current != NULL)
- widget_set_state (WIDGET (mc_current->data), WST_ACTIVE, TRUE);
- }
- /* --------------------------------------------------------------------------------------------- */
- size_t
- dialog_switch_num (void)
- {
- return g_list_length (mc_dialogs);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_next (void)
- {
- GList *next;
- if (mc_global.midnight_shutdown || mc_current == NULL)
- return;
- next = g_list_next (mc_current);
- if (next == NULL)
- next = mc_dialogs;
- dialog_switch_goto (next);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_prev (void)
- {
- GList *prev;
- if (mc_global.midnight_shutdown || mc_current == NULL)
- return;
- prev = g_list_previous (mc_current);
- if (prev == NULL)
- prev = g_list_last (mc_dialogs);
- dialog_switch_goto (prev);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_list (void)
- {
- const size_t dlg_num = g_list_length (mc_dialogs);
- int lines, cols;
- Listbox *listbox;
- GList *h, *selected;
- int i = 0;
- if (mc_global.midnight_shutdown || mc_current == NULL)
- return;
- lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
- cols = COLS * 2 / 3;
- listbox = listbox_window_new (lines, cols, _ ("Screens"), "[Screen selector]");
- for (h = mc_dialogs; h != NULL; h = g_list_next (h))
- {
- WDialog *dlg = DIALOG (h->data);
- char *title;
- if (dlg->get_title != NULL)
- title = dlg->get_title (dlg, WIDGET (listbox->list)->rect.cols - 2);
- else
- title = g_strdup ("");
- listbox_add_item_take (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h,
- FALSE);
- }
- selected = listbox_run_with_data (listbox, mc_current);
- if (selected != NULL)
- dialog_switch_goto (selected);
- }
- /* --------------------------------------------------------------------------------------------- */
- int
- dialog_switch_process_pending (void)
- {
- int ret = 0;
- while (dialog_switch_pending)
- {
- WDialog *h = DIALOG (mc_current->data);
- Widget *wh = WIDGET (h);
- dialog_switch_pending = FALSE;
- widget_set_state (wh, WST_SUSPENDED, TRUE);
- ret = dlg_run (h);
- if (widget_get_state (wh, WST_CLOSED))
- {
- widget_destroy (wh);
- /* return to panels */
- if (mc_global.mc_run_mode == MC_RUN_FULL)
- {
- mc_current = g_list_find (mc_dialogs, filemanager);
- mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
- }
- }
- }
- repaint_screen ();
- return ret;
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_got_winch (void)
- {
- GList *dlg;
- for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
- if (dlg != mc_current)
- GROUP (dlg->data)->winch_pending = TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_switch_shutdown (void)
- {
- while (mc_dialogs != NULL)
- {
- WDialog *dlg = DIALOG (mc_dialogs->data);
- dlg_run (dlg);
- widget_destroy (WIDGET (dlg));
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- do_refresh (void)
- {
- GList *d = top_dlg;
- if (fast_refresh)
- {
- if (d != NULL)
- widget_draw (WIDGET (d->data));
- }
- else
- {
- /* Search first fullscreen dialog */
- for (; d != NULL; d = g_list_next (d))
- if ((WIDGET (d->data)->pos_flags & WPOS_FULLSCREEN) != 0)
- break;
- /* when small dialog (i.e. error message) is created first,
- there is no fullscreen dialog in the stack */
- if (d == NULL)
- d = g_list_last (top_dlg);
- /* back to top dialog */
- for (; d != NULL; d = g_list_previous (d))
- widget_draw (WIDGET (d->data));
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- repaint_screen (void)
- {
- do_refresh ();
- tty_refresh ();
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- mc_refresh (void)
- {
- #ifdef ENABLE_BACKGROUND
- if (mc_global.we_are_background)
- return;
- #endif /* ENABLE_BACKGROUND */
- if (!tty_got_winch ())
- tty_refresh ();
- else
- {
- /* if winch was caugth, we should do not only redraw screen, but
- reposition/resize all */
- dialog_change_screen_size ();
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- dialog_change_screen_size (void)
- {
- GList *d;
- tty_flush_winch ();
- tty_change_screen_size ();
- #ifdef HAVE_SLANG
- tty_keypad (TRUE);
- tty_nodelay (FALSE);
- #endif
- /* Inform all suspending dialogs */
- dialog_switch_got_winch ();
- /* 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));
- /* Now, force the redraw */
- repaint_screen ();
- }
- /* --------------------------------------------------------------------------------------------- */
|