4 Copyright (C) 2000 Timo Sirainen
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.
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.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "module-formats.h"
31 #include "fe-windows.h"
32 #include "window-items.h"
33 #include "printtext.h"
35 static void window_item_add_signal(WINDOW_REC *window, WI_ITEM_REC *item, int automatic, int send_signal)
37 g_return_if_fail(window != NULL);
38 g_return_if_fail(item != NULL);
39 g_return_if_fail(item->window == NULL);
41 item->window = window;
43 if (window->items == NULL) {
44 window->active = item;
45 window->active_server = item->server;
48 if (!automatic || settings_get_bool("window_auto_change")) {
50 signal_emit("window changed automatic", 1, window);
51 window_set_active(window);
54 window->items = g_slist_append(window->items, item);
56 signal_emit("window item new", 2, window, item);
58 if (g_slist_length(window->items) == 1 ||
59 (!automatic && settings_get_bool("autofocus_new_items"))) {
60 window->active = NULL;
61 window_item_set_active(window, item);
65 void window_item_add(WINDOW_REC *window, WI_ITEM_REC *item, int automatic)
67 window_item_add_signal(window, item, automatic, TRUE);
70 static void window_item_remove_signal(WI_ITEM_REC *item, int emit_signal)
74 g_return_if_fail(item != NULL);
76 window = window_item_window(item);
82 window->items = g_slist_remove(window->items, item);
84 if (window->active == item) {
85 window_item_set_active(window, window->items == NULL ? NULL :
90 signal_emit("window item remove", 2, window, item);
93 void window_item_remove(WI_ITEM_REC *item)
95 window_item_remove_signal(item, TRUE);
98 void window_item_destroy(WI_ITEM_REC *item)
100 window_item_remove(item);
104 void window_item_change_server(WI_ITEM_REC *item, void *server)
108 g_return_if_fail(item != NULL);
110 window = window_item_window(item);
111 item->server = server;
113 signal_emit("window item server changed", 2, window, item);
114 if (window->active == item) window_change_server(window, item->server);
117 void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item)
119 WINDOW_REC *old_window;
121 g_return_if_fail(window != NULL);
124 old_window = window_item_window(item);
125 if (old_window != window) {
126 /* move item to different window */
127 window_item_remove_signal(item, FALSE);
128 window_item_add_signal(window, item, FALSE, FALSE);
129 signal_emit("window item moved", 3, window, item, old_window);
133 if (window->active != item) {
134 window->active = item;
135 if (item != NULL && window->active_server != item->server)
136 window_change_server(window, item->server);
137 signal_emit("window item changed", 2, window, item);
141 /* Return TRUE if `item' is the active window item in the window.
142 `item' can be NULL. */
143 int window_item_is_active(WI_ITEM_REC *item)
150 window = window_item_window(item);
154 return window->active == item;
157 void window_item_prev(WINDOW_REC *window)
162 g_return_if_fail(window != NULL);
165 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
166 WI_ITEM_REC *rec = tmp->data;
168 if (rec != window->active)
171 /* current channel. did we find anything?
172 if not, go to the last channel */
173 if (last != NULL) break;
178 window_item_set_active(window, last);
181 void window_item_next(WINDOW_REC *window)
187 g_return_if_fail(window != NULL);
189 next = NULL; gone = FALSE;
190 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
191 WI_ITEM_REC *rec = tmp->data;
193 if (rec == window->active)
197 /* found the next channel */
203 next = rec; /* fallback to first channel */
208 window_item_set_active(window, next);
211 WI_ITEM_REC *window_item_find_window(WINDOW_REC *window,
212 void *server, const char *name)
214 CHANNEL_REC *channel;
217 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
218 WI_ITEM_REC *rec = tmp->data;
220 if ((server == NULL || rec->server == server) &&
221 g_strcasecmp(name, rec->visible_name) == 0)
225 /* try with channel name too, it's not necessarily
226 same as visible_name (!channels) */
227 channel = channel_find(server, name);
228 if (channel != NULL && window_item_window(channel) == window)
229 return (WI_ITEM_REC *) channel;
234 /* Find wanted window item by name. `server' can be NULL. */
235 WI_ITEM_REC *window_item_find(void *server, const char *name)
240 g_return_val_if_fail(name != NULL, NULL);
242 for (tmp = windows; tmp != NULL; tmp = tmp->next) {
243 WINDOW_REC *rec = tmp->data;
245 item = window_item_find_window(rec, server, name);
246 if (item != NULL) return item;
252 static int window_bind_has_sticky(WINDOW_REC *window)
256 for (tmp = window->bound_items; tmp != NULL; tmp = tmp->next) {
257 WINDOW_BIND_REC *rec = tmp->data;
266 void window_item_create(WI_ITEM_REC *item, int automatic)
269 WINDOW_BIND_REC *bind;
270 GSList *tmp, *sorted;
271 int clear_waiting, reuse_unused_windows;
273 g_return_if_fail(item != NULL);
275 reuse_unused_windows = settings_get_bool("reuse_unused_windows");
277 clear_waiting = TRUE;
279 sorted = windows_get_sorted();
280 for (tmp = sorted; tmp != NULL; tmp = tmp->next) {
281 WINDOW_REC *rec = tmp->data;
283 /* is item bound to this window? */
284 if (item->server != NULL) {
285 bind = window_bind_find(rec, item->server->tag,
289 window_bind_destroy(rec, bind);
291 clear_waiting = FALSE;
296 /* use this window IF:
297 - reuse_unused_windows is ON
298 - window has no existing items
300 - window has no sticky binds (/LAYOUT SAVEd)
301 - we already haven't found "good enough" window,
303 - this is the active window
304 - old window had some temporary bounds and this
307 if (reuse_unused_windows && rec->items == NULL &&
308 rec->name == NULL && !window_bind_has_sticky(rec) &&
309 (window == NULL || rec == active_win ||
310 window->bound_items != NULL))
313 g_slist_free(sorted);
315 if (window == NULL && !settings_get_bool("autocreate_windows")) {
316 /* never create new windows automatically */
320 if (window == NULL) {
321 /* create new window to use */
322 if (settings_get_bool("autocreate_split_windows")) {
323 signal_emit("gui window create override", 1,
326 window = window_create(item, automatic);
328 /* use existing window */
329 window_item_add(window, item, automatic);
333 window_bind_remove_unsticky(window);
336 static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item)
338 g_return_if_fail(window != NULL);
340 if (g_slist_length(window->items) > 1) {
341 /* default to printing "talking with ...",
342 you can override it it you wish */
343 printformat(item->server, item->visible_name,
344 MSGLEVEL_CLIENTNOTICE,
345 TXT_TALKING_WITH, item->visible_name);
349 void window_items_init(void)
351 settings_add_bool("lookandfeel", "reuse_unused_windows", FALSE);
352 settings_add_bool("lookandfeel", "autocreate_windows", TRUE);
353 settings_add_bool("lookandfeel", "autocreate_split_windows", FALSE);
354 settings_add_bool("lookandfeel", "autofocus_new_items", TRUE);
356 signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
359 void window_items_deinit(void)
361 signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed);