about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/command/command.c153
-rw-r--r--src/command/commands.c345
-rw-r--r--src/muc.c54
-rw-r--r--src/profanity.c13
-rw-r--r--src/ui/core.c396
-rw-r--r--src/ui/titlebar.c14
-rw-r--r--src/ui/ui.h23
-rw-r--r--src/ui/window.c96
-rw-r--r--src/ui/window.h20
-rw-r--r--src/ui/windows.c235
-rw-r--r--src/ui/windows.h16
11 files changed, 760 insertions, 605 deletions
diff --git a/src/command/command.c b/src/command/command.c
index a66fc5ad..f73a8aee 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1612,12 +1612,6 @@ cmd_reset_autocomplete()
     autocomplete_reset(notify_typing_ac);
     autocomplete_reset(sub_ac);
 
-    if (ui_current_win_type() == WIN_MUC) {
-        char *recipient = ui_current_recipient();
-        muc_autocomplete_reset(recipient);
-        muc_jid_autocomplete_reset(recipient);
-    }
-
     autocomplete_reset(who_room_ac);
     autocomplete_reset(who_roster_ac);
     autocomplete_reset(prefs_ac);
@@ -1664,22 +1658,27 @@ cmd_reset_autocomplete()
     autocomplete_reset(time_ac);
     autocomplete_reset(resource_ac);
 
-    if (ui_current_win_type() == WIN_MUC_CONFIG) {
-        ProfWin *window = wins_get_current();
-        ProfMucConfWin *confwin = (ProfMucConfWin*)window;
-        if (window && confwin->form) {
-            form_reset_autocompleters(confwin->form);
-        }
-    }
-
     if (ui_current_win_type() == WIN_CHAT) {
-        char *recipient = ui_current_recipient();
-        PContact contact = roster_get_contact(recipient);
+        ProfChatWin *chatwin = wins_get_current_chat();
+        PContact contact = roster_get_contact(chatwin->barejid);
         if (contact) {
             p_contact_resource_ac_reset(contact);
         }
     }
 
+    if (ui_current_win_type() == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        muc_autocomplete_reset(mucwin->roomjid);
+        muc_jid_autocomplete_reset(mucwin->roomjid);
+    }
+
+    if (ui_current_win_type() == WIN_MUC_CONFIG) {
+        ProfMucConfWin *confwin = wins_get_current_muc_conf();
+        if (confwin->form) {
+            form_reset_autocompleters(confwin->form);
+        }
+    }
+
     bookmark_autocomplete_reset();
 }
 
