Ticket #1490: fix of mult-screen engine.
[midnight-commander.git] / src / dialog-switch.c
blob3db7de685fca66a2817110e99112f62311aea6c2
1 /*
2 * Copyright (c) 2009, 2010 Free Software Foundation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 * Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
19 * Written by: 2007 Daniel Borca <dborca@yahoo.com>
20 * 2010 Andrew Borodin <aborodin@vmail.ru>
23 /** \file dialog-switch.c
24 * \brief Source: support of multiply editors and viewers.
27 #include <config.h>
29 #include "lib/global.h"
30 #include "lib/tty/tty.h" /* LINES, COLS */
32 #include "dialog.h"
33 #include "widget.h"
34 #include "layout.h" /* repaint_screen() */
35 #include "main-widgets.h" /* midnight_dlg */
36 #include "main.h" /* midnight_shutdown */
37 #include "wtools.h" /* Listbox */
38 #include "dialog-switch.h"
40 /*** global variables **************************************************/
42 /*** file scope macro definitions **************************************/
44 /*** file scope type declarations **************************************/
46 /*** file scope variables **********************************************/
48 /* List of dialogs: filemanagers, editors, viewers */
49 static GList *mc_dialogs = NULL;
50 /* Currently active dialog */
51 static GList *mc_current = NULL;
52 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
53 static gboolean dialog_switch_pending = FALSE;
55 /*** file scope functions **********************************************/
57 static unsigned char
58 get_hotkey (int n)
60 return (n <= 9) ? '0' + n : 'a' + n - 10;
63 static void
64 dialog_switch_goto (GList *dlg)
66 if (mc_current != dlg)
68 Dlg_head *old = (Dlg_head *) mc_current->data;
70 mc_current = dlg;
72 if (old == midnight_dlg)
74 /* switch from panels to another dialog (editor, viewer, etc) */
75 dialog_switch_pending = TRUE;
76 dialog_switch_process_pending ();
78 else
80 /* switch from editor, viewer, etc to another dialog */
81 old->state = DLG_SUSPENDED;
83 if ((Dlg_head *) dlg->data != midnight_dlg)
84 /* switch to another editor, viewer, etc */
85 /* return to panels before run the required dialog */
86 dialog_switch_pending = TRUE;
87 else
88 /* switch to panels */
89 do_refresh ();
94 /*** public functions **************************************************/
96 void
97 dialog_switch_add (Dlg_head *h)
99 GList *dlg;
101 dlg = g_list_find (mc_dialogs, h);
103 if (dlg != NULL)
104 mc_current = dlg;
105 else
107 mc_dialogs = g_list_prepend (mc_dialogs, h);
108 mc_current = mc_dialogs;
112 void
113 dialog_switch_remove (Dlg_head *h)
115 GList *this;
117 if ((Dlg_head *) mc_current->data == h)
118 this = mc_current;
119 else
120 this = g_list_find (mc_dialogs, h);
122 mc_dialogs = g_list_delete_link (mc_dialogs, this);
124 /* adjust current dialog */
125 if (top_dlg != NULL)
126 mc_current = g_list_find (mc_dialogs, (Dlg_head *) top_dlg->data);
127 else
128 mc_current = mc_dialogs;
131 size_t
132 dialog_switch_num (void)
134 return g_list_length (mc_dialogs);
137 void
138 dialog_switch_next (void)
140 GList *next;
142 if (midnight_shutdown || mc_current == NULL)
143 return;
145 next = g_list_next (mc_current);
146 if (next == NULL)
147 next = mc_dialogs;
149 dialog_switch_goto (next);
152 void
153 dialog_switch_prev (void)
155 GList *prev;
157 if (midnight_shutdown || mc_current == NULL)
158 return;
160 prev = g_list_previous (mc_current);
161 if (prev == NULL)
162 prev = g_list_last (mc_dialogs);
164 dialog_switch_goto (prev);
167 void
168 dialog_switch_list (void)
170 const size_t dlg_num = g_list_length (mc_dialogs);
171 int lines, cols;
172 Listbox *listbox;
173 GList *h;
174 int i = 0;
175 int rv;
177 if (midnight_shutdown || mc_current == NULL)
178 return;
180 lines = min ((size_t) (LINES * 2/3), dlg_num);
181 cols = COLS * 2/3;
183 listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
185 for (h = mc_dialogs; h != NULL; h = g_list_next (h))
187 Dlg_head *dlg;
188 char *title;
190 dlg = (Dlg_head *) h->data;
192 if ((dlg != NULL) && (dlg->get_title != NULL))
193 title = dlg->get_title (dlg, listbox->list->widget.cols - 2); /* FIXME! */
194 else
195 title = g_strdup ("");
197 listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, NULL);
199 g_free (title);
202 listbox_select_entry (listbox->list, dlg_num - 1 - g_list_position (mc_dialogs, mc_current));
203 rv = run_listbox (listbox);
205 if (rv >= 0)
207 h = g_list_nth (mc_dialogs, dlg_num - 1 - rv);
208 dialog_switch_goto (h);
213 dialog_switch_process_pending (void)
215 int ret = 0;
217 while (dialog_switch_pending)
219 Dlg_head *h = (Dlg_head *) mc_current->data;
221 dialog_switch_pending = FALSE;
222 h->state = DLG_SUSPENDED;
223 ret = run_dlg (h);
224 if (h->state == DLG_CLOSED)
226 destroy_dlg (h);
227 /* return to panels */
228 if (mc_run_mode == MC_RUN_FULL)
230 mc_current = g_list_find (mc_dialogs, midnight_dlg);
231 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
236 repaint_screen ();
238 return ret;
241 void
242 dialog_switch_got_winch (void)
244 GList *dlg;
246 for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
247 if (dlg != mc_current)
248 ((Dlg_head *) dlg->data)->winch_pending = TRUE;
251 void
252 dialog_switch_shutdown (void)
254 while (mc_dialogs != NULL)
256 Dlg_head *dlg = (Dlg_head *) mc_dialogs->data;
258 run_dlg (dlg);
259 destroy_dlg (dlg);