Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / fe-text / gui-windows.c
1 /*
2  gui-windows.c : irssi
3
4     Copyright (C) 1999-2001 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "signals.h"
23 #include "misc.h"
24 #include "settings.h"
25 #include "special-vars.h"
26
27 #include "term.h"
28 #include "gui-entry.h"
29 #include "gui-windows.h"
30 #include "gui-printtext.h"
31
32 static int window_create_override;
33
34 static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window,
35                                        MAIN_WINDOW_REC *parent)
36 {
37         GUI_WINDOW_REC *gui;
38
39         window->width = parent->width;
40         window->height = MAIN_WINDOW_TEXT_HEIGHT(parent);
41
42         gui = g_new0(GUI_WINDOW_REC, 1);
43         gui->parent = parent;
44         gui->view = textbuffer_view_create(textbuffer_create(),
45                                            window->width, window->height,
46                                            settings_get_bool("scroll"),
47                                            term_type == TERM_TYPE_UTF8);
48         textbuffer_view_set_default_indent(gui->view,
49                                            settings_get_int("indent"),
50                                            !settings_get_bool("indent_always"),
51                                            get_default_indent_func());
52         if (parent->active == window)
53                 textbuffer_view_set_window(gui->view, parent->screen_win);
54         return gui;
55 }
56
57 static void gui_window_deinit(GUI_WINDOW_REC *gui)
58 {
59         textbuffer_view_destroy(gui->view);
60         g_free(gui);
61 }
62
63 static void sig_window_create_override(gpointer tab)
64 {
65         window_create_override = GPOINTER_TO_INT(tab);
66 }
67
68 static void gui_window_created(WINDOW_REC *window, void *automatic)
69 {
70         MAIN_WINDOW_REC *parent;
71         int empty_window, new_parent;
72
73         g_return_if_fail(window != NULL);
74
75         new_parent = window_create_override == 0 ||
76                 window_create_override == 2 ||
77                 active_win == NULL || WINDOW_GUI(active_win) == NULL;
78         parent = !new_parent ? WINDOW_MAIN(active_win) : mainwindow_create();
79         if (parent == NULL) {
80                 /* not enough space for new window, but we really can't
81                    abort creation of the window anymore, so create hidden
82                    window instead. */
83                 parent = WINDOW_MAIN(active_win);
84         }
85         window_create_override = -1;
86
87         empty_window = parent->active == NULL;
88
89         if (parent->active == NULL) parent->active = window;
90         window->gui_data = gui_window_init(window, parent);
91
92         /* set only non-automatic windows sticky so that the windows
93            irssi creates at startup wont get sticky. */
94         if (automatic == NULL &&
95             (parent->sticky_windows ||
96              (new_parent && settings_get_bool("autostick_split_windows"))))
97                 gui_window_set_sticky(window);
98
99         signal_emit("gui window created", 1, window);
100 }
101
102 static void gui_window_destroyed(WINDOW_REC *window)
103 {
104         MAIN_WINDOW_REC *parent;
105         GUI_WINDOW_REC *gui;
106
107         g_return_if_fail(window != NULL);
108
109         gui = WINDOW_GUI(window);
110         parent = gui->parent;
111
112         gui_window_set_unsticky(window);
113
114         signal_emit("gui window destroyed", 1, window);
115
116         gui_window_deinit(gui);
117         window->gui_data = NULL;
118
119         if (parent->active == window)
120                 mainwindow_change_active(parent, window);
121 }
122
123 void gui_window_resize(WINDOW_REC *window, int width, int height)
124 {
125         GUI_WINDOW_REC *gui;
126
127         if (window->width == width && window->height == height)
128                 return;
129
130         gui = WINDOW_GUI(window);
131
132         irssi_set_dirty();
133         WINDOW_MAIN(window)->dirty = TRUE;
134
135         window->width = width;
136         window->height = height;
137         textbuffer_view_resize(gui->view, width, height);
138 }
139
140 void gui_window_scroll(WINDOW_REC *window, int lines)
141 {
142         g_return_if_fail(window != NULL);
143
144         textbuffer_view_scroll(WINDOW_GUI(window)->view, lines);
145         signal_emit("gui page scrolled", 1, window);
146 }
147
148 void gui_window_scroll_line(WINDOW_REC *window, LINE_REC *line)
149 {
150         g_return_if_fail(window != NULL);
151         g_return_if_fail(line != NULL);
152
153         textbuffer_view_scroll_line(WINDOW_GUI(window)->view, line);
154         signal_emit("gui page scrolled", 1, window);
155 }
156
157 void gui_window_set_sticky(WINDOW_REC *window)
158 {
159         GUI_WINDOW_REC *gui = WINDOW_GUI(window);
160
161         if (!gui->sticky) {
162                 gui->sticky = TRUE;
163                 gui->parent->sticky_windows++;
164         }
165 }
166
167 void gui_window_set_unsticky(WINDOW_REC *window)
168 {
169         GUI_WINDOW_REC *gui = WINDOW_GUI(window);
170
171         if (gui->sticky) {
172                 gui->sticky = FALSE;
173                 gui->parent->sticky_windows--;
174         }
175 }
176
177 void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent)
178 {
179         MAIN_WINDOW_REC *oldparent;
180
181         oldparent = WINDOW_MAIN(window);
182         if (oldparent == parent)
183                 return;
184
185         gui_window_set_unsticky(window);
186         textbuffer_view_set_window(WINDOW_GUI(window)->view, NULL);
187
188         WINDOW_MAIN(window) = parent;
189         if (parent->sticky_windows)
190                 gui_window_set_sticky(window);
191
192         if (MAIN_WINDOW_TEXT_HEIGHT(parent) !=
193             MAIN_WINDOW_TEXT_HEIGHT(oldparent) ||
194             parent->width != oldparent->width) {
195                 gui_window_resize(window, parent->width,
196                                   MAIN_WINDOW_TEXT_HEIGHT(parent));
197         }
198 }
199
200 void gui_windows_reset_settings(void)
201 {
202         GSList *tmp;
203
204         for (tmp = windows; tmp != NULL; tmp = tmp->next) {
205                 WINDOW_REC *rec = tmp->data;
206                 GUI_WINDOW_REC *gui = WINDOW_GUI(rec);
207
208                 textbuffer_view_set_default_indent(gui->view,
209                                                    settings_get_int("indent"),
210                                                    !settings_get_bool("indent_always"),
211                                                    get_default_indent_func());
212
213                 textbuffer_view_set_scroll(gui->view,
214                                            gui->use_scroll ? gui->scroll :
215                                            settings_get_bool("scroll"));
216         }
217 }
218
219 static MAIN_WINDOW_REC *mainwindow_find_unsticky(void)
220 {
221         GSList *tmp;
222
223         for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
224                 MAIN_WINDOW_REC *rec = tmp->data;
225
226                 if (!rec->sticky_windows)
227                         return rec;
228         }
229
230         /* all windows are sticky, fallback to active window */
231         return active_mainwin;
232 }
233
234 static void signal_window_changed(WINDOW_REC *window)
235 {
236         MAIN_WINDOW_REC *parent;
237         WINDOW_REC *old_window;
238
239         g_return_if_fail(window != NULL);
240
241         if (quitting) return;
242
243         parent = WINDOW_MAIN(window);
244         if (is_window_visible(window)) {
245                 /* already visible */
246                 active_mainwin = parent;
247         } else if (active_mainwin == NULL) {
248                 /* no main window set yet */
249                 active_mainwin = parent;
250         } else if (WINDOW_GUI(window)->sticky) {
251                 /* window is sticky, switch to correct main window */
252                 if (parent != active_mainwin)
253                         active_mainwin = parent;
254         } else {
255                 /* move window to active main window */
256                 if (active_mainwin->sticky_windows) {
257                         /* active mainwindow is sticky, we'll need to
258                            set the window active somewhere else */
259                         active_mainwin = mainwindow_find_unsticky();
260                 }
261                 gui_window_reparent(window, active_mainwin);
262         }
263
264         old_window = active_mainwin->active;
265         if (old_window != NULL && old_window != window)
266                 textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL);
267
268         active_mainwin->active = window;
269
270         textbuffer_view_set_window(WINDOW_GUI(window)->view,
271                                    active_mainwin->screen_win);
272         if (WINDOW_GUI(window)->view->dirty)
273                 active_mainwin->dirty = TRUE;
274 }
275
276 static void read_settings(void)
277 {
278         gui_windows_reset_settings();
279 }
280
281 void gui_windows_init(void)
282 {
283         settings_add_bool("lookandfeel", "autostick_split_windows", TRUE);
284         settings_add_int("lookandfeel", "indent", 10);
285         settings_add_bool("lookandfeel", "indent_always", FALSE);
286         settings_add_bool("lookandfeel", "scroll", TRUE);
287
288         window_create_override = -1;
289
290         read_settings();
291         signal_add("gui window create override", (SIGNAL_FUNC) sig_window_create_override);
292         signal_add("window created", (SIGNAL_FUNC) gui_window_created);
293         signal_add("window destroyed", (SIGNAL_FUNC) gui_window_destroyed);
294         signal_add_first("window changed", (SIGNAL_FUNC) signal_window_changed);
295         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
296 }
297
298 void gui_windows_deinit(void)
299 {
300         while (windows != NULL)
301                 window_destroy(windows->data);
302
303         signal_remove("gui window create override", (SIGNAL_FUNC) sig_window_create_override);
304         signal_remove("window created", (SIGNAL_FUNC) gui_window_created);
305         signal_remove("window destroyed", (SIGNAL_FUNC) gui_window_destroyed);
306         signal_remove("window changed", (SIGNAL_FUNC) signal_window_changed);
307         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
308 }