2 Support of multiply editors and viewers.
4 Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
6 Copyright (C) 2009-2024
7 Free Software Foundation, Inc.
10 Daniel Borca <dborca@yahoo.com>, 2007
11 Andrew Borodin <aborodin@vmail.ru>, 2010-2022
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 #include "lib/global.h"
36 #include "lib/tty/tty.h" /* LINES, COLS */
37 #include "lib/tty/color.h" /* tty_set_normal_attrs() */
38 #include "lib/widget.h"
39 #include "lib/event.h"
41 /*** global variables ****************************************************************************/
43 /* Primitive way to check if the the current dialog is our dialog */
44 /* This is needed by async routines like load_prompt */
45 GList
*top_dlg
= NULL
;
47 /* If set then dialogs just clean the screen when refreshing, else */
48 /* they do a complete refresh, refreshing all the parts of the program */
49 gboolean fast_refresh
= FALSE
;
51 WDialog
*filemanager
= NULL
;
53 /*** file scope macro definitions ****************************************************************/
55 /*** file scope type declarations ****************************************************************/
57 /*** forward declarations (file scope functions) *************************************************/
59 /*** file scope variables ************************************************************************/
61 /* List of dialogs: filemanagers, editors, viewers */
62 static GList
*mc_dialogs
= NULL
;
63 /* Currently active dialog */
64 static GList
*mc_current
= NULL
;
65 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
66 static gboolean dialog_switch_pending
= FALSE
;
68 /* --------------------------------------------------------------------------------------------- */
69 /*** file scope functions ************************************************************************/
70 /* --------------------------------------------------------------------------------------------- */
75 return (n
<= 9) ? '0' + n
: 'a' + n
- 10;
78 /* --------------------------------------------------------------------------------------------- */
81 dialog_switch_suspend (void *data
, void *user_data
)
85 if (data
!= mc_current
->data
)
86 widget_set_state (WIDGET (data
), WST_SUSPENDED
, TRUE
);
89 /* --------------------------------------------------------------------------------------------- */
92 dialog_switch_goto (GList
*dlg
)
94 if (mc_current
!= dlg
)
96 WDialog
*old
= DIALOG (mc_current
->data
);
100 if (old
== filemanager
)
102 /* switch from panels to another dialog (editor, viewer, etc) */
103 dialog_switch_pending
= TRUE
;
104 dialog_switch_process_pending ();
108 /* switch from editor, viewer, etc to another dialog */
109 widget_set_state (WIDGET (old
), WST_SUSPENDED
, TRUE
);
111 if (DIALOG (dlg
->data
) != filemanager
)
112 /* switch to another editor, viewer, etc */
113 /* return to panels before run the required dialog */
114 dialog_switch_pending
= TRUE
;
117 /* switch to panels */
118 widget_set_state (WIDGET (filemanager
), WST_ACTIVE
, TRUE
);
125 /* --------------------------------------------------------------------------------------------- */
128 dialog_switch_resize (WDialog
*d
)
130 if (widget_get_state (WIDGET (d
), WST_ACTIVE
))
131 send_message (d
, NULL
, MSG_RESIZE
, 0, NULL
);
133 GROUP (d
)->winch_pending
= TRUE
;
136 /* --------------------------------------------------------------------------------------------- */
137 /*** public functions ****************************************************************************/
138 /* --------------------------------------------------------------------------------------------- */
141 dialog_switch_add (WDialog
*h
)
145 dlg
= g_list_find (mc_dialogs
, h
);
151 mc_dialogs
= g_list_prepend (mc_dialogs
, h
);
152 mc_current
= mc_dialogs
;
155 /* suspend forced all other screens */
156 g_list_foreach (mc_dialogs
, dialog_switch_suspend
, NULL
);
159 /* --------------------------------------------------------------------------------------------- */
162 dialog_switch_remove (WDialog
*h
)
166 if (DIALOG (mc_current
->data
) == h
)
169 this = g_list_find (mc_dialogs
, h
);
171 mc_dialogs
= g_list_delete_link (mc_dialogs
, this);
173 /* adjust current dialog */
175 mc_current
= g_list_find (mc_dialogs
, DIALOG (top_dlg
->data
));
177 mc_current
= mc_dialogs
;
179 /* resume forced the current screen */
180 if (mc_current
!= NULL
)
181 widget_set_state (WIDGET (mc_current
->data
), WST_ACTIVE
, TRUE
);
184 /* --------------------------------------------------------------------------------------------- */
187 dialog_switch_num (void)
189 return g_list_length (mc_dialogs
);
192 /* --------------------------------------------------------------------------------------------- */
195 dialog_switch_next (void)
199 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
202 next
= g_list_next (mc_current
);
206 dialog_switch_goto (next
);
209 /* --------------------------------------------------------------------------------------------- */
212 dialog_switch_prev (void)
216 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
219 prev
= g_list_previous (mc_current
);
221 prev
= g_list_last (mc_dialogs
);
223 dialog_switch_goto (prev
);
226 /* --------------------------------------------------------------------------------------------- */
229 dialog_switch_list (void)
231 const size_t dlg_num
= g_list_length (mc_dialogs
);
237 if (mc_global
.midnight_shutdown
|| mc_current
== NULL
)
240 lines
= MIN ((size_t) (LINES
* 2 / 3), dlg_num
);
243 listbox
= listbox_window_new (lines
, cols
, _("Screens"), "[Screen selector]");
245 for (h
= mc_dialogs
; h
!= NULL
; h
= g_list_next (h
))
247 WDialog
*dlg
= DIALOG (h
->data
);
250 if (dlg
->get_title
!= NULL
)
251 title
= dlg
->get_title (dlg
, WIDGET (listbox
->list
)->rect
.cols
- 2);
253 title
= g_strdup ("");
255 listbox_add_item_take (listbox
->list
, LISTBOX_APPEND_BEFORE
, get_hotkey (i
++), title
, h
,
259 selected
= listbox_run_with_data (listbox
, mc_current
);
260 if (selected
!= NULL
)
261 dialog_switch_goto (selected
);
264 /* --------------------------------------------------------------------------------------------- */
267 dialog_switch_process_pending (void)
271 while (dialog_switch_pending
)
273 WDialog
*h
= DIALOG (mc_current
->data
);
274 Widget
*wh
= WIDGET (h
);
276 dialog_switch_pending
= FALSE
;
277 widget_set_state (wh
, WST_SUSPENDED
, TRUE
);
279 if (widget_get_state (wh
, WST_CLOSED
))
283 /* return to panels */
284 if (mc_global
.mc_run_mode
== MC_RUN_FULL
)
286 mc_current
= g_list_find (mc_dialogs
, filemanager
);
287 mc_event_raise (MCEVENT_GROUP_FILEMANAGER
, "update_panels", NULL
);
297 /* --------------------------------------------------------------------------------------------- */
300 dialog_switch_got_winch (void)
304 for (dlg
= mc_dialogs
; dlg
!= NULL
; dlg
= g_list_next (dlg
))
305 if (dlg
!= mc_current
)
306 GROUP (dlg
->data
)->winch_pending
= TRUE
;
309 /* --------------------------------------------------------------------------------------------- */
312 dialog_switch_shutdown (void)
314 while (mc_dialogs
!= NULL
)
316 WDialog
*dlg
= DIALOG (mc_dialogs
->data
);
319 widget_destroy (WIDGET (dlg
));
323 /* --------------------------------------------------------------------------------------------- */
333 widget_draw (WIDGET (d
->data
));
337 /* Search first fullscreen dialog */
338 for (; d
!= NULL
; d
= g_list_next (d
))
339 if ((WIDGET (d
->data
)->pos_flags
& WPOS_FULLSCREEN
) != 0)
342 /* when small dialog (i.e. error message) is created first,
343 there is no fullscreen dialog in the stack */
345 d
= g_list_last (top_dlg
);
347 /* back to top dialog */
348 for (; d
!= NULL
; d
= g_list_previous (d
))
349 widget_draw (WIDGET (d
->data
));
353 /* --------------------------------------------------------------------------------------------- */
356 repaint_screen (void)
362 /* --------------------------------------------------------------------------------------------- */
367 #ifdef ENABLE_BACKGROUND
368 if (mc_global
.we_are_background
)
370 #endif /* ENABLE_BACKGROUND */
372 if (!tty_got_winch ())
376 /* if winch was caugth, we should do not only redraw screen, but
377 reposition/resize all */
378 dialog_change_screen_size ();
382 /* --------------------------------------------------------------------------------------------- */
385 dialog_change_screen_size (void)
390 tty_change_screen_size ();
397 /* Inform all suspending dialogs */
398 dialog_switch_got_winch ();
400 /* Inform all running dialogs from first to last */
401 for (d
= g_list_last (top_dlg
); d
!= NULL
; d
= g_list_previous (d
))
402 dialog_switch_resize (DIALOG (d
->data
));
404 /* Now, force the redraw */
408 /* --------------------------------------------------------------------------------------------- */