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.c39
-rw-r--r--src/command/commands.c126
-rw-r--r--src/otr/otr.c2
-rw-r--r--src/server_events.c26
-rw-r--r--src/ui/console.c2
-rw-r--r--src/ui/core.c649
-rw-r--r--src/ui/occupantswin.c2
-rw-r--r--src/ui/ui.h122
-rw-r--r--src/ui/window.c8
-rw-r--r--src/ui/windows.c67
-rw-r--r--src/ui/windows.h6
-rw-r--r--src/xmpp/message.c59
-rw-r--r--src/xmpp/xmpp.h18
13 files changed, 590 insertions, 536 deletions
diff --git a/src/command/command.c b/src/command/command.c
index f73a8aee..776dd533 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1751,7 +1751,6 @@ cmd_execute_alias(const char * const inp, gboolean *ran)
 gboolean
 cmd_execute_default(const char * inp)
 {
-    win_type_t win_type = ui_current_win_type();
     jabber_conn_status_t status = jabber_get_connection_status();
 
     // handle escaped commands - treat as normal message
@@ -1765,14 +1764,15 @@ cmd_execute_default(const char * inp)
         return TRUE;
     }
 
+    win_type_t win_type = ui_current_win_type();
     switch (win_type)
     {
         case WIN_MUC:
             if (status != JABBER_CONNECTED) {
                 ui_current_print_line("You are not currently connected.");
             } else {
-                ProfWin
-                message_send_groupchat(inp, recipient);
+                ProfMucWin *mucwin = wins_get_current_muc();
+                message_send_groupchat(mucwin->roomjid, inp);
             }
             break;
 
@@ -1780,63 +1780,63 @@ cmd_execute_default(const char * inp)
             if (status != JABBER_CONNECTED) {
                 ui_current_print_line("You are not currently connected.");
             } else {
-                GString *send_recipient = g_string_new(recipient);
                 ProfWin *current = wins_get_current();
                 ProfChatWin *chatwin = (ProfChatWin*)current;
+                GString *send_recipient = g_string_new(chatwin->barejid);
                 if (current && win_has_chat_resource(current)) {
                     g_string_append(send_recipient, "/");
                     g_string_append(send_recipient, chatwin->resource);
                 }
 
 #ifdef HAVE_LIBOTR
-                prof_otrpolicy_t policy = otr_get_policy(recipient);
-                if (policy == PROF_OTRPOLICY_ALWAYS && !otr_is_secure(recipient)) {
+                prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid);
+                if (policy == PROF_OTRPOLICY_ALWAYS && !otr_is_secure(chatwin->barejid)) {
                     cons_show_error("Failed to send message. Please check OTR policy");
                     return TRUE;
                 }
-                if (otr_is_secure(recipient)) {
-                    char *encrypted = otr_encrypt_message(recipient, inp);
+                if (otr_is_secure(chatwin->barejid)) {
+                    char *encrypted = otr_encrypt_message(chatwin->barejid, inp);
                     if (encrypted != NULL) {
-                        message_send(encrypted, recipient);
+                        message_send_chat(chatwin->barejid, encrypted);
                         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, inp, PROF_OUT_LOG, NULL);
+                                chat_log_chat(jidp->barejid, chatwin->barejid, inp, 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, inp);
+                        ui_outgoing_chat_msg("me", chatwin->barejid, inp);
                     } else {
                         cons_show_error("Failed to send message.");
                     }
                 } else {
-                    message_send(inp, send_recipient->str);
+                    message_send_chat(send_recipient->str, inp);
                     if (prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
                         Jid *jidp = jid_create(jid);
-                        chat_log_chat(jidp->barejid, recipient, inp, PROF_OUT_LOG, NULL);
+                        chat_log_chat(jidp->barejid, chatwin->barejid, inp, PROF_OUT_LOG, NULL);
                         jid_destroy(jidp);
                     }
 
-                    ui_outgoing_msg("me", recipient, inp);
+                    ui_outgoing_chat_msg("me", chatwin->barejid, inp);
                 }
 #else
                 message_send(inp, 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, inp, PROF_OUT_LOG, NULL);
+                    chat_log_chat(jidp->barejid, chatwin->barejid, inp, PROF_OUT_LOG, NULL);
                     jid_destroy(jidp);
                 }
 
-                ui_outgoing_msg("me", recipient, inp);
+                ui_outgoing_chat_msg("me", chatwin->barejid, inp);
 #endif
                 g_string_free(send_recipient, TRUE);
             }
@@ -1846,8 +1846,9 @@ cmd_execute_default(const char * inp)
             if (status != JABBER_CONNECTED) {
                 ui_current_print_line("You are not currently connected.");
             } else {
-                message_send(inp, recipient);
-                ui_outgoing_msg("me", recipient, inp);
+                ProfPrivateWin *privatewin = wins_get_current_private();
+                message_send_private(privatewin->fulljid, inp);
+                ui_outgoing_private_msg("me", privatewin->fulljid, inp);
             }
             break;
 
diff --git a/src/command/commands.c b/src/command/commands.c
index 1b3ab45a..7316de2f 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -1130,10 +1130,12 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             g_string_append(full_jid, usr);
 
             if (msg != NULL) {
-                message_send(msg, full_jid->str);
-                ui_outgoing_msg("me", full_jid->str, msg);
+                // TODO use message send private
+                message_send_private(full_jid->str, msg);
+                ui_outgoing_private_msg("me", full_jid->str, msg);
             } else {
-                ui_new_chat_win(full_jid->str);
+                // TODO use new private win
+                ui_new_private_win(full_jid->str);
             }
 
             g_string_free(full_jid, TRUE);
@@ -1144,6 +1146,7 @@ cmd_msg(gchar **args, struct cmd_help_t help)
 
         return TRUE;
 
+    // TODO handle different window types (OTR only for chat etc)
     } else {
         char *usr_jid = roster_barejid_from_name(usr);
         if (usr_jid == NULL) {
@@ -1162,9 +1165,9 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             if (otr_is_secure(usr_jid)) {
                 char *encrypted = otr_encrypt_message(usr_jid, msg);
                 if (encrypted != NULL) {
-                    message_send(encrypted, usr_jid);
+                    message_send_chat(usr_jid, encrypted);
                     otr_free_message(encrypted);
-                    ui_outgoing_msg("me", usr_jid, msg);
+                    ui_outgoing_chat_msg("me", usr_jid, msg);
 
                     if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
@@ -1191,12 +1194,12 @@ cmd_msg(gchar **args, struct cmd_help_t help)
                     GString *otr_message = g_string_new(msg);
                     g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE);
                     g_string_append(otr_message, OTRL_MESSAGE_TAG_V2);
-                    message_send(otr_message->str, usr_jid);
+                    message_send_chat(usr_jid, otr_message->str);
                     g_string_free(otr_message, TRUE);
                 } else {
-                    message_send(msg, send_jid->str);
+                    message_send_chat(send_jid->str, msg);
                 }
-                ui_outgoing_msg("me", usr_jid, msg);
+                ui_outgoing_chat_msg("me", usr_jid, msg);
 
                 if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
                     const char *jid = jabber_get_fulljid();
@@ -1207,8 +1210,8 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             }
             return TRUE;
 #else
-            message_send(msg, send_jid->str);
-            ui_outgoing_msg("me", usr_jid, msg);
+            message_send_chat(send_jid->str, msg);
+            ui_outgoing_chat_msg("me", usr_jid, msg);
 
             if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
                 const char *jid = jabber_get_fulljid();
@@ -1219,7 +1222,7 @@ cmd_msg(gchar **args, struct cmd_help_t help)
             return TRUE;
 #endif
 
-        } else {
+        } else { // msg == NULL
             const char * jid = NULL;
 
             if (roster_barejid_from_name(usr_jid) != NULL) {
@@ -1605,11 +1608,11 @@ cmd_status(gchar **args, struct cmd_help_t help)
         case WIN_MUC:
             if (usr != NULL) {
                 ProfMucWin *mucwin = wins_get_current_muc();
-                Occupant *occupant = muc_roster_item(mucwin->roomjid, contact);
+                Occupant *occupant = muc_roster_item(mucwin->roomjid, usr);
                 if (occupant) {
-                    win_show_occupant(mucwin->super, occupant);
+                    win_show_occupant(&mucwin->super, occupant);
                 } else {
-                    win_save_vprint(mucwin->super, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", contact);
+                    win_save_vprint(&mucwin->super, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", usr);
                 }
             } else {
                 ui_current_print_line("You must specify a nickname.");
@@ -1622,9 +1625,9 @@ cmd_status(gchar **args, struct cmd_help_t help)
                 ProfChatWin *chatwin = wins_get_current_chat();
                 PContact pcontact = roster_get_contact(chatwin->barejid);
                 if (pcontact != NULL) {
-                    win_show_contact(chatwin->super, pcontact);
+                    win_show_contact(&chatwin->super, pcontact);
                 } else {
-                    win_save_println(chatwin->super, "Error getting contact info.");
+                    win_save_println(&chatwin->super, "Error getting contact info.");
                 }
             }
             break;
@@ -1636,9 +1639,9 @@ cmd_status(gchar **args, struct cmd_help_t help)
                 Jid *jid = jid_create(privatewin->fulljid);
                 Occupant *occupant = muc_roster_item(jid->barejid, jid->resourcepart);
                 if (occupant) {
-                    win_show_occupant(privatewin->super, occupant);
+                    win_show_occupant(&privatewin->super, occupant);
                 } else {
-                    win_save_println(privatewin->super, "Error getting contact info.");
+                    win_save_println(&privatewin->super, "Error getting contact info.");
                 }
                 jid_destroy(jid);
             }
@@ -1702,9 +1705,9 @@ cmd_info(gchar **args, struct cmd_help_t help)
                 ProfChatWin *chatwin = wins_get_current_chat();
                 PContact pcontact = roster_get_contact(chatwin->barejid);
                 if (pcontact != NULL) {
-                    win_show_info(chatwin->super, pcontact);
+                    win_show_info(&chatwin->super, pcontact);
                 } else {
-                    win_save_println(chatwin->super, "Error getting contact info.");
+                    win_save_println(&chatwin->super, "Error getting contact info.");
                 }
             }
             break;
@@ -1716,9 +1719,9 @@ cmd_info(gchar **args, struct cmd_help_t help)
                 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);
+                    win_show_occupant_info(&privatewin->super, jid->barejid, occupant);
                 } else {
-                    win_save_println(privatewin->super, "Error getting contact info.");
+                    win_save_println(&privatewin->super, "Error getting contact info.");
                 }
                 jid_destroy(jid);
             }
