Added locale setting before calling dpkg to fix "link to" parsing on non-C locales
[midnight-commander.git] / lib / widget / dialog-switch.c
blobf4ae9e86c9f46bbbed118862733eb9128199ddb0
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 /* If TIOCGWINSZ supported, make it available here, because window resizing code
30 * depends on it... */
31 #ifdef HAVE_SYS_IOCTL_H
32 #include <sys/ioctl.h>
33 #endif
34 #include <termios.h>
36 #include "lib/global.h"
37 #include "lib/tty/tty.h" /* LINES, COLS */
38 #include "lib/tty/win.h" /* do_enter_ca_mode() */
39 #include "lib/tty/color.h" /* tty_set_normal_attrs() */
40 #include "lib/widget.h"
41 #include "lib/event.h"
43 /*** global variables ****************************************************************************/
45 Dlg_head *midnight_dlg = NULL;
47 /*** file scope macro definitions ****************************************************************/
49 /*** file scope type declarations ****************************************************************/
51 /*** file scope variables ************************************************************************/
53 /* List of dialogs: filemanagers, editors, viewers */
54 static GList *mc_dialogs = NULL;
55 /* Currently active dialog */
56 static GList *mc_current = NULL;
57 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
58 static gboolean dialog_switch_pending = FALSE;
60 /*** file scope functions ************************************************************************/
61 /* --------------------------------------------------------------------------------------------- */
63 static unsigned char
64 get_hotkey (int n)
66 return (n <= 9) ? '0' + n : 'a' + n - 10;
69 /* --------------------------------------------------------------------------------------------- */
71 static void
72 dialog_switch_goto (GList * dlg)
74 if (mc_current != dlg)
76 Dlg_head *old = (Dlg_head *) mc_current->data;
78 mc_current = dlg;
80 if (old == midnight_dlg)
82 /* switch from panels to another dialog (editor, viewer, etc) */
83 dialog_switch_pending = TRUE;
84 dialog_switch_process_pending ();
86 else
88 /* switch from editor, viewer, etc to another dialog */
89 old->state = DLG_SUSPENDED;
91 if ((Dlg_head *) dlg->data != midnight_dlg)
92 /* switch to another editor, viewer, etc */
93 /* return to panels before run the required dialog */
94 dialog_switch_pending = TRUE;
95 else
96 /* switch to panels */
97 do_refresh ();
102 /* --------------------------------------------------------------------------------------------- */
104 #if defined TIOCGWINSZ
105 static void
106 dlg_resize_cb (void *data, void *user_data)
108 Dlg_head *d = data;
110 (void) user_data;
111 d->callback (d, NULL, DLG_RESIZE, 0, NULL);
113 #endif
115 /* --------------------------------------------------------------------------------------------- */
116 /*** public functions ****************************************************************************/
117 /* --------------------------------------------------------------------------------------------- */
119 void
120 dialog_switch_add (Dlg_head * h)
122 GList *dlg;
124 dlg = g_list_find (mc_dialogs, h);
126 if (dlg != NULL)
127 mc_current = dlg;
128 else
130 mc_dialogs = g_list_prepend (mc_dialogs, h);
131 mc_current = mc_dialogs;
135 /* --------------------------------------------------------------------------------------------- */
137 void
138 dialog_switch_remove (Dlg_head * h)
140 GList *this;
142 if ((Dlg_head *) mc_current->data == h)
143 this = mc_current;
144 else
145 this = g_list_find (mc_dialogs, h);
147 mc_dialogs = g_list_delete_link (mc_dialogs, this);
149 /* adjust current dialog */
150 if (top_dlg != NULL)
151 mc_current = g_list_find (mc_dialogs, (Dlg_head *) top_dlg->data);
152 else
153 mc_current = mc_dialogs;
156 /* --------------------------------------------------------------------------------------------- */
158 size_t
159 dialog_switch_num (void)
161 return g_list_length (mc_dialogs);
164 /* --------------------------------------------------------------------------------------------- */
166 void
167 dialog_switch_next (void)
169 GList *next;
171 if (mc_global.widget.midnight_shutdown || mc_current == NULL)
172 return;
174 next = g_list_next (mc_current);
175 if (next == NULL)
176 next = mc_dialogs;
178 dialog_switch_goto (next);
181 /* --------------------------------------------------------------------------------------------- */
183 void
184 dialog_switch_prev (void)
186 GList *prev;
188 if (mc_global.widget.midnight_shutdown || mc_current == NULL)
189 return;
191 prev = g_list_previous (mc_current);
192 if (prev == NULL)
193 prev = g_list_last (mc_dialogs);
195 dialog_switch_goto (prev);
198 /* --------------------------------------------------------------------------------------------- */
200 void
201 dialog_switch_list (void)
203 const size_t dlg_num = g_list_length (mc_dialogs);
204 int lines, cols;
205 Listbox *listbox;
206 GList *h;
207 int i = 0;
208 int rv;
210 if (mc_global.widget.midnight_shutdown || mc_current == NULL)
211 return;
213 lines = min ((size_t) (LINES * 2 / 3), dlg_num);
214 cols = COLS * 2 / 3;
216 listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
218 for (h = mc_dialogs; h != NULL; h = g_list_next (h))
220 Dlg_head *dlg;
221 char *title;
223 dlg = (Dlg_head *) h->data;
225 if ((dlg != NULL) && (dlg->get_title != NULL))
226 title = dlg->get_title (dlg, listbox->list->widget.cols - 2); /* FIXME! */
227 else
228 title = g_strdup ("");
230 listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, NULL);
232 g_free (title);
235 listbox_select_entry (listbox->list, dlg_num - 1 - g_list_position (mc_dialogs, mc_current));
236 rv = run_listbox (listbox);
238 if (rv >= 0)
240 h = g_list_nth (mc_dialogs, dlg_num - 1 - rv);
241 dialog_switch_goto (h);
245 /* --------------------------------------------------------------------------------------------- */
248 dialog_switch_process_pending (void)
250 int ret = 0;
252 while (dialog_switch_pending)
254 Dlg_head *h = (Dlg_head *) mc_current->data;
256 dialog_switch_pending = FALSE;
257 h->state = DLG_SUSPENDED;
258 ret = run_dlg (h);
259 if (h->state == DLG_CLOSED)
261 destroy_dlg (h);
262 /* return to panels */
263 if (mc_global.mc_run_mode == MC_RUN_FULL)
265 mc_current = g_list_find (mc_dialogs, midnight_dlg);
266 mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
271 repaint_screen ();
273 return ret;
276 /* --------------------------------------------------------------------------------------------- */
278 void
279 dialog_switch_got_winch (void)
281 GList *dlg;
283 for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
284 if (dlg != mc_current)
285 ((Dlg_head *) dlg->data)->winch_pending = TRUE;
288 /* --------------------------------------------------------------------------------------------- */
290 void
291 dialog_switch_shutdown (void)
293 while (mc_dialogs != NULL)
295 Dlg_head *dlg = (Dlg_head *) mc_dialogs->data;
297 run_dlg (dlg);
298 destroy_dlg (dlg);
302 /* --------------------------------------------------------------------------------------------- */
304 void
305 clr_scr (void)
307 tty_set_normal_attrs ();
308 tty_fill_region (0, 0, LINES, COLS, ' ');
309 tty_refresh ();
312 /* --------------------------------------------------------------------------------------------- */
314 void
315 repaint_screen (void)
317 do_refresh ();
318 tty_refresh ();
321 /* --------------------------------------------------------------------------------------------- */
323 void
324 dialog_change_screen_size (void)
326 mc_global.tty.winch_flag = FALSE;
327 #if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
328 #if defined TIOCGWINSZ
330 #ifndef NCURSES_VERSION
331 tty_noraw_mode ();
332 tty_reset_screen ();
333 #endif
334 tty_low_level_change_screen_size ();
335 #ifdef HAVE_SLANG
336 /* XSI Curses spec states that portable applications shall not invoke
337 * initscr() more than once. This kludge could be done within the scope
338 * of the specification by using endwin followed by a refresh (in fact,
339 * more than one curses implementation does this); it is guaranteed to work
340 * only with slang.
342 SLsmg_init_smg ();
343 do_enter_ca_mode ();
344 tty_keypad (TRUE);
345 tty_nodelay (FALSE);
346 #endif
348 /* Inform all suspending dialogs */
349 dialog_switch_got_winch ();
350 /* Inform all running dialogs */
351 g_list_foreach (top_dlg, (GFunc) dlg_resize_cb, NULL);
353 /* Now, force the redraw */
354 repaint_screen ();
356 #endif /* TIOCGWINSZ */
357 #endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */
360 /* --------------------------------------------------------------------------------------------- */