Merged from irssi tree
[crypto.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 "screen.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 char *prompt, *prompt_window;
35
36 static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window,
37                                        MAIN_WINDOW_REC *parent)
38 {
39         GUI_WINDOW_REC *gui;
40
41         window->width = parent->width;
42         window->height = parent->height;
43
44         gui = g_new0(GUI_WINDOW_REC, 1);
45         gui->parent = parent;
46         gui->view = textbuffer_view_create(textbuffer_create(),
47                                            window->width, window->height,
48                                            settings_get_int("indent"),
49                                            settings_get_bool("indent_always"));
50         return gui;
51 }
52
53 static void gui_window_deinit(GUI_WINDOW_REC *gui)
54 {
55         textbuffer_view_destroy(gui->view);
56         g_free(gui);
57 }
58
59 static void sig_window_create_override(gpointer tab)
60 {
61         window_create_override = GPOINTER_TO_INT(tab);
62 }
63
64 static void gui_window_created(WINDOW_REC *window)
65 {
66         MAIN_WINDOW_REC *parent;
67
68         g_return_if_fail(window != NULL);
69
70         parent = window_create_override != 0 &&
71                 active_win != NULL && WINDOW_GUI(active_win) != NULL ?
72                 WINDOW_GUI(active_win)->parent : mainwindow_create();
73         if (parent == NULL) {
74                 /* not enough space for new window, but we really can't
75                    abort creation of the window anymore, so create hidden
76                    window instead. */
77                 parent = WINDOW_GUI(active_win)->parent;
78         }
79         window_create_override = -1;
80
81         if (settings_get_bool("autostick_split_windows") &&
82             (parent->sticky_windows != NULL ||
83              (mainwindows->next != NULL && parent->active == NULL))) {
84                 /* set the window sticky */
85                 parent->sticky_windows =
86                         g_slist_append(parent->sticky_windows, window);
87         }
88
89         if (parent->active == NULL) parent->active = window;
90         window->gui_data = gui_window_init(window, parent);
91         signal_emit("gui window created", 1, window);
92 }
93
94 static void gui_window_destroyed(WINDOW_REC *window)
95 {
96         MAIN_WINDOW_REC *parent;
97         GUI_WINDOW_REC *gui;
98
99         g_return_if_fail(window != NULL);
100
101         gui = WINDOW_GUI(window);
102         parent = gui->parent;
103
104         signal_emit("gui window destroyed", 1, window);
105
106         gui_window_deinit(gui);
107         window->gui_data = NULL;
108
109         if (parent->active == window && mainwindows->next != NULL)
110                 mainwindow_destroy(parent);
111 }
112
113 void gui_window_resize(WINDOW_REC *window, int width, int height)
114 {
115         GUI_WINDOW_REC *gui;
116
117         gui = WINDOW_GUI(window);
118
119         window->width = width;
120         window->height = height;
121         textbuffer_view_resize(gui->view, width, height);
122 }
123
124 void gui_window_scroll(WINDOW_REC *window, int lines)
125 {
126         g_return_if_fail(window != NULL);
127
128         textbuffer_view_scroll(WINDOW_GUI(window)->view, lines);
129         signal_emit("gui page scrolled", 1, window);
130 }
131
132 void gui_window_scroll_line(WINDOW_REC *window, LINE_REC *line)
133 {
134         g_return_if_fail(window != NULL);
135         g_return_if_fail(line != NULL);
136
137         textbuffer_view_scroll_line(WINDOW_GUI(window)->view, line);
138         signal_emit("gui page scrolled", 1, window);
139 }
140
141 void window_update_prompt(void)
142 {
143         const char *special;
144         char *prompt, *text;
145         int var_used;
146
147         special = settings_get_str(active_win->active != NULL ?
148                                    "prompt" : "prompt_window");
149         if (*special == '\0') {
150                 gui_entry_set_prompt("");
151                 return;
152         }
153
154         prompt = parse_special_string(special, active_win->active_server,
155                                       active_win->active, "", &var_used,
156                                       PARSE_FLAG_ISSET_ANY |
157                                       PARSE_FLAG_ESCAPE_VARS);
158         if (!var_used && strchr(special, '$') != NULL) {
159                 /* none of the $vars had non-empty values, use empty prompt */
160                 *prompt = '\0';
161         }
162
163         /* set prompt */
164         text = show_lowascii(prompt);
165         gui_entry_set_prompt(text);
166         g_free(text);
167
168         g_free(prompt);
169 }
170
171 static void window_update_prompt_server(SERVER_REC *server)
172 {
173         if (server == active_win->active_server)
174                 window_update_prompt();
175 }
176
177 static void window_update_prompt_window(WINDOW_REC *window)
178 {
179         if (window == active_win)
180                 window_update_prompt();
181 }
182
183 static void window_update_prompt_window_item(WI_ITEM_REC *item)
184 {
185         if (item == active_win->active)
186                 window_update_prompt();
187 }
188
189 void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent)
190 {
191         MAIN_WINDOW_REC *oldparent;
192
193         oldparent = WINDOW_GUI(window)->parent;
194         if (oldparent == parent)
195                 return;
196
197         textbuffer_view_set_window(WINDOW_GUI(window)->view, NULL);
198
199         WINDOW_GUI(window)->parent = parent;
200         if (parent->height != oldparent->height ||
201             parent->width != oldparent->width)
202                 gui_window_resize(window, parent->width, parent->height);
203 }
204
205 static MAIN_WINDOW_REC *mainwindow_find_unsticky(void)
206 {
207         GSList *tmp;
208
209         for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
210                 MAIN_WINDOW_REC *rec = tmp->data;
211
212                 if (rec->sticky_windows == NULL)
213                         return rec;
214         }
215
216         /* all windows are sticky, fallback to active window */
217         return active_mainwin;
218 }
219
220 static void signal_window_changed(WINDOW_REC *window)
221 {
222         MAIN_WINDOW_REC *parent;
223         WINDOW_REC *old_window;
224
225         g_return_if_fail(window != NULL);
226
227         if (quitting) return;
228
229         parent = WINDOW_GUI(window)->parent;
230         if (is_window_visible(window)) {
231                 /* already visible */
232                 active_mainwin = parent;
233         } else if (active_mainwin == NULL) {
234                 /* no main window set yet */
235                 active_mainwin = parent;
236         } else if (g_slist_find(parent->sticky_windows, window) != NULL) {
237                 /* window is sticky, switch to correct main window */
238                 if (parent != active_mainwin)
239                         active_mainwin = parent;
240         } else {
241                 /* move window to active main window */
242                 if (active_mainwin->sticky_windows != NULL) {
243                         /* active mainwindow is sticky, we'll need to
244                            set the window active somewhere else */
245                         active_mainwin = mainwindow_find_unsticky();
246                 }
247                 gui_window_reparent(window, active_mainwin);
248         }
249
250         old_window = active_mainwin->active;
251         if (old_window != NULL)
252                 textbuffer_view_set_window(WINDOW_GUI(old_window)->view, NULL);
253         active_mainwin->active = window;
254
255         textbuffer_view_set_window(WINDOW_GUI(window)->view,
256                                    parent->curses_win);
257
258         window_update_prompt();
259 }
260
261 static void sig_check_window_update(WINDOW_REC *window)
262 {
263         if (window == active_win)
264                 window_update_prompt();
265 }
266
267 static void read_settings(void)
268 {
269         GSList *tmp;
270
271         SIGNAL_FUNC funcs[] = {
272                 (SIGNAL_FUNC) window_update_prompt,
273                 (SIGNAL_FUNC) window_update_prompt_server,
274                 (SIGNAL_FUNC) window_update_prompt_window,
275                 (SIGNAL_FUNC) window_update_prompt_window_item
276         };
277
278         if (prompt != NULL) {
279                 special_vars_remove_signals(prompt, 4, funcs);
280                 special_vars_remove_signals(prompt_window, 4, funcs);
281                 g_free(prompt);
282                 g_free(prompt_window);
283         }
284         prompt = g_strdup(settings_get_str("prompt"));
285         prompt_window = g_strdup(settings_get_str("prompt_window"));
286
287         for (tmp = windows; tmp != NULL; tmp = tmp->next) {
288                 WINDOW_REC *rec = tmp->data;
289
290                 textbuffer_view_set_default_indent(WINDOW_GUI(rec)->view,
291                                                    settings_get_int("indent"),
292                                                    settings_get_bool("indent_always"));
293         }
294
295         special_vars_add_signals(prompt, 4, funcs);
296         special_vars_add_signals(prompt_window, 4, funcs);
297
298         if (active_win != NULL) window_update_prompt();
299 }
300
301 void gui_windows_init(void)
302 {
303         settings_add_bool("lookandfeel", "autostick_split_windows", TRUE);
304         settings_add_int("lookandfeel", "indent", 10);
305         settings_add_bool("lookandfeel", "indent_always", FALSE);
306         settings_add_str("lookandfeel", "prompt", "[$[.15]T] ");
307         settings_add_str("lookandfeel", "prompt_window", "[$winname] ");
308
309         prompt = NULL; prompt_window = NULL;
310         window_create_override = -1;
311
312         read_settings();
313         signal_add("gui window create override", (SIGNAL_FUNC) sig_window_create_override);
314         signal_add("window created", (SIGNAL_FUNC) gui_window_created);
315         signal_add("window destroyed", (SIGNAL_FUNC) gui_window_destroyed);
316         signal_add_first("window changed", (SIGNAL_FUNC) signal_window_changed);
317         signal_add("window item remove", (SIGNAL_FUNC) sig_check_window_update);
318         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
319 }
320
321 void gui_windows_deinit(void)
322 {
323         g_free_not_null(prompt);
324         g_free_not_null(prompt_window);
325
326         while (windows != NULL)
327                 window_destroy(windows->data);
328
329         signal_remove("gui window create override", (SIGNAL_FUNC) sig_window_create_override);
330         signal_remove("window created", (SIGNAL_FUNC) gui_window_created);
331         signal_remove("window destroyed", (SIGNAL_FUNC) gui_window_destroyed);
332         signal_remove("window changed", (SIGNAL_FUNC) signal_window_changed);
333         signal_remove("window item remove", (SIGNAL_FUNC) sig_check_window_update);
334         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
335 }