@@ -1828,7 +1831,6 @@ cmd_software(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();
     Occupant *occupant = NULL;
-    char *recipient;
 
     if (conn_status != JABBER_CONNECTED) {
         cons_show("You are not currently connected.");
@@ -1963,7 +1965,6 @@ cmd_invite(gchar **args, struct cmd_help_t help)
 {
     char *contact = args[0];
     char *reason = args[1];
-    char *room = NULL;
     jabber_conn_status_t conn_status = jabber_get_connection_status();
 
     if (conn_status != JABBER_CONNECTED) {
@@ -1981,7 +1982,7 @@ cmd_invite(gchar **args, struct cmd_help_t help)
         usr_jid = contact;
     }
 
-    ProfMucWin mucwin = wins_get_current_muc();
+    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\".",
@@ -2052,7 +2053,7 @@ cmd_form_field(char *tag, gchar **args)
                 ui_show_form_field(current, form, tag);
             } else {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
             }
             break;
@@ -2063,7 +2064,7 @@ cmd_form_field(char *tag, gchar **args)
             value = args[0];
             if (value == NULL) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
             } else {
                 form_set_value(form, tag, value);
@@ -2075,7 +2076,7 @@ cmd_form_field(char *tag, gchar **args)
             value = args[0];
             if ((value == NULL) || !form_field_contains_option(form, tag, value)) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
             } else {
                 form_set_value(form, tag, value);
@@ -2091,13 +2092,13 @@ cmd_form_field(char *tag, gchar **args)
             }
             if ((g_strcmp0(cmd, "add") != 0) && (g_strcmp0(cmd, "remove"))) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
             if (value == NULL) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
@@ -2110,13 +2111,13 @@ cmd_form_field(char *tag, gchar **args)
             if (g_strcmp0(args[0], "remove") == 0) {
                 if (!g_str_has_prefix(value, "val")) {
                     ui_current_print_line("Invalid command, usage:");
-                    ui_show_form_field_help(current, form, tag);
+                    ui_show_form_field_help(confwin, tag);
                     ui_current_print_line("");
                     break;
                 }
                 if (strlen(value) < 4) {
                     ui_current_print_line("Invalid command, usage:");
-                    ui_show_form_field_help(current, form, tag);
+                    ui_show_form_field_help(confwin, tag);
                     ui_current_print_line("");
                     break;
                 }
@@ -2124,7 +2125,7 @@ cmd_form_field(char *tag, gchar **args)
                 int index = strtol(&value[3], NULL, 10);
                 if ((index < 1) || (index > form_get_value_count(form, tag))) {
                     ui_current_print_line("Invalid command, usage:");
-                    ui_show_form_field_help(current, form, tag);
+                    ui_show_form_field_help(confwin, tag);
                     ui_current_print_line("");
                     break;
                 }
@@ -2145,13 +2146,13 @@ cmd_form_field(char *tag, gchar **args)
             }
             if ((g_strcmp0(cmd, "add") != 0) && (g_strcmp0(cmd, "remove"))) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
             if (value == NULL) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
@@ -2167,7 +2168,7 @@ cmd_form_field(char *tag, gchar **args)
                     }
                 } else {
                     ui_current_print_line("Invalid command, usage:");
-                    ui_show_form_field_help(current, form, tag);
+                    ui_show_form_field_help(confwin, tag);
                     ui_current_print_line("");
                 }
                 break;
@@ -2184,7 +2185,7 @@ cmd_form_field(char *tag, gchar **args)
                     }
                 } else {
                     ui_current_print_line("Invalid command, usage:");
-                    ui_show_form_field_help(current, form, tag);
+                    ui_show_form_field_help(confwin, tag);
                     ui_current_print_line("");
                 }
             }
@@ -2196,13 +2197,13 @@ cmd_form_field(char *tag, gchar **args)
             }
             if ((g_strcmp0(cmd, "add") != 0) && (g_strcmp0(cmd, "remove"))) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
             if (value == NULL) {
                 ui_current_print_line("Invalid command, usage:");
-                ui_show_form_field_help(current, form, tag);
+                ui_show_form_field_help(confwin, tag);
                 ui_current_print_line("");
                 break;
             }
@@ -2280,7 +2281,7 @@ cmd_form(gchar **args, struct cmd_help_t help)
                 help_text = command->help.long_help;
             }
 
-            ui_show_lines(confwin->super, help_text);
+            ui_show_lines(&confwin->super, help_text);
         }
         ui_current_print_line("");
         return TRUE;
@@ -2303,7 +2304,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(roomjid);
+        ProfWin *current = (ProfWin*)wins_get_muc(roomjid);
         if (current == NULL) {
             current = wins_get_console();
         }
@@ -2340,7 +2341,7 @@ cmd_kick(gchar **args, struct cmd_help_t help)
             char *reason = args[1];
             iq_room_kick_occupant(mucwin->roomjid, nick, reason);
         } else {
-            win_save_vprint(mucwin->super, '!', 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);
@@ -2398,10 +2399,10 @@ cmd_subject(gchar **args, struct cmd_help_t help)
     if (args[0] == NULL) {
         char *subject = muc_subject(mucwin->roomjid);
         if (subject) {
-            win_save_vprint(mucwin->super, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
-            win_save_vprint(mucwin->super, '!', 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(mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
+            win_save_print(&mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
         }
         return TRUE;
     }
@@ -2464,9 +2465,9 @@ cmd_affiliation(gchar **args, struct cmd_help_t help)
             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");
+            iq_room_affiliation_list(mucwin->roomjid, "outcast");
         } else if (g_strcmp0(affiliation, "none") == 0) {
-            win_save_print(mucwin->super, '!', 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(mucwin->roomjid, affiliation);
         }
@@ -2534,7 +2535,7 @@ cmd_role(gchar **args, struct cmd_help_t help)
             iq_room_role_list(mucwin->roomjid, "participant");
             iq_room_role_list(mucwin->roomjid, "visitor");
         } else if (g_strcmp0(role, "none") == 0) {
-            win_save_print(mucwin->super, '!', 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(mucwin->roomjid, role);
         }
@@ -2586,7 +2587,7 @@ cmd_room(gchar **args, struct cmd_help_t help)
     }
 
     ProfMucWin *mucwin = wins_get_current_muc();
-    int num = wins_get_num(mucwin->super);
+    int num = wins_get_num(&mucwin->super);
 
     int ui_index = num;
     if (ui_index == 10) {
@@ -2596,12 +2597,12 @@ cmd_room(gchar **args, struct cmd_help_t help)
     if (g_strcmp0(args[0], "accept") == 0) {
         gboolean requires_config = muc_requires_config(mucwin->roomjid);
         if (!requires_config) {
-            win_save_print(mucwin->super, '!', 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(mucwin->roomjid);
             muc_set_requires_config(mucwin->roomjid, FALSE);
-            win_save_print(mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
+            win_save_print(&mucwin->super, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
             return TRUE;
         }
     }
@@ -2614,11 +2615,11 @@ cmd_room(gchar **args, struct cmd_help_t help)
     if (g_strcmp0(args[0], "config") == 0) {
         GString *win_title = g_string_new(mucwin->roomjid);
         g_string_append(win_title, " config");
-        ProfMucConfWin *confwin = wins_get_muc_conf_win(win_title->str);
+        ProfMucConfWin *confwin = wins_get_muc_conf(win_title->str);
         g_string_free(win_title, TRUE);
 
         if (confwin != NULL) {
-            num = wins_get_num(confwin->super);
+            num = wins_get_num(&confwin->super);
             ui_switch_win(num);
         } else {
             iq_request_room_config_form(mucwin->roomjid);
@@ -2942,6 +2943,7 @@ cmd_alias(gchar **args, struct cmd_help_t help)
     }
 }
 
+// TODO reuse cmd_msg
 gboolean
 cmd_tiny(gchar **args, struct cmd_help_t help)
 {
@@ -2972,7 +2974,7 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                 if (otr_is_secure(chatwin->barejid)) {
                     char *encrypted = otr_encrypt_message(chatwin->barejid, tiny);
                     if (encrypted != NULL) {
-                        message_send(encrypted, chatwin->barejid);
+                        message_send_chat(chatwin->barejid, encrypted);
                         otr_free_message(encrypted);
                         if (prefs_get_boolean(PREF_CHLOG)) {
                             const char *jid = jabber_get_fulljid();
@@ -2987,12 +2989,12 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                             jid_destroy(jidp);
                         }
 
-                        ui_outgoing_msg("me", chatwin->barejid, tiny);
+                        ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
                     } else {
                         cons_show_error("Failed to send message.");
                     }
                 } else {
-                    message_send(tiny, send_recipient->str);
+                    message_send_chat(send_recipient->str, tiny);
                     if (prefs_get_boolean(PREF_CHLOG)) {
                         const char *jid = jabber_get_fulljid();
                         Jid *jidp = jid_create(jid);
@@ -3000,7 +3002,7 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                         jid_destroy(jidp);
                     }
 
-                    ui_outgoing_msg("me", chatwin->barejid, tiny);
+                    ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
                 }
 #else
                 message_send(tiny, send_recipient->str);
@@ -3011,14 +3013,14 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
                     jid_destroy(jidp);
                 }
 
-                ui_outgoing_msg("me", chatwin->barejid, tiny);
+                ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
 #endif
                 g_string_free(send_recipient, TRUE);
 
             } else if (win_type == WIN_PRIVATE) {
                 ProfPrivateWin *privatewin = wins_get_current_private();
-                message_send(tiny, privatewin->fulljid);
-                ui_outgoing_msg("me", privatewin->fulljid, tiny);
+                message_send_private(tiny, privatewin->fulljid);
+                ui_outgoing_private_msg("me", privatewin->fulljid, tiny);
             } else if (win_type == WIN_MUC) {
                 ProfMucWin *mucwin = wins_get_current_muc();
                 message_send_groupchat(tiny, mucwin->roomjid);
@@ -3915,7 +3917,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                     ui_current_print_formatted_line('!', 0, "You have not generated or loaded a private key, use '/otr gen'");
                 } else if (!otr_is_secure(barejid)) {
                     char *otr_query_message = otr_start_query();
-                    message_send(otr_query_message, barejid);
+                    message_send_chat(barejid, otr_query_message);
                 } else {
                     ui_gone_secure(barejid, otr_is_trusted(barejid));
                 }
@@ -3933,7 +3935,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
                 } else {
                     ProfChatWin *chatwin = wins_get_current_chat();
                     char *otr_query_message = otr_start_query();
-                    message_send(otr_query_message, chatwin->barejid);
+                    message_send_chat(chatwin->barejid, otr_query_message);
                 }
             }
         }
diff --git a/src/otr/otr.c b/src/otr/otr.c
index 9661089e..3f51ed18 100644
--- a/src/otr/otr.c
+++ b/src/otr/otr.c
@@ -109,7 +109,7 @@ static void
 cb_inject_message(void *opdata, const char *accountname,
     const char *protocol, const char *recipient, const char *message)
 {
-    message_send(message, recipient);
+    message_send_chat(recipient, message);
 }
 
 static void
diff --git a/src/server_events.c b/src/server_events.c
index bf243c3b..c730d0fa 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -320,7 +320,7 @@ handle_incoming_message(char *barejid, char *message)
                 memmove(whitespace_base, whitespace_base+tag_length, tag_length);
                 char *otr_query_message = otr_start_query();
                 cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
-                message_send(otr_query_message, barejid);
+                message_send_chat(barejid, otr_query_message);
             }
         }
     }
@@ -334,7 +334,7 @@ handle_incoming_message(char *barejid, char *message)
     if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
         char *otr_query_message = otr_start_query();
         cons_show("Attempting to start OTR session...");
-        message_send(otr_query_message, barejid);
+        message_send_chat(barejid, otr_query_message);
     }
 
     ui_incoming_msg(barejid, newmessage, NULL);
@@ -399,27 +399,27 @@ handle_gone(const char * const from)
 }
 
 void
