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.
29 /* If TIOCGWINSZ supported, make it available here, because window resizing code
31 #ifdef HAVE_SYS_IOCTL_H
32 #include <sys/ioctl.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 /* --------------------------------------------------------------------------------------------- */
66 return (n
<= 9) ? '0' + n
: 'a' + n
- 10;
69 /* --------------------------------------------------------------------------------------------- */
72 dialog_switch_goto (GList
* dlg
)
74 if (mc_current
!= dlg
)
76 Dlg_head
*old
= (Dlg_head
*) mc_current
->data
;
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 ();
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
;
96 /* switch to panels */
102 /* --------------------------------------------------------------------------------------------- */
104 #if defined TIOCGWINSZ
106 dlg_resize_cb (void *data
, void *user_data
)
111 d
->callback (d
, NULL
, DLG_RESIZE
, 0, NULL
);
115 /* --------------------------------------------------------------------------------------------- */
116 /*** public functions ****************************************************************************/
117 /* --------------------------------------------------------------------------------------------- */
120 dialog_switch_add (Dlg_head
* h
)
124 dlg
= g_list_find (mc_dialogs
, h
);
130 mc_dialogs
= g_list_prepend (mc_dialogs
, h
);
131 mc_current
= mc_dialogs
;
135 /* --------------------------------------------------------------------------------------------- */
138 dialog_switch_remove (Dlg_head
* h
)
142 if ((Dlg_head
*) mc_current
->data
== h
)
145 this = g_list_find (mc_dialogs
, h
);
147 mc_dialogs
= g_list_delete_link (mc_dialogs
, this);
149 /* adjust current dialog */
151 mc_current
= g_list_find (mc_dialogs
, (Dlg_head
*) top_dlg
->data
);
153 mc_current
= mc_dialogs
;
156 /* --------------------------------------------------------------------------------------------- */
159 dialog_switch_num (void)
161 return g_list_length (mc_dialogs
);
164 /* --------------------------------------------------------------------------------------------- */
167 dialog_switch_next (void)
171 if (mc_global
.widget
.midnight_shutdown
|| mc_current
== NULL
)
174 next
= g_list_next (mc_current
);
178 dialog_switch_goto (next
);
181 /* --------------------------------------------------------------------------------------------- */
184 dialog_switch_prev (void)
188 if (mc_global
.widget
.midnight_shutdown
|| mc_current
== NULL
)
191 prev
= g_list_previous (mc_current
);
193 prev
= g_list_last (mc_dialogs
);
195 dialog_switch_goto (prev
);
198 /* --------------------------------------------------------------------------------------------- */
201 dialog_switch_list (void)
203 const size_t dlg_num
= g_list_length (mc_dialogs
);
210 if (mc_global
.widget
.midnight_shutdown
|| mc_current
== NULL
)
213 lines
= min ((size_t) (LINES
* 2 / 3), dlg_num
);
216 listbox
= create_listbox_window (lines
, cols
, _("Screens"), "[Screen selector]");
218 for (h
= mc_dialogs
; h
!= NULL
; h
= g_list_next (h
))
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! */
228 title
= g_strdup ("");
230 listbox_add_item (listbox
->list
, LISTBOX_APPEND_BEFORE
, get_hotkey (i
++), title
, NULL
);
235 listbox_select_entry (listbox
->list
, dlg_num
- 1 - g_list_position (mc_dialogs
, mc_current
));
236 rv
= run_listbox (listbox
);
240 h
= g_list_nth (mc_dialogs
, dlg_num
- 1 - rv
);
241 dialog_switch_goto (h
);
245 /* --------------------------------------------------------------------------------------------- */
248 dialog_switch_process_pending (void)
252 while (dialog_switch_pending
)
254 Dlg_head
*h
= (Dlg_head
*) mc_current
->data
;
256 dialog_switch_pending
= FALSE
;
257 h
->state
= DLG_SUSPENDED
;
259 if (h
->state
== DLG_CLOSED
)
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
);
276 /* --------------------------------------------------------------------------------------------- */
279 dialog_switch_got_winch (void)
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 /* --------------------------------------------------------------------------------------------- */
291 dialog_switch_shutdown (void)
293 while (mc_dialogs
!= NULL
)
295 Dlg_head
*dlg
= (Dlg_head
*) mc_dialogs
->data
;
302 /* --------------------------------------------------------------------------------------------- */
307 tty_set_normal_attrs ();
308 tty_fill_region (0, 0, LINES
, COLS
, ' ');
312 /* --------------------------------------------------------------------------------------------- */
315 repaint_screen (void)
321 /* --------------------------------------------------------------------------------------------- */
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
334 tty_low_level_change_screen_size ();
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
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 */
356 #endif /* TIOCGWINSZ */
357 #endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */
360 /* --------------------------------------------------------------------------------------------- */