dialog-switch.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Copyright (c) 2009, 2010 Free Software Foundation
  3. *
  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.
  8. *
  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.
  13. *
  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
  17. *
  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>
  21. */
  22. /** \file dialog-switch.c
  23. * \brief Source: support of multiply editors and viewers.
  24. */
  25. #include <config.h>
  26. #include "lib/global.h"
  27. #include "lib/tty/tty.h" /* LINES, COLS */
  28. #include "lib/widget.h"
  29. /* TODO: these includes should be removed! */
  30. #include "src/filemanager/layout.h" /* repaint_screen() */
  31. #include "src/filemanager/midnight.h" /* midnight_dlg */
  32. #include "src/main.h" /* midnight_shutdown */
  33. /*** global variables ****************************************************************************/
  34. /*** file scope macro definitions ****************************************************************/
  35. /*** file scope type declarations ****************************************************************/
  36. /*** file scope variables ************************************************************************/
  37. /* List of dialogs: filemanagers, editors, viewers */
  38. static GList *mc_dialogs = NULL;
  39. /* Currently active dialog */
  40. static GList *mc_current = NULL;
  41. /* Is there any dialogs that we have to run after returning to the manager from another dialog */
  42. static gboolean dialog_switch_pending = FALSE;
  43. /*** file scope functions ************************************************************************/
  44. /* --------------------------------------------------------------------------------------------- */
  45. static unsigned char
  46. get_hotkey (int n)
  47. {
  48. return (n <= 9) ? '0' + n : 'a' + n - 10;
  49. }
  50. /* --------------------------------------------------------------------------------------------- */
  51. static void
  52. dialog_switch_goto (GList * dlg)
  53. {
  54. if (mc_current != dlg)
  55. {
  56. Dlg_head *old = (Dlg_head *) mc_current->data;
  57. mc_current = dlg;
  58. if (old == midnight_dlg)
  59. {
  60. /* switch from panels to another dialog (editor, viewer, etc) */
  61. dialog_switch_pending = TRUE;
  62. dialog_switch_process_pending ();
  63. }
  64. else
  65. {
  66. /* switch from editor, viewer, etc to another dialog */
  67. old->state = DLG_SUSPENDED;
  68. if ((Dlg_head *) dlg->data != midnight_dlg)
  69. /* switch to another editor, viewer, etc */
  70. /* return to panels before run the required dialog */
  71. dialog_switch_pending = TRUE;
  72. else
  73. /* switch to panels */
  74. do_refresh ();
  75. }
  76. }
  77. }
  78. /* --------------------------------------------------------------------------------------------- */
  79. /*** public functions ****************************************************************************/
  80. /* --------------------------------------------------------------------------------------------- */
  81. void
  82. dialog_switch_add (Dlg_head * h)
  83. {
  84. GList *dlg;
  85. dlg = g_list_find (mc_dialogs, h);
  86. if (dlg != NULL)
  87. mc_current = dlg;
  88. else
  89. {
  90. mc_dialogs = g_list_prepend (mc_dialogs, h);
  91. mc_current = mc_dialogs;
  92. }
  93. }
  94. /* --------------------------------------------------------------------------------------------- */
  95. void
  96. dialog_switch_remove (Dlg_head * h)
  97. {
  98. GList *this;
  99. if ((Dlg_head *) mc_current->data == h)
  100. this = mc_current;
  101. else
  102. this = g_list_find (mc_dialogs, h);
  103. mc_dialogs = g_list_delete_link (mc_dialogs, this);
  104. /* adjust current dialog */
  105. if (top_dlg != NULL)
  106. mc_current = g_list_find (mc_dialogs, (Dlg_head *) top_dlg->data);
  107. else
  108. mc_current = mc_dialogs;
  109. }
  110. /* --------------------------------------------------------------------------------------------- */
  111. size_t
  112. dialog_switch_num (void)
  113. {
  114. return g_list_length (mc_dialogs);
  115. }
  116. /* --------------------------------------------------------------------------------------------- */
  117. void
  118. dialog_switch_next (void)
  119. {
  120. GList *next;
  121. if (midnight_shutdown || mc_current == NULL)
  122. return;
  123. next = g_list_next (mc_current);
  124. if (next == NULL)
  125. next = mc_dialogs;
  126. dialog_switch_goto (next);
  127. }
  128. /* --------------------------------------------------------------------------------------------- */
  129. void
  130. dialog_switch_prev (void)
  131. {
  132. GList *prev;
  133. if (midnight_shutdown || mc_current == NULL)
  134. return;
  135. prev = g_list_previous (mc_current);
  136. if (prev == NULL)
  137. prev = g_list_last (mc_dialogs);
  138. dialog_switch_goto (prev);
  139. }
  140. /* --------------------------------------------------------------------------------------------- */
  141. void
  142. dialog_switch_list (void)
  143. {
  144. const size_t dlg_num = g_list_length (mc_dialogs);
  145. int lines, cols;
  146. Listbox *listbox;
  147. GList *h;
  148. int i = 0;
  149. int rv;
  150. if (midnight_shutdown || mc_current == NULL)
  151. return;
  152. lines = min ((size_t) (LINES * 2 / 3), dlg_num);
  153. cols = COLS * 2 / 3;
  154. listbox = create_listbox_window (lines, cols, _("Screens"), "[Screen selector]");
  155. for (h = mc_dialogs; h != NULL; h = g_list_next (h))
  156. {
  157. Dlg_head *dlg;
  158. char *title;
  159. dlg = (Dlg_head *) h->data;
  160. if ((dlg != NULL) && (dlg->get_title != NULL))
  161. title = dlg->get_title (dlg, listbox->list->widget.cols - 2); /* FIXME! */
  162. else
  163. title = g_strdup ("");
  164. listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, NULL);
  165. g_free (title);
  166. }
  167. listbox_select_entry (listbox->list, dlg_num - 1 - g_list_position (mc_dialogs, mc_current));
  168. rv = run_listbox (listbox);
  169. if (rv >= 0)
  170. {
  171. h = g_list_nth (mc_dialogs, dlg_num - 1 - rv);
  172. dialog_switch_goto (h);
  173. }
  174. }
  175. /* --------------------------------------------------------------------------------------------- */
  176. int
  177. dialog_switch_process_pending (void)
  178. {
  179. int ret = 0;
  180. while (dialog_switch_pending)
  181. {
  182. Dlg_head *h = (Dlg_head *) mc_current->data;
  183. dialog_switch_pending = FALSE;
  184. h->state = DLG_SUSPENDED;
  185. ret = run_dlg (h);
  186. if (h->state == DLG_CLOSED)
  187. {
  188. destroy_dlg (h);
  189. /* return to panels */
  190. if (mc_run_mode == MC_RUN_FULL)
  191. {
  192. mc_current = g_list_find (mc_dialogs, midnight_dlg);
  193. update_panels (UP_OPTIMIZE, UP_KEEPSEL);
  194. }
  195. }
  196. }
  197. repaint_screen ();
  198. return ret;
  199. }
  200. /* --------------------------------------------------------------------------------------------- */
  201. void
  202. dialog_switch_got_winch (void)
  203. {
  204. GList *dlg;
  205. for (dlg = mc_dialogs; dlg != NULL; dlg = g_list_next (dlg))
  206. if (dlg != mc_current)
  207. ((Dlg_head *) dlg->data)->winch_pending = TRUE;
  208. }
  209. /* --------------------------------------------------------------------------------------------- */
  210. void
  211. dialog_switch_shutdown (void)
  212. {
  213. while (mc_dialogs != NULL)
  214. {
  215. Dlg_head *dlg = (Dlg_head *) mc_dialogs->data;
  216. run_dlg (dlg);
  217. destroy_dlg (dlg);
  218. }
  219. }
  220. /* --------------------------------------------------------------------------------------------- */