-handle_subscription(const char *from, jabber_subscr_t type)
+handle_subscription(const char *barejid, jabber_subscr_t type)
 {
     switch (type) {
     case PRESENCE_SUBSCRIBE:
         /* TODO: auto-subscribe if needed */
-        cons_show("Received authorization request from %s", from);
-        log_info("Received authorization request from %s", from);
-        ui_print_system_msg_from_recipient(from, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
+        cons_show("Received authorization request from %s", barejid);
+        log_info("Received authorization request from %s", barejid);
+        ui_print_system_msg_from_recipient(barejid, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
         if (prefs_get_boolean(PREF_NOTIFY_SUB)) {
-            notify_subscription(from);
+            notify_subscription(barejid);
         }
         break;
     case PRESENCE_SUBSCRIBED:
-        cons_show("Subscription received from %s", from);
-        log_info("Subscription received from %s", from);
-        ui_print_system_msg_from_recipient(from, "Subscribed");
+        cons_show("Subscription received from %s", barejid);
+        log_info("Subscription received from %s", barejid);
+        ui_print_system_msg_from_recipient(barejid, "Subscribed");
         break;
     case PRESENCE_UNSUBSCRIBED:
-        cons_show("%s deleted subscription", from);
-        log_info("%s deleted subscription", from);
-        ui_print_system_msg_from_recipient(from, "Unsubscribed");
+        cons_show("%s deleted subscription", barejid);
+        log_info("%s deleted subscription", barejid);
+        ui_print_system_msg_from_recipient(barejid, "Unsubscribed");
         break;
     default:
         /* unknown type */
diff --git a/src/ui/console.c b/src/ui/console.c
index fab5a4ac..3a280eb5 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -469,7 +469,7 @@ _cons_show_bookmarks(const GList *list)
                 win_save_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (private)");
             }
             if (muc_active(item->jid)) {
-                ProfWin *roomwin = wins_get_by_recipient(item->jid);
+                ProfWin *roomwin = (ProfWin*)wins_get_muc(item->jid);
                 if (roomwin != NULL) {
                     int num = wins_get_num(roomwin);
                     win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%d)", num);
diff --git a/src/ui/core.c b/src/ui/core.c
index 2373fb77..ef203838 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -570,46 +570,58 @@ _ui_update_presence(const resource_presence_t resource_presence,
 static void
 _ui_handle_recipient_not_found(const char * const recipient, const char * const err_msg)
 {
-    ProfWin *win = wins_get_by_recipient(recipient);
-    GString *msg = g_string_new("");
-
-    // no window for intended recipient, show message in current and console
-    if (win == NULL) {
-        g_string_printf(msg, "Recipient %s not found: %s", recipient, err_msg);
-        cons_show_error(msg->str);
+    // unknown chat recipient
+    ProfChatWin *chatwin = wins_get_chat(recipient);
+    if (chatwin) {
+        cons_show_error("Recipient %s not found: %s", recipient, err_msg);
+        // TODO change super references to superclass cast
+        win_save_vprint(&chatwin->super, '!', NULL, 0, THEME_ERROR, "", "Recipient %s not found: %s", recipient, err_msg);
+        return;
+    }
 
     // intended recipient was invalid chat room
-    } else if (win->type == WIN_MUC) {
-        g_string_printf(msg, "Room %s not found: %s", recipient, err_msg);
-        cons_show_error(msg->str);
-        win_save_print(win, '!', NULL, 0, THEME_ERROR, "", msg->str);
+    ProfMucWin *mucwin = wins_get_muc(recipient);
+    if (mucwin) {
+        cons_show_error("Room %s not found: %s", recipient, err_msg);
+        win_save_vprint(&mucwin->super, '!', NULL, 0, THEME_ERROR, "", "Room %s not found: %s", recipient, err_msg);
+        return;
+    }
 
-    // unknown chat recipient
-    } else {
-        g_string_printf(msg, "Recipient %s not found: %s", recipient, err_msg);
-        cons_show_error(msg->str);
-        win_save_print(win, '!', NULL, 0, THEME_ERROR, "", msg->str);
+    // unknown private recipient
+    ProfPrivateWin *privatewin = wins_get_private(recipient);
+    if (privatewin) {
+        cons_show_error("Recipient %s not found: %s", recipient, err_msg);
+        win_save_vprint(&privatewin->super, '!', NULL, 0, THEME_ERROR, "", "Recipient %s not found: %s", recipient, err_msg);
+        return;
     }
 
-    g_string_free(msg, TRUE);
+    // no window
+    cons_show_error("Recipient %s not found: %s", recipient, err_msg);
 }
 
 static void
 _ui_handle_recipient_error(const char * const recipient, const char * const err_msg)
 {
-    ProfWin *win = wins_get_by_recipient(recipient);
-    GString *msg = g_string_new("");
-    g_string_printf(msg, "Error from %s: %s", recipient, err_msg);
-
     // always show in console
-    cons_show_error(msg->str);
+    cons_show_error("Error from %s: %s", recipient, err_msg);
 
-    // show in window if exists for recipient
-    if (win != NULL)  {
-        win_save_print(win, '!', NULL, 0, THEME_ERROR, "", msg->str);
+    ProfChatWin *chatwin = wins_get_chat(recipient);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+        return;
     }
 
-    g_string_free(msg, TRUE);
+    ProfMucWin *mucwin = wins_get_muc(recipient);
+    if (mucwin) {
+        win_save_vprint((ProfWin*)mucwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+        return;
+    }
+
+    ProfPrivateWin *privatewin = wins_get_private(recipient);
+    if (privatewin) {
+        win_save_vprint((ProfWin*)privatewin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+        return;
+    }
 }
 
 static void
@@ -918,19 +930,20 @@ _ui_next_win(void)
     }
 }
 
+// TODO move OTR UI to new module
 static void
 _ui_gone_secure(const char * const barejid, gboolean trusted)
 {
-    ProfWin *window = wins_get_by_recipient(barejid);
-    if (window == NULL) {
-        window = wins_new_chat(barejid);
-    }
+    ProfWin *window = NULL;
 
-    if (window->type != WIN_CHAT) {
-        return;
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        window = (ProfWin*)chatwin;
+    } else {
+        window = wins_new_chat(barejid);
+        chatwin = (ProfChatWin*)window;
     }
 
-    ProfChatWin *chatwin = (ProfChatWin*)window;
     FREE_SET_NULL(chatwin->resource);
 
     chatwin->is_otr = TRUE;
@@ -959,129 +972,125 @@ _ui_gone_secure(const char * const barejid, gboolean trusted)
 }
 
 static void
-_ui_smp_recipient_initiated(const char * const recipient)
+_ui_gone_insecure(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "%s wants to authenticate your identity, use '/otr secret <secret>'.", recipient);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        chatwin->is_otr = FALSE;
+        chatwin->is_trusted = FALSE;
+
+        ProfWin *window = (ProfWin*)chatwin;
+        win_save_print(window, '!', NULL, 0, THEME_OTR_ENDED, "", "OTR session ended.");
+        if (wins_is_current(window)) {
+            GString *recipient_str = win_get_recipient_string(window);
+            title_bar_set_recipient(recipient_str->str);
+            g_string_free(recipient_str, TRUE);
+        }
     }
 }
 
 static void
-_ui_smp_recipient_initiated_q(const char * const recipient, const char *question)
+_ui_smp_recipient_initiated(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "%s wants to authenticate your identity with the following question:", recipient);
-        win_save_vprint(window, '!', NULL, 0, 0, "", "  %s", question);
-        win_save_print(window, '!', NULL, 0, 0, "", "use '/otr answer <answer>'.");
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity, use '/otr secret <secret>'.", barejid);
     }
 }
 
 static void
-_ui_smp_unsuccessful_sender(const char * const recipient)
+_ui_smp_recipient_initiated_q(const char * const barejid, const char *question)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "Authentication failed, the secret you entered does not match the secret entered by %s.", recipient);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity with the following question:", barejid);
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "  %s", question);
+        win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "use '/otr answer <answer>'.");
     }
 }
 
 static void
-_ui_smp_unsuccessful_receiver(const char * const recipient)
+_ui_smp_unsuccessful_sender(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "Authentication failed, the secret entered by %s does not match yours.", recipient);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret you entered does not match the secret entered by %s.", barejid);
     }
 }
 
 static void
-_ui_smp_aborted(const char * const recipient)
+_ui_smp_unsuccessful_receiver(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_print(window, '!', NULL, 0, 0, "", "SMP session aborted.");
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret entered by %s does not match yours.", barejid);
     }
 }
 
 static void
-_ui_smp_successful(const char * const recipient)
+_ui_smp_aborted(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_print(window, '!', NULL, 0, 0, "", "Authentication successful.");
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "SMP session aborted.");
     }
 }
 
 static void
-_ui_smp_answer_success(const char * const recipient)
+_ui_smp_successful(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "%s successfully authenticated you.", recipient);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication successful.");
     }
 }
 
 static void
-_ui_smp_answer_failure(const char * const recipient)
+_ui_smp_answer_success(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "%s failed to authenticate you.", recipient);
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s successfully authenticated you.", barejid);
     }
 }
 
 static void
-_ui_gone_insecure(const char * const recipient)
+_ui_smp_answer_failure(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window != NULL) {
-        if (window->type != WIN_CHAT) {
-            return;
-        }
-        ProfChatWin *chatwin = (ProfChatWin*)window;
-        chatwin->is_otr = FALSE;
-        chatwin->is_trusted = FALSE;
-        win_save_print(window, '!', NULL, 0, THEME_OTR_ENDED, "", "OTR session ended.");
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s failed to authenticate you.", barejid);
+    }
+}
 
-        if (wins_is_current(window)) {
-            GString *recipient_str = win_get_recipient_string(window);
-            title_bar_set_recipient(recipient_str->str);
-            g_string_free(recipient_str, TRUE);
-        }
+static void
+_ui_otr_authenticating(const char * const barejid)
+{
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authenticating %s...", barejid);
     }
 }
 
 static void
