Added SILC Thread Queue API
[crypto.git] / apps / irssi / src / fe-common / core / fe-windows.c
index af8e4297e9fe3fe5b1f2b9061b4df521cbf461b2..06621c776a2e83b7eaf435cff6ffc4456505d62c 100644 (file)
@@ -70,7 +70,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic)
 
        rec = g_new0(WINDOW_REC, 1);
        rec->refnum = window_get_new_refnum();
-       rec->level = level2bits(settings_get_str("window_default_level"));
+       rec->level = settings_get_level("window_default_level");
 
        windows = g_slist_prepend(windows, rec);
        signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic));
@@ -161,11 +161,30 @@ void window_set_active(WINDOW_REC *window)
 
 void window_change_server(WINDOW_REC *window, void *server)
 {
+       SERVER_REC *active, *connect;
+
        if (server != NULL && SERVER(server)->disconnected)
                return;
 
-       window->active_server = server;
-       signal_emit("window server changed", 2, window, server);
+       if (server == NULL) {
+               active = connect = NULL;
+       } else if (g_slist_find(servers, server) != NULL) {
+               active = server;
+               connect = NULL;
+       } else {
+               active = NULL;
+               connect = server;
+       }
+
+       if (window->connect_server != connect) {
+               window->connect_server = connect;
+               signal_emit("window connect changed", 2, window, connect);
+       }
+
+       if (window->active_server != active) {
+               window->active_server = active;
+               signal_emit("window server changed", 2, window, active);
+       } 
 }
 
 void window_set_refnum(WINDOW_REC *window, int refnum)
@@ -232,12 +251,12 @@ void window_set_immortal(WINDOW_REC *window, int immortal)
 }
 
 /* return active item's name, or if none is active, window's name */
-char *window_get_active_name(WINDOW_REC *window)
+const char *window_get_active_name(WINDOW_REC *window)
 {
        g_return_val_if_fail(window != NULL, NULL);
 
        if (window->active != NULL)
-               return window->active->name;
+               return window->active->visible_name;
 
        return window->name;
 }
@@ -249,46 +268,69 @@ char *window_get_active_name(WINDOW_REC *window)
 WINDOW_REC *window_find_level(void *server, int level)
 {
        GSList *tmp;
+       WINDOW_REC *match;
 
-        /* prefer active window if possible */
-       if (active_win != NULL &&
-           WINDOW_LEVEL_MATCH(active_win, server, level))
-                return active_win;
-
+       match = NULL;
        for (tmp = windows; tmp != NULL; tmp = tmp->next) {
                WINDOW_REC *rec = tmp->data;
 
-               if (WINDOW_LEVEL_MATCH(rec, server, level))
-                        return rec;
+               if (WINDOW_LEVEL_MATCH(rec, server, level)) {
+                       /* prefer windows without any items */
+                       if (rec->items == NULL)
+                               return rec;
+
+                       if (match == NULL)
+                               match = rec;
+                       else if (active_win == rec) {
+                               /* prefer active window over others */
+                               match = rec;
+                       }
+               }
        }
 
-       return NULL;
+       return match;
 }
 
 WINDOW_REC *window_find_closest(void *server, const char *name, int level)
 {
        WINDOW_REC *window,*namewindow=NULL;
        WI_ITEM_REC *item;
+       int i;
 
        /* match by name */
        item = name == NULL ? NULL :
                window_item_find(server, name);
        if (item != NULL) {
                namewindow = window_item_window(item);
-               if (namewindow != NULL && ((namewindow->level & level) != 0 ||
-                   !settings_get_bool("window_check_level_first")))
-                 return namewindow;
+               if (namewindow != NULL &&
+                   ((namewindow->level & level) != 0 ||
+                    !settings_get_bool("window_check_level_first"))) {
+                       /* match, but if multiple windows have the same level
+                          we could be choosing a bad one here, eg.
+                          name=nick1 would get nick2's query instead of
+                          generic msgs window.
+
+                          And check for prefixed !channel name --Borys  */
+                       if (g_strcasecmp(name, item->visible_name) == 0 ||
+                           g_strcasecmp(name, (char *) window_item_get_target((WI_ITEM_REC *) item)) == 0)
+                               return namewindow;
+               }
        }
 
-       /* match by level */
-       if (level != MSGLEVEL_HILIGHT)
-               level &= ~(MSGLEVEL_HILIGHT | MSGLEVEL_NOHILIGHT);
-       window = window_find_level(server, level);
-       if (window != NULL) return window;
-
-       /* match by level - ignore server */
-       window = window_find_level(NULL, level);
-       if (window != NULL) return window;
+       /* prefer windows without items */
+       for (i = 0; i < 2; i++) {
+               /* match by level */
+               if (level != MSGLEVEL_HILIGHT)
+                       level &= ~(MSGLEVEL_HILIGHT | MSGLEVEL_NOHILIGHT);
+               window = window_find_level(server, level);
+               if (window != NULL && (i == 1 || window->items == NULL))
+                       return window;
+
+               /* match by level - ignore server */
+               window = window_find_level(NULL, level);
+               if (window != NULL && (i == 1 || window->items == NULL))
+                       return window;
+       }
 
        /* still return item's window if we didnt find anything */
        if (namewindow != NULL) return namewindow;
@@ -489,7 +531,7 @@ void window_bind_remove_unsticky(WINDOW_REC *window)
        }
 }
 
-static void sig_server_looking(SERVER_REC *server)
+static void sig_server_connected(SERVER_REC *server)
 {
        GSList *tmp;
 
@@ -519,7 +561,8 @@ static void sig_server_disconnected(SERVER_REC *server)
        for (tmp = windows; tmp != NULL; tmp = tmp->next) {
                WINDOW_REC *rec = tmp->data;
 
-               if (rec->active_server == server) {
+               if (rec->active_server == server ||
+                   rec->connect_server == server) {
                        window_change_server(rec, rec->servertag != NULL ?
                                             NULL : new_server);
                }
@@ -606,10 +649,11 @@ void windows_init(void)
        settings_add_bool("lookandfeel", "window_auto_change", FALSE);
        settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE);
        settings_add_bool("lookandfeel", "window_check_level_first", FALSE);
-       settings_add_str("lookandfeel", "window_default_level", "NONE");
+       settings_add_level("lookandfeel", "window_default_level", "NONE");
 
        read_settings();
-       signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
+       signal_add("server looking", (SIGNAL_FUNC) sig_server_connected);
+       signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
        signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
        signal_add("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
        signal_add("setup changed", (SIGNAL_FUNC) read_settings);
@@ -620,7 +664,8 @@ void windows_deinit(void)
        if (daytag != -1) g_source_remove(daytag);
        if (daycheck == 1) signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
 
-       signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
+       signal_remove("server looking", (SIGNAL_FUNC) sig_server_connected);
+       signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected);
        signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
        signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
        signal_remove("setup changed", (SIGNAL_FUNC) read_settings);