@@ -1754,7 +1753,6 @@ cmd_execute_default(const char * inp)
 {
     win_type_t win_type = ui_current_win_type();
     jabber_conn_status_t status = jabber_get_connection_status();
-    char *recipient = ui_current_recipient();
 
     // handle escaped commands - treat as normal message
     if (g_str_has_prefix(inp, "//")) {
@@ -1773,6 +1771,7 @@ cmd_execute_default(const char * inp)
             if (status != JABBER_CONNECTED) {
                 ui_current_print_line("You are not currently connected.");
             } else {
+                ProfWin
                 message_send_groupchat(inp, recipient);
             }
             break;
@@ -1887,8 +1886,8 @@ _cmd_complete_parameters(char *input, int *size)
 
     // autocomplete nickname in chat rooms
     if (ui_current_win_type() == WIN_MUC) {
-        char *recipient = ui_current_recipient();
-        Autocomplete nick_ac = muc_roster_ac(recipient);
+        ProfMucWin *mucwin = wins_get_current_muc();
+        Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
         if (nick_ac != NULL) {
             gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ;
 
@@ -2435,8 +2434,8 @@ _resource_autocomplete(char *input, int *size)
 
     ProfWin *current = wins_get_current();
     if (current && current->type == WIN_CHAT) {
-        char *recipient = ui_current_recipient();
-        PContact contact = roster_get_contact(recipient);
+        ProfChatWin *chatwin = wins_get_current_chat();
+        PContact contact = roster_get_contact(chatwin->barejid);
         if (contact) {
             Autocomplete ac = p_contact_resource_ac(contact);
             found = autocomplete_param_with_ac(input, size, "/resource set", ac, FALSE);
@@ -2575,62 +2574,71 @@ static char *
 _kick_autocomplete(char *input, int *size)
 {
     char *result = NULL;
-    char *recipient = ui_current_recipient();
-    Autocomplete nick_ac = muc_roster_ac(recipient);
 
-    if (nick_ac != NULL) {
-        result = autocomplete_param_with_ac(input, size, "/kick", nick_ac, TRUE);
-        if (result != NULL) {
-            return result;
+    if (ui_current_win_type() == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
+
+        if (nick_ac != NULL) {
+            result = autocomplete_param_with_ac(input, size, "/kick", nick_ac, TRUE);
+            if (result != NULL) {
+                return result;
+            }
         }
     }
 
-    return NULL;
+    return result;
 }
 
 static char *
 _ban_autocomplete(char *input, int *size)
 {
     char *result = NULL;
-    char *recipient = ui_current_recipient();
-    Autocomplete jid_ac = muc_roster_jid_ac(recipient);
 
-    if (jid_ac != NULL) {
-        result = autocomplete_param_with_ac(input, size, "/ban", jid_ac, TRUE);
-        if (result != NULL) {
-            return result;
+    if (ui_current_win_type() == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
+
+        if (jid_ac != NULL) {
+            result = autocomplete_param_with_ac(input, size, "/ban", jid_ac, TRUE);
+            if (result != NULL) {
+                return result;
+            }
         }
     }
 
-    return NULL;
+    return result;
 }
 
 static char *
 _affiliation_autocomplete(char *input, int *size)
 {
     char *result = NULL;
-    char *recipient = ui_current_recipient();
-    gboolean parse_result;
-    Autocomplete jid_ac = muc_roster_jid_ac(recipient);
 
-    input[*size] = '\0';
-    gchar **args = parse_args(input, 3, 3, &parse_result);
+    if (ui_current_win_type() == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        gboolean parse_result;
+        Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
 
-    if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) {
-        GString *beginning = g_string_new("/affiliation ");
-        g_string_append(beginning, args[0]);
-        g_string_append(beginning, " ");
-        g_string_append(beginning, args[1]);
+        input[*size] = '\0';
+        gchar **args = parse_args(input, 3, 3, &parse_result);
 
-        result = autocomplete_param_with_ac(input, size, beginning->str, jid_ac, TRUE);
-        g_string_free(beginning, TRUE);
-        if (result != NULL) {
-            g_strfreev(args);
-            return result;
+        if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) {
+            GString *beginning = g_string_new("/affiliation ");
+            g_string_append(beginning, args[0]);
+            g_string_append(beginning, " ");
+            g_string_append(beginning, args[1]);
+
+            result = autocomplete_param_with_ac(input, size, beginning->str, jid_ac, TRUE);
+            g_string_free(beginning, TRUE);
+            if (result != NULL) {
+                g_strfreev(args);
+                return result;
+            }
         }
-    }
 
-    g_strfreev(args);
+        g_strfreev(args);
+    }
 
     result = autocomplete_param_with_ac(input, size, "/affiliation set", affiliation_ac, TRUE);
     if (result != NULL) {
@@ -2647,35 +2655,38 @@ _affiliation_autocomplete(char *input, int *size)
         return result;
     }
 
-    return NULL;
+    return result;
 }
 
 static char *
 _role_autocomplete(char *input, int *size)
 {
     char *result = NULL;
-    char *recipient = ui_current_recipient();
-    gboolean parse_result;
-    Autocomplete nick_ac = muc_roster_ac(recipient);
 
-    input[*size] = '\0';
-    gchar **args = parse_args(input, 3, 3, &parse_result);
+    if (ui_current_win_type() == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        gboolean parse_result;
+        Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
 
-    if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) {
-        GString *beginning = g_string_new("/role ");
-        g_string_append(beginning, args[0]);
-        g_string_append(beginning, " ");
-        g_string_append(beginning, args[1]);
+        input[*size] = '\0';
+        gchar **args = parse_args(input, 3, 3, &parse_result);
 
-        result = autocomplete_param_with_ac(input, size, beginning->str, nick_ac, TRUE);
-        g_string_free(beginning, TRUE);
-        if (result != NULL) {
-            g_strfreev(args);
-            return result;
+        if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) {
+            GString *beginning = g_string_new("/role ");
+            g_string_append(beginning, args[0]);
+            g_string_append(beginning, " ");
+            g_string_append(beginning, args[1]);
+
+            result = autocomplete_param_with_ac(input, size, beginning->str, nick_ac, TRUE);
+            g_string_free(beginning, TRUE);
+            if (result != NULL) {
+                g_strfreev(args);
+                return result;
+            }
         }
-    }
 
-    g_strfreev(args);
+        g_strfreev(args);
+    }
 
     result = autocomplete_param_with_ac(input, size, "/role set", role_ac, TRUE);
     if (result != NULL) {
@@ -2692,7 +2703,7 @@ _role_autocomplete(char *input, int *size)
         return result;
     }
 
-    return NULL;
+    return result;
 }
 
 static char *
diff --git a/src/command/commands.c b/src/command/commands.c
index 7c1a2ce8..1b3ab45a 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -436,7 +436,8 @@ cmd_sub(gchar **args, struct cmd_help_t help)
     }
 
     if (jid == NULL) {
-        jid = ui_current_recipient();
+        ProfChatWin *chatwin = wins_get_current_chat();
+        jid = chatwin->barejid;
     }
 
     Jid *jidp = jid_create(jid);
@@ -783,7 +784,7 @@ _who_room(gchar **args, struct cmd_help_t help)
         return;
     }
 
-    char *room = ui_current_recipient();
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     // presence filter
     if (args[0] == NULL ||
@@ -797,11 +798,11 @@ _who_room(gchar **args, struct cmd_help_t help)
             (g_strcmp0(args[0], "any") == 0)) {
 
         char *presence = args[0];
-        GList *occupants = muc_roster(room);
+        GList *occupants = muc_roster(mucwin->roomjid);
 
         // no arg, show all contacts
         if ((presence == NULL) || (g_strcmp0(presence, "any") == 0)) {
-            ui_room_roster(room, occupants, NULL);
+            ui_room_roster(mucwin->roomjid, occupants, NULL);
 
         // available
         } else if (strcmp("available", presence) == 0) {
@@ -815,7 +816,7 @@ _who_room(gchar **args, struct cmd_help_t help)
                 occupants = g_list_next(occupants);
             }
 
-            ui_room_roster(room, filtered, "available");
+            ui_room_roster(mucwin->roomjid, filtered, "available");
 
         // unavailable
         } else if (strcmp("unavailable", presence) == 0) {
@@ -829,7 +830,7 @@ _who_room(gchar **args, struct cmd_help_t help)
                 occupants = g_list_next(occupants);
             }
 
-            ui_room_roster(room, filtered, "unavailable");
+            ui_room_roster(mucwin->roomjid, filtered, "unavailable");
 
         // show specific status
         } else {
@@ -844,41 +845,40 @@ _who_room(gchar **args, struct cmd_help_t help)
                 occupants = g_list_next(occupants);
             }
 
-            ui_room_roster(room, filtered, presence);
+            ui_room_roster(mucwin->roomjid, filtered, presence);
         }
 
         g_list_free(occupants);
 
     // role or affiliation filter
     } else {
-        ProfWin *window = wins_get_by_recipient(room);
         if (g_strcmp0(args[0], "moderator") == 0) {
-            ui_show_room_role_list(window, room, MUC_ROLE_MODERATOR);
+            ui_show_room_role_list(mucwin, MUC_ROLE_MODERATOR);
             return;
         }
         if (g_strcmp0(args[0], "participant") == 0) {
-            ui_show_room_role_list(window, room, MUC_ROLE_PARTICIPANT);
+            ui_show_room_role_list(mucwin, MUC_ROLE_PARTICIPANT);
             return;
         }
         if (g_strcmp0(args[0], "visitor") == 0) {
-            ui_show_room_role_list(window, room, MUC_ROLE_VISITOR);
+            ui_show_room_role_list(mucwin, MUC_ROLE_VISITOR);
             return;
         }
 
         if (g_strcmp0(args[0], "owner") == 0) {
-            ui_show_room_affiliation_list(window, room, MUC_AFFILIATION_OWNER);
+            ui_show_room_affiliation_list(mucwin, MUC_AFFILIATION_OWNER);
             return;
         }
         if (g_strcmp0(args[0], "admin") == 0) {
-            ui_show_room_affiliation_list(window, room, MUC_AFFILIATION_ADMIN);
+            ui_show_room_affiliation_list(mucwin, MUC_AFFILIATION_ADMIN);
             return;
         }
         if (g_strcmp0(args[0], "member") == 0) {
-            ui_show_room_affiliation_list(window, room, MUC_AFFILIATION_MEMBER);
+            ui_show_room_affiliation_list(mucwin, MUC_AFFILIATION_MEMBER);
             return;
         }
         if (g_strcmp0(args[0], "outcast") == 0) {
-            ui_show_room_affiliation_list(window, room, MUC_AFFILIATION_OUTCAST);
+            ui_show_room_affiliation_list(mucwin, MUC_AFFILIATION_OUTCAST);
             return;
         }
     }
@@ -1123,9 +1123,9 @@ cmd_msg(gchar **args, struct cmd_help_t help)
     }
 
     if (win_type == WIN_MUC) {
-        char *room_name = ui_current_recipient();
-        if (muc_roster_contains_nick(room_name, usr)) {
-            GString *full_jid = g_string_new(room_name);
+        ProfMucWin *mucwin = wins_get_current_muc();
+        if (muc_roster_contains_nick(mucwin->roomjid, usr)) {
+            GString *full_jid = g_string_new(mucwin->roomjid);
             g_string_append(full_jid, "/");
             g_string_append(full_jid, usr);
 
@@ -1557,16 +1557,14 @@ cmd_resource(gchar **args, struct cmd_help_t help)
             return TRUE;
         }
 
-        char *recipient = ui_current_recipient();
-
 #ifdef HAVE_LIBOTR
-        if (otr_is_secure(recipient)) {
+        if (otr_is_secure(chatwin->barejid)) {
             cons_show("Cannot choose resource during an OTR session.");
             return TRUE;
         }
 #endif
 
-        PContact contact = roster_get_contact(recipient);
+        PContact contact = roster_get_contact(chatwin->barejid);
         if (!contact) {
             cons_show("Cannot choose resource for contact not in roster.");
             return TRUE;
@@ -1606,7 +1604,13 @@ cmd_status(gchar **args, struct cmd_help_t help)
     {
         case WIN_MUC:
             if (usr != NULL) {
-                ui_status_room(usr);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                Occupant *occupant = muc_roster_item(mucwin->roomjid, contact);
+                if (occupant) {
+                    win_show_occupant(mucwin->super, occupant);
+                } else {
+                    win_save_vprint(mucwin->super, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", contact);
+                }
             } else {
                 ui_current_print_line("You must specify a nickname.");
             }
@@ -1615,14 +1619,28 @@ cmd_status(gchar **args, struct cmd_help_t help)
             if (usr != NULL) {
                 ui_current_print_line("No parameter required when in chat.");
             } else {
-                ui_status();
+                ProfChatWin *chatwin = wins_get_current_chat();
+                PContact pcontact = roster_get_contact(chatwin->barejid);
+                if (pcontact != NULL) {
+                    win_show_contact(chatwin->super, pcontact);
+                } else {
+                    win_save_println(chatwin->super, "Error getting contact info.");
+                }
             }
             break;
         case WIN_PRIVATE:
             if (usr != NULL) {
                 ui_current_print_line("No parameter required when in chat.");
             } else {
-                ui_status_private();
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                Jid *jid = jid_create(privatewin->fulljid);
+                Occupant *occupant = muc_roster_item(jid->barejid, jid->resourcepart);
+                if (occupant) {
+                    win_show_occupant(privatewin->super, occupant);
+                } else {
+                    win_save_println(privatewin->super, "Error getting contact info.");
+                }
+                jid_destroy(jid);
             }
             break;
         case WIN_CONSOLE:
@@ -1651,7 +1669,6 @@ cmd_info(gchar **args, struct cmd_help_t help)
     jabber_conn_status_t conn_status = jabber_get_connection_status();
     win_type_t win_type = ui_current_win_type();
     PContact pcontact = NULL;
-    Occupant *occupant = NULL;
     char *room = NULL;
 
     if (conn_status != JABBER_CONNECTED) {
@@ -1662,19 +1679,19 @@ cmd_info(gchar **args, struct cmd_help_t help)
     switch (win_type)
     {
         case WIN_MUC:
-            room = ui_current_recipient();
             if (usr) {
-                char *room = ui_current_recipient();
-                occupant = muc_roster_item(room, usr);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                Occupant *occupant = muc_roster_item(mucwin->roomjid, usr);
                 if (occupant) {
-                    ui_info_room(room, occupant);
+                    ProfWin *current = wins_get_current();
+                    win_show_occupant_info(current, room, occupant);
                 } else {
                     ui_current_print_line("No such occupant \"%s\" in room.", usr);
                 }
             } else {
-                ProfWin *window = wins_get_by_recipient(room);
-                iq_room_info_request(room);
-                ui_show_room_info(window, room);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                iq_room_info_request(mucwin->roomjid);
+                ui_show_room_info(mucwin);
                 return TRUE;
             }
             break;
@@ -1682,14 +1699,28 @@ cmd_info(gchar **args, struct cmd_help_t help)
             if (usr) {
                 ui_current_print_line("No parameter required when in chat.");
             } else {
-                ui_info();
+                ProfChatWin *chatwin = wins_get_current_chat();
+                PContact pcontact = roster_get_contact(chatwin->barejid);
+                if (pcontact != NULL) {
+                    win_show_info(chatwin->super, pcontact);
+                } else {
+                    win_save_println(chatwin->super, "Error getting contact info.");
+                }
             }
             break;
         case WIN_PRIVATE:
             if (usr) {
                 ui_current_print_line("No parameter required when in chat.");
             } else {
-                ui_info_private();
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                Jid *jid = jid_create(privatewin->fulljid);
+                Occupant *occupant = muc_roster_item(jid->barejid, jid->resourcepart);
+                if (occupant) {
+                    win_show_occupant_info(privatewin->super, jid->barejid, occupant);
+                } else {
+                    win_save_println(privatewin->super, "Error getting contact info.");
+                }
+                jid_destroy(jid);
             }
             break;
         case WIN_CONSOLE:
@@ -1732,10 +1763,10 @@ cmd_caps(gchar **args, struct cmd_help_t help)
     {
         case WIN_MUC:
             if (args[0] != NULL) {
-                char *room = ui_current_recipient();
-                occupant = muc_roster_item(room, args[0]);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                occupant = muc_roster_item(mucwin->roomjid, args[0]);
                 if (occupant) {
-                    Jid *jidp = jid_create_from_bare_and_resource(room, args[0]);
+                    Jid *jidp = jid_create_from_bare_and_resource(mucwin->roomjid, args[0]);
                     cons_show_caps(jidp->fulljid, occupant->presence);
                     jid_destroy(jidp);
                 } else {
@@ -1774,8 +1805,8 @@ cmd_caps(gchar **args, struct cmd_help_t help)
             if (args[0] != NULL) {
                 cons_show("No parameter needed to /caps when in private chat.");
             } else {
-                char *recipient = ui_current_recipient();
-                Jid *jid = jid_create(recipient);
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                Jid *jid = jid_create(privatewin->fulljid);
                 if (jid) {
                     occupant = muc_roster_item(jid->barejid, jid->resourcepart);
                     cons_show_caps(jid->resourcepart, occupant->presence);
@@ -1808,10 +1839,10 @@ cmd_software(gchar **args, struct cmd_help_t help)
     {
         case WIN_MUC:
             if (args[0] != NULL) {
-                recipient = ui_current_recipient();
-                occupant = muc_roster_item(recipient, args[0]);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                occupant = muc_roster_item(mucwin->roomjid, args[0]);
                 if (occupant) {
-                    Jid *jid = jid_create_from_bare_and_resource(recipient, args[0]);
+                    Jid *jid = jid_create_from_bare_and_resource(mucwin->roomjid, args[0]);
                     iq_send_software_version(jid->fulljid);
                     jid_destroy(jid);
                 } else {
@@ -1840,8 +1871,8 @@ cmd_software(gchar **args, struct cmd_help_t help)
             if (args[0] != NULL) {
                 cons_show("No parameter needed to /software when in private chat.");
             } else {
-                recipient = ui_current_recipient();
-                iq_send_software_version(recipient);
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                iq_send_software_version(privatewin->fulljid);
             }
             break;
         default:
@@ -1949,14 +1980,15 @@ cmd_invite(gchar **args, struct cmd_help_t help)
     if (usr_jid == NULL) {
         usr_jid = contact;
     }
-    room = ui_current_recipient();
-    message_send_invite(room, usr_jid, reason);
+
+    ProfMucWin mucwin = wins_get_current_muc();
+    message_send_invite(mucwin->roomjid, usr_jid, reason);
     if (reason != NULL) {
         cons_show("Room invite sent, contact: %s, room: %s, reason: \"%s\".",
-            contact, room, reason);
+            contact, mucwin->roomjid, reason);
     } else {
         cons_show("Room invite sent, contact: %s, room: %s.",
-            contact, room);
+            contact, mucwin->roomjid);
     }
 
     return TRUE;
@@ -2227,24 +2259,19 @@ cmd_form(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *recipient = ui_current_recipient();
-    ProfWin *current = wins_get_current();
-    ProfMucConfWin *confwin = (ProfMucConfWin*)current;
-    gchar **split_recipient = g_strsplit(recipient, " ", 2);
-    char *room = split_recipient[0];
+    ProfMucConfWin *confwin = wins_get_current_muc_conf();
 
     if (g_strcmp0(args[0], "show") == 0) {
-        ui_show_form(current, room, confwin->form);
-        g_strfreev(split_recipient);
+        ui_show_form(confwin);
         return TRUE;
     }
 
     if (g_strcmp0(args[0], "help") == 0) {
         char *tag = args[1];
         if (tag != NULL) {
-            ui_show_form_field_help(current, confwin->form, tag);
+            ui_show_form_field_help(confwin, tag);
         } else {
-            ui_show_form_help(current, confwin->form);
+            ui_show_form_help(confwin);
 
             const gchar **help_text = NULL;
             Command *command = g_hash_table_lookup(commands, "/form");
@@ -2253,20 +2280,22 @@ cmd_form(gchar **args, struct cmd_help_t help)
                 help_text = command->help.long_help;
             }
 
-            ui_show_lines(current, help_text);
+            ui_show_lines(confwin->super, help_text);
         }
         ui_current_print_line("");
-        g_strfreev(split_recipient);
         return TRUE;
     }
 
+    gchar **split_recipient = g_strsplit(confwin->from, " ", 2);
+    char *roomjid = split_recipient[0];
+
     if (g_strcmp0(args[0], "submit") == 0) {
-        iq_submit_room_config(room, confwin->form);
+        iq_submit_room_config(roomjid, confwin->form);
 
     }
 
     if (g_strcmp0(args[0], "cancel") == 0) {
-        iq_room_config_cancel(room);
+        iq_room_config_cancel(roomjid);
     }
 
     if ((g_strcmp0(args[0], "submit") == 0) || (g_strcmp0(args[0], "cancel") == 0)) {
@@ -2274,7 +2303,7 @@ cmd_form(gchar **args, struct cmd_help_t help)
             cmd_autocomplete_remove_form_fields(confwin->form);
         }
         wins_close_current();
-        current = wins_get_by_recipient(room);
+        current = wins_get_by_recipient(roomjid);
         if (current == NULL) {
             current = wins_get_console();
         }
@@ -2303,16 +2332,15 @@ cmd_kick(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     char *nick = args[0];
     if (nick) {
-        if (muc_roster_contains_nick(room, nick)) {
+        if (muc_roster_contains_nick(mucwin->roomjid, nick)) {
             char *reason = args[1];
-            iq_room_kick_occupant(room, nick, reason);
+            iq_room_kick_occupant(mucwin->roomjid, nick, reason);
         } else {
-            win_save_vprint(window, '!', NULL, 0, 0, "", "Occupant does not exist: %s", nick);
+            win_save_vprint(mucwin->super, '!', NULL, 0, 0, "", "Occupant does not exist: %s", nick);
         }
     } else {
         cons_show("Usage: %s", help.usage);
@@ -2337,12 +2365,12 @@ cmd_ban(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     char *jid = args[0];
     if (jid) {
         char *reason = args[1];
-        iq_room_affiliation_set(room, jid, "outcast", reason);
+        iq_room_affiliation_set(mucwin->roomjid, jid, "outcast", reason);
     } else {
         cons_show("Usage: %s", help.usage);
     }
@@ -2365,23 +2393,22 @@ cmd_subject(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     if (args[0] == NULL) {
-        char *subject = muc_subject(room);
+        char *subject = muc_subject(mucwin->roomjid);
         if (subject) {
-            win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
-            win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
+            win_save_vprint(mucwin->super, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
+            win_save_vprint(mucwin->super, '!', NULL, NO_DATE, 0, "", "%s", subject);
         } else {
-            win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
+            win_save_print(mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
         }
         return TRUE;
     }
 
     if (g_strcmp0(args[0], "set") == 0) {
         if (args[1]) {
-            message_send_groupchat_subject(room, args[1]);
+            message_send_groupchat_subject(mucwin->roomjid, args[1]);
         } else {
             cons_show("Usage: %s", help.usage);
         }
@@ -2389,7 +2416,7 @@ cmd_subject(gchar **args, struct cmd_help_t help)
     }
 
     if (g_strcmp0(args[0], "clear") == 0) {
-        message_send_groupchat_subject(room, NULL);
+        message_send_groupchat_subject(mucwin->roomjid, NULL);
         return TRUE;
     }
 
@@ -2430,19 +2457,18 @@ cmd_affiliation(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     if (g_strcmp0(cmd, "list") == 0) {
         if (!affiliation) {
-            iq_room_affiliation_list(room, "owner");
-            iq_room_affiliation_list(room, "admin");
-            iq_room_affiliation_list(room, "member");
-            iq_room_affiliation_list(room, "outcast");
+            iq_room_affiliation_list(mucwin->roomjid, "owner");
+            iq_room_affiliation_list(mucwin->roomjid, "admin");
+            iq_room_affiliation_list(mucwin->roomjid, "member");
+            iq_room_affiliation_list(mucwin->roomjid), "outcast");
         } else if (g_strcmp0(affiliation, "none") == 0) {
-            win_save_print(window, '!', NULL, 0, 0, "", "Cannot list users with no affiliation.");
+            win_save_print(mucwin->super, '!', NULL, 0, 0, "", "Cannot list users with no affiliation.");
         } else {
-            iq_room_affiliation_list(room, affiliation);
+            iq_room_affiliation_list(mucwin->roomjid, affiliation);
         }
         return TRUE;
     }
@@ -2459,7 +2485,7 @@ cmd_affiliation(gchar **args, struct cmd_help_t help)
             return TRUE;
         } else {
             char *reason = args[3];
-            iq_room_affiliation_set(room, jid, affiliation, reason);
+            iq_room_affiliation_set(mucwin->roomjid, jid, affiliation, reason);
             return TRUE;
         }
     }
@@ -2500,18 +2526,17 @@ cmd_role(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     if (g_strcmp0(cmd, "list") == 0) {
         if (!role) {
-            iq_room_role_list(room, "moderator");
-            iq_room_role_list(room, "participant");
-            iq_room_role_list(room, "visitor");
+            iq_room_role_list(mucwin->roomjid, "moderator");
+            iq_room_role_list(mucwin->roomjid, "participant");
+            iq_room_role_list(mucwin->roomjid, "visitor");
         } else if (g_strcmp0(role, "none") == 0) {
-            win_save_print(window, '!', NULL, 0, 0, "", "Cannot list users with no role.");
+            win_save_print(mucwin->super, '!', NULL, 0, 0, "", "Cannot list users with no role.");
         } else {
-            iq_room_role_list(room, role);
+            iq_room_role_list(mucwin->roomjid, role);
         }
         return TRUE;
     }
@@ -2528,7 +2553,7 @@ cmd_role(gchar **args, struct cmd_help_t help)
             return TRUE;
         } else {
             char *reason = args[3];
-            iq_room_role_set(room, nick, role, reason);
+            iq_room_role_set(mucwin->roomjid, nick, role, reason);
             return TRUE;
         }
     }
@@ -2560,9 +2585,8 @@ cmd_room(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
-    ProfWin *window = wins_get_by_recipient(room);
-    int num = wins_get_num(window);
+    ProfMucWin *mucwin = wins_get_current_muc();
+    int num = wins_get_num(mucwin->super);
 
     int ui_index = num;
     if (ui_index == 10) {
@@ -2570,33 +2594,34 @@ cmd_room(gchar **args, struct cmd_help_t help)
     }
 
     if (g_strcmp0(args[0], "accept") == 0) {
-        gboolean requires_config = muc_requires_config(room);
+        gboolean requires_config = muc_requires_config(mucwin->roomjid);
         if (!requires_config) {
-            win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Current room does not require configuration.");
+            win_save_print(mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Current room does not require configuration.");
             return TRUE;
         } else {
-            iq_confirm_instant_room(room);
-            muc_set_requires_config(room, FALSE);
-            win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
+            iq_confirm_instant_room(mucwin->roomjid);
+            muc_set_requires_config(mucwin->roomjid, FALSE);
+            win_save_print(mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
             return TRUE;
         }
     }
 
     if (g_strcmp0(args[0], "destroy") == 0) {
-        iq_destroy_room(room);
+        iq_destroy_room(mucwin->roomjid);
         return TRUE;
     }
 
     if (g_strcmp0(args[0], "config") == 0) {
-        GString *win_title = g_string_new(room);
+        GString *win_title = g_string_new(mucwin->roomjid);
         g_string_append(win_title, " config");
-        ProfWin *window = wins_get_by_recipient(win_title->str);
+        ProfMucConfWin *confwin = wins_get_muc_conf_win(win_title->str);
         g_string_free(win_title, TRUE);
-        if (window != NULL) {
-            num = wins_get_num(window);
+
+        if (confwin != NULL) {
+            num = wins_get_num(confwin->super);
             ui_switch_win(num);
         } else {
-            iq_request_room_config_form(room);
+            iq_request_room_config_form(mucwin->roomjid);
         }
         return TRUE;
     }
@@ -2648,12 +2673,12 @@ cmd_occupants(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
+    ProfMucWin *mucwin = wins_get_current_muc();
 
     if (g_strcmp0(args[0], "show") == 0) {
-        ui_room_show_occupants(room);
+        ui_room_show_occupants(mucwin->roomjid);
     } else if (g_strcmp0(args[0], "hide") == 0) {
-        ui_room_hide_occupants(room);
+        ui_room_hide_occupants(mucwin->roomjid);
     } else {
         cons_show("Usage: %s", help.usage);
     }
@@ -2697,14 +2722,14 @@ cmd_bookmark(gchar **args, struct cmd_help_t help)
     gchar *cmd = args[0];
     if (win_type == WIN_MUC && cmd == NULL) {
         // default to current nickname, password, and autojoin "on"
-        char *jid = ui_current_recipient();
-        char *nick = muc_nick(jid);
-        char *password = muc_password(jid);
-        gboolean added = bookmark_add(jid, nick, password, "on");
+        ProfMucWin *mucwin = wins_get_current_muc();
+        char *nick = muc_nick(mucwin->roomjid);
+        char *password = muc_password(mucwin->roomjid);
+        gboolean added = bookmark_add(mucwin->roomjid, nick, password, "on");
         if (added) {
-            ui_current_print_formatted_line('!', 0, "Bookmark added for %s.", jid);
+            ui_current_print_formatted_line('!', 0, "Bookmark added for %s.", mucwin->roomjid);
         } else {
-            ui_current_print_formatted_line('!', 0, "Bookmark already exists for %s.", jid);
+            ui_current_print_formatted_line('!', 0, "Bookmark already exists for %s.", mucwin->roomjid);
         }
         return TRUE;
 
@@ -2838,9 +2863,9 @@ cmd_nick(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
-    char *room = ui_current_recipient();
+    ProfMucWin *mucwin = wins_get_current_muc();
     char *nick = args[0];
-    presence_change_room_nick(room, nick);
+    presence_change_room_nick(mucwin->roomjid, nick);
 
     return TRUE;
 }
@@ -2936,35 +2961,33 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
 
         if (tiny != NULL) {
             if (win_type == WIN_CHAT) {
-                char *recipient = ui_current_recipient();
-                GString *send_recipient = g_string_new(recipient);
-                ProfWin *current = wins_get_current();
-                ProfChatWin *chatwin = (ProfChatWin*)current;
-                if (current && win_has_chat_resource(current)) {
+                ProfChatWin *chatwin = wins_get_current_chat();
+                GString *send_recipient = g_string_new(chatwin->barejid);
+                if (chatwin->resource) {
                     g_string_append(send_recipient, "/");
                     g_string_append(send_recipient, chatwin->resource);
                 }
 
 #ifdef HAVE_LIBOTR
-                if (otr_is_secure(recipient)) {
-                    char *encrypted = otr_encrypt_message(recipient, tiny);
+                if (otr_is_secure(chatwin->barejid)) {
+                    char *encrypted = otr_encrypt_message(chatwin->barejid, tiny);
                     if (encrypted != NULL) {
-                        message_send(encrypted, recipient);
+                        message_send(encrypted, chatwin->barejid);
                         otr_free_message(encrypted);
                         if (prefs_get_boolean(PREF_CHLOG)) {
                             const char *jid = jabber_get_fulljid();
                             Jid *jidp = jid_create(jid);
                             char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
                             if (strcmp(pref_otr_log, "on") == 0) {
-                                chat_log_chat(jidp->barejid, recipient, tiny, PROF_OUT_LOG, NULL);
+                                chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
                             } else if (strcmp(pref_otr_log, "redact") == 0) {
-                                chat_log_chat(jidp->barejid, recipient, "[redacted]", PROF_OUT_LOG, NULL);
+                                chat_log_chat(jidp->barejid, chatwin->barejid, "[redacted]", PROF_OUT_LOG, NULL);
                             }
                             prefs_free_string(pref_otr_log);
                             jid_destroy(jidp);
                         }
 
-                        ui_outgoing_msg("me", recipient, tiny);
+                        ui_outgoing_msg("me", chatwin->barejid, tiny);
                     } else {
                         cons_show_error("Failed to send message.");
                     }
@@ -2973,32 +2996,32 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                     if (prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
                         Jid *jidp = jid_create(jid);
-                        chat_log_chat(jidp->barejid, recipient, tiny, PROF_OUT_LOG, NULL);
+                        chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
                         jid_destroy(jidp);
                     }
 
-                    ui_outgoing_msg("me", recipient, tiny);
+                    ui_outgoing_msg("me", chatwin->barejid, tiny);
                 }
 #else
                 message_send(tiny, send_recipient->str);
                 if (prefs_get_boolean(PREF_CHLOG)) {
                     const char *jid = jabber_get_fulljid();
                     Jid *jidp = jid_create(jid);
-                    chat_log_chat(jidp->barejid, recipient, tiny, PROF_OUT_LOG, NULL);
+                    chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
                     jid_destroy(jidp);
                 }
 
-                ui_outgoing_msg("me", recipient, tiny);
+                ui_outgoing_msg("me", chatwin->barejid, tiny);
 #endif
                 g_string_free(send_recipient, TRUE);
 
             } else if (win_type == WIN_PRIVATE) {
-                char *recipient = ui_current_recipient();
-                message_send(tiny, recipient);
-                ui_outgoing_msg("me", recipient, tiny);
-            } else { // groupchat
-                char *recipient = ui_current_recipient();
-                message_send_groupchat(tiny, recipient);
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                message_send(tiny, privatewin->fulljid);
+                ui_outgoing_msg("me", privatewin->fulljid, tiny);
+            } else if (win_type == WIN_MUC) {
+                ProfMucWin *mucwin = wins_get_current_muc();
+                message_send_groupchat(tiny, mucwin->roomjid);
             }
             free(tiny);
         } else {
@@ -3862,9 +3885,9 @@ cmd_otr(gchar **args, struct cmd_help_t help)
         } else if (!ui_current_win_is_otr()) {
             ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
         } else {
-            char *recipient = ui_current_recipient();
-            char *fingerprint = otr_get_their_fingerprint(recipient);
-            ui_current_print_formatted_line('!', 0, "%s's OTR fingerprint: %s", recipient, fingerprint);
+            ProfChatWin *chatwin = wins_get_current_chat();
+            char *fingerprint = otr_get_their_fingerprint(chatwin->barejid);
+            ui_current_print_formatted_line('!', 0, "%s's OTR fingerprint: %s", chatwin->barejid, fingerprint);
             free(fingerprint);
         }
         return TRUE;
@@ -3908,9 +3931,9 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                 if (!otr_key_loaded()) {
                     ui_current_print_formatted_line('!', 0, "You have not generated or loaded a private key, use '/otr gen'");
                 } else {
-                    char *recipient = ui_current_recipient();
+                    ProfChatWin *chatwin = wins_get_current_chat();
                     char *otr_query_message = otr_start_query();
-                    message_send(otr_query_message, recipient);
+                    message_send(otr_query_message, chatwin->barejid);
                 }
             }
         }
@@ -3924,9 +3947,9 @@ cmd_otr(gchar **args, struct cmd_help_t help)
         } else if (!ui_current_win_is_otr()) {
             ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
         } else {
-            char *recipient = ui_current_recipient();
-            ui_gone_insecure(recipient);
-            otr_end_session(recipient);
+            ProfChatWin *chatwin = wins_get_current_chat();
+            ui_gone_insecure(chatwin->barejid);
+            otr_end_session(chatwin->barejid);
         }
         return TRUE;
 
@@ -3938,9 +3961,9 @@ cmd_otr(gchar **args, struct cmd_help_t help)
         } else if (!ui_current_win_is_otr()) {
             ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
         } else {
-            char *recipient = ui_current_recipient();
-            ui_trust(recipient);
-            otr_trust(recipient);
+            ProfChatWin *chatwin = wins_get_current_chat();
+            ui_trust(chatwin->barejid);
+            otr_trust(chatwin->barejid);
         }
         return TRUE;
 
@@ -3952,9 +3975,9 @@ cmd_otr(gchar **args, struct cmd_help_t help)
         } else if (!ui_current_win_is_otr()) {
             ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
         } else {
-            char *recipient = ui_current_recipient();
-            ui_untrust(recipient);
-            otr_untrust(recipient);
+            ProfChatWin *chatwin = wins_get_current_chat();
+            ui_untrust(chatwin->barejid);
+            otr_untrust(chatwin->barejid);
         }
         return TRUE;
 
@@ -3969,8 +3992,8 @@ cmd_otr(gchar **args, struct cmd_help_t help)
             if (secret == NULL) {
                 cons_show("Usage: %s", help.usage);
             } else {
-                char *recipient = ui_current_recipient();
-                otr_smp_secret(recipient, secret);
+                ProfChatWin *chatwin = wins_get_current_chat();
+                otr_smp_secret(chatwin->barejid, secret);
             }
         }
         return TRUE;
@@ -3989,8 +4012,8 @@ cmd_otr(gchar **args, struct cmd_help_t help)
             } else if (!ui_current_win_is_otr()) {
                 ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
             } else {
-                char *recipient = ui_current_recipient();
-                otr_smp_question(recipient, question, answer);
+                ProfChatWin *chatwin = wins_get_current_chat();
+                otr_smp_question(chatwin->barejid, question, answer);
             }
             return TRUE;
         }
@@ -4006,8 +4029,8 @@ cmd_otr(gchar **args, struct cmd_help_t help)
             if (answer == NULL) {
                 cons_show("Usage: %s", help.usage);
             } else {
-                char *recipient = ui_current_recipient();
-                otr_smp_answer(recipient, answer);
+                ProfChatWin *chatwin = wins_get_current_chat();
+                otr_smp_answer(chatwin->barejid, answer);
             }
         }
         return TRUE;
diff --git a/src/muc.c b/src/muc.c
index f3505647..74e0d66e 100644
--- a/src/muc.c
+++ b/src/muc.c
@@ -42,6 +42,7 @@
 #include "jid.h"
 #include "tools/autocomplete.h"
 #include "ui/ui.h"
+#include "ui/windows.h"
 #include "muc.h"
 
 typedef struct _muc_room_t {
@@ -634,36 +635,39 @@ muc_roster_nick_change_complete(const char * const room,
 void
 muc_autocomplete(char *input, int *size)
 {
-    char *recipient = ui_current_recipient();
-    ChatRoom *chat_room = g_hash_table_lookup(rooms, recipient);
+    win_type_t wintype = ui_current_win_type();
+    if (wintype == WIN_MUC) {
+        ProfMucWin *mucwin = wins_get_current_muc();
+        ChatRoom *chat_room = g_hash_table_lookup(rooms, mucwin->roomjid);
 
-    if (chat_room && chat_room->nick_ac) {
-        input[*size] = '\0';
-        char *search_str = NULL;
+        if (chat_room && chat_room->nick_ac) {
+            input[*size] = '\0';
+            char *search_str = NULL;
 
-        gchar *last_space = g_strrstr(input, " ");
-        if (!last_space) {
-            search_str = input;
-            if (!chat_room->autocomplete_prefix) {
-                chat_room->autocomplete_prefix = strdup("");
-            }
-        } else {
-            search_str = last_space+1;
-            if (!chat_room->autocomplete_prefix) {
-                chat_room->autocomplete_prefix = g_strndup(input, search_str - input);
+            gchar *last_space = g_strrstr(input, " ");
+            if (!last_space) {
+                search_str = input;
+                if (!chat_room->autocomplete_prefix) {
+                    chat_room->autocomplete_prefix = strdup("");
+                }
+            } else {
+                search_str = last_space+1;
+                if (!chat_room->autocomplete_prefix) {
+                    chat_room->autocomplete_prefix = g_strndup(input, search_str - input);
+                }
             }
-        }
 
-        char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE);
-        if (result) {
-            GString *replace_with = g_string_new(chat_room->autocomplete_prefix);
-            g_string_append(replace_with, result);
-            if (!last_space || (*(last_space+1) == '\0')) {
-                g_string_append(replace_with, ": ");
+            char *result = autocomplete_complete(chat_room->nick_ac, search_str, FALSE);
+            if (result) {
+                GString *replace_with = g_string_new(chat_room->autocomplete_prefix);
+                g_string_append(replace_with, result);
+                if (!last_space || (*(last_space+1) == '\0')) {
+                    g_string_append(replace_with, ": ");
+                }
+                ui_replace_input(input, replace_with->str, size);
+                g_string_free(replace_with, TRUE);
+                g_free(result);
             }
-            ui_replace_input(input, replace_with->str, size);
-            g_string_free(replace_with, TRUE);
-            g_free(result);
         }
     }
 }
diff --git a/src/profanity.c b/src/profanity.c
index 2514bc50..bb7036fe 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -61,6 +61,7 @@
 #include "resource.h"
 #include "xmpp/xmpp.h"
 #include "ui/ui.h"
+#include "ui/windows.h"
 
 static void _handle_idle_time(void);
 static void _init(const int disable_tls, char *log_level);
@@ -173,12 +174,12 @@ prof_handle_activity(void)
     jabber_conn_status_t status = jabber_get_connection_status();
 
     if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
-        char *recipient = ui_current_recipient();
-        if (chat_session_get_recipient_supports(recipient)) {
-            chat_session_set_composing(recipient);
-            if (!chat_session_get_sent(recipient) ||
-                    chat_session_is_paused(recipient)) {
-                message_send_composing(recipient);
+        ProfChatWin *chatwin = wins_get_current_chat();
+        if (chat_session_get_recipient_supports(chatwin->barejid)) {
+            chat_session_set_composing(chatwin->barejid);
+            if (!chat_session_get_sent(chatwin->barejid) ||
+                    chat_session_is_paused(chatwin->barejid)) {
+                message_send_composing(chatwin->barejid);
             }
         }
     }
diff --git a/src/ui/core.c b/src/ui/core.c
index 1d378348..2373fb77 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -40,6 +40,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 #ifdef HAVE_LIBXSS
 #include <X11/extensions/scrnsaver.h>
 #endif
@@ -268,30 +269,30 @@ _ui_handle_stanza(const char * const msg)
 static void
 _ui_contact_typing(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(barejid);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
 
     if (prefs_get_boolean(PREF_INTYPE)) {
         // no chat window for user
-        if (window == NULL) {
+        if (chatwin == NULL) {
             cons_show_typing(barejid);
 
         // have chat window but not currently in it
-        } else if (!wins_is_current(window)) {
+        } else if (!wins_is_current(&chatwin->super)) {
             cons_show_typing(barejid);
 
         // in chat window with user
         } else {
             title_bar_set_typing(TRUE);
 
-            int num = wins_get_num(window);
+            int num = wins_get_num(&chatwin->super);
             status_bar_active(num);
        }
     }
 
     if (prefs_get_boolean(PREF_NOTIFY_TYPING)) {
         gboolean is_current = FALSE;
-        if (window != NULL) {
-            is_current = wins_is_current(window);
+        if (&chatwin->super != NULL) {
+            is_current = wins_is_current(&chatwin->super);
         }
         if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_TYPING_CURRENT)) ) {
             PContact contact = roster_get_contact(barejid);
@@ -330,23 +331,23 @@ _ui_incoming_msg(const char * const barejid, const char * const message, GTimeVa
         display_from = strdup(barejid);
     }
 
-    ProfWin *window = wins_get_by_recipient(barejid);
-    if (window == NULL) {
-        window = wins_new_chat(barejid);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin == NULL) {
+        ProfWin *window = wins_new_chat(barejid);
+        chatwin = (ProfChatWin*)window;
 #ifdef HAVE_LIBOTR
         if (otr_is_secure(barejid)) {
-            ProfChatWin *chatwin = (ProfChatWin*)window;
             chatwin->is_otr = TRUE;
         }
 #endif
         win_created = TRUE;
     }
 
-    int num = wins_get_num(window);
+    int num = wins_get_num(&chatwin->super);
 
     // currently viewing chat window with sender
-    if (wins_is_current(window)) {
-        win_print_incoming_message(window, tv_stamp, display_from, message);
+    if (wins_is_current(&chatwin->super)) {
+        win_print_incoming_message(&chatwin->super, tv_stamp, display_from, message);
         title_bar_set_typing(FALSE);
         status_bar_active(num);
 
@@ -359,7 +360,7 @@ _ui_incoming_msg(const char * const barejid, const char * const message, GTimeVa
             flash();
         }
 
-        window->unread++;
+        chatwin->super.unread++;
         if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
             _win_show_history(num, barejid);
         }
@@ -368,11 +369,11 @@ _ui_incoming_msg(const char * const barejid, const char * const message, GTimeVa
         if ((tv_stamp != NULL) && (win_created)) {
             PContact pcontact = roster_get_contact(barejid);
             if (pcontact != NULL) {
-                win_show_contact(window, pcontact);
+                win_show_contact(&chatwin->super, pcontact);
             }
         }
 
-        win_print_incoming_message(window, tv_stamp, display_from, message);
+        win_print_incoming_message(&chatwin->super, tv_stamp, display_from, message);
     }
 
     int ui_index = num;
@@ -385,7 +386,7 @@ _ui_incoming_msg(const char * const barejid, const char * const message, GTimeVa
     }
 
     if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) {
-        gboolean is_current = wins_is_current(window);
+        gboolean is_current = wins_is_current(&chatwin->super);
         if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
             if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT)) {
                 notify_message(display_from, ui_index, message);
@@ -404,16 +405,17 @@ _ui_incoming_private_msg(const char * const fulljid, const char * const message,
     char *display_from = NULL;
     display_from = get_nick_from_full_jid(fulljid);
 
-    ProfWin *window = wins_get_by_recipient(fulljid);
-    if (window == NULL) {
-        window = wins_new_private(fulljid);
+    ProfPrivateWin *privatewin = wins_get_private(fulljid);
+    if (privatewin == NULL) {
+        ProfWin *window = wins_new_private(fulljid);
+        privatewin = (ProfPrivateWin*)window;
     }
 
-    int num = wins_get_num(window);
+    int num = wins_get_num(&privatewin->super);
 
     // currently viewing chat window with sender
-    if (wins_is_current(window)) {
-        win_print_incoming_message(window, tv_stamp, display_from, message);
+    if (wins_is_current(&privatewin->super)) {
+        win_print_incoming_message(&privatewin->super, tv_stamp, display_from, message);
         title_bar_set_typing(FALSE);
         status_bar_active(num);
 
@@ -426,12 +428,12 @@ _ui_incoming_private_msg(const char * const fulljid, const char * const message,
             flash();
         }
 
-        window->unread++;
+        privatewin->super.unread++;
         if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
             _win_show_history(num, fulljid);
         }
 
-        win_print_incoming_message(window, tv_stamp, display_from, message);
+        win_print_incoming_message(&privatewin->super, tv_stamp, display_from, message);
     }
 
     int ui_index = num;
@@ -444,7 +446,7 @@ _ui_incoming_private_msg(const char * const fulljid, const char * const message,
     }
 
     if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) {
-        gboolean is_current = wins_is_current(window);
+        gboolean is_current = wins_is_current(&privatewin->super);
         if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
             if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT)) {
                 notify_message(display_from, ui_index, message);
@@ -664,23 +666,21 @@ _ui_close_connected_win(int index)
 {
     win_type_t win_type = ui_win_type(index);
     if (win_type == WIN_MUC) {
-        char *room_jid = ui_recipient(index);
-        presence_leave_chat_room(room_jid);
-    } else if ((win_type == WIN_CHAT) || (win_type == WIN_PRIVATE)) {
+        ProfMucWin *mucwin = wins_get_muc_by_num(index);
+        presence_leave_chat_room(mucwin->roomjid);
+    } else if (win_type == WIN_CHAT) {
 #ifdef HAVE_LIBOTR
-        ProfWin *window = wins_get_by_num(index);
-        if (win_is_otr(window)) {
-            otr_end_session(window->from);
+        ProfChatWin *chatwin = wins_get_chat_by_num(index);
+        if (chatwin->is_otr) {
+            otr_end_session(chatwin->barejid);
         }
 #endif
         if (prefs_get_boolean(PREF_STATES)) {
-            char *recipient = ui_recipient(index);
-
             // send <gone/> chat state before closing
-            if (chat_session_get_recipient_supports(recipient)) {
-                chat_session_set_gone(recipient);
-                message_send_gone(recipient);
-                chat_session_end(recipient);
+            if (chat_session_get_recipient_supports(chatwin->barejid)) {
+                chat_session_set_gone(chatwin->barejid);
+                message_send_gone(chatwin->barejid);
+                chat_session_end(chatwin->barejid);
             }
         }
     }
@@ -750,8 +750,9 @@ _ui_redraw_all_room_rosters(void)
         int num = GPOINTER_TO_INT(curr->data);
         ProfWin *window = wins_get_by_num(num);
         if (window->type == WIN_MUC && win_has_active_subwin(window)) {
-            char *room = window->from;
-            occupantswin_occupants(room);
+            ProfMucWin *mucwin = (ProfMucWin*)window;
+            assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+            occupantswin_occupants(mucwin->roomjid);
         }
         curr = g_list_next(curr);
     }
@@ -770,8 +771,9 @@ _ui_hide_all_room_rosters(void)
         int num = GPOINTER_TO_INT(curr->data);
         ProfWin *window = wins_get_by_num(num);
         if (window->type == WIN_MUC && win_has_active_subwin(window)) {
-            char *room = window->from;
-            ui_room_hide_occupants(room);
+            ProfMucWin *mucwin = (ProfMucWin*)window;
+            assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+            ui_room_hide_occupants(mucwin->roomjid);
         }
         curr = g_list_next(curr);
     }
@@ -790,8 +792,9 @@ _ui_show_all_room_rosters(void)
         int num = GPOINTER_TO_INT(curr->data);
         ProfWin *window = wins_get_by_num(num);
         if (window->type == WIN_MUC && !win_has_active_subwin(window)) {
-            char *room = window->from;
-            ui_room_show_occupants(room);
+            ProfMucWin *mucwin = (ProfMucWin*)window;
+            assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+            ui_room_show_occupants(mucwin->roomjid);
         }
         curr = g_list_next(curr);
     }
@@ -812,24 +815,6 @@ _ui_win_has_unsaved_form(int num)
     return win_has_modified_form(window);
 }
 
-GString *
-_get_recipient_string(ProfWin *window)
-{
-    GString *result = g_string_new("");
-    PContact contact = roster_get_contact(window->from);
-    if (contact != NULL) {
-        if (p_contact_name(contact) != NULL) {
-            g_string_append(result, p_contact_name(contact));
-        } else {
-            g_string_append(result, window->from);
-        }
-    } else {
-        g_string_append(result, window->from);
-    }
-
-    return result;
-}
-
 static gboolean
 _ui_switch_win(const int i)
 {
@@ -855,7 +840,7 @@ _ui_switch_win(const int i)
             status_bar_current(1);
             status_bar_active(1);
         } else {
-            GString *recipient_str = _get_recipient_string(new_current);
+            GString *recipient_str = win_get_recipient_string(new_current);
             title_bar_set_recipient(recipient_str->str);
             g_string_free(recipient_str, TRUE);
             status_bar_current(i);
@@ -892,7 +877,7 @@ _ui_previous_win(void)
         status_bar_current(1);
         status_bar_active(1);
     } else {
-        GString *recipient_str = _get_recipient_string(new_current);
+        GString *recipient_str = win_get_recipient_string(new_current);
         title_bar_set_recipient(recipient_str->str);
         g_string_free(recipient_str, TRUE);
         status_bar_current(i);
@@ -925,7 +910,7 @@ _ui_next_win(void)
         status_bar_current(1);
         status_bar_active(1);
     } else {
-        GString *recipient_str = _get_recipient_string(new_current);
+        GString *recipient_str = win_get_recipient_string(new_current);
         title_bar_set_recipient(recipient_str->str);
         g_string_free(recipient_str, TRUE);
         status_bar_current(i);
@@ -957,7 +942,7 @@ _ui_gone_secure(const char * const barejid, gboolean trusted)
     }
 
     if (wins_is_current(window)) {
-        GString *recipient_str = _get_recipient_string(window);
+        GString *recipient_str = win_get_recipient_string(window);
         title_bar_set_recipient(recipient_str->str);
         g_string_free(recipient_str, TRUE);
     } else {
@@ -1077,7 +1062,7 @@ _ui_gone_insecure(const char * const recipient)
         win_save_print(window, '!', NULL, 0, THEME_OTR_ENDED, "", "OTR session ended.");
 
         if (wins_is_current(window)) {
-            GString *recipient_str = _get_recipient_string(window);
+            GString *recipient_str = win_get_recipient_string(window);
             title_bar_set_recipient(recipient_str->str);
             g_string_free(recipient_str, TRUE);
         }
@@ -1098,7 +1083,7 @@ _ui_trust(const char * const recipient)
         win_save_print(window, '!', NULL, 0, THEME_OTR_TRUSTED, "", "OTR session trusted.");
 
         if (wins_is_current(window)) {
-            GString *recipient_str = _get_recipient_string(window);
+            GString *recipient_str = win_get_recipient_string(window);
             title_bar_set_recipient(recipient_str->str);
             g_string_free(recipient_str, TRUE);
         }
@@ -1119,7 +1104,7 @@ _ui_untrust(const char * const recipient)
         win_save_print(window, '!', NULL, 0, THEME_OTR_UNTRUSTED, "", "OTR session untrusted.");
 
         if (wins_is_current(window)) {
-            GString *recipient_str = _get_recipient_string(window);
+            GString *recipient_str = win_get_recipient_string(window);
             title_bar_set_recipient(recipient_str->str);
             g_string_free(recipient_str, TRUE);
         }
@@ -1234,7 +1219,13 @@ static gboolean
 _ui_current_win_is_otr(void)
 {
     ProfWin *current = wins_get_current();
-    return win_is_otr(current);
+    if (current->type == WIN_CHAT) {
+        ProfChatWin *chatwin = (ProfChatWin*)current;
+        assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
+        return chatwin->is_otr;
+    } else {
+        return FALSE;
+    }
 }
 
 static void
@@ -1282,20 +1273,6 @@ _ui_win_type(int index)
     return window->type;
 }
 
-static char *
-_ui_recipient(int index)
-{
-    ProfWin *window = wins_get_by_num(index);
-    return window->from;
-}
-
-static char *
-_ui_current_recipient(void)
-{
-    ProfWin *current = wins_get_current();
-    return current->from;
-}
-
 static void
 _ui_current_print_line(const char * const msg, ...)
 {
@@ -2237,86 +2214,6 @@ _ui_handle_room_role_set_error(const char * const room, const char * const nick,
     }
 }
 
-static void
-_ui_status(void)
-{
-    char *recipient = ui_current_recipient();
-    PContact pcontact = roster_get_contact(recipient);
-    ProfWin *window = wins_get_current();
-
-    if (pcontact != NULL) {
-        win_show_contact(window, pcontact);
-    } else {
-        win_save_println(window, "Error getting contact info.");
-    }
-}
-
-static void
-_ui_info(void)
-{
-    char *recipient = ui_current_recipient();
-    PContact pcontact = roster_get_contact(recipient);
-    ProfWin *window = wins_get_current();
-
-    if (pcontact != NULL) {
-        win_show_info(window, pcontact);
-    } else {
-        win_save_println(window, "Error getting contact info.");
-    }
-}
-
-static void
-_ui_status_private(void)
-{
-    Jid *jid = jid_create(ui_current_recipient());
-    Occupant *occupant = muc_roster_item(jid->barejid, jid->resourcepart);
-    ProfWin *window = wins_get_current();
-
-    if (occupant) {
-        win_show_occupant(window, occupant);
-    } else {
-        win_save_println(window, "Error getting contact info.");
-    }
-
-    jid_destroy(jid);
-}
-
-static void
-_ui_info_private(void)
-{
-    Jid *jid = jid_create(ui_current_recipient());
-    Occupant *occupant = muc_roster_item(jid->barejid, jid->resourcepart);
-    ProfWin *window = wins_get_current();
-
-    if (occupant) {
-        win_show_occupant_info(window, jid->barejid, occupant);
-    } else {
-        win_save_println(window, "Error getting contact info.");
-    }
-
-    jid_destroy(jid);
-}
-
-static void
-_ui_status_room(const char * const contact)
-{
-    Occupant *occupant = muc_roster_item(ui_current_recipient(), contact);
-    ProfWin *current = wins_get_current();
-
-    if (occupant) {
-        win_show_occupant(current, occupant);
-    } else {
-        win_save_vprint(current, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", contact);
-    }
-}
-
-static void
-_ui_info_room(const char * const room, Occupant *occupant)
-{
-    ProfWin *current = wins_get_current();
-    win_show_occupant_info(current, room, occupant);
-}
-
 static gint
 _ui_unread(void)
 {
@@ -2426,47 +2323,47 @@ _ui_draw_term_title(void)
 }
 
 static void
-_ui_show_room_info(ProfWin *window, const char * const room)
+_ui_show_room_info(ProfMucWin *mucwin)
 {
-    char *role = muc_role_str(room);
-    char *affiliation = muc_affiliation_str(room);
+    char *role = muc_role_str(mucwin->roomjid);
+    char *affiliation = muc_affiliation_str(mucwin->roomjid);
 
-    win_save_vprint(window, '!', NULL, 0, 0, "", "Room: %s", room);
-    win_save_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
-    win_save_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
-    win_save_print(window, '-', NULL, 0, 0, "", "");
+    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "Room: %s", mucwin->roomjid);
+    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
+    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "Role: %s", role);
+    win_save_print(&mucwin->super, '-', NULL, 0, 0, "", "");
 }
 
 static void
-_ui_show_room_role_list(ProfWin *window, const char * const room, muc_role_t role)
+_ui_show_room_role_list(ProfMucWin *mucwin, muc_role_t role)
 {
-    GSList *occupants = muc_occupants_by_role(room, role);
+    GSList *occupants = muc_occupants_by_role(mucwin->roomjid, role);
 
     if (!occupants) {
         switch (role) {
             case MUC_ROLE_MODERATOR:
-                win_save_print(window, '!', NULL, 0, 0, "", "No moderators found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No moderators found.");
                 break;
             case MUC_ROLE_PARTICIPANT:
-                win_save_print(window, '!', NULL, 0, 0, "", "No participants found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No participants found.");
                 break;
             case MUC_ROLE_VISITOR:
-                win_save_print(window, '!', NULL, 0, 0, "", "No visitors found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No visitors found.");
                 break;
             default:
                 break;
         }
-        win_save_print(window, '-', NULL, 0, 0, "", "");
+        win_save_print(&mucwin->super, '-', NULL, 0, 0, "", "");
     } else {
         switch (role) {
             case MUC_ROLE_MODERATOR:
-                win_save_print(window, '!', NULL, 0, 0, "", "Moderators:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Moderators:");
                 break;
             case MUC_ROLE_PARTICIPANT:
-                win_save_print(window, '!', NULL, 0, 0, "", "Participants:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Participants:");
                 break;
             case MUC_ROLE_VISITOR:
-                win_save_print(window, '!', NULL, 0, 0, "", "Visitors:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Visitors:");
                 break;
             default:
                 break;
@@ -2477,55 +2374,55 @@ _ui_show_room_role_list(ProfWin *window, const char * const room, muc_role_t rol
             Occupant *occupant = curr_occupant->data;
             if (occupant->role == role) {
                 if (occupant->jid) {
-                    win_save_vprint(window, '!', NULL, 0, 0, "", "  %s (%s)", occupant->nick, occupant->jid);
+                    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "  %s (%s)", occupant->nick, occupant->jid);
                 } else {
-                    win_save_vprint(window, '!', NULL, 0, 0, "", "  %s", occupant->nick);
+                    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "  %s", occupant->nick);
                 }
             }
 
             curr_occupant = g_slist_next(curr_occupant);
         }
 
-        win_save_print(window, '-', NULL, 0, 0, "", "");
+        win_save_print(&mucwin->super, '-', NULL, 0, 0, "", "");
     }
 }
 
 static void
-_ui_show_room_affiliation_list(ProfWin *window, const char * const room, muc_affiliation_t affiliation)
+_ui_show_room_affiliation_list(ProfMucWin *mucwin, muc_affiliation_t affiliation)
 {
-    GSList *occupants = muc_occupants_by_affiliation(room, affiliation);
+    GSList *occupants = muc_occupants_by_affiliation(mucwin->roomjid, affiliation);
 
     if (!occupants) {
         switch (affiliation) {
             case MUC_AFFILIATION_OWNER:
-                win_save_print(window, '!', NULL, 0, 0, "", "No owners found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No owners found.");
                 break;
             case MUC_AFFILIATION_ADMIN:
-                win_save_print(window, '!', NULL, 0, 0, "", "No admins found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No admins found.");
                 break;
             case MUC_AFFILIATION_MEMBER:
-                win_save_print(window, '!', NULL, 0, 0, "", "No members found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No members found.");
                 break;
             case MUC_AFFILIATION_OUTCAST:
-                win_save_print(window, '!', NULL, 0, 0, "", "No outcasts found.");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "No outcasts found.");
                 break;
             default:
                 break;
         }
-        win_save_print(window, '-', NULL, 0, 0, "", "");
+        win_save_print(&mucwin->super, '-', NULL, 0, 0, "", "");
     } else {
         switch (affiliation) {
             case MUC_AFFILIATION_OWNER:
-                win_save_print(window, '!', NULL, 0, 0, "", "Owners:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Owners:");
                 break;
             case MUC_AFFILIATION_ADMIN:
-                win_save_print(window, '!', NULL, 0, 0, "", "Admins:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Admins:");
                 break;
             case MUC_AFFILIATION_MEMBER:
-                win_save_print(window, '!', NULL, 0, 0, "", "Members:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Members:");
                 break;
             case MUC_AFFILIATION_OUTCAST:
-                win_save_print(window, '!', NULL, 0, 0, "", "Outcasts:");
+                win_save_print(&mucwin->super, '!', NULL, 0, 0, "", "Outcasts:");
                 break;
             default:
                 break;
@@ -2536,16 +2433,16 @@ _ui_show_room_affiliation_list(ProfWin *window, const char * const room, muc_aff
             Occupant *occupant = curr_occupant->data;
             if (occupant->affiliation == affiliation) {
                 if (occupant->jid) {
-                    win_save_vprint(window, '!', NULL, 0, 0, "", "  %s (%s)", occupant->nick, occupant->jid);
+                    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "  %s (%s)", occupant->nick, occupant->jid);
                 } else {
-                    win_save_vprint(window, '!', NULL, 0, 0, "", "  %s", occupant->nick);
+                    win_save_vprint(&mucwin->super, '!', NULL, 0, 0, "", "  %s", occupant->nick);
                 }
             }
 
             curr_occupant = g_slist_next(curr_occupant);
         }
 
-        win_save_print(window, '-', NULL, 0, 0, "", "");
+        win_save_print(&mucwin->super, '-', NULL, 0, 0, "", "");
     }
 }
 
@@ -2681,19 +2578,22 @@ _ui_handle_form_field(ProfWin *window, char *tag, FormField *field)
 }
 
 static void
-_ui_show_form(ProfWin *window, const char * const room, DataForm *form)
+_ui_show_form(ProfMucConfWin *confwin)
 {
-    if (form->title != NULL) {
-        win_save_print(window, '-', NULL, NO_EOL, 0, "", "Form title: ");
-        win_save_print(window, '-', NULL, NO_DATE, 0, "", form->title);
+    if (confwin->form->title != NULL) {
+        win_save_print(&confwin->super, '-', NULL, NO_EOL, 0, "", "Form title: ");
+        win_save_print(&confwin->super, '-', NULL, NO_DATE, 0, "", confwin->form->title);
     } else {
-        win_save_vprint(window, '-', NULL, 0, 0, "", "Configuration for room %s.", room);
+        gchar **split_recipient = g_strsplit(confwin->from, " ", 2);
+        char *roomjid = split_recipient[0];
+        win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "Configuration for room %s.", roomjid);
+        g_strfreev(split_recipient);
     }
-    win_save_print(window, '-', NULL, 0, 0, "", "");
+    win_save_print(&confwin->super, '-', NULL, 0, 0, "", "");
 
-    ui_show_form_help(window, form);
+    ui_show_form_help(confwin);
 
-    GSList *fields = form->fields;
+    GSList *fields = confwin->form->fields;
     GSList *curr_field = fields;
     while (curr_field != NULL) {
         FormField *field = curr_field->data;
@@ -2701,11 +2601,11 @@ _ui_show_form(ProfWin *window, const char * const room, DataForm *form)
         if ((g_strcmp0(field->type, "fixed") == 0) && field->values) {
             if (field->values) {
                 char *value = field->values->data;
-                win_save_print(window, '-', NULL, 0, 0, "", value);
+                win_save_print(&confwin->super, '-', NULL, 0, 0, "", value);
             }
         } else if (g_strcmp0(field->type, "hidden") != 0 && field->var) {
-            char *tag = g_hash_table_lookup(form->var_to_tag, field->var);
-            _ui_handle_form_field(window, tag, field);
+            char *tag = g_hash_table_lookup(confwin->form->var_to_tag, field->var);
+            _ui_handle_form_field(&confwin->super, tag, field);
         }
 
         curr_field = g_slist_next(curr_field);
@@ -2726,12 +2626,14 @@ _ui_handle_room_configuration(const char * const room, DataForm *form)
     GString *title = g_string_new(room);
     g_string_append(title, " config");
     ProfWin *window = wins_new_muc_config(title->str, form);
+    ProfMucConfWin *confwin = (ProfMucConfWin*)window;
+    assert(confwin->memcheck = PROFCONFWIN_MEMCHECK);
     g_string_free(title, TRUE);
 
     int num = wins_get_num(window);
     ui_switch_win(num);
 
-    ui_show_form(window, room, form);
+    ui_show_form(confwin);
 
     win_save_print(window, '-', NULL, 0, 0, "", "");
     win_save_print(window, '-', NULL, 0, 0, "", "Use '/form submit' to save changes.");
@@ -2837,20 +2739,20 @@ _ui_handle_room_config_submit_result_error(const char * const room, const char *
 }
 
 static void
-_ui_show_form_field_help(ProfWin *window, DataForm *form, char *tag)
+_ui_show_form_field_help(ProfMucConfWin *confwin, char *tag)
 {
-    FormField *field = form_get_field_by_tag(form, tag);
+    FormField *field = form_get_field_by_tag(confwin->form, tag);
     if (field != NULL) {
-        win_save_print(window, '-', NULL, NO_EOL, 0, "", field->label);
+        win_save_print(&confwin->super, '-', NULL, NO_EOL, 0, "", field->label);
         if (field->required) {
-            win_save_print(window, '-', NULL, NO_DATE, 0, "", " (Required):");
+            win_save_print(&confwin->super, '-', NULL, NO_DATE, 0, "", " (Required):");
         } else {
-            win_save_print(window, '-', NULL, NO_DATE, 0, "", ":");
+            win_save_print(&confwin->super, '-', NULL, NO_DATE, 0, "", ":");
         }
         if (field->description != NULL) {
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Description : %s", field->description);
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Description : %s", field->description);
         }
-        win_save_vprint(window, '-', NULL, 0, 0, "", "  Type        : %s", field->type);
+        win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Type        : %s", field->type);
 
         int num_values = 0;
         GSList *curr_option = NULL;
@@ -2859,51 +2761,51 @@ _ui_show_form_field_help(ProfWin *window, DataForm *form, char *tag)
         switch (field->type_t) {
         case FIELD_TEXT_SINGLE:
         case FIELD_TEXT_PRIVATE:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is any text");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is any text");
             break;
         case FIELD_TEXT_MULTI:
-            num_values = form_get_value_count(form, tag);
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is any text");
+            num_values = form_get_value_count(confwin->form, tag);
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is any text");
             if (num_values > 0) {
-                win_save_vprint(window, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
-                win_save_vprint(window, '-', NULL, 0, 0, "", "  Where       : <value> between 'val1' and 'val%d'", num_values);
+                win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
+                win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> between 'val1' and 'val%d'", num_values);
             }
             break;
         case FIELD_BOOLEAN:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is either 'on' or 'off'");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is either 'on' or 'off'");
             break;
         case FIELD_LIST_SINGLE:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is one of");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is one of");
             curr_option = field->options;
             while (curr_option != NULL) {
                 option = curr_option->data;
-                win_save_vprint(window, '-', NULL, 0, 0, "", "                  %s", option->value);
+                win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "                  %s", option->value);
                 curr_option = g_slist_next(curr_option);
             }
             break;
         case FIELD_LIST_MULTI:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is one of");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is one of");
             curr_option = field->options;
             while (curr_option != NULL) {
                 option = curr_option->data;
-                win_save_vprint(window, '-', NULL, 0, 0, "", "                  %s", option->value);
+                win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "                  %s", option->value);
                 curr_option = g_slist_next(curr_option);
             }
             break;
         case FIELD_JID_SINGLE:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is a valid Jabber ID");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Set         : /%s <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is a valid Jabber ID");
             break;
         case FIELD_JID_MULTI:
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
-            win_save_vprint(window, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
-            win_save_print(window, '-', NULL, 0, 0, "", "  Where       : <value> is a valid Jabber ID");
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Add         : /%s add <value>", tag);
+            win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "  Remove      : /%s remove <value>", tag);
+            win_save_print(&confwin->super, '-', NULL, 0, 0, "", "  Where       : <value> is a valid Jabber ID");
             break;
         case FIELD_FIXED:
         case FIELD_UNKNOWN:
@@ -2912,17 +2814,17 @@ _ui_show_form_field_help(ProfWin *window, DataForm *form, char *tag)
             break;
         }
     } else {
-        win_save_vprint(window, '-', NULL, 0, 0, "", "No such field %s", tag);
+        win_save_vprint(&confwin->super, '-', NULL, 0, 0, "", "No such field %s", tag);
     }
 }
 
 static void
-_ui_show_form_help(ProfWin *window, DataForm *form)
+_ui_show_form_help(ProfMucConfWin *confwin)
 {
-    if (form->instructions != NULL) {
-        win_save_print(window, '-', NULL, 0, 0, "", "Supplied instructions:");
-        win_save_print(window, '-', NULL, 0, 0, "", form->instructions);
-        win_save_print(window, '-', NULL, 0, 0, "", "");
+    if (confwin->form->instructions != NULL) {
+        win_save_print(&confwin->super, '-', NULL, 0, 0, "", "Supplied instructions:");
+        win_save_print(&confwin->super, '-', NULL, 0, 0, "", confwin->form->instructions);
+        win_save_print(&confwin->super, '-', NULL, 0, 0, "", "");
     }
 }
 
@@ -3184,8 +3086,6 @@ ui_init_module(void)
     ui_current_win_type = _ui_current_win_type;
     ui_current_win_index = _ui_current_win_index;
     ui_win_type = _ui_win_type;
-    ui_recipient = _ui_recipient;
-    ui_current_recipient = _ui_current_recipient;
     ui_current_print_line = _ui_current_print_line;
     ui_current_print_formatted_line = _ui_current_print_formatted_line;
     ui_current_error_line = _ui_current_error_line;
@@ -3204,12 +3104,6 @@ ui_init_module(void)
     ui_room_message = _ui_room_message;
     ui_room_subject = _ui_room_subject;
     ui_room_broadcast = _ui_room_broadcast;
-    ui_status = _ui_status;
-    ui_info = _ui_info;
-    ui_status_private = _ui_status_private;
-    ui_info_private = _ui_info_private;
-    ui_status_room = _ui_status_room;
-    ui_info_room = _ui_info_room;
     ui_unread = _ui_unread;
     ui_win_unread = _ui_win_unread;
     ui_ask_password = _ui_ask_password;
diff --git a/src/ui/titlebar.c b/src/ui/titlebar.c
index cd254aba..c4f4e772 100644
--- a/src/ui/titlebar.c
+++ b/src/ui/titlebar.c
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include "config.h"
 
@@ -61,7 +62,7 @@ static void _title_bar_draw(void);
 static void _show_contact_presence(void);
 static void _show_self_presence(void);
 #ifdef HAVE_LIBOTR
-static void _show_privacy(void);
+static void _show_privacy(ProfChatWin *chatwin);
 #endif
 
 void
@@ -181,9 +182,11 @@ _title_bar_draw(void)
     mvwprintw(win, 0, 0, " %s", current_title);
 
     if (current && current->type == WIN_CHAT) {
+        ProfChatWin *chatwin = (ProfChatWin*)current;
+        assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
         _show_contact_presence();
 #ifdef HAVE_LIBOTR
-        _show_privacy();
+        _show_privacy(chatwin);
 #endif
         if (typing) {
             wprintw(win, " (typing...)");
@@ -258,12 +261,11 @@ _show_self_presence(void)
 
 #ifdef HAVE_LIBOTR
 static void
-_show_privacy(void)
+_show_privacy(ProfChatWin *chatwin)
 {
     int bracket_attrs = theme_attrs(THEME_TITLE_BRACKET);
 
-    ProfWin *current = wins_get_current();
-    if (!win_is_otr(current)) {
+    if (chatwin->is_otr) {
         if (prefs_get_boolean(PREF_OTR_WARN)) {
             int unencrypted_attrs = theme_attrs(THEME_TITLE_UNENCRYPTED);
             wprintw(win, " ");
@@ -289,7 +291,7 @@ _show_privacy(void)
         wattron(win, bracket_attrs);
         wprintw(win, "]");
         wattroff(win, bracket_attrs);
-        if (win_is_trusted(current)) {
+        if (chatwin->is_trusted) {
             int trusted_attrs = theme_attrs(THEME_TITLE_TRUSTED);
             wprintw(win, " ");
             wattron(win, bracket_attrs);
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 2cabd62f..5d6352b3 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -103,7 +103,7 @@ win_type_t (*ui_current_win_type)(void);
 int (*ui_current_win_index)(void);
 gboolean (*ui_current_win_is_otr)(void);
 void (*ui_current_set_otr)(gboolean value);
-char* (*ui_current_recipient)(void);
+
 void (*ui_current_print_line)(const char * const msg, ...);
 void (*ui_current_print_formatted_line)(const char show_char, int attrs, const char * const msg, ...);
 void (*ui_current_error_line)(const char * const msg);
@@ -112,7 +112,6 @@ void (*ui_otr_authenticating)(const char * const recipient);
 void (*ui_otr_authetication_waiting)(const char * const recipient);
 
 win_type_t (*ui_win_type)(int index);
-char * (*ui_recipient)(int index);
 void (*ui_close_win)(int index);
 gboolean (*ui_win_exists)(int index);
 int (*ui_win_unread)(int index);
@@ -151,9 +150,9 @@ void (*ui_room_message)(const char * const room_jid, const char * const nick,
 void (*ui_room_subject)(const char * const room, const char * const nick, const char * const subject);
 void (*ui_room_requires_config)(const char * const room_jid);
 void (*ui_room_destroy)(const char * const room_jid);
-void (*ui_show_room_info)(ProfWin *window, const char * const room);
-void (*ui_show_room_role_list)(ProfWin *window, const char * const room, muc_role_t role);
-void (*ui_show_room_affiliation_list)(ProfWin *window, const char * const room, muc_affiliation_t affiliation);
+void (*ui_show_room_info)(ProfMucWin *mucwin);
+void (*ui_show_room_role_list)(ProfMucWin *mucwin, muc_role_t role);
+void (*ui_show_room_affiliation_list)(ProfMucWin *mucwin, muc_affiliation_t affiliation);
 void (*ui_handle_room_info_error)(const char * const room, const char * const error);
 void (*ui_show_room_disco_info)(const char * const room, GSList *identities, GSList *features);
 void (*ui_room_destroyed)(const char * const room, const char * const reason, const char * const new_jid,
@@ -206,23 +205,15 @@ void (*ui_handle_room_role_set_error)(const char * const room, const char * cons
 void (*ui_handle_room_role_list_error)(const char * const room, const char * const role, const char * const error);
 void (*ui_handle_room_role_list)(const char * const room, const char * const role, GSList *nicks);
 void (*ui_handle_room_kick_error)(const char * const room, const char * const nick, const char * const error);
-void (*ui_show_form)(ProfWin *window, const char * const room, DataForm *form);
+void (*ui_show_form)(ProfMucConfWin *confwin);
 void (*ui_show_form_field)(ProfWin *window, DataForm *form, char *tag);
-void (*ui_show_form_help)(ProfWin *window, DataForm *form);
-void (*ui_show_form_field_help)(ProfWin *window, DataForm *form, char *tag);
+void (*ui_show_form_help)(ProfMucConfWin *confwin);
+void (*ui_show_form_field_help)(ProfMucConfWin *confwin, char *tag);
 void (*ui_show_lines)(ProfWin *window, const gchar** lines);
 void (*ui_redraw_all_room_rosters)(void);
 void (*ui_show_all_room_rosters)(void);
 void (*ui_hide_all_room_rosters)(void);
 
-// contact status functions
-void (*ui_status_room)(const char * const contact);
-void (*ui_info_room)(const char * const room, Occupant *occupant);
-void (*ui_status)(void);
-void (*ui_info)(void);
-void (*ui_status_private)(void);
-void (*ui_info_private)(void);
-
 void (*ui_tidy_wins)(void);
 void (*ui_prune_wins)(void);
 gboolean (*ui_swap_wins)(int source_win, int target_win);
diff --git a/src/ui/window.c b/src/ui/window.c
index dfeb61a6..9f96212a 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -47,6 +47,7 @@
 
 #include "config/theme.h"
 #include "config/preferences.h"
+#include "roster_list.h"
 #include "ui/ui.h"
 #include "ui/window.h"
 #include "xmpp/xmpp.h"
@@ -119,9 +120,10 @@ win_create_console(void)
     ProfConsoleWin *new_win = malloc(sizeof(ProfConsoleWin));
     new_win->super.type = WIN_CONSOLE;
     new_win->super.layout = _win_create_split_layout();
-    new_win->super.from = strdup(CONS_WIN_TITLE);
     new_win->super.unread = 0;
 
+    new_win->from = strdup(CONS_WIN_TITLE);
+
     return &new_win->super;
 }
 
@@ -131,9 +133,9 @@ win_create_chat(const char * const barejid)
     ProfChatWin *new_win = malloc(sizeof(ProfChatWin));
     new_win->super.type = WIN_CHAT;
     new_win->super.layout = _win_create_simple_layout();
-    new_win->super.from = strdup(barejid);
     new_win->super.unread = 0;
 
+    new_win->barejid = strdup(barejid);
     new_win->resource = NULL;
     new_win->is_otr = FALSE;
     new_win->is_trusted = FALSE;
@@ -172,7 +174,7 @@ win_create_muc(const char * const roomjid)
     scrollok(layout->super.win, TRUE);
     new_win->super.layout = (ProfLayout*)layout;
 
-    new_win->super.from = strdup(roomjid);
+    new_win->roomjid = strdup(roomjid);
     new_win->super.unread = 0;
 
     return &new_win->super;
@@ -184,9 +186,9 @@ win_create_muc_config(const char * const title, DataForm *form)
     ProfMucConfWin *new_win = malloc(sizeof(ProfMucConfWin));
     new_win->super.type = WIN_MUC_CONFIG;
     new_win->super.layout = _win_create_simple_layout();
-    new_win->super.from = strdup(title);
     new_win->super.unread = 0;
 
+    new_win->from = strdup(title);
     new_win->form = form;
 
     return &new_win->super;
@@ -198,9 +200,10 @@ win_create_private(const char * const fulljid)
     ProfPrivateWin *new_win = malloc(sizeof(ProfPrivateWin));
     new_win->super.type = WIN_PRIVATE;
     new_win->super.layout = _win_create_simple_layout();
-    new_win->super.from = strdup(fulljid);
     new_win->super.unread = 0;
 
+    new_win->fulljid = strdup(fulljid);
+
     return &new_win->super;
 }
 
@@ -210,9 +213,10 @@ win_create_xmlconsole(void)
     ProfXMLWin *new_win = malloc(sizeof(ProfXMLWin));
     new_win->super.type = WIN_XML;
     new_win->super.layout = _win_create_simple_layout();
-    new_win->super.from = strdup(XML_WIN_TITLE);
     new_win->super.unread = 0;
 
+    new_win->from = strdup(XML_WIN_TITLE);
+
     return &new_win->super;
 }
 
@@ -252,26 +256,6 @@ win_show_subwin(ProfWin *window)
     }
 }
 
-gboolean win_is_otr(ProfWin *window)
-{
-    if (window->type == WIN_CHAT) {
-        ProfChatWin *chatwin = (ProfChatWin*)window;
-        return chatwin->is_otr;
-    } else {
-        return FALSE;
-    }
-}
-
-gboolean win_is_trusted(ProfWin *window)
-{
-    if (window->type == WIN_CHAT) {
-        ProfChatWin *chatwin = (ProfChatWin*)window;
-        return chatwin->is_trusted;
-    } else {
-        return FALSE;
-    }
-}
-
 void
 win_free(ProfWin* window)
 {
@@ -289,19 +273,77 @@ win_free(ProfWin* window)
 
     if (window->type == WIN_CHAT) {
         ProfChatWin *chatwin = (ProfChatWin*)window;
+        free(chatwin->barejid);
         free(chatwin->resource);
     }
 
-    free(window->from);
+    if (window->type == WIN_CONSOLE) {
+        ProfConsoleWin *consolewin = (ProfConsoleWin*)window;
+        free(consolewin->from);
+    }
+
+    if (window->type == WIN_MUC) {
+        ProfMucWin *mucwin = (ProfMucWin*)window;
+        free(mucwin->roomjid);
+    }
 
     if (window->type == WIN_MUC_CONFIG) {
         ProfMucConfWin *mucconf = (ProfMucConfWin*)window;
+        free(mucconf->from);
         form_destroy(mucconf->form);
     }
 
+    if (window->type == WIN_PRIVATE) {
+        ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
+        free(privatewin->fulljid);
+    }
+
+    if (window->type == WIN_XML) {
+        ProfXMLWin *xmlwin = (ProfXMLWin*)window;
+        free(xmlwin->from);
+    }
+
     free(window);
 }
 
+GString *
+win_get_recipient_string(ProfWin *window)
+{
+    GString *result = g_string_new("");
+
+    if (window->type == WIN_CONSOLE) {
+        ProfConsoleWin *conswin = (ProfConsoleWin*)window;
+        g_string_append(result, conswin->from);
+    }
+    if (window->type == WIN_CHAT) {
+        ProfChatWin *chatwin = (ProfChatWin*)window;
+        PContact contact = roster_get_contact(chatwin->barejid);
+        if (p_contact_name(contact) != NULL) {
+            g_string_append(result, p_contact_name(contact));
+        } else {
+            g_string_append(result, chatwin->barejid);
+        }
+    }
+    if (window->type == WIN_MUC) {
+        ProfMucWin *mucwin = (ProfMucWin*)window;
+        g_string_append(result, mucwin->roomjid);
+    }
+    if (window->type == WIN_MUC_CONFIG) {
+        ProfMucConfWin *confwin = (ProfMucConfWin*)window;
+        g_string_append(result, confwin->from);
+    }
+    if (window->type == WIN_PRIVATE) {
+        ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
+        g_string_append(result, privatewin->fulljid);
+    }
+    if (window->type == WIN_XML) {
+        ProfXMLWin *xmlwin = (ProfXMLWin*)window;
+        g_string_append(result, xmlwin->from);
+    }
+
+    return result;
+}
+
 void
 win_update_virtual(ProfWin *window)
 {
diff --git a/src/ui/window.h b/src/ui/window.h
index 444b82c6..ddf34c51 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -56,7 +56,11 @@
 
 #define PAD_SIZE 1000
 
-#define LAYOUT_SPLIT_MEMCHECK 1234567
+#define LAYOUT_SPLIT_MEMCHECK       12345671
+#define PROFCHATWIN_MEMCHECK        22374522
+#define PROFMUCWIN_MEMCHECK         52345276
+#define PROFPRIVATEWIN_MEMCHECK     77437483
+#define PROFCONFWIN_MEMCHECK        64334685
 
 typedef enum {
     LAYOUT_SIMPLE,
@@ -94,37 +98,46 @@ typedef enum {
 typedef struct prof_win_t {
     win_type_t type;
     ProfLayout *layout;
-    char *from;
     int unread;
 } ProfWin;
 
 typedef struct prof_console_win_t {
     ProfWin super;
+    char *from;
 } ProfConsoleWin;
 
 typedef struct prof_chat_win_t {
     ProfWin super;
+    char *barejid;
     gboolean is_otr;
     gboolean is_trusted;
     char *resource;
     gboolean history_shown;
+    unsigned long memcheck;
 } ProfChatWin;
 
 typedef struct prof_muc_win_t {
     ProfWin super;
+    char *roomjid;
+    unsigned long memcheck;
 } ProfMucWin;
 
 typedef struct prof_mucconf_win_t {
     ProfWin super;
+    char *from;
     DataForm *form;
+    unsigned long memcheck;
 } ProfMucConfWin;
 
 typedef struct prof_private_win_t {
     ProfWin super;
+    char *fulljid;
+    unsigned long memcheck;
 } ProfPrivateWin;
 
 typedef struct prof_xml_win_t {
     ProfWin super;
+    char *from;
 } ProfXMLWin;
 
 ProfWin* win_create_console(void);
@@ -157,8 +170,7 @@ void win_show_subwin(ProfWin *window);
 int win_roster_cols(void);
 int win_occpuants_cols(void);
 void win_printline_nowrap(WINDOW *win, char *msg);
-gboolean win_is_otr(ProfWin *window);
-gboolean win_is_trusted(ProfWin *window);
+GString* win_get_recipient_string(ProfWin *window);
 
 gboolean win_has_active_subwin(ProfWin *window);
 gboolean win_has_modified_form(ProfWin *window);
diff --git a/src/ui/windows.c b/src/ui/windows.c
index 5e8c6a9f..3bdff9a2 100644
--- a/src/ui/windows.c
+++ b/src/ui/windows.c
@@ -35,6 +35,7 @@
 #include "config.h"
 
 #include <string.h>
+#include <assert.h>
 
 #include <glib.h>
 
@@ -75,6 +76,90 @@ wins_get_console(void)
     return g_hash_table_lookup(windows, GINT_TO_POINTER(1));
 }
 
+ProfChatWin *
+wins_get_chat(const char * const barejid)
+{
+    GList *values = g_hash_table_get_values(windows);
+    GList *curr = values;
+
+    while (curr != NULL) {
+        ProfWin *window = curr->data;
+        if (window->type == WIN_CHAT) {
+            ProfChatWin *chatwin = (ProfChatWin*)window;
+            if (g_strcmp0(chatwin->barejid, barejid) == 0) {
+                g_list_free(values);
+                return chatwin;
+            }
+        }
+        curr = g_list_next(curr);
+    }
+
+    g_list_free(values);
+    return NULL;
+}
+
+ProfMucConfWin *
+wins_get_muc_conf_win(const char * const title)
+{
+    GList *values = g_hash_table_get_values(windows);
+    GList *curr = values;
+
+    while (curr != NULL) {
+        ProfWin *window = curr->data;
+        if (window->type == WIN_MUC_CONFIG) {
+            ProfMucConfWin *confwin = (ProfMucConfWin*)window;
+            if (g_strcmp0(confwin->from, title) == 0) {
+                g_list_free(values);
+                return confwin;
+            }
+        }
+        curr = g_list_next(curr);
+    }
+
+    g_list_free(values);
+    return NULL;
+}
+
+ProfMucWin *
+wins_get_muc_win(const char * const roomjid)
+{
+    GList *values = g_hash_table_get_values(windows);
+    GList *curr = values;
+
+    while (curr != NULL) {
+        ProfWin *window = curr->data;
+        if ((g_strcmp0(window->from, roomjid) == 0) && window->type == WIN_MUC) {
+            g_list_free(values);
+            return (ProfMucWin*)window;
+        }
+        curr = g_list_next(curr);
+    }
+
+    g_list_free(values);
+    return NULL;
+}
+
+ProfPrivateWin *
+wins_get_private(const char * const fulljid)
+{
+    GList *values = g_hash_table_get_values(windows);
+    GList *curr = values;
+
+    while (curr != NULL) {
+        ProfWin *window = curr->data;
+        if (window->type == WIN_PRIVATE) {
+            ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
+            if (g_strcmp0(privatewin->fulljid, fulljid) == 0) {
+                return privatewin;
+            }
+        }
+        curr = g_list_next(curr);
+    }
+
+    g_list_free(values);
+    return NULL;
+}
+
 ProfWin *
 wins_get_current(void)
 {
@@ -85,6 +170,74 @@ wins_get_current(void)
     }
 }
 
+ProfChatWin *
+wins_get_current_chat(void)
+{
+    if (windows) {
+        ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(current));
+        if (window) {
+            ProfChatWin *chatwin = (ProfChatWin*)window;
+            assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
+            return chatwin;
+        } else {
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+}
+
+ProfMucWin *
+wins_get_current_muc(void)
+{
+    if (windows) {
+        ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(current));
+        if (window) {
+            ProfMucWin *mucwin = (ProfMucWin*)window;
+            assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+            return mucwin;
+        } else {
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+}
+
+ProfPrivateWin *
+wins_get_current_private(void)
+{
+    if (windows) {
+        ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(current));
+        if (window) {
+            ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
+            assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK);
+            return privatewin;
+        } else {
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+}
+
+ProfMucConfWin *
+wins_get_current_muc_conf(void)
+{
+    if (windows) {
+        ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(current));
+        if (window) {
+            ProfMucConfWin *confwin = (ProfMucConfWin*)window;
+            assert(confwin->memcheck == PROFCONFWIN_MEMCHECK);
+            return confwin;
+        } else {
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+}
+
 GList *
 wins_get_nums(void)
 {
@@ -105,6 +258,32 @@ wins_get_by_num(int i)
     return g_hash_table_lookup(windows, GINT_TO_POINTER(i));
 }
 
+ProfChatWin *
+wins_get_chat_by_num(int i)
+{
+    ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(i));
+    if (window) {
+        ProfChatWin *chatwin = (ProfChatWin*)window;
+        assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
+        return chatwin;
+    } else {
+        return NULL;
+    }
+}
+
+ProfMucWin *
+wins_get_muc_by_num(int i)
+{
+    ProfWin *window = g_hash_table_lookup(windows, GINT_TO_POINTER(i));
+    if (window) {
+        ProfMucWin *mucwin = (ProfMucWin*)window;
+        assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+        return mucwin;
+    } else {
+        return NULL;
+    }
+}
+
 ProfWin *
 wins_get_next(void)
 {
@@ -164,43 +343,25 @@ wins_get_previous(void)
     }
 }
 
-ProfWin *
-wins_get_by_recipient(const char * const recipient)
-{
-    GList *values = g_hash_table_get_values(windows);
-    GList *curr = values;
-
-    while (curr != NULL) {
-        ProfWin *window = curr->data;
-        if (g_strcmp0(window->from, recipient) == 0) {
-            g_list_free(values);
-            return window;
-        }
-        curr = g_list_next(curr);
-    }
-
-    g_list_free(values);
-    return NULL;
-}
-
-ProfMucWin *
-wins_get_muc_win(const char * const roomjid)
-{
-    GList *values = g_hash_table_get_values(windows);
-    GList *curr = values;
-
-    while (curr != NULL) {
-        ProfWin *window = curr->data;
-        if ((g_strcmp0(window->from, roomjid) == 0) && window->type == WIN_MUC) {
-            g_list_free(values);
-            return (ProfMucWin*)window;
-        }
-        curr = g_list_next(curr);
-    }
-
-    g_list_free(values);
-    return NULL;
-}
+// TODO REMOVE
+//ProfWin *
+//wins_get_by_recipient(const char * const recipient)
+//{
+//    GList *values = g_hash_table_get_values(windows);
+//    GList *curr = values;
+//
+//    while (curr != NULL) {
+//        ProfWin *window = curr->data;
+//        if (g_strcmp0(window->from, recipient) == 0) {
+//            g_list_free(values);
+//            return window;
+//        }
+//        curr = g_list_next(curr);
+//    }
+//
+//    g_list_free(values);
+//    return NULL;
+//}
 
 int
 wins_get_num(ProfWin *window)
diff --git a/src/ui/windows.h b/src/ui/windows.h
index 50660bfc..4eb2e50e 100644
--- a/src/ui/windows.h
+++ b/src/ui/windows.h
@@ -44,14 +44,28 @@ ProfWin * wins_new_muc_config(const char * const title, DataForm *form);
 ProfWin * wins_new_private(const char * const fulljid);
 
 ProfWin * wins_get_console(void);
+ProfChatWin *wins_get_chat(const char * const barejid);
 ProfMucWin * wins_get_muc_win(const char * const roomjid);
+ProfMucConfWin * wins_get_muc_conf_win(const char * const title);
+ProfPrivateWin *wins_get_private(const char * const fulljid);
+
+// TODO remove
+//ProfWin * wins_get_by_recipient(const char * const recipient);
 
 ProfWin * wins_get_current(void);
+ProfChatWin * wins_get_current_chat(void);
+ProfMucWin * wins_get_current_muc(void);
+ProfPrivateWin * wins_get_current_private(void);
+ProfMucConfWin * wins_get_current_muc_conf(void);
+
 void wins_set_current_by_num(int i);
+
 ProfWin * wins_get_by_num(int i);
+ProfChatWin * wins_get_chat_by_num(int i);
+ProfMucWin * wins_get_muc_by_num(int i);
+
 ProfWin * wins_get_next(void);
 ProfWin * wins_get_previous(void);
-ProfWin * wins_get_by_recipient(const char * const recipient);
 int wins_get_num(ProfWin *window);
 int wins_get_current_num(void);
 void wins_close_current(void);