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
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
22 #include "module-formats.h"
30 #include "fe-windows.h"
31 #include "window-items.h"
32 #include "printtext.h"
34 void window_item_add(WINDOW_REC *window, WI_ITEM_REC *item, int automatic)
36 g_return_if_fail(window != NULL);
37 g_return_if_fail(item != NULL);
39 item->window = window;
41 if (window->items == NULL) {
42 window->active = item;
43 window->active_server = item->server;
46 if (!automatic || settings_get_bool("window_auto_change")) {
48 signal_emit("window changed automatic", 1, window);
49 window_set_active(window);
52 window->items = g_slist_append(window->items, item);
53 signal_emit("window item new", 2, window, item);
55 if (!automatic || g_slist_length(window->items) == 1) {
56 window->active = NULL;
57 window_item_set_active(window, item);
61 void window_item_remove(WI_ITEM_REC *item)
65 g_return_if_fail(item != NULL);
67 window = window_item_window(item);
69 if (g_slist_find(window->items, item) == NULL)
73 window->items = g_slist_remove(window->items, item);
75 if (window->active == item) {
76 window_item_set_active(window, window->items == NULL ? NULL :
80 signal_emit("window item remove", 2, window, item);
83 void window_item_destroy(WI_ITEM_REC *item)
87 window = window_item_window(item);
88 window_item_remove(item);
90 signal_emit("window item destroy", 2, window, item);
93 void window_item_change_server(WI_ITEM_REC *item, void *server)
97 g_return_if_fail(item != NULL);
99 window = window_item_window(item);
100 item->server = server;
102 signal_emit("window item server changed", 2, window, item);
103 if (window->active == item) window_change_server(window, item->server);
106 void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item)
108 g_return_if_fail(window != NULL);
110 if (item != NULL && window_item_window(item) != window) {
111 /* move item to different window */
112 window_item_remove(item);
113 window_item_add(window, item, FALSE);
116 if (window->active != item) {
117 window->active = item;
118 if (item != NULL && window->active_server != item->server)
119 window_change_server(window, item->server);
120 signal_emit("window item changed", 2, window, item);
124 /* Return TRUE if `item' is the active window item in the window.
125 `item' can be NULL. */
126 int window_item_is_active(WI_ITEM_REC *item)
133 window = window_item_window(item);
137 return window->active == item;
140 void window_item_prev(WINDOW_REC *window)
145 g_return_if_fail(window != NULL);
148 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
149 WI_ITEM_REC *rec = tmp->data;
151 if (rec != window->active)
154 /* current channel. did we find anything?
155 if not, go to the last channel */
156 if (last != NULL) break;
161 window_item_set_active(window, last);
164 void window_item_next(WINDOW_REC *window)
170 g_return_if_fail(window != NULL);
172 next = NULL; gone = FALSE;
173 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
174 WI_ITEM_REC *rec = tmp->data;
176 if (rec == window->active)
180 /* found the next channel */
186 next = rec; /* fallback to first channel */
191 window_item_set_active(window, next);
194 WI_ITEM_REC *window_item_find_window(WINDOW_REC *window,
195 void *server, const char *name)
199 for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
200 WI_ITEM_REC *rec = tmp->data;
202 if ((server == NULL || rec->server == server) &&
203 g_strcasecmp(name, rec->name) == 0) return rec;
209 /* Find wanted window item by name. `server' can be NULL. */
210 WI_ITEM_REC *window_item_find(void *server, const char *name)
215 g_return_val_if_fail(name != NULL, NULL);
217 for (tmp = windows; tmp != NULL; tmp = tmp->next) {
218 WINDOW_REC *rec = tmp->data;
220 item = window_item_find_window(rec, server, name);
221 if (item != NULL) return item;
227 static int window_bind_has_sticky(WINDOW_REC *window)
231 for (tmp = window->bound_items; tmp != NULL; tmp = tmp->next) {
232 WINDOW_BIND_REC *rec = tmp->data;
241 void window_item_create(WI_ITEM_REC *item, int automatic)
244 GSList *tmp, *sorted;
245 int clear_waiting, reuse_unused_windows;
247 g_return_if_fail(item != NULL);
249 reuse_unused_windows =
250 !settings_get_bool("autoclose_windows") ||
251 settings_get_bool("reuse_unused_windows");
253 clear_waiting = TRUE;
255 sorted = windows_get_sorted();
256 for (tmp = sorted; tmp != NULL; tmp = tmp->next) {
257 WINDOW_REC *rec = tmp->data;
259 /* is item bound to this window? */
260 if (item->server != NULL &&
261 window_bind_find(rec, item->server->tag, item->name)) {
263 clear_waiting = FALSE;
267 /* use this window IF:
268 - reuse_unused_windows is ON
269 - window has no existing items
271 - window has no sticky binds (/LAYOUT SAVEd)
272 - we already haven't found "good enough" window,
274 - this is the active window
275 - old window had some temporary bounds and this
278 if (reuse_unused_windows && rec->items == NULL &&
279 rec->name == NULL && !window_bind_has_sticky(rec) &&
280 (window == NULL || rec == active_win ||
281 window->bound_items != NULL))
284 g_slist_free(sorted);
286 if (window == NULL && !settings_get_bool("autocreate_windows")) {
287 /* never create new windows automatically */
291 if (window == NULL) {
292 /* create new window to use */
293 window = window_create(item, automatic);
295 /* use existing window */
296 window_item_add(window, item, automatic);
300 window_bind_remove_unsticky(window);
303 static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item)
305 g_return_if_fail(window != NULL);
307 if (g_slist_length(window->items) > 1) {
308 /* default to printing "talking with ...",
309 you can override it it you wish */
310 printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE,
311 TXT_TALKING_WITH, item->name);
315 void window_items_init(void)
317 settings_add_bool("lookandfeel", "reuse_unused_windows", FALSE);
318 settings_add_bool("lookandfeel", "autocreate_windows", TRUE);
320 signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
323 void window_items_deinit(void)
325 signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed);