Check perl, python and ruby programs and substitute them in various files.
[midnight-commander.git] / lib / widget / dialog-switch.c
blob7d851a71c2d35e84aa21ceb74b99dde0d8c12b75
1 /*
2 Support of multiply editors and viewers.
4 Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
6 Copyright (c) 2009, 2010, 2011
7 The Free Software Foundation
9 Written by:
10 Daniel Borca <dborca@yahoo.com>, 2007
11 Andrew Borodin <aborodin@vmail.ru>, 2010
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 /* If TIOCGWINSZ supported, make it available here, because window resizing code
36 * depends on it... */
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
39 #endif
40 #include <termios.h>
42 #include "lib/global.h"
43 #include "lib/tty/tty.h" /* LINES, COLS */
44 #include "lib/tty/win.h" /* do_enter_ca_mode() */
45 #include "lib/tty/color.h" /* tty_set_normal_attrs() */
46 #include "lib/widget.h"
47 #include "lib/event.h"
49 /*** global variables ****************************************************************************/
51 Dlg_head *midnight_dlg = NULL;
53 /*** file scope macro definitions ****************************************************************/
55 /*** file scope type declarations ****************************************************************/
57 /*** file scope variables ************************************************************************/
59 /* List of dialogs: filemanagers, editors, viewers */
60 static GList *mc_dialogs = NULL;
61 /* Currently active dialog */
62 static GList *mc_current = NULL;
63 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
64 static gboolean dialog_switch_pending = FALSE;
66 /*** file scope functions ************************************************************************/
67 /* --------------------------------------------------------------------------------------------- */
69 static unsigned char
70 get_hotkey (int n)
72 return (n <= 9) ? '0' + n : 'a' + n - 10;
75 /* --------------------------------------------------------------------------------------------- */
77 static void
78 dialog_switch_suspend (void *data, void *user_data)
80 (void) user_data;
82 if (data != mc_current->data)
83 ((Dlg_head *) data)->state = DLG_SUSPENDED;
86 /* --------------------------------------------------------------------------------------------- */
88 static void
89 dialog_switch_goto (GList * dlg)
91 if (mc_current != dlg)
93 Dlg_head *old = (Dlg_head *) mc_current->data;
95 mc_current = dlg;
97 if (old == midnight_dlg)
99 /* switch from panels to another dialog (editor, viewer, etc) */
100 dialog_switch_pending = TRUE;
101 dialog_switch_process_pending ();
103 else
105 /* switch from editor, viewer, etc to another dialog */
106 old->state = DLG_SUSPENDED;
108 if ((Dlg_head *) dlg->data != midnight_dlg)
109 /* switch to another editor, viewer, etc */
110 /* return to panels before run the required dialog */
111 dialog_switch_pending = TRUE;
112 else
114 /* switch to panels */
115 midnight_dlg->state = DLG_ACTIVE;
116 do_refresh ();
122 /* --------------------------------------------------------------------------------------------- */
124 #if defined TIOCGWINSZ
125 static void
126 dlg_resize_cb (void *data, void *user_data)
128 Dlg_head *d = data;
130 (void) user_data;
131 if (d->state == DLG_ACTIVE)
132 d->callback (d, NULL, DLG_RESIZE, 0, NULL);
133 else
134 d->winch_pending = TRUE;
136 #endif
138 /* --------------------------------------------------------------------------------------------- */
139 /*** public functions ****************************************************************************/
140 /* --------------------------------------------------------------------------------------------- */
142 void
143 dialog_switch_add (Dlg_head * h)
145 GList *dlg;
147 dlg = g_list_find (mc_dialogs, h);
149 if (dlg != NULL)
150 mc_current = dlg;
151 else
153 mc_dialogs = g_list_prepend (mc_dialogs, h);
154 mc_current = mc_dialogs;
157 /* suspend forced all other screens */
158 g_list_foreach (mc_dialogs, dialog_switch_suspend, NULL);
161 /* --------------------------------------------------------------------------------------------- */
163 void
164 dialog_switch_remove (Dlg_head * h)
166 GList *this;
168 if ((Dlg_head *) mc_current->data == h)
169 this = mc_current;
170 else
171 this = g_list_find (mc_dialogs, h);
173 mc_dialogs = g_list_delete_link (mc_dialogs, this);
175 /* adjust current dialog */
176 if (top_dlg != NULL)
177 mc_current = g_list_find (mc_dialogs, (Dlg_head *) top_dlg->data);
178 else
179 mc_current = mc_dialogs;
181 /* resume forced the current screen */
182 if (mc_current != NULL)
183 ((Dlg_head *) mc_current->data)->state = DLG_ACTIVE;
186 /* --------------------------------------------------------------------------------------------- */
188 size_t
189 dialog_switch_num (void)
191 return g_list_length (mc_dialogs);
194 /* --------------------------------------------------------------------------------------------- */
196 void
197 dialog_switch_next (void)
199 GList *next;
201 if (mc_global.midnight_shutdown || mc_current == NULL)
202 return;
204 next = g_list_next (mc_current);
205 if (next == NULL)
206 next = mc_dialogs;
208 dialog_switch_goto (next);
211 /* --------------------------------------------------------------------------------------------- */
213 void
214 dialog_switch_prev (void)
216 GList *prev;
218 if (mc_global.midnight_shutdown || mc_current == NULL)
219 return;
221 prev = g_list_previous (mc_current);
222 if (prev == NULL)
223 prev = g_list_last (mc_dialogs);
225 dialog_switch_goto (prev);
228 /* --------------------------------------------------------------------------------------------- */
230 void
231 dialog_switch_list (void)
233 const size_t dlg_num = g_list_length (mc_dialogs);
234 int lines, cols;
235 Listbox *listbox;
236 GList *h;
237 int i = 0;
238 int rv;
240 if (mc_global.midnight_shutdown || mc_current == NULL)
241 return;
243 lines = min ((size_t) (LINES * 2 / 3), dlg_num);
244 cols = COLS * 2 / 3;
246 listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
248 for (h = mc_dialogs; h != NULL; h = g_list_next (h))
250 Dlg_head *dlg;
251 char *title;
253 dlg = (Dlg_head *) h->data;
255 if ((dlg != NULL) && (dlg->get_title != NULL))
256 title = dlg->get_title (dlg, listbox->list->widget.cols - 2); /* FIXME! */
257 else
258 title = g_strdup ("");
260 listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, NULL);
262 g_free (title);
265 listbox_select_entry (listbox->list, dlg_num - 1 - g_list_position (mc_dialogs, mc_current));
266 rv = run_listbox (listbox);
268 if (rv >= 0)
270 h = g_list_nth (mc_dialogs, dlg_num - 1 - rv);
271 dialog_switch_goto (h);
275 /* --------------------------------------------------------------------------------------------- */
278 dialog_switch_process_pending (void)
280 int ret = 0;
282 while (dialog_switch_pending)
284 Dlg_head *h = (Dlg_head *) mc_current->data;
286 dialog_switch_pending = FALSE;
287 h->state = DLG_SUSPENDED;
288 ret = run_dlg (h);
289 if (h->state == DLG_CLOSED)
291 destroy_dlg (h);
293 /* return to panels */
294 if (mc_global.mc_run_mode == MC_RUN_FULL)
296 mc_current = g_list_find (mc_dialogs, midnight_dlg);
297 mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
302 repaint_screen ();
304 return ret;
307 /* --------------------------------------------------------------------------------------------- */
309 void
310 dialog_switch_got_winch (void)
312 GList *dlg;
314 for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
315 if (dlg != mc_current)
316 ((Dlg_head *) dlg->data)->winch_pending = TRUE;
319 /* --------------------------------------------------------------------------------------------- */
321 void
322 dialog_switch_shutdown (void)
324 while (mc_dialogs != NULL)
326 Dlg_head *dlg = (Dlg_head *) mc_dialogs->data;
328 run_dlg (dlg);
329 destroy_dlg (dlg);
333 /* --------------------------------------------------------------------------------------------- */
335 void
336 clr_scr (void)
338 tty_set_normal_attrs ();
339 tty_fill_region (0, 0, LINES, COLS, ' ');
340 tty_refresh ();
343 /* --------------------------------------------------------------------------------------------- */
345 void
346 repaint_screen (void)
348 do_refresh ();
349 tty_refresh ();
352 /* --------------------------------------------------------------------------------------------- */
354 void
355 mc_refresh (void)
357 #ifdef ENABLE_BACKGROUND
358 if (mc_global.we_are_background)
359 return;
360 #endif /* ENABLE_BACKGROUND */
361 if (!mc_global.tty.winch_flag)
362 tty_refresh ();
363 else
365 /* if winch was caugth, we should do not only redraw screen, but
366 reposition/resize all */
367 dialog_change_screen_size ();
371 /* --------------------------------------------------------------------------------------------- */
373 void
374 dialog_change_screen_size (void)
376 mc_global.tty.winch_flag = FALSE;
377 #if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
378 #if defined TIOCGWINSZ
380 #ifndef NCURSES_VERSION
381 tty_noraw_mode ();
382 tty_reset_screen ();
383 #endif
384 tty_change_screen_size ();
385 #ifdef HAVE_SLANG
386 /* XSI Curses spec states that portable applications shall not invoke
387 * initscr() more than once. This kludge could be done within the scope
388 * of the specification by using endwin followed by a refresh (in fact,
389 * more than one curses implementation does this); it is guaranteed to work
390 * only with slang.
392 SLsmg_init_smg ();
393 do_enter_ca_mode ();
394 tty_keypad (TRUE);
395 tty_nodelay (FALSE);
396 #endif
398 /* Inform all suspending dialogs */
399 dialog_switch_got_winch ();
400 /* Inform all running dialogs */
401 g_list_foreach (top_dlg, (GFunc) dlg_resize_cb, NULL);
403 /* Now, force the redraw */
404 repaint_screen ();
406 #endif /* TIOCGWINSZ */
407 #endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */
410 /* --------------------------------------------------------------------------------------------- */