diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:18:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:18:39 +0000 |
commit | fff5217f02d91268ce90c8c05665602c059faaef (patch) | |
tree | 2ba24d32dc96eafe7ed0a85269548e76796d849d /src/fe-common/core/window-items.c | |
parent | Initial commit. (diff) | |
download | irssi-fff5217f02d91268ce90c8c05665602c059faaef.tar.xz irssi-fff5217f02d91268ce90c8c05665602c059faaef.zip |
Adding upstream version 1.4.5.upstream/1.4.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/fe-common/core/window-items.c')
-rw-r--r-- | src/fe-common/core/window-items.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/fe-common/core/window-items.c b/src/fe-common/core/window-items.c new file mode 100644 index 0000000..c60c796 --- /dev/null +++ b/src/fe-common/core/window-items.c @@ -0,0 +1,355 @@ +/* + window-items.c : irssi + + Copyright (C) 2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "module.h" +#include <irssi/src/fe-common/core/module-formats.h> +#include <irssi/src/core/modules.h> +#include <irssi/src/core/signals.h> +#include <irssi/src/core/servers.h> +#include <irssi/src/core/channels.h> +#include <irssi/src/core/settings.h> + +#include <irssi/src/core/levels.h> + +#include <irssi/src/fe-common/core/fe-windows.h> +#include <irssi/src/fe-common/core/window-items.h> +#include <irssi/src/fe-common/core/printtext.h> + +static void window_item_add_signal(WINDOW_REC *window, WI_ITEM_REC *item, int automatic, int send_signal) +{ + g_return_if_fail(window != NULL); + g_return_if_fail(item != NULL); + g_return_if_fail(item->window == NULL); + + item->window = window; + + if (window->items == NULL) { + window->active = item; + window->active_server = item->server; + } + + if (!automatic || settings_get_bool("window_auto_change")) { + if (automatic) + signal_emit("window changed automatic", 1, window); + window_set_active(window); + } + + window->items = g_slist_append(window->items, item); + if (send_signal) + signal_emit("window item new", 2, window, item); + + if (g_slist_length(window->items) == 1 || + (!automatic && settings_get_bool("autofocus_new_items"))) { + window->active = NULL; + window_item_set_active(window, item); + } +} + +void window_item_add(WINDOW_REC *window, WI_ITEM_REC *item, int automatic) +{ + window_item_add_signal(window, item, automatic, TRUE); +} + +static void window_item_remove_signal(WI_ITEM_REC *item, int emit_signal) +{ + WINDOW_REC *window; + + g_return_if_fail(item != NULL); + + window = window_item_window(item); + + if (window == NULL) + return; + + item->window = NULL; + window->items = g_slist_remove(window->items, item); + + if (window->active == item) { + window_item_set_active(window, window->items == NULL ? NULL : + window->items->data); + } + + if (emit_signal) + signal_emit("window item remove", 2, window, item); +} + +void window_item_remove(WI_ITEM_REC *item) +{ + window_item_remove_signal(item, TRUE); +} + +void window_item_destroy(WI_ITEM_REC *item) +{ + window_item_remove(item); + item->destroy(item); +} + +void window_item_change_server(WI_ITEM_REC *item, void *server) +{ + WINDOW_REC *window; + + g_return_if_fail(item != NULL); + + window = window_item_window(item); + item->server = server; + + signal_emit("window item server changed", 2, window, item); + if (window->active == item) window_change_server(window, item->server); +} + +void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item) +{ + WINDOW_REC *old_window; + + g_return_if_fail(window != NULL); + + if (item != NULL) { + old_window = window_item_window(item); + if (old_window != window) { + /* move item to different window */ + window_item_remove_signal(item, FALSE); + window_item_add_signal(window, item, FALSE, FALSE); + signal_emit("window item moved", 3, window, item, old_window); + } + } + + if (window->active != item) { + window->active = item; + if (item != NULL && window->active_server != item->server) + window_change_server(window, item->server); + signal_emit("window item changed", 2, window, item); + } +} + +/* Return TRUE if `item' is the active window item in the window. + `item' can be NULL. */ +int window_item_is_active(WI_ITEM_REC *item) +{ + WINDOW_REC *window; + + if (item == NULL) + return FALSE; + + window = window_item_window(item); + if (window == NULL) + return FALSE; + + return window->active == item; +} + +void window_item_prev(WINDOW_REC *window) +{ + WI_ITEM_REC *last; + GSList *tmp; + + g_return_if_fail(window != NULL); + + last = NULL; + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + WI_ITEM_REC *rec = tmp->data; + + if (rec != window->active) + last = rec; + else { + /* current channel. did we find anything? + if not, go to the last channel */ + if (last != NULL) break; + } + } + + if (last != NULL) + window_item_set_active(window, last); +} + +void window_item_next(WINDOW_REC *window) +{ + WI_ITEM_REC *next; + GSList *tmp; + int gone; + + g_return_if_fail(window != NULL); + + next = NULL; gone = FALSE; + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + WI_ITEM_REC *rec = tmp->data; + + if (rec == window->active) + gone = TRUE; + else { + if (gone) { + /* found the next channel */ + next = rec; + break; + } + + if (next == NULL) + next = rec; /* fallback to first channel */ + } + } + + if (next != NULL) + window_item_set_active(window, next); +} + +WI_ITEM_REC *window_item_find_window(WINDOW_REC *window, + void *server, const char *name) +{ + GSList *tmp; + + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + WI_ITEM_REC *rec = tmp->data; + + if ((server == NULL || rec->server == server) && + (g_ascii_strcasecmp(name, rec->visible_name) == 0 + || (rec->name && g_ascii_strcasecmp(name, rec->name) == 0))) + return rec; + } + return NULL; +} + +/* Find wanted window item by name. `server' can be NULL. */ +WI_ITEM_REC *window_item_find(void *server, const char *name) +{ + WI_ITEM_REC *item; + GSList *tmp; + + g_return_val_if_fail(name != NULL, NULL); + + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + item = window_item_find_window(rec, server, name); + if (item != NULL) return item; + } + + return NULL; +} + +static int window_bind_has_sticky(WINDOW_REC *window) +{ + GSList *tmp; + + for (tmp = window->bound_items; tmp != NULL; tmp = tmp->next) { + WINDOW_BIND_REC *rec = tmp->data; + + if (rec->sticky) + return TRUE; + } + + return FALSE; +} + +void window_item_create(WI_ITEM_REC *item, int automatic) +{ + WINDOW_REC *window; + WINDOW_BIND_REC *bind; + GSList *tmp, *sorted; + int clear_waiting, reuse_unused_windows; + + g_return_if_fail(item != NULL); + + reuse_unused_windows = settings_get_bool("reuse_unused_windows"); + + clear_waiting = TRUE; + window = NULL; + sorted = windows_get_sorted(); + for (tmp = sorted; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + /* is item bound to this window? */ + if (item->server != NULL) { + bind = window_bind_find(rec, item->server->tag, + item->visible_name); + if (bind != NULL) { + if (!bind->sticky) + window_bind_destroy(rec, bind); + window = rec; + clear_waiting = FALSE; + break; + } + } + + /* use this window IF: + - reuse_unused_windows is ON + - window has no existing items + - window has no name + - window has no sticky binds (/LAYOUT SAVEd) + - we already haven't found "good enough" window, + except if + - this is the active window + - old window had some temporary bounds and this + one doesn't + */ + if (reuse_unused_windows && rec->items == NULL && + rec->name == NULL && !window_bind_has_sticky(rec) && + (window == NULL || rec == active_win || + window->bound_items != NULL)) + window = rec; + } + g_slist_free(sorted); + + if (window == NULL && !settings_get_bool("autocreate_windows")) { + /* never create new windows automatically */ + window = active_win; + } + + if (window == NULL) { + /* create new window to use */ + if (settings_get_bool("autocreate_split_windows")) { + signal_emit("gui window create override", 1, + GINT_TO_POINTER(MAIN_WINDOW_TYPE_SPLIT)); + } + window = window_create(item, automatic); + } else { + /* use existing window */ + window_item_add(window, item, automatic); + } + + if (clear_waiting) + window_bind_remove_unsticky(window); +} + +static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item) +{ + g_return_if_fail(window != NULL); + + if (g_slist_length(window->items) > 1) { + /* default to printing "talking with ...", + you can override it it you wish */ + printformat(item->server, item->visible_name, + MSGLEVEL_CLIENTNOTICE, + TXT_TALKING_WITH, item->visible_name); + } +} + +void window_items_init(void) +{ + settings_add_bool("lookandfeel", "reuse_unused_windows", FALSE); + settings_add_bool("lookandfeel", "autocreate_windows", TRUE); + settings_add_bool("lookandfeel", "autocreate_split_windows", FALSE); + settings_add_bool("lookandfeel", "autofocus_new_items", TRUE); + + signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed); +} + +void window_items_deinit(void) +{ + signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed); +} |