root/lib/widget/dialog-switch.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. get_hotkey
  2. dialog_switch_suspend
  3. dialog_switch_goto
  4. dialog_switch_resize
  5. dialog_switch_add
  6. dialog_switch_remove
  7. dialog_switch_num
  8. dialog_switch_next
  9. dialog_switch_prev
  10. dialog_switch_list
  11. dialog_switch_process_pending
  12. dialog_switch_got_winch
  13. dialog_switch_shutdown
  14. clr_scr
  15. repaint_screen
  16. mc_refresh
  17. dialog_change_screen_size

   1 /*
   2    Support of multiply editors and viewers.
   3 
   4    Original idea and code: Oleg "Olegarch" Konovalov <olegarch@linuxinside.com>
   5 
   6    Copyright (C) 2009-2019
   7    Free Software Foundation, Inc.
   8 
   9    Written by:
  10    Daniel Borca <dborca@yahoo.com>, 2007
  11    Andrew Borodin <aborodin@vmail.ru>, 2010, 2013
  12 
  13    This file is part of the Midnight Commander.
  14 
  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.
  19 
  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.
  24 
  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/>.
  27  */
  28 
  29 /** \file dialog-switch.c
  30  *  \brief Source: support of multiply editors and viewers.
  31  */
  32 
  33 #include <config.h>
  34 
  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"
  40 
  41 /*** global variables ****************************************************************************/
  42 
  43 WDialog *midnight_dlg = NULL;
  44 
  45 /*** file scope macro definitions ****************************************************************/
  46 
  47 /*** file scope type declarations ****************************************************************/
  48 
  49 /*** file scope variables ************************************************************************/
  50 
  51 /* List of dialogs: filemanagers, editors, viewers */
  52 static GList *mc_dialogs = NULL;
  53 /* Currently active dialog */
  54 static GList *mc_current = NULL;
  55 /* Is there any dialogs that we have to run after returning to the manager from another dialog */
  56 static gboolean dialog_switch_pending = FALSE;
  57 
  58 /*** file scope functions ************************************************************************/
  59 /* --------------------------------------------------------------------------------------------- */
  60 
  61 static unsigned char
  62 get_hotkey (int n)
     /* [previous][next][first][last][top][bottom][index][help]  */
  63 {
  64     return (n <= 9) ? '0' + n : 'a' + n - 10;
  65 }
  66 
  67 /* --------------------------------------------------------------------------------------------- */
  68 
  69 static void
  70 dialog_switch_suspend (void *data, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help]  */
  71 {
  72     (void) user_data;
  73 
  74     if (data != mc_current->data)
  75         widget_set_state (WIDGET (data), WST_SUSPENDED, TRUE);
  76 }
  77 
  78 /* --------------------------------------------------------------------------------------------- */
  79 
  80 static void
  81 dialog_switch_goto (GList * dlg)
     /* [previous][next][first][last][top][bottom][index][help]  */
  82 {
  83     if (mc_current != dlg)
  84     {
  85         WDialog *old = DIALOG (mc_current->data);
  86 
  87         mc_current = dlg;
  88 
  89         if (old == midnight_dlg)
  90         {
  91             /* switch from panels to another dialog (editor, viewer, etc) */
  92             dialog_switch_pending = TRUE;
  93             dialog_switch_process_pending ();
  94         }
  95         else
  96         {
  97             /* switch from editor, viewer, etc to another dialog */
  98             widget_set_state (WIDGET (old), WST_SUSPENDED, TRUE);
  99 
 100             if (DIALOG (dlg->data) != midnight_dlg)
 101                 /* switch to another editor, viewer, etc */
 102                 /* return to panels before run the required dialog */
 103                 dialog_switch_pending = TRUE;
 104             else
 105             {
 106                 /* switch to panels */
 107                 widget_set_state (WIDGET (midnight_dlg), WST_ACTIVE, TRUE);
 108                 do_refresh ();
 109             }
 110         }
 111     }
 112 }
 113 
 114 /* --------------------------------------------------------------------------------------------- */
 115 
 116 static void
 117 dialog_switch_resize (WDialog * d)
     /* [previous][next][first][last][top][bottom][index][help]  */
 118 {
 119     if (widget_get_state (WIDGET (d), WST_ACTIVE))
 120         send_message (d, NULL, MSG_RESIZE, 0, NULL);
 121     else
 122         d->winch_pending = TRUE;
 123 }
 124 
 125 /* --------------------------------------------------------------------------------------------- */
 126 /*** public functions ****************************************************************************/
 127 /* --------------------------------------------------------------------------------------------- */
 128 
 129 void
 130 dialog_switch_add (WDialog * h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 131 {
 132     GList *dlg;
 133 
 134     dlg = g_list_find (mc_dialogs, h);
 135 
 136     if (dlg != NULL)
 137         mc_current = dlg;
 138     else
 139     {
 140         mc_dialogs = g_list_prepend (mc_dialogs, h);
 141         mc_current = mc_dialogs;
 142     }
 143 
 144     /* suspend forced all other screens */
 145     g_list_foreach (mc_dialogs, dialog_switch_suspend, NULL);
 146 }
 147 
 148 /* --------------------------------------------------------------------------------------------- */
 149 
 150 void
 151 dialog_switch_remove (WDialog * h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 152 {
 153     GList *this;
 154 
 155     if (DIALOG (mc_current->data) == h)
 156         this = mc_current;
 157     else
 158         this = g_list_find (mc_dialogs, h);
 159 
 160     mc_dialogs = g_list_delete_link (mc_dialogs, this);
 161 
 162     /* adjust current dialog */
 163     if (top_dlg != NULL)
 164         mc_current = g_list_find (mc_dialogs, DIALOG (top_dlg->data));
 165     else
 166         mc_current = mc_dialogs;
 167 
 168     /* resume forced the current screen */
 169     if (mc_current != NULL)
 170         widget_set_state (WIDGET (mc_current->data), WST_ACTIVE, TRUE);
 171 }
 172 
 173 /* --------------------------------------------------------------------------------------------- */
 174 
 175 size_t
 176 dialog_switch_num (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 177 {
 178     return g_list_length (mc_dialogs);
 179 }
 180 
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 void
 184 dialog_switch_next (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 185 {
 186     GList *next;
 187 
 188     if (mc_global.midnight_shutdown || mc_current == NULL)
 189         return;
 190 
 191     next = g_list_next (mc_current);
 192     if (next == NULL)
 193         next = mc_dialogs;
 194 
 195     dialog_switch_goto (next);
 196 }
 197 
 198 /* --------------------------------------------------------------------------------------------- */
 199 
 200 void
 201 dialog_switch_prev (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 202 {
 203     GList *prev;
 204 
 205     if (mc_global.midnight_shutdown || mc_current == NULL)
 206         return;
 207 
 208     prev = g_list_previous (mc_current);
 209     if (prev == NULL)
 210         prev = g_list_last (mc_dialogs);
 211 
 212     dialog_switch_goto (prev);
 213 }
 214 
 215 /* --------------------------------------------------------------------------------------------- */
 216 
 217 void
 218 dialog_switch_list (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 219 {
 220     const size_t dlg_num = g_list_length (mc_dialogs);
 221     int lines, cols;
 222     Listbox *listbox;
 223     GList *h, *selected;
 224     int i = 0;
 225 
 226     if (mc_global.midnight_shutdown || mc_current == NULL)
 227         return;
 228 
 229     lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
 230     cols = COLS * 2 / 3;
 231 
 232     listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
 233 
 234     for (h = mc_dialogs; h != NULL; h = g_list_next (h))
 235     {
 236         WDialog *dlg = DIALOG (h->data);
 237         char *title;
 238 
 239         if (dlg->get_title != NULL)
 240             title = dlg->get_title (dlg, WIDGET (listbox->list)->cols - 2);
 241         else
 242             title = g_strdup ("");
 243 
 244         listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h, FALSE);
 245 
 246         g_free (title);
 247     }
 248 
 249     selected = run_listbox_with_data (listbox, mc_current);
 250     if (selected != NULL)
 251         dialog_switch_goto (selected);
 252 }
 253 
 254 /* --------------------------------------------------------------------------------------------- */
 255 
 256 int
 257 dialog_switch_process_pending (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 258 {
 259     int ret = 0;
 260 
 261     while (dialog_switch_pending)
 262     {
 263         WDialog *h = DIALOG (mc_current->data);
 264         Widget *wh = WIDGET (h);
 265 
 266         dialog_switch_pending = FALSE;
 267         widget_set_state (wh, WST_SUSPENDED, TRUE);
 268         ret = dlg_run (h);
 269         if (widget_get_state (wh, WST_CLOSED))
 270         {
 271             dlg_destroy (h);
 272 
 273             /* return to panels */
 274             if (mc_global.mc_run_mode == MC_RUN_FULL)
 275             {
 276                 mc_current = g_list_find (mc_dialogs, midnight_dlg);
 277                 mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "update_panels", NULL);
 278             }
 279         }
 280     }
 281 
 282     repaint_screen ();
 283 
 284     return ret;
 285 }
 286 
 287 /* --------------------------------------------------------------------------------------------- */
 288 
 289 void
 290 dialog_switch_got_winch (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 291 {
 292     GList *dlg;
 293 
 294     for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
 295         if (dlg != mc_current)
 296             DIALOG (dlg->data)->winch_pending = TRUE;
 297 }
 298 
 299 /* --------------------------------------------------------------------------------------------- */
 300 
 301 void
 302 dialog_switch_shutdown (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 303 {
 304     while (mc_dialogs != NULL)
 305     {
 306         WDialog *dlg = DIALOG (mc_dialogs->data);
 307 
 308         dlg_run (dlg);
 309         dlg_destroy (dlg);
 310     }
 311 }
 312 
 313 /* --------------------------------------------------------------------------------------------- */
 314 
 315 void
 316 clr_scr (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 317 {
 318     tty_set_normal_attrs ();
 319     tty_fill_region (0, 0, LINES, COLS, ' ');
 320     tty_refresh ();
 321 }
 322 
 323 /* --------------------------------------------------------------------------------------------- */
 324 
 325 void
 326 repaint_screen (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 327 {
 328     do_refresh ();
 329     tty_refresh ();
 330 }
 331 
 332 /* --------------------------------------------------------------------------------------------- */
 333 
 334 void
 335 mc_refresh (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 336 {
 337 #ifdef ENABLE_BACKGROUND
 338     if (mc_global.we_are_background)
 339         return;
 340 #endif /* ENABLE_BACKGROUND */
 341 
 342     if (!tty_got_winch ())
 343         tty_refresh ();
 344     else
 345     {
 346         /* if winch was caugth, we should do not only redraw screen, but
 347            reposition/resize all */
 348         dialog_change_screen_size ();
 349     }
 350 }
 351 
 352 /* --------------------------------------------------------------------------------------------- */
 353 
 354 void
 355 dialog_change_screen_size (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 356 {
 357     GList *d;
 358 
 359     tty_flush_winch ();
 360     tty_change_screen_size ();
 361 
 362 #ifdef HAVE_SLANG
 363     tty_keypad (TRUE);
 364     tty_nodelay (FALSE);
 365 #endif
 366 
 367     /* Inform all suspending dialogs */
 368     dialog_switch_got_winch ();
 369 
 370     /* Inform all running dialogs from first to last */
 371     for (d = g_list_last (top_dlg); d != NULL; d = g_list_previous (d))
 372         dialog_switch_resize (DIALOG (d->data));
 373 
 374     /* Now, force the redraw */
 375     repaint_screen ();
 376 }
 377 
 378 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */