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
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.
35 /* If TIOCGWINSZ supported, make it available here, because window resizing code
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.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 /* --------------------------------------------------------------------------------------------- */
72 return (n
<= 9) ? '0' + n
: 'a' + n
- 10;
75 /* --------------------------------------------------------------------------------------------- */
78 dialog_switch_suspend (void *data
, void *user_data
)
82 if (data
!= mc_current
->data
)
83 ((Dlg_head
*) data
)->state
= DLG_SUSPENDED
;
86 /* --------------------------------------------------------------------------------------------- */
89 dialog_switch_goto (GList
* dlg
)
91 if (mc_current
!= dlg
)
93 Dlg_head
*old
= (Dlg_head
*) mc_current
->data
;
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 ();
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
;
114 /* switch to panels */
115 midnight_dlg
->state
= DLG_ACTIVE
;
122 /* --------------------------------------------------------------------------------------------- */
124 #if defined TIOCGWINSZ
126 dlg_resize_cb (void *data
, void *user_data
)
131 if (d
->state
== DLG_ACTIVE
)
132 d
->callback (d
, NULL
, DLG_RESIZE
, 0, NULL
);
134 d
->winch_pending
= TRUE
;
138 /* --------------------------------------------------------------------------------------------- */
139 /*** public functions ****************************************************************************/
140 /* --------------------------------------------------------------------------------------------- */
143 dialog_switch_add (Dlg_head
* h
)
147 dlg
= g_list_find (mc_dialogs
, h
);
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 /* --------------------------------------------------------------------------------------------- */
164 dialog_switch_remove (Dlg_head
* h
)
168 if ((Dlg_head
*) mc_current
->data
== h
)
171 this = g_list_find (mc_dialogs
, h
);
173 mc_dialogs
= g_list_delete_link (mc_dialogs
, this);
175 /* adjust current dialog */
177 mc_current
= g_list_find (mc_dialogs
, (Dlg_head
*) top_dlg
->data
);
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 /* --------------------------------------------------------------------------------------------- */
189 dialog_switch_num (void)
191 return g_list_length (mc_dialogs
);
194 /* --------------------------------------------------------------------------------------------- */
197 dialog_switch_next (void)
201 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
204 next
= g_list_next (mc_current
);
208 dialog_switch_goto (next
);
211 /* --------------------------------------------------------------------------------------------- */
214 dialog_switch_prev (void)
218 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
221 prev
= g_list_previous (mc_current
);
223 prev
= g_list_last (mc_dialogs
);
225 dialog_switch_goto (prev
);
228 /* --------------------------------------------------------------------------------------------- */
231 dialog_switch_list (void)
233 const size_t dlg_num
= g_list_length (mc_dialogs
);
240 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
243 lines
= min ((size_t) (LINES
* 2 / 3), dlg_num
);
246 listbox
= create_listbox_window (lines
, cols
, _("Screens"), "[Screen selector]");
248 for (h
= mc_dialogs
; h
!= NULL
; h
= g_list_next (h
))
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! */
258 title
= g_strdup ("");
260 listbox_add_item (listbox
->list
, LISTBOX_APPEND_BEFORE
, get_hotkey (i
++), title
, NULL
);
265 listbox_select_entry (listbox
->list
, dlg_num
- 1 - g_list_position (mc_dialogs
, mc_current
));
266 rv
= run_listbox (listbox
);
270 h
= g_list_nth (mc_dialogs
, dlg_num
- 1 - rv
);
271 dialog_switch_goto (h
);
275 /* --------------------------------------------------------------------------------------------- */
278 dialog_switch_process_pending (void)
282 while (dialog_switch_pending
)
284 Dlg_head
*h
= (Dlg_head
*) mc_current
->data
;
286 dialog_switch_pending
= FALSE
;
287 h
->state
= DLG_SUSPENDED
;
289 if (h
->state
== DLG_CLOSED
)
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
);
307 /* --------------------------------------------------------------------------------------------- */
310 dialog_switch_got_winch (void)
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 /* --------------------------------------------------------------------------------------------- */
322 dialog_switch_shutdown (void)
324 while (mc_dialogs
!= NULL
)
326 Dlg_head
*dlg
= (Dlg_head
*) mc_dialogs
->data
;
333 /* --------------------------------------------------------------------------------------------- */
338 tty_set_normal_attrs ();
339 tty_fill_region (0, 0, LINES
, COLS
, ' ');
343 /* --------------------------------------------------------------------------------------------- */
346 repaint_screen (void)
352 /* --------------------------------------------------------------------------------------------- */
357 #ifdef ENABLE_BACKGROUND
358 if (mc_global
.we_are_background
)
360 #endif /* ENABLE_BACKGROUND */
361 if (!mc_global
.tty
.winch_flag
)
365 /* if winch was caugth, we should do not only redraw screen, but
366 reposition/resize all */
367 dialog_change_screen_size ();
371 /* --------------------------------------------------------------------------------------------- */
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
384 tty_change_screen_size ();
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
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 */
406 #endif /* TIOCGWINSZ */
407 #endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */
410 /* --------------------------------------------------------------------------------------------- */