-_ui_trust(const char * const recipient)
+_ui_otr_authetication_waiting(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window != NULL) {
-        if (window->type != WIN_CHAT) {
-            return;
-        }
-        ProfChatWin *chatwin = (ProfChatWin*)window;
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
+        win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Awaiting authentication from %s...", barejid);
+    }
+}
+
+static void
+_ui_trust(const char * const barejid)
+{
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
         chatwin->is_otr = TRUE;
         chatwin->is_trusted = TRUE;
-        win_save_print(window, '!', NULL, 0, THEME_OTR_TRUSTED, "", "OTR session trusted.");
 
+        ProfWin *window = (ProfWin*)chatwin;
+        win_save_print(window, '!', NULL, 0, THEME_OTR_TRUSTED, "", "OTR session trusted.");
         if (wins_is_current(window)) {
             GString *recipient_str = win_get_recipient_string(window);
             title_bar_set_recipient(recipient_str->str);
@@ -1091,18 +1100,15 @@ _ui_trust(const char * const recipient)
 }
 
 static void
-_ui_untrust(const char * const recipient)
+_ui_untrust(const char * const barejid)
 {
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window != NULL) {
-        if (window->type != WIN_CHAT) {
-            return;
-        }
-        ProfChatWin *chatwin = (ProfChatWin*)window;
+    ProfChatWin *chatwin = wins_get_chat(barejid);
+    if (chatwin) {
         chatwin->is_otr = TRUE;
         chatwin->is_trusted = FALSE;
-        win_save_print(window, '!', NULL, 0, THEME_OTR_UNTRUSTED, "", "OTR session untrusted.");
 
+        ProfWin *window = (ProfWin*)chatwin;
+        win_save_print(window, '!', NULL, 0, THEME_OTR_UNTRUSTED, "", "OTR session untrusted.");
         if (wins_is_current(window)) {
             GString *recipient_str = win_get_recipient_string(window);
             title_bar_set_recipient(recipient_str->str);
@@ -1163,35 +1169,40 @@ _ui_prune_wins(void)
     jabber_conn_status_t conn_status = jabber_get_connection_status();
     gboolean pruned = FALSE;
 
-    GSList *recipients = wins_get_prune_recipients();
-    if (recipients != NULL) {
+    GSList *wins = wins_get_prune_wins();
+    if (wins != NULL) {
         pruned = TRUE;
     }
-    GSList *curr = recipients;
-    while (curr != NULL) {
-        char *recipient = curr->data;
 
-        if (conn_status == JABBER_CONNECTED) {
-            if (prefs_get_boolean(PREF_STATES)) {
+    GSList *curr = wins;
+    while (curr != NULL) {
+        ProfWin *window = curr->data;
 
-                // 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);
+        // TODO move to ui_close_win
+        if (window->type == WIN_CHAT) {
+            if (conn_status == JABBER_CONNECTED) {
+                if (prefs_get_boolean(PREF_STATES)) {
+                    ProfChatWin *chatwin = (ProfChatWin*)window;
+
+                    // send <gone/> chat state before closing
+                    if (chat_session_get_recipient_supports(chatwin->barejid)) {
+                        chat_session_set_gone(chatwin->barejid);
+                        message_send_gone(chatwin->barejid);
+                        chat_session_end(chatwin->barejid);
+                    }
                 }
             }
         }
 
-        ProfWin *window = wins_get_by_recipient(recipient);
+        // TODO make one function
         int num = wins_get_num(window);
         ui_close_win(num);
 
         curr = g_slist_next(curr);
     }
 
-    if (recipients != NULL) {
-        g_slist_free(recipients);
+    if (wins != NULL) {
+        g_slist_free(wins);
     }
 
     wins_tidy();
@@ -1238,28 +1249,6 @@ _ui_current_set_otr(gboolean value)
     }
 }
 
-static void
-_ui_otr_authenticating(const char * const recipient)
-{
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "Authenticating %s...", recipient);
-    }
-}
-
-static void
-_ui_otr_authetication_waiting(const char * const recipient)
-{
-    ProfWin *window = wins_get_by_recipient(recipient);
-    if (window == NULL) {
-        return;
-    } else {
-        win_save_vprint(window, '!', NULL, 0, 0, "", "Awaiting authentication from %s...", recipient);
-    }
-}
-
 static int
 _ui_current_win_index(void)
 {
@@ -1312,7 +1301,7 @@ _ui_print_system_msg_from_recipient(const char * const barejid, const char *mess
     if (barejid == NULL || message == NULL)
         return;
 
-    ProfWin *window = wins_get_by_recipient(barejid);
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
     if (window == NULL) {
         int num = 0;
         window = wins_new_chat(barejid);
@@ -1347,42 +1336,52 @@ _ui_recipient_gone(const char * const barejid)
         display_usr = barejid;
     }
 
-    ProfWin *window = wins_get_by_recipient(barejid);
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
     if (window != NULL) {
         win_save_vprint(window, '!', NULL, 0, THEME_GONE, "", "<- %s has left the conversation.", display_usr);
     }
 }
 
 static void
-_ui_new_chat_win(const char * const to)
+_ui_new_private_win(const char * const fulljid)
 {
-    // if the contact is offline, show a message
-    PContact contact = roster_get_contact(to);
-    ProfWin *window = wins_get_by_recipient(to);
+    ProfWin *window = (ProfWin*)wins_get_private(fulljid);
     int num = 0;
 
     // create new window
     if (window == NULL) {
-        Jid *jid = jid_create(to);
+        window = wins_new_private(fulljid);
+        num = wins_get_num(window);
+    } else {
+        num = wins_get_num(window);
+    }
 
-        if (muc_active(jid->barejid)) {
-            window = wins_new_private(to);
-        } else {
-            window = wins_new_chat(to);
-        }
+    ui_switch_win(num);
+}
+
+static void
+_ui_new_chat_win(const char * const barejid)
+{
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
+    int num = 0;
+
+    // create new window
+    if (window == NULL) {
+        window = wins_new_chat(barejid);
 
-        jid_destroy(jid);
         num = wins_get_num(window);
 
         if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
-            _win_show_history(num, to);
+            _win_show_history(num, barejid);
         }
 
+        // if the contact is offline, show a message
+        PContact contact = roster_get_contact(barejid);
         if (contact != NULL) {
             if (strcmp(p_contact_presence(contact), "offline") == 0) {
                 const char * const show = p_contact_presence(contact);
                 const char * const status = p_contact_status(contact);
-                win_show_status_string(window, to, show, status, NULL, "--", "offline");
+                win_show_status_string(window, barejid, show, status, NULL, "--", "offline");
             }
         }
     } else {
@@ -1403,7 +1402,7 @@ _ui_create_xmlconsole_win(void)
 static void
 _ui_open_xmlconsole_win(void)
 {
-    ProfWin *window = wins_get_by_recipient("XML Console");
+    ProfWin *window = wins_get_xmlconsole();
     if (window != NULL) {
         int num = wins_get_num(window);
         ui_switch_win(num);
@@ -1411,41 +1410,33 @@ _ui_open_xmlconsole_win(void)
 }
 
 static void
-_ui_outgoing_msg(const char * const from, const char * const to,
+_ui_outgoing_chat_msg(const char * const from, const char * const barejid,
     const char * const message)
 {
-    PContact contact = roster_get_contact(to);
-    ProfWin *window = wins_get_by_recipient(to);
+    PContact contact = roster_get_contact(barejid);
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
     int num = 0;
 
     // create new window
     if (window == NULL) {
-        Jid *jid = jid_create(to);
-
-        if (muc_active(jid->barejid)) {
-            window = wins_new_private(to);
-        } else {
-            window = wins_new_chat(to);
+        window = wins_new_chat(barejid);
 #ifdef HAVE_LIBOTR
-            if (otr_is_secure(to)) {
-                ProfChatWin *chatwin = (ProfChatWin*)window;
-                chatwin->is_otr = TRUE;
-            }
-#endif
+        if (otr_is_secure(barejid)) {
+            ProfChatWin *chatwin = (ProfChatWin*)window;
+            chatwin->is_otr = TRUE;
         }
-
-        jid_destroy(jid);
+#endif
         num = wins_get_num(window);
 
         if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
-            _win_show_history(num, to);
+            _win_show_history(num, barejid);
         }
 
         if (contact != NULL) {
             if (strcmp(p_contact_presence(contact), "offline") == 0) {
                 const char *show = p_contact_presence(contact);
                 const char *status = p_contact_status(contact);
-                win_show_status_string(window, to, show, status, NULL, "--", "offline");
+                win_show_status_string(window, barejid, show, status, NULL, "--", "offline");
             }
         }
 
@@ -1459,21 +1450,42 @@ _ui_outgoing_msg(const char * const from, const char * const to,
 }
 
 static void
-_ui_room_join(const char * const room, gboolean focus)
+_ui_outgoing_private_msg(const char * const from, const char * const fulljid,
+    const char * const message)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_private(fulljid);
     int num = 0;
 
     // create new window
     if (window == NULL) {
-        window = wins_new_muc(room);
+        window = wins_new_private(fulljid);
+        num = wins_get_num(window);
+
+    // use existing window
+    } else {
+        num = wins_get_num(window);
     }
 
-    char *nick = muc_nick(room);
+    win_save_print(window, '-', NULL, 0, THEME_TEXT_ME, from, message);
+    ui_switch_win(num);
+}
+
+static void
+_ui_room_join(const char * const roomjid, gboolean focus)
+{
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
+    int num = 0;
+
+    // create new window
+    if (window == NULL) {
+        window = wins_new_muc(roomjid);
+    }
+
+    char *nick = muc_nick(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "-> You have joined the room as %s", nick);
     if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
-        char *role = muc_role_str(room);
-        char *affiliation = muc_affiliation_str(room);
+        char *role = muc_role_str(roomjid);
+        char *affiliation = muc_affiliation_str(roomjid);
         if (role) {
             win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", role: %s", role);
         }
@@ -1490,25 +1502,25 @@ _ui_room_join(const char * const room, gboolean focus)
     } else {
         status_bar_active(num);
         ProfWin *console = wins_get_console();
-        char *nick = muc_nick(room);
-        win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "-> Autojoined %s as %s (%d).", room, nick, num);
+        char *nick = muc_nick(roomjid);
+        win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "-> Autojoined %s as %s (%d).", roomjid, nick, num);
     }
 }
 
 static void
-_ui_switch_to_room(const char * const room)
+_ui_switch_to_room(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     int num = wins_get_num(window);
     num = wins_get_num(window);
     ui_switch_win(num);
 }
 
 static void
-_ui_room_role_change(const char * const room, const char * const role, const char * const actor,
+_ui_room_role_change(const char * const roomjid, const char * const role, const char * const actor,
     const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role has been changed to: %s", role);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1520,10 +1532,10 @@ _ui_room_role_change(const char * const room, const char * const role, const cha
 }
 
 static void
-_ui_room_affiliation_change(const char * const room, const char * const affiliation, const char * const actor,
+_ui_room_affiliation_change(const char * const roomjid, const char * const affiliation, const char * const actor,
     const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your affiliation has been changed to: %s", affiliation);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1535,10 +1547,10 @@ _ui_room_affiliation_change(const char * const room, const char * const affiliat
 }
 
 static void
-_ui_room_role_and_affiliation_change(const char * const room, const char * const role, const char * const affiliation,
+_ui_room_role_and_affiliation_change(const char * const roomjid, const char * const role, const char * const affiliation,
     const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role and affiliation have been changed, role: %s, affiliation: %s", role, affiliation);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1551,10 +1563,10 @@ _ui_room_role_and_affiliation_change(const char * const room, const char * const
 
 
 static void
-_ui_room_occupant_role_change(const char * const room, const char * const nick, const char * const role,
+_ui_room_occupant_role_change(const char * const roomjid, const char * const nick, const char * const role,
     const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role has been changed to: %s", nick, role);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1566,10 +1578,10 @@ _ui_room_occupant_role_change(const char * const room, const char * const nick,
 }
 
 static void
-_ui_room_occupant_affiliation_change(const char * const room, const char * const nick, const char * const affiliation,
+_ui_room_occupant_affiliation_change(const char * const roomjid, const char * const nick, const char * const affiliation,
     const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's affiliation has been changed to: %s", nick, affiliation);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1581,10 +1593,10 @@ _ui_room_occupant_affiliation_change(const char * const room, const char * const
 }
 
 static void
-_ui_room_occupant_role_and_affiliation_change(const char * const room, const char * const nick, const char * const role,
+_ui_room_occupant_role_and_affiliation_change(const char * const roomjid, const char * const nick, const char * const role,
     const char * const affiliation, const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role and affiliation have been changed, role: %s, affiliation: %s", nick, role, affiliation);
     if (actor) {
         win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
@@ -1596,9 +1608,9 @@ _ui_room_occupant_role_and_affiliation_change(const char * const room, const cha
 }
 
 static void
-_ui_handle_room_info_error(const char * const room, const char * const error)
+_ui_handle_room_info_error(const char * const roomjid, const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         win_save_vprint(window, '!', NULL, 0, 0, "", "Room info request failed: %s", error);
         win_save_print(window, '-', NULL, 0, 0, "", "");
@@ -1606,9 +1618,9 @@ _ui_handle_room_info_error(const char * const room, const char * const error)
 }
 
 static void
-_ui_show_room_disco_info(const char * const room, GSList *identities, GSList *features)
+_ui_show_room_disco_info(const char * const roomjid, GSList *identities, GSList *features)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         if (((identities != NULL) && (g_slist_length(identities) > 0)) ||
             ((features != NULL) && (g_slist_length(features) > 0))) {
@@ -1647,11 +1659,11 @@ _ui_show_room_disco_info(const char * const room, GSList *identities, GSList *fe
 }
 
 static void
-_ui_room_roster(const char * const room, GList *roster, const char * const presence)
+_ui_room_roster(const char * const roomjid, GList *roster, const char * const presence)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room roster but no window open for %s.", room);
+        log_error("Received room roster but no window open for %s.", roomjid);
     } else {
         if ((roster == NULL) || (g_list_length(roster) == 0)) {
             if (presence == NULL) {
@@ -1687,29 +1699,29 @@ _ui_room_roster(const char * const room, GList *roster, const char * const prese
 }
 
 static void
-_ui_handle_room_join_error(const char * const room, const char * const err)
+_ui_handle_room_join_error(const char * const roomjid, const char * const err)
 {
-    cons_show_error("Error joining room %s, reason: %s", room, err);
+    cons_show_error("Error joining room %s, reason: %s", roomjid, err);
 }
 
 static void
-_ui_room_member_offline(const char * const room, const char * const nick)
+_ui_room_member_offline(const char * const roomjid, const char * const nick)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received offline presence for room participant %s, but no window open for %s.", nick, room);
+        log_error("Received offline presence for room participant %s, but no window open for %s.", nick, roomjid);
     } else {
         win_save_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s has left the room.", nick);
     }
 }
 
 static void
-_ui_room_member_kicked(const char * const room, const char * const nick, const char * const actor,
+_ui_room_member_kicked(const char * const roomjid, const char * const nick, const char * const actor,
     const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received kick for room participant %s, but no window open for %s.", nick, room);
+        log_error("Received kick for room participant %s, but no window open for %s.", nick, roomjid);
     } else {
         GString *message = g_string_new(nick);
         g_string_append(message, " has been kicked from the room");
@@ -1728,12 +1740,12 @@ _ui_room_member_kicked(const char * const room, const char * const nick, const c
 }
 
 static void
-_ui_room_member_banned(const char * const room, const char * const nick, const char * const actor,
+_ui_room_member_banned(const char * const roomjid, const char * const nick, const char * const actor,
     const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received ban for room participant %s, but no window open for %s.", nick, room);
+        log_error("Received ban for room participant %s, but no window open for %s.", nick, roomjid);
     } else {
         GString *message = g_string_new(nick);
         g_string_append(message, " has been banned from the room");
@@ -1752,12 +1764,12 @@ _ui_room_member_banned(const char * const room, const char * const nick, const c
 }
 
 static void
-_ui_room_member_online(const char * const room, const char * const nick, const char * const role,
+_ui_room_member_online(const char * const roomjid, const char * const nick, const char * const role,
     const char * const affiliation, const char * const show, const char * const status)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received online presence for room participant %s, but no window open for %s.", nick, room);
+        log_error("Received online presence for room participant %s, but no window open for %s.", nick, roomjid);
     } else {
         win_save_vprint(window, '!', NULL, NO_EOL, THEME_ONLINE, "", "-> %s has joined the room", nick);
         if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
@@ -1773,47 +1785,47 @@ _ui_room_member_online(const char * const room, const char * const nick, const c
 }
 
 static void
-_ui_room_member_presence(const char * const room, const char * const nick,
+_ui_room_member_presence(const char * const roomjid, const char * const nick,
     const char * const show, const char * const status)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received presence for room participant %s, but no window open for %s.", nick, room);
+        log_error("Received presence for room participant %s, but no window open for %s.", nick, roomjid);
     } else {
         win_show_status_string(window, nick, show, status, NULL, "++", "online");
     }
 }
 
 static void
-_ui_room_member_nick_change(const char * const room,
+_ui_room_member_nick_change(const char * const roomjid,
     const char * const old_nick, const char * const nick)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received nick change for room participant %s, but no window open for %s.", old_nick, room);
+        log_error("Received nick change for room participant %s, but no window open for %s.", old_nick, roomjid);
     } else {
         win_save_vprint(window, '!', NULL, 0, THEME_THEM, "", "** %s is now known as %s", old_nick, nick);
     }
 }
 
 static void
-_ui_room_nick_change(const char * const room, const char * const nick)
+_ui_room_nick_change(const char * const roomjid, const char * const nick)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received self nick change %s, but no window open for %s.", nick, room);
+        log_error("Received self nick change %s, but no window open for %s.", nick, roomjid);
     } else {
         win_save_vprint(window, '!', NULL, 0, THEME_ME, "", "** You are now known as %s", nick);
     }
 }
 
 static void
-_ui_room_history(const char * const room_jid, const char * const nick,
+_ui_room_history(const char * const roomjid, const char * const nick,
     GTimeVal tv_stamp, const char * const message)
 {
-    ProfWin *window = wins_get_by_recipient(room_jid);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Room history message received from %s, but no window open for %s", nick, room_jid);
+        log_error("Room history message received from %s, but no window open for %s", nick, roomjid);
     } else {
         GString *line = g_string_new("");
 
@@ -1834,15 +1846,15 @@ _ui_room_history(const char * const room_jid, const char * const nick,
 }
 
 static void
-_ui_room_message(const char * const room_jid, const char * const nick,
+_ui_room_message(const char * const roomjid, const char * const nick,
     const char * const message)
 {
-    ProfWin *window = wins_get_by_recipient(room_jid);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Room message received from %s, but no window open for %s", nick, room_jid);
+        log_error("Room message received from %s, but no window open for %s", nick, roomjid);
     } else {
         int num = wins_get_num(window);
-        char *my_nick = muc_nick(room_jid);
+        char *my_nick = muc_nick(roomjid);
 
         if (g_strcmp0(nick, my_nick) != 0) {
             if (g_strrstr(message, my_nick) != NULL) {
@@ -1877,7 +1889,7 @@ _ui_room_message(const char * const room_jid, const char * const nick,
             ui_index = 0;
         }
 
-        if (strcmp(nick, muc_nick(room_jid)) != 0) {
+        if (strcmp(nick, muc_nick(roomjid)) != 0) {
             if (prefs_get_boolean(PREF_BEEP)) {
                 beep();
             }
@@ -1901,7 +1913,7 @@ _ui_room_message(const char * const room_jid, const char * const nick,
             if (notify) {
                 gboolean is_current = wins_is_current(window);
                 if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_ROOM_CURRENT)) ) {
-                    Jid *jidp = jid_create(room_jid);
+                    Jid *jidp = jid_create(roomjid);
                     if (prefs_get_boolean(PREF_NOTIFY_ROOM_TEXT)) {
                         notify_room_message(nick, jidp->localpart, ui_index, message);
                     } else {
@@ -1915,11 +1927,11 @@ _ui_room_message(const char * const room_jid, const char * const nick,
 }
 
 static void
-_ui_room_requires_config(const char * const room_jid)
+_ui_room_requires_config(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room_jid);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room config request, but no window open for %s.", room_jid);
+        log_error("Received room config request, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
         int ui_index = num;
@@ -1950,44 +1962,45 @@ _ui_room_requires_config(const char * const room_jid)
 }
 
 static void
-_ui_room_destroy(const char * const room_jid)
+_ui_room_destroy(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room_jid);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room destroy result, but no window open for %s.", room_jid);
+        log_error("Received room destroy result, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
         ui_close_win(num);
-        cons_show("Room destroyed: %s", room_jid);
+        cons_show("Room destroyed: %s", roomjid);
     }
 }
 
 static void
-_ui_leave_room(const char * const room)
+_ui_leave_room(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         int num = wins_get_num(window);
         ui_close_win(num);
     }
 }
 
+// TODO move to muc ui module
 static void
-_ui_room_destroyed(const char * const room, const char * const reason, const char * const new_jid,
+_ui_room_destroyed(const char * const roomjid, const char * const reason, const char * const new_jid,
     const char * const password)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room destroy, but no window open for %s.", room);
+        log_error("Received room destroy, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
         ui_close_win(num);
         ProfWin *console = wins_get_console();
 
         if (reason) {
-            win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s, reason: %s", room, reason);
+            win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s, reason: %s", roomjid, reason);
         } else {
-            win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s", room);
+            win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s", roomjid);
         }
 
         if (new_jid) {
@@ -2001,17 +2014,17 @@ _ui_room_destroyed(const char * const room, const char * const reason, const cha
 }
 
 static void
-_ui_room_kicked(const char * const room, const char * const actor, const char * const reason)
+_ui_room_kicked(const char * const roomjid, const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received kick, but no window open for %s.", room);
+        log_error("Received kick, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
         ui_close_win(num);
 
         GString *message = g_string_new("Kicked from ");
-        g_string_append(message, room);
+        g_string_append(message, roomjid);
         if (actor) {
             g_string_append(message, " by ");
             g_string_append(message, actor);
@@ -2028,17 +2041,17 @@ _ui_room_kicked(const char * const room, const char * const actor, const char *
 }
 
 static void
-_ui_room_banned(const char * const room, const char * const actor, const char * const reason)
+_ui_room_banned(const char * const roomjid, const char * const actor, const char * const reason)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received ban, but no window open for %s.", room);
+        log_error("Received ban, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
         ui_close_win(num);
 
         GString *message = g_string_new("Banned from ");
-        g_string_append(message, room);
+        g_string_append(message, roomjid);
         if (actor) {
             g_string_append(message, " by ");
             g_string_append(message, actor);
@@ -2055,11 +2068,11 @@ _ui_room_banned(const char * const room, const char * const actor, const char *
 }
 
 static void
-_ui_room_subject(const char * const room, const char * const nick, const char * const subject)
+_ui_room_subject(const char * const roomjid, const char * const nick, const char * const subject)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room subject, but no window open for %s.", room);
+        log_error("Received room subject, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
 
@@ -2091,22 +2104,22 @@ _ui_room_subject(const char * const room, const char * const nick, const char *
 }
 
 static void
-_ui_handle_room_kick_error(const char * const room, const char * const nick, const char * const error)
+_ui_handle_room_kick_error(const char * const roomjid, const char * const nick, const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Kick error received for %s, but no window open for %s.", nick, room);
+        log_error("Kick error received for %s, but no window open for %s.", nick, roomjid);
     } else {
         win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error kicking %s: %s", nick, error);
     }
 }
 
 static void
-_ui_room_broadcast(const char * const room_jid, const char * const message)
+_ui_room_broadcast(const char * const roomjid, const char * const message)
 {
-    ProfWin *window = wins_get_by_recipient(room_jid);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window == NULL) {
-        log_error("Received room broadcast, but no window open for %s.", room_jid);
+        log_error("Received room broadcast, but no window open for %s.", roomjid);
     } else {
         int num = wins_get_num(window);
 
@@ -2125,19 +2138,19 @@ _ui_room_broadcast(const char * const room_jid, const char * const message)
 }
 
 static void
-_ui_handle_room_affiliation_list_error(const char * const room, const char * const affiliation,
+_ui_handle_room_affiliation_list_error(const char * const roomjid, const char * const affiliation,
     const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", affiliation, error);
     }
 }
 
 static void
-_ui_handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids)
+_ui_handle_room_affiliation_list(const char * const roomjid, const char * const affiliation, GSList *jids)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         if (jids) {
             win_save_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
@@ -2156,25 +2169,25 @@ _ui_handle_room_affiliation_list(const char * const room, const char * const aff
 }
 
 static void
-_ui_handle_room_role_list_error(const char * const room, const char * const role, const char * const error)
+_ui_handle_room_role_list_error(const char * const roomjid, const char * const role, const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", role, error);
     }
 }
 
 static void
-_ui_handle_room_role_list(const char * const room, const char * const role, GSList *nicks)
+_ui_handle_room_role_list(const char * const roomjid, const char * const role, GSList *nicks)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         if (nicks) {
             win_save_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
             GSList *curr_nick = nicks;
             while (curr_nick) {
                 char *nick = curr_nick->data;
-                Occupant *occupant = muc_roster_item(room, nick);
+                Occupant *occupant = muc_roster_item(roomjid, nick);
                 if (occupant) {
                     if (occupant->jid) {
                         win_save_vprint(window, '!', NULL, 0, 0, "", "  %s (%s)", nick, occupant->jid);
@@ -2195,20 +2208,20 @@ _ui_handle_room_role_list(const char * const room, const char * const role, GSLi
 }
 
 static void
-_ui_handle_room_affiliation_set_error(const char * const room, const char * const jid, const char * const affiliation,
+_ui_handle_room_affiliation_set_error(const char * const roomjid, const char * const jid, const char * const affiliation,
     const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s affiliation for %s: %s", affiliation, jid, error);
     }
 }
 
 static void
-_ui_handle_room_role_set_error(const char * const room, const char * const nick, const char * const role,
+_ui_handle_room_role_set_error(const char * const roomjid, const char * const nick, const char * const role,
     const char * const error)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window) {
         win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s role for %s: %s", role, nick, error);
     }
@@ -2251,7 +2264,7 @@ _ui_chat_win_contact_online(PContact contact, Resource *resource, GDateTime *las
     char *display_str = p_contact_create_display_string(contact, resource->name);
     const char *barejid = p_contact_barejid(contact);
 
-    ProfWin *window = wins_get_by_recipient(barejid);
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
     if (window != NULL) {
         win_show_status_string(window, display_str, show, resource->status,
             last_activity, "++", "online");
@@ -2267,7 +2280,7 @@ _ui_chat_win_contact_offline(PContact contact, char *resource, char *status)
     char *display_str = p_contact_create_display_string(contact, resource);
     const char *barejid = p_contact_barejid(contact);
 
-    ProfWin *window = wins_get_by_recipient(barejid);
+    ProfWin *window = (ProfWin*)wins_get_chat(barejid);
     if (window != NULL) {
         win_show_status_string(window, display_str, "offline", status, NULL, "--",
             "offline");
@@ -2643,14 +2656,14 @@ _ui_handle_room_configuration(const char * const room, DataForm *form)
 }
 
 static void
-_ui_handle_room_configuration_form_error(const char * const room, const char * const message)
+_ui_handle_room_configuration_form_error(const char * const roomjid, const char * const message)
 {
     ProfWin *window = NULL;
     GString *message_str = g_string_new("");
 
-    if (room) {
-        window = wins_get_by_recipient(room);
-        g_string_printf(message_str, "Could not get room configuration for %s", room);
+    if (roomjid) {
+        window = (ProfWin*)wins_get_muc(roomjid);
+        g_string_printf(message_str, "Could not get room configuration for %s", roomjid);
     } else {
         window = wins_get_console();
         g_string_printf(message_str, "Could not get room configuration");
@@ -2667,18 +2680,18 @@ _ui_handle_room_configuration_form_error(const char * const room, const char * c
 }
 
 static void
-_ui_handle_room_config_submit_result(const char * const room)
+_ui_handle_room_config_submit_result(const char * const roomjid)
 {
     ProfWin *muc_window = NULL;
     ProfWin *form_window = NULL;
     int num;
 
-    if (room) {
-        GString *form_recipient = g_string_new(room);
-        g_string_append(form_recipient, " config");
+    if (roomjid) {
+        muc_window = (ProfWin*)wins_get_muc(roomjid);
 
-        muc_window = wins_get_by_recipient(room);
-        form_window = wins_get_by_recipient(form_recipient->str);
+        GString *form_recipient = g_string_new(roomjid);
+        g_string_append(form_recipient, " config");
+        form_window = (ProfWin*) wins_get_muc_conf(form_recipient->str);
         g_string_free(form_recipient, TRUE);
 
         if (form_window) {
@@ -2692,7 +2705,7 @@ _ui_handle_room_config_submit_result(const char * const room)
             win_save_print(muc_window, '!', NULL, 0, THEME_ROOMINFO, "", "Room configuration successful");
         } else {
             ui_switch_win(1);
-            cons_show("Room configuration successful: %s", room);
+            cons_show("Room configuration successful: %s", roomjid);
         }
     } else {
         cons_show("Room configuration successful");
@@ -2700,18 +2713,18 @@ _ui_handle_room_config_submit_result(const char * const room)
 }
 
 static void
-_ui_handle_room_config_submit_result_error(const char * const room, const char * const message)
+_ui_handle_room_config_submit_result_error(const char * const roomjid, const char * const message)
 {
     ProfWin *console = wins_get_console();
     ProfWin *muc_window = NULL;
     ProfWin *form_window = NULL;
 
-    if (room) {
-        GString *form_recipient = g_string_new(room);
-        g_string_append(form_recipient, " config");
+    if (roomjid) {
+        muc_window = (ProfWin*)wins_get_muc(roomjid);
 
-        muc_window = wins_get_by_recipient(room);
-        form_window = wins_get_by_recipient(form_recipient->str);
+        GString *form_recipient = g_string_new(roomjid);
+        g_string_append(form_recipient, " config");
+        form_window = (ProfWin*) wins_get_muc_conf(form_recipient->str);
         g_string_free(form_recipient, TRUE);
 
         if (form_window) {
@@ -2728,9 +2741,9 @@ _ui_handle_room_config_submit_result_error(const char * const room, const char *
             }
         } else {
             if (message) {
-                win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s: %s", room, message);
+                win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s: %s", roomjid, message);
             } else {
-                win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s", room);
+                win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s", roomjid);
             }
         }
     } else {
@@ -2840,19 +2853,19 @@ _ui_show_lines(ProfWin *window, const gchar** lines)
 }
 
 static void
-_ui_room_show_occupants(const char * const room)
+_ui_room_show_occupants(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window && !win_has_active_subwin(window)) {
         wins_show_subwin(window);
-        occupantswin_occupants(room);
+        occupantswin_occupants(roomjid);
     }
 }
 
 static void
-_ui_room_hide_occupants(const char * const room)
+_ui_room_hide_occupants(const char * const roomjid)
 {
-    ProfWin *window = wins_get_by_recipient(room);
+    ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
     if (window && win_has_active_subwin(window)) {
         wins_hide_subwin(window);
     }
@@ -3092,7 +3105,9 @@ ui_init_module(void)
     ui_print_system_msg_from_recipient = _ui_print_system_msg_from_recipient;
     ui_recipient_gone = _ui_recipient_gone;
     ui_new_chat_win = _ui_new_chat_win;
-    ui_outgoing_msg = _ui_outgoing_msg;
+    ui_new_private_win = _ui_new_private_win;
+    ui_outgoing_chat_msg = _ui_outgoing_chat_msg;
+    ui_outgoing_private_msg = _ui_outgoing_private_msg;
     ui_room_join = _ui_room_join;
     ui_room_roster = _ui_room_roster;
     ui_room_member_offline = _ui_room_member_offline;
diff --git a/src/ui/occupantswin.c b/src/ui/occupantswin.c
index e3cfec28..2afc3e26 100644
--- a/src/ui/occupantswin.c
+++ b/src/ui/occupantswin.c
@@ -57,7 +57,7 @@ _occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant)
 static void
 _occupantswin_occupants(const char * const roomjid)
 {
-    ProfMucWin *mucwin = wins_get_muc_win(roomjid);
+    ProfMucWin *mucwin = wins_get_muc(roomjid);
     if (mucwin) {
         GList *occupants = muc_roster(roomjid);
         if (occupants) {
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 5d6352b3..ec8d38c0 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -73,23 +73,28 @@ void (*ui_next_win)(void);
 void (*ui_previous_win)(void);
 
 void (*ui_gone_secure)(const char * const barejid, gboolean trusted);
-void (*ui_gone_insecure)(const char * const recipient);
-void (*ui_trust)(const char * const recipient);
-void (*ui_untrust)(const char * const recipient);
-void (*ui_smp_recipient_initiated)(const char * const recipient);
-void (*ui_smp_recipient_initiated_q)(const char * const recipient, const char *question);
+void (*ui_gone_insecure)(const char * const barejid);
+void (*ui_trust)(const char * const barejid);
+void (*ui_untrust)(const char * const barejid);
+// TODO rename other recipients to barejid etc
+void (*ui_smp_recipient_initiated)(const char * const barejid);
+void (*ui_smp_recipient_initiated_q)(const char * const barejid, const char *question);
 
-void (*ui_smp_successful)(const char * const recipient);
-void (*ui_smp_unsuccessful_sender)(const char * const recipient);
-void (*ui_smp_unsuccessful_receiver)(const char * const recipient);
-void (*ui_smp_aborted)(const char * const recipient);
+void (*ui_smp_successful)(const char * const barejid);
+void (*ui_smp_unsuccessful_sender)(const char * const barejid);
+void (*ui_smp_unsuccessful_receiver)(const char * const barejid);
+void (*ui_smp_aborted)(const char * const barejid);
 
-void (*ui_smp_answer_success)(const char * const recipient);
-void (*ui_smp_answer_failure)(const char * const recipient);
+void (*ui_smp_answer_success)(const char * const barejid);
+void (*ui_smp_answer_failure)(const char * const barejid);
+
+void (*ui_otr_authenticating)(const char * const barejid);
+void (*ui_otr_authetication_waiting)(const char * const recipient);
 
 unsigned long (*ui_get_idle_time)(void);
 void (*ui_reset_idle_time)(void);
-void (*ui_new_chat_win)(const char * const to);
+void (*ui_new_chat_win)(const char * const barejid);
+void (*ui_new_private_win)(const char * const fulljid);
 void (*ui_print_system_msg_from_recipient)(const char * const barejid, const char *message);
 gint (*ui_unread)(void);
 void (*ui_close_connected_win)(int index);
@@ -108,9 +113,6 @@ 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);
 
-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);
 void (*ui_close_win)(int index);
 gboolean (*ui_win_exists)(int index);
@@ -126,56 +128,62 @@ void (*ui_incoming_private_msg)(const char * const fulljid, const char * const m
 
 void (*ui_disconnected)(void);
 void (*ui_recipient_gone)(const char * const barejid);
-void (*ui_outgoing_msg)(const char * const from, const char * const to,
+
+void (*ui_outgoing_chat_msg)(const char * const from, const char * const barejid,
+    const char * const message);
+void (*ui_outgoing_private_msg)(const char * const from, const char * const fulljid,
     const char * const message);
-void (*ui_room_join)(const char * const room, gboolean focus);
-void (*ui_switch_to_room)(const char * const room);
-void (*ui_room_role_change)(const char * const room, const char * const role, const char * const actor,
+
+void (*ui_room_join)(const char * const roomjid, gboolean focus);
+void (*ui_switch_to_room)(const char * const roomjid);
+
+// TODO change all room -> roomjid
+void (*ui_room_role_change)(const char * const roomjid, const char * const role, const char * const actor,
     const char * const reason);
-void (*ui_room_affiliation_change)(const char * const room, const char * const affiliation, const char * const actor,
+void (*ui_room_affiliation_change)(const char * const roomjid, const char * const affiliation, const char * const actor,
     const char * const reason);
-void (*ui_room_role_and_affiliation_change)(const char * const room, const char * const role,
+void (*ui_room_role_and_affiliation_change)(const char * const roomjid, const char * const role,
     const char * const affiliation, const char * const actor, const char * const reason);
-void (*ui_room_occupant_role_change)(const char * const room, const char * const nick, const char * const role,
+void (*ui_room_occupant_role_change)(const char * const roomjid, const char * const nick, const char * const role,
     const char * const actor, const char * const reason);
-void (*ui_room_occupant_affiliation_change)(const char * const room, const char * const nick, const char * const affiliation,
+void (*ui_room_occupant_affiliation_change)(const char * const roomjid, const char * const nick, const char * const affiliation,
     const char * const actor, const char * const reason);
-void (*ui_room_occupant_role_and_affiliation_change)(const char * const room, const char * const nick, const char * const role,
+void (*ui_room_occupant_role_and_affiliation_change)(const char * const roomjid, const char * const nick, const char * const role,
     const char * const affiliation, const char * const actor, const char * const reason);
-void (*ui_room_roster)(const char * const room, GList *occupants, const char * const presence);
-void (*ui_room_history)(const char * const room_jid, const char * const nick,
+void (*ui_room_roster)(const char * const roomjid, GList *occupants, const char * const presence);
+void (*ui_room_history)(const char * const roomjid, const char * const nick,
     GTimeVal tv_stamp, const char * const message);
-void (*ui_room_message)(const char * const room_jid, const char * const nick,
+void (*ui_room_message)(const char * const roomjid, const char * const nick,
     const char * const message);
-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_room_subject)(const char * const roomjid, const char * const nick, const char * const subject);
+void (*ui_room_requires_config)(const char * const roomjid);
+void (*ui_room_destroy)(const char * const roomjid);
 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,
+void (*ui_handle_room_info_error)(const char * const roomjid, const char * const error);
+void (*ui_show_room_disco_info)(const char * const roomjid, GSList *identities, GSList *features);
+void (*ui_room_destroyed)(const char * const roomjid, const char * const reason, const char * const new_jid,
     const char * const password);
-void (*ui_room_kicked)(const char * const room, const char * const actor, const char * const reason);
-void (*ui_room_member_kicked)(const char * const room, const char * const nick, const char * const actor,
+void (*ui_room_kicked)(const char * const roomjid, const char * const actor, const char * const reason);
+void (*ui_room_member_kicked)(const char * const roomjid, const char * const nick, const char * const actor,
     const char * const reason);
-void (*ui_room_banned)(const char * const room, const char * const actor, const char * const reason);
-void (*ui_room_member_banned)(const char * const room, const char * const nick, const char * const actor,
+void (*ui_room_banned)(const char * const roomjid, const char * const actor, const char * const reason);
+void (*ui_room_member_banned)(const char * const roomjid, const char * const nick, const char * const actor,
     const char * const reason);
-void (*ui_leave_room)(const char * const room);
-void (*ui_room_broadcast)(const char * const room_jid,
+void (*ui_leave_room)(const char * const roomjid);
+void (*ui_room_broadcast)(const char * const roomjid,
     const char * const message);
-void (*ui_room_member_offline)(const char * const room, const char * const nick);
-void (*ui_room_member_online)(const char * const room, const char * const nick, const char * const roles,
+void (*ui_room_member_offline)(const char * const roomjid, const char * const nick);
+void (*ui_room_member_online)(const char * const roomjid, const char * const nick, const char * const roles,
     const char * const affiliation, const char * const show, const char * const status);
-void (*ui_room_member_nick_change)(const char * const room,
+void (*ui_room_member_nick_change)(const char * const roomjid,
     const char * const old_nick, const char * const nick);
-void (*ui_room_nick_change)(const char * const room, const char * const nick);
-void (*ui_room_member_presence)(const char * const room,
+void (*ui_room_nick_change)(const char * const roomjid, const char * const nick);
+void (*ui_room_member_presence)(const char * const roomjid,
     const char * const nick, const char * const show, const char * const status);
-void (*ui_room_show_occupants)(const char * const room);
-void (*ui_room_hide_occupants)(const char * const room);
+void (*ui_room_show_occupants)(const char * const roomjid);
+void (*ui_room_hide_occupants)(const char * const roomjid);
 void (*ui_show_roster)(void);
 void (*ui_hide_roster)(void);
 void (*ui_roster_add)(const char * const barejid, const char * const name);
@@ -190,21 +198,21 @@ void (*ui_handle_recipient_not_found)(const char * const recipient, const char *
 void (*ui_handle_recipient_error)(const char * const recipient, const char * const err_msg);
 void (*ui_handle_error)(const char * const err_msg);
 void (*ui_clear_win_title)(void);
-void (*ui_handle_room_join_error)(const char * const room, const char * const err);
+void (*ui_handle_room_join_error)(const char * const roomjid, const char * const err);
 void (*ui_handle_room_configuration)(const char * const room, DataForm *form);
-void (*ui_handle_room_configuration_form_error)(const char * const room, const char * const message);
-void (*ui_handle_room_config_submit_result)(const char * const room);
-void (*ui_handle_room_config_submit_result_error)(const char * const room, const char * const message);
-void (*ui_handle_room_affiliation_list_error)(const char * const room, const char * const affiliation,
+void (*ui_handle_room_configuration_form_error)(const char * const roomjid, const char * const message);
+void (*ui_handle_room_config_submit_result)(const char * const roomjid);
+void (*ui_handle_room_config_submit_result_error)(const char * const roomjid, const char * const message);
+void (*ui_handle_room_affiliation_list_error)(const char * const roomjid, const char * const affiliation,
     const char * const error);
-void (*ui_handle_room_affiliation_list)(const char * const room, const char * const affiliation, GSList *jids);
-void (*ui_handle_room_affiliation_set_error)(const char * const room, const char * const jid,
+void (*ui_handle_room_affiliation_list)(const char * const roomjid, const char * const affiliation, GSList *jids);
+void (*ui_handle_room_affiliation_set_error)(const char * const roomjid, const char * const jid,
     const char * const affiliation, const char * const error);
-void (*ui_handle_room_role_set_error)(const char * const room, const char * const nick, const char * const role,
+void (*ui_handle_room_role_set_error)(const char * const roomjid, const char * const nick, const char * const role,
     const char * const error);
-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_handle_room_role_list_error)(const char * const roomjid, const char * const role, const char * const error);
+void (*ui_handle_room_role_list)(const char * const roomjid, const char * const role, GSList *nicks);
+void (*ui_handle_room_kick_error)(const char * const roomjid, const char * const nick, const char * const error);
 void (*ui_show_form)(ProfMucConfWin *confwin);
 void (*ui_show_form_field)(ProfWin *window, DataForm *form, char *tag);
 void (*ui_show_form_help)(ProfMucConfWin *confwin);
diff --git a/src/ui/window.c b/src/ui/window.c
index 9f96212a..6849da9d 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -141,6 +141,8 @@ win_create_chat(const char * const barejid)
     new_win->is_trusted = FALSE;
     new_win->history_shown = FALSE;
 
+    new_win->memcheck = PROFCHATWIN_MEMCHECK;
+
     return &new_win->super;
 }
 
@@ -177,6 +179,8 @@ win_create_muc(const char * const roomjid)
     new_win->roomjid = strdup(roomjid);
     new_win->super.unread = 0;
 
+    new_win->memcheck = PROFMUCWIN_MEMCHECK;
+
     return &new_win->super;
 }
 
@@ -191,6 +195,8 @@ win_create_muc_config(const char * const title, DataForm *form)
     new_win->from = strdup(title);
     new_win->form = form;
 
+    new_win->memcheck = PROFCONFWIN_MEMCHECK;
+
     return &new_win->super;
 }
 
@@ -204,6 +210,8 @@ win_create_private(const char * const fulljid)
 
     new_win->fulljid = strdup(fulljid);
 
+    new_win->memcheck = PROFPRIVATEWIN_MEMCHECK;
+
     return &new_win->super;
 }
 
diff --git a/src/ui/windows.c b/src/ui/windows.c
index 3bdff9a2..e62fc240 100644
--- a/src/ui/windows.c
+++ b/src/ui/windows.c
@@ -99,7 +99,7 @@ wins_get_chat(const char * const barejid)
 }
 
 ProfMucConfWin *
-wins_get_muc_conf_win(const char * const title)
+wins_get_muc_conf(const char * const title)
 {
     GList *values = g_hash_table_get_values(windows);
     GList *curr = values;
@@ -121,16 +121,18 @@ wins_get_muc_conf_win(const char * const title)
 }
 
 ProfMucWin *
-wins_get_muc_win(const char * const roomjid)
+wins_get_muc(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;
+        if (window->type == WIN_MUC) {
+            ProfMucWin *mucwin = (ProfMucWin*)window;
+            if (g_strcmp0(mucwin->roomjid, roomjid) == 0) {
+                return mucwin;
+            }
         }
         curr = g_list_next(curr);
     }
@@ -372,7 +374,7 @@ wins_get_num(ProfWin *window)
     while (curr != NULL) {
         gconstpointer num_p = curr->data;
         ProfWin *curr_win = g_hash_table_lookup(windows, num_p);
-        if (g_strcmp0(curr_win->from, window->from) == 0) {
+        if (curr_win == window) {
             g_list_free(keys);
             return GPOINTER_TO_INT(num_p);
         }
@@ -426,7 +428,7 @@ wins_is_current(ProfWin *window)
 {
     ProfWin *current_window = wins_get_current();
 
-    if (g_strcmp0(current_window->from, window->from) == 0) {
+    if (current_window == window) {
         return TRUE;
     } else {
         return FALSE;
@@ -438,10 +440,10 @@ wins_new_xmlconsole(void)
 {
     GList *keys = g_hash_table_get_keys(windows);
     int result = get_next_available_win_num(keys);
-    ProfWin *new = win_create_xmlconsole();
-    g_hash_table_insert(windows, GINT_TO_POINTER(result), new);
+    ProfWin *newwin = win_create_xmlconsole();
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
     g_list_free(keys);
-    return new;
+    return newwin;
 }
 
 ProfWin *
@@ -449,10 +451,10 @@ wins_new_chat(const char * const barejid)
 {
     GList *keys = g_hash_table_get_keys(windows);
     int result = get_next_available_win_num(keys);
-    ProfWin *new = win_create_chat(barejid);
-    g_hash_table_insert(windows, GINT_TO_POINTER(result), new);
+    ProfWin *newwin = win_create_chat(barejid);
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
     g_list_free(keys);
-    return new;
+    return newwin;
 }
 
 ProfWin *
@@ -460,10 +462,10 @@ wins_new_muc(const char * const roomjid)
 {
     GList *keys = g_hash_table_get_keys(windows);
     int result = get_next_available_win_num(keys);
-    ProfWin *new = win_create_muc(roomjid);
-    g_hash_table_insert(windows, GINT_TO_POINTER(result), new);
+    ProfWin *newwin = win_create_muc(roomjid);
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
     g_list_free(keys);
-    return new;
+    return newwin;
 }
 
 ProfWin *
@@ -471,10 +473,10 @@ wins_new_muc_config(const char * const title, DataForm *form)
 {
     GList *keys = g_hash_table_get_keys(windows);
     int result = get_next_available_win_num(keys);
-    ProfWin *new = win_create_muc_config(title, form);
-    g_hash_table_insert(windows, GINT_TO_POINTER(result), new);
+    ProfWin *newwin = win_create_muc_config(title, form);
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
     g_list_free(keys);
-    return new;
+    return newwin;
 }
 
 ProfWin *
@@ -482,10 +484,10 @@ wins_new_private(const char * const fulljid)
 {
     GList *keys = g_hash_table_get_keys(windows);
     int result = get_next_available_win_num(keys);
-    ProfWin *new = win_create_private(fulljid);
-    g_hash_table_insert(windows, GINT_TO_POINTER(result), new);
+    ProfWin *newwin = win_create_private(fulljid);
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
     g_list_free(keys);
-    return new;
+    return newwin;
 }
 
 int
@@ -627,7 +629,8 @@ wins_get_chat_recipients(void)
     while (curr != NULL) {
         ProfWin *window = curr->data;
         if (window->type == WIN_CHAT) {
-            result = g_slist_append(result, window->from);
+            ProfChatWin *chatwin = (ProfChatWin*)window;
+            result = g_slist_append(result, chatwin->barejid);
         }
         curr = g_list_next(curr);
     }
@@ -636,7 +639,7 @@ wins_get_chat_recipients(void)
 }
 
 GSList *
-wins_get_prune_recipients(void)
+wins_get_prune_wins(void)
 {
     GSList *result = NULL;
     GList *values = g_hash_table_get_values(windows);
@@ -649,7 +652,7 @@ wins_get_prune_recipients(void)
                 window->type != WIN_MUC_CONFIG &&
                 window->type != WIN_XML &&
                 window->type != WIN_CONSOLE) {
-            result = g_slist_append(result, window->from);
+            result = g_slist_append(result, window);
         }
         curr = g_list_next(curr);
     }
@@ -813,9 +816,10 @@ wins_create_summary(void)
             case WIN_CHAT:
                 chat_string = g_string_new("");
 
-                PContact contact = roster_get_contact(window->from);
+                ProfChatWin *chatwin = (ProfChatWin*)window;
+                PContact contact = roster_get_contact(chatwin->barejid);
                 if (contact == NULL) {
-                    g_string_printf(chat_string, "%d: Chat %s", ui_index, window->from);
+                    g_string_printf(chat_string, "%d: Chat %s", ui_index, chatwin->barejid);
                 } else {
                     const char *display_name = p_contact_name_or_jid(contact);
                     g_string_printf(chat_string, "%d: Chat %s", ui_index, display_name);
@@ -839,7 +843,8 @@ wins_create_summary(void)
 
             case WIN_PRIVATE:
                 priv_string = g_string_new("");
-                g_string_printf(priv_string, "%d: Private %s", ui_index, window->from);
+                ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
+                g_string_printf(priv_string, "%d: Private %s", ui_index, privatewin->fulljid);
 
                 if (window->unread > 0) {
                     GString *priv_unread = g_string_new("");
@@ -855,7 +860,8 @@ wins_create_summary(void)
 
             case WIN_MUC:
                 muc_string = g_string_new("");
-                g_string_printf(muc_string, "%d: Room %s", ui_index, window->from);
+                ProfMucWin *mucwin = (ProfMucWin*)window;
+                g_string_printf(muc_string, "%d: Room %s", ui_index, mucwin->roomjid);
 
                 if (window->unread > 0) {
                     GString *muc_unread = g_string_new("");
@@ -871,7 +877,8 @@ wins_create_summary(void)
 
             case WIN_MUC_CONFIG:
                 muc_config_string = g_string_new("");
-                g_string_printf(muc_config_string, "%d: %s", ui_index, window->from);
+                ProfMucConfWin *confwin = (ProfMucConfWin*)window;
+                g_string_printf(muc_config_string, "%d: %s", ui_index, confwin->from);
                 if (win_has_modified_form(window)) {
                     g_string_append(muc_config_string, " *");
                 }
diff --git a/src/ui/windows.h b/src/ui/windows.h
index 4eb2e50e..2bb2561d 100644
--- a/src/ui/windows.h
+++ b/src/ui/windows.h
@@ -45,8 +45,8 @@ 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);
+ProfMucWin * wins_get_muc(const char * const roomjid);
+ProfMucConfWin * wins_get_muc_conf(const char * const title);
 ProfPrivateWin *wins_get_private(const char * const fulljid);
 
 // TODO remove
@@ -75,7 +75,7 @@ gboolean wins_is_current(ProfWin *window);
 int wins_get_total_unread(void);
 void wins_resize_all(void);
 GSList * wins_get_chat_recipients(void);
-GSList * wins_get_prune_recipients(void);
+GSList * wins_get_prune_wins(void);
 void wins_lost_connection(void);
 gboolean wins_tidy(void);
 GSList * wins_create_summary(void);
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index a2dadb9f..84769213 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -80,14 +80,14 @@ message_add_handlers(void)
 }
 
 static void
-_message_send(const char * const msg, const char * const recipient)
+_message_send_chat(const char * const barejid, const char * const msg)
 {
     const char * jid = NULL;
 
-    if (roster_barejid_from_name(recipient) != NULL) {
-        jid = roster_barejid_from_name(recipient);
+    if (roster_barejid_from_name(barejid) != NULL) {
+        jid = roster_barejid_from_name(barejid);
     } else {
-        jid = recipient;
+        jid = barejid;
     }
 
     if (prefs_get_boolean(PREF_STATES)) {
@@ -113,90 +113,100 @@ _message_send(const char * const msg, const char * const recipient)
 }
 
 static void
-_message_send_groupchat(const char * const msg, const char * const recipient)
+_message_send_private(const char * const fulljid, const char * const msg)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *message = stanza_create_message(ctx, recipient,
-        STANZA_TYPE_GROUPCHAT, msg, NULL);
+    xmpp_stanza_t *message = stanza_create_message(ctx, fulljid, STANZA_TYPE_CHAT, msg, NULL);
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
 }
 
 static void
-_message_send_groupchat_subject(const char * const room, const char * const subject)
+_message_send_groupchat(const char * const roomjid, const char * const msg)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *message = stanza_create_room_subject_message(ctx, room, subject);
+    xmpp_stanza_t *message = stanza_create_message(ctx, roomjid, STANZA_TYPE_GROUPCHAT, msg, NULL);
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
 }
 
 static void
-_message_send_invite(const char * const room, const char * const contact,
+_message_send_groupchat_subject(const char * const roomjid, const char * const subject)
+{
+    xmpp_conn_t * const conn = connection_get_conn();
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    xmpp_stanza_t *message = stanza_create_room_subject_message(ctx, roomjid, subject);
+
+    xmpp_send(conn, message);
+    xmpp_stanza_release(message);
+}
+
+static void
+_message_send_invite(const char * const roomjid, const char * const contact,
     const char * const reason)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_invite(ctx, room, contact, reason);
+    xmpp_stanza_t *stanza = stanza_create_invite(ctx, roomjid, contact, reason);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
 }
 
 static void
-_message_send_composing(const char * const recipient)
+_message_send_composing(const char * const barejid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, recipient,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
         STANZA_NAME_COMPOSING);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
-    chat_session_set_sent(recipient);
+    chat_session_set_sent(barejid);
 }
 
 static void
-_message_send_paused(const char * const recipient)
+_message_send_paused(const char * const barejid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, recipient,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
         STANZA_NAME_PAUSED);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
-    chat_session_set_sent(recipient);
+    chat_session_set_sent(barejid);
 }
 
 static void
-_message_send_inactive(const char * const recipient)
+_message_send_inactive(const char * const barejid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, recipient,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
         STANZA_NAME_INACTIVE);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
-    chat_session_set_sent(recipient);
+    chat_session_set_sent(barejid);
 }
 
 static void
-_message_send_gone(const char * const recipient)
+_message_send_gone(const char * const barejid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
-    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, recipient,
+    xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid,
         STANZA_NAME_GONE);
 
     xmpp_send(conn, stanza);
     xmpp_stanza_release(stanza);
-    chat_session_set_sent(recipient);
+    chat_session_set_sent(barejid);
 }
 
 static int
@@ -505,7 +515,8 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
 void
 message_init_module(void)
 {
-    message_send = _message_send;
+    message_send_chat = _message_send_chat;
+    message_send_private = _message_send_private;
     message_send_groupchat = _message_send_groupchat;
     message_send_invite = _message_send_invite;
     message_send_composing = _message_send_composing;
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index f300e84f..e893747e 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -154,14 +154,16 @@ char* (*jabber_get_account_name)(void);
 GList * (*jabber_get_available_resources)(void);
 
 // message functions
-void (*message_send)(const char * const msg, const char * const recipient);
-void (*message_send_groupchat)(const char * const msg, const char * const recipient);
-void (*message_send_groupchat_subject)(const char * const room, const char * const subject);
-
-void (*message_send_inactive)(const char * const recipient);
-void (*message_send_composing)(const char * const recipient);
-void (*message_send_paused)(const char * const recipient);
-void (*message_send_gone)(const char * const recipient);
+void (*message_send_chat)(const char * const barejid, const char * const msg);
+void (*message_send_private)(const char * const fulljid, const char * const msg);
+void (*message_send_groupchat)(const char * const roomjid, const char * const msg);
+void (*message_send_groupchat_subject)(const char * const roomjid, const char * const subject);
+
+void (*message_send_inactive)(const char * const barejid);
+void (*message_send_composing)(const char * const barejid);
+void (*message_send_paused)(const char * const barejid);
+void (*message_send_gone)(const char * const barejid);
+
 void (*message_send_invite)(const char * const room, const char * const contact,
     const char * const reason);