src/filemanager/filegui.c: fix coding style.
[midnight-commander.git] / lib / widget / dialog-switch.c
blob5427c82e4905f9104aae4a5b901eeb029af0a241
1 /*
2 Support of multiply editors and viewers.
4 Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
6 Copyright (C) 2009-2019
7 Free Software Foundation, Inc.
9 Written by:
10 Daniel Borca <dborca@yahoo.com>, 2007
11 Andrew Borodin <aborodin@vmail.ru>, 2010, 2013
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 /** \file dialog-switch.c
30 * \brief Source: support of multiply editors and viewers.
33 #include <config.h>
35 #include "lib/global.h"
36 #include "lib/tty/tty.h" /* LINES, COLS */
37 #include "lib/tty/color.h" /* tty_set_normal_attrs() */
38 #include "lib/widget.h"
39 #include "lib/event.h"
41 /*** global variables ****************************************************************************/
43 WDialog *midnight_dlg = NULL;
45 /*** file scope macro definitions ****************************************************************/
47 /*** file scope type declarations ****************************************************************/
49 /*** file scope variables ************************************************************************/
51 /* List of dialogs: filemanagers, editors, viewers */
52 static GList *mc_dialogs = NULL;
53 /* Currently active dialog */
54 static GList *mc_current = NULL;
55 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
56 static gboolean dialog_switch_pending = FALSE;
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
61 static unsigned char
62 get_hotkey (int n)
64 return (n <= 9) ? '0' + n : 'a' + n - 10;
67 /* --------------------------------------------------------------------------------------------- */
69 static void
70 dialog_switch_suspend (void *data, void *user_data)
72 (void) user_data;
74 if (data != mc_current->data)
75 widget_set_state (WIDGET (data), WST_SUSPENDED, TRUE);
78 /* --------------------------------------------------------------------------------------------- */
80 static void
81 dialog_switch_goto (GList * dlg)
83 if (mc_current != dlg)
85 WDialog *old = DIALOG (mc_current->data);
87 mc_current = dlg;
89 if (old == midnight_dlg)
91 /* switch from panels to another dialog (editor, viewer, etc) */
92 dialog_switch_pending = TRUE;
93 dialog_switch_process_pending ();
95 else
97 /* switch from editor, viewer, etc to another dialog */
98 widget_set_state (WIDGET (old), WST_SUSPENDED, TRUE);
100 if (DIALOG (dlg->data) != midnight_dlg)
101 /* switch to another editor, viewer, etc */
102 /* return to panels before run the required dialog */
103 dialog_switch_pending = TRUE;
104 else
106 /* switch to panels */
107 widget_set_state (WIDGET (midnight_dlg), WST_ACTIVE, TRUE);
108 do_refresh ();
114 /* --------------------------------------------------------------------------------------------- */
116 static void
117 dialog_switch_resize (WDialog * d)
119 if (widget_get_state (WIDGET (d), WST_ACTIVE))
120 send_message (d, NULL, MSG_RESIZE, 0, NULL);
121 else
122 d->winch_pending = TRUE;
125 /* --------------------------------------------------------------------------------------------- */
126 /*** public functions ****************************************************************************/
127 /* --------------------------------------------------------------------------------------------- */
129 void
130 dialog_switch_add (WDialog * h)
132 GList *dlg;
134 dlg = g_list_find (mc_dialogs, h);
136 if (dlg != NULL)
137 mc_current = dlg;
138 else
140 mc_dialogs = g_list_prepend (mc_dialogs, h);
141 mc_current = mc_dialogs;
144 /* suspend forced all other screens */
145 g_list_foreach (mc_dialogs, dialog_switch_suspend, NULL);
148 /* --------------------------------------------------------------------------------------------- */
150 void
151 dialog_switch_remove (WDialog * h)
153 GList *this;
155 if (DIALOG (mc_current->data) == h)
156 this = mc_current;
157 else
158 this = g_list_find (mc_dialogs, h);
160 mc_dialogs = g_list_delete_link (mc_dialogs, this);
162 /* adjust current dialog */
163 if (top_dlg != NULL)
164 mc_current = g_list_find (mc_dialogs, DIALOG (top_dlg->data));
165 else
166 mc_current = mc_dialogs;
168 /* resume forced the current screen */
169 if (mc_current != NULL)
170 widget_set_state (WIDGET (mc_current->data), WST_ACTIVE, TRUE);
173 /* --------------------------------------------------------------------------------------------- */
175 size_t
176 dialog_switch_num (void)
178 return g_list_length (mc_dialogs);
181 /* --------------------------------------------------------------------------------------------- */
183 void
184 dialog_switch_next (void)
186 GList *next;
188 if (mc_global.midnight_shutdown || mc_current == NULL)
189 return;
191 next = g_list_next (mc_current);
192 if (next == NULL)
193 next = mc_dialogs;
195 dialog_switch_goto (next);
198 /* --------------------------------------------------------------------------------------------- */
200 void
201 dialog_switch_prev (void)
203 GList *prev;
205 if (mc_global.midnight_shutdown || mc_current == NULL)
206 return;
208 prev = g_list_previous (mc_current);
209 if (prev == NULL)
210 prev = g_list_last (mc_dialogs);
212 dialog_switch_goto (prev);
215 /* --------------------------------------------------------------------------------------------- */
217 void
218 dialog_switch_list (void)
220 const size_t dlg_num = g_list_length (mc_dialogs);
221 int lines, cols;
222 Listbox *listbox;
223 GList *h, *selected;
224 int i = 0;
226 if (mc_global.midnight_shutdown || mc_current == NULL)
227 return;
229 lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
230 cols = COLS * 2 / 3;
232 listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
234 for (h = mc_dialogs; h != NULL; h = g_list_next (h))
236 WDialog *dlg = DIALOG (h->data);
237 char *title;
239 if (dlg->get_title != NULL)
240 title = dlg->get_title (dlg, WIDGET (listbox->list)->cols - 2);
241 else
242 title = g_strdup ("");
244 listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h, FALSE);
246 g_free (title);
249 selected = run_listbox_with_data (listbox, mc_current);
250 if (selected != NULL)
251 dialog_switch_goto (selected);
254 /* --------------------------------------------------------------------------------------------- */
257 dialog_switch_process_pending (void)
259 int ret = 0;
261 while (dialog_switch_pending)
263 WDialog *h = DIALOG (mc_current->data);
264 Widget *wh = WIDGET (h);
266 dialog_switch_pending = FALSE;
267 widget_set_state (wh, WST_SUSPENDED, TRUE);
268 ret = dlg_run (h);
269 if (widget_get_state (wh, WST_CLOSED))
271 dlg_destroy (h);
273 /* return to panels */
274 if (mc_global.mc_run_mode == MC_RUN_FULL)
276 mc_current = g_list_find (mc_dialogs, midnight_dlg);
277 mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
282 repaint_screen ();
284 return ret;
287 /* --------------------------------------------------------------------------------------------- */
289 void
290 dialog_switch_got_winch (void)
292 GList *dlg;
294 for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
295 if (dlg != mc_current)
296 DIALOG (dlg->data)->winch_pending = TRUE;
299 /* --------------------------------------------------------------------------------------------- */
301 void
302 dialog_switch_shutdown (void)
304 while (mc_dialogs != NULL)
306 WDialog *dlg = DIALOG (mc_dialogs->data);
308 dlg_run (dlg);
309 dlg_destroy (dlg);
313 /* --------------------------------------------------------------------------------------------- */
315 void
316 clr_scr (void)
318 tty_set_normal_attrs ();
319 tty_fill_region (0, 0, LINES, COLS, ' ');
320 tty_refresh ();
323 /* --------------------------------------------------------------------------------------------- */
325 void
326 repaint_screen (void)
328 do_refresh ();
329 tty_refresh ();
332 /* --------------------------------------------------------------------------------------------- */
334 void
335 mc_refresh (void)
337 #ifdef ENABLE_BACKGROUND
338 if (mc_global.we_are_background)
339 return;
340 #endif /* ENABLE_BACKGROUND */
341 if (mc_global.tty.winch_flag == 0)
342 tty_refresh ();
343 else
345 /* if winch was caugth, we should do not only redraw screen, but
346 reposition/resize all */
347 dialog_change_screen_size ();
351 /* --------------------------------------------------------------------------------------------- */
353 void
354 dialog_change_screen_size (void)
356 GList *d;
358 mc_global.tty.winch_flag = 0;
360 tty_change_screen_size ();
362 #ifdef HAVE_SLANG
363 tty_keypad (TRUE);
364 tty_nodelay (FALSE);
365 #endif
367 /* Inform all suspending dialogs */
368 dialog_switch_got_winch ();
370 /* Inform all running dialogs from first to last */
371 for (d = g_list_last (top_dlg); d != NULL; d = g_list_previous (d))
372 dialog_switch_resize (DIALOG (d->data));
374 /* Now, force the redraw */
375 repaint_screen ();
378 /* --------------------------------------------------------------------------------------------- */