about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am8
-rw-r--r--src/command/command.c2
-rw-r--r--src/command/commands.c5
-rw-r--r--src/common.c12
-rw-r--r--src/common.h7
-rw-r--r--src/config/preferences.c6
-rw-r--r--src/config/preferences.h5
-rw-r--r--src/config/theme.h5
-rw-r--r--src/event/client_events.c2
-rw-r--r--src/event/ui_events.c4
-rw-r--r--src/muc.c4
-rw-r--r--src/otr/otr.h2
-rw-r--r--src/profanity.c2
-rw-r--r--src/ui/console.c2
-rw-r--r--src/ui/core.c14
-rw-r--r--src/ui/inputwin.c6
-rw-r--r--src/ui/notifier.c2
-rw-r--r--src/ui/occupantswin.c4
-rw-r--r--src/ui/rosterwin.c4
-rw-r--r--src/ui/statusbar.h6
-rw-r--r--src/ui/titlebar.c2
-rw-r--r--src/ui/ui.h137
-rw-r--r--src/ui/window.c71
-rw-r--r--src/ui/window.h133
-rw-r--r--src/window_list.c (renamed from src/ui/windows.c)74
-rw-r--r--src/window_list.h (renamed from src/ui/windows.h)9
-rw-r--r--tests/unittests/ui/stub_ui.c57
-rw-r--r--themes/boothj52
28 files changed, 312 insertions, 275 deletions
diff --git a/Makefile.am b/Makefile.am
index c82bf381..a485b1ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ core_sources = \
 	src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
 	src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
 	src/ui/console.c src/ui/notifier.c \
-	src/ui/windows.c src/ui/windows.h \
+	src/window_list.c src/window_list.h \
 	src/ui/rosterwin.c src/ui/occupantswin.c \
 	src/ui/buffer.c src/ui/buffer.h \
 	src/command/command.h src/command/command.c \
@@ -58,11 +58,7 @@ unittest_sources = \
 	src/config/account.c src/config/account.h \
 	src/config/preferences.c src/config/preferences.h \
 	src/config/theme.c src/config/theme.h \
-	src/ui/windows.c src/ui/windows.h \
-	src/ui/window.c src/ui/window.h \
-	src/ui/buffer.c \
-	src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
-	src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
+	src/window_list.c src/window_list.h \
 	src/event/server_events.c src/event/server_events.h \
 	src/event/client_events.c src/event/client_events.h \
 	src/event/ui_events.c src/event/ui_events.h \
diff --git a/src/command/command.c b/src/command/command.c
index 4599a022..840a23e5 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -66,7 +66,7 @@
 #include "xmpp/xmpp.h"
 #include "xmpp/bookmark.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 
 typedef char*(*autocompleter)(char*, int*);
 
diff --git a/src/command/commands.c b/src/command/commands.c
index 3c8bd118..96cca6e1 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -67,7 +67,7 @@
 #include "xmpp/xmpp.h"
 #include "xmpp/bookmark.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "event/client_events.h"
 #include "event/ui_events.h"
 
@@ -3240,7 +3240,8 @@ cmd_tiny(gchar **args, struct cmd_help_t help)
 gboolean
 cmd_clear(gchar **args, struct cmd_help_t help)
 {
-    ui_clear_current();
+    ProfWin *win = wins_get_current();
+    ui_clear_win(win);
     return TRUE;
 }
 
diff --git a/src/common.c b/src/common.c
index 4fa45608..832e85dd 100644
--- a/src/common.c
+++ b/src/common.c
@@ -253,18 +253,6 @@ utf8_display_len(const char * const str)
     return len;
 }
 
-gboolean
-utf8_is_printable(const wint_t ch)
-{
-    char bytes[MB_CUR_MAX+1];
-    size_t utf_len = wcrtomb(bytes, ch, NULL);
-    bytes[utf_len] = '\0';
-
-    gunichar unichar = g_utf8_get_char(bytes);
-
-    return g_unichar_isprint(unichar) && (ch != KEY_MOUSE);
-}
-
 char *
 prof_getline(FILE *stream)
 {
diff --git a/src/common.h b/src/common.h
index c1aa532d..9da0c974 100644
--- a/src/common.h
+++ b/src/common.h
@@ -38,12 +38,6 @@
 #include <stdio.h>
 #include <wchar.h>
 
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
-
 #include <glib.h>
 
 #if !GLIB_CHECK_VERSION(2,28,0)
@@ -113,7 +107,6 @@ char * str_replace(const char *string, const char *substr,
 int str_contains(const char str[], int size, char ch);
 gboolean strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg);
 int utf8_display_len(const char * const str);
-gboolean utf8_is_printable(const wint_t ch);
 char * prof_getline(FILE *stream);
 char* release_get_latest(void);
 gboolean release_is_new(char *found_version);
diff --git a/src/config/preferences.c b/src/config/preferences.c
index 36250cd8..62e2522b 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -41,12 +41,6 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
-
 #include "common.h"
 #include "log.h"
 #include "preferences.h"
diff --git a/src/config/preferences.h b/src/config/preferences.h
index d1faca63..273ce6bb 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -38,11 +38,6 @@
 #include "config.h"
 
 #include <glib.h>
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
 
 #define PREFS_MIN_LOG_SIZE 64
 #define PREFS_MAX_LOG_SIZE 1048580
diff --git a/src/config/theme.h b/src/config/theme.h
index 13099eb4..2ddbb17b 100644
--- a/src/config/theme.h
+++ b/src/config/theme.h
@@ -38,11 +38,6 @@
 #include "config.h"
 
 #include <glib.h>
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
 
 typedef enum {
     THEME_TEXT,
diff --git a/src/event/client_events.c b/src/event/client_events.c
index 3feeeca1..a1cff93d 100644
--- a/src/event/client_events.c
+++ b/src/event/client_events.c
@@ -37,7 +37,7 @@
 #include "config.h"
 #include "log.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "xmpp/xmpp.h"
 #ifdef HAVE_LIBOTR
 #include "otr/otr.h"
diff --git a/src/event/ui_events.c b/src/event/ui_events.c
index ff1d7273..11296739 100644
--- a/src/event/ui_events.c
+++ b/src/event/ui_events.c
@@ -33,7 +33,7 @@
  */
 
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 
 void
 ui_ev_focus_win(ProfWin *win)
@@ -53,4 +53,4 @@ ProfPrivateWin*
 ui_ev_new_private_win(const char * const fulljid)
 {
     return ui_new_private_win(fulljid);
-}
\ No newline at end of file
+}
diff --git a/src/muc.c b/src/muc.c
index d283b55e..8110f9a5 100644
--- a/src/muc.c
+++ b/src/muc.c
@@ -42,7 +42,7 @@
 #include "jid.h"
 #include "tools/autocomplete.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "muc.h"
 
 typedef struct _muc_room_t {
@@ -978,4 +978,4 @@ _occupant_free(Occupant *occupant)
         free(occupant);
         occupant = NULL;
     }
-}
\ No newline at end of file
+}
diff --git a/src/otr/otr.h b/src/otr/otr.h
index e020c0c8..3c46ac3d 100644
--- a/src/otr/otr.h
+++ b/src/otr/otr.h
@@ -39,7 +39,7 @@
 #include <libotr/message.h>
 
 #include "config/accounts.h"
-#include "ui/window.h"
+#include "ui/ui.h"
 
 typedef enum {
     PROF_OTRPOLICY_MANUAL,
diff --git a/src/profanity.c b/src/profanity.c
index 7aee7a67..6ce31cc3 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -65,7 +65,7 @@
 #include "resource.h"
 #include "xmpp/xmpp.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "event/client_events.h"
 
 static void _check_autoaway(void);
diff --git a/src/ui/console.c b/src/ui/console.c
index cb52619e..118656dd 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -50,7 +50,7 @@
 #include "config/preferences.h"
 #include "config/theme.h"
 #include "ui/window.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "ui/ui.h"
 #include "ui/statusbar.h"
 #include "xmpp/xmpp.h"
diff --git a/src/ui/core.c b/src/ui/core.c
index 3b29c094..127405f6 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -72,7 +72,7 @@
 #include "ui/statusbar.h"
 #include "ui/inputwin.h"
 #include "ui/window.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "xmpp/xmpp.h"
 #include "event/ui_events.h"
 
@@ -1083,12 +1083,6 @@ ui_untrust(const char * const barejid)
 }
 
 void
-ui_clear_current(void)
-{
-    wins_clear_current();
-}
-
-void
 ui_close_win(int index)
 {
     ProfWin *window = wins_get_by_num(index);
@@ -2223,6 +2217,12 @@ ui_clear_win_title(void)
 }
 
 void
+ui_clear_win(ProfWin *window)
+{
+    win_clear(window);
+}
+
+void
 ui_goodbye_title(void)
 {
     int result = system("/bin/echo -ne \"\033]0;Thanks for using Profanity\007\"");
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c
index caea8ea9..57814414 100644
--- a/src/ui/inputwin.c
+++ b/src/ui/inputwin.c
@@ -62,7 +62,8 @@
 #include "ui/ui.h"
 #include "ui/statusbar.h"
 #include "ui/inputwin.h"
-#include "ui/windows.h"
+#include "ui/window.h"
+#include "window_list.h"
 #include "event/ui_events.h"
 #include "xmpp/xmpp.h"
 
@@ -422,7 +423,8 @@ _inp_rl_getc(FILE *stream)
 static int
 _inp_rl_clear_handler(int count, int key)
 {
-    ui_clear_current();
+    ProfWin *win = wins_get_current();
+    win_clear(win);
     return 0;
 }
 
diff --git a/src/ui/notifier.c b/src/ui/notifier.c
index 76290daf..12367190 100644
--- a/src/ui/notifier.c
+++ b/src/ui/notifier.c
@@ -48,7 +48,7 @@
 #include "log.h"
 #include "muc.h"
 #include "ui/ui.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "config/preferences.h"
 
 static void _notify(const char * const message, int timeout, const char * const category);
diff --git a/src/ui/occupantswin.c b/src/ui/occupantswin.c
index bba9d0b9..fe4a600c 100644
--- a/src/ui/occupantswin.c
+++ b/src/ui/occupantswin.c
@@ -36,7 +36,7 @@
 
 #include "ui/ui.h"
 #include "ui/window.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "config/preferences.h"
 
 static void
@@ -124,4 +124,4 @@ occupantswin_occupants(const char * const roomjid)
 
         g_list_free(occupants);
     }
-}
\ No newline at end of file
+}
diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c
index 763490c3..00bc28a4 100644
--- a/src/ui/rosterwin.c
+++ b/src/ui/rosterwin.c
@@ -38,7 +38,7 @@
 #include "contact.h"
 #include "ui/ui.h"
 #include "ui/window.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "config/preferences.h"
 #include "roster_list.h"
 
@@ -192,4 +192,4 @@ rosterwin_roster(void)
         }
         free(by);
     }
-}
\ No newline at end of file
+}
diff --git a/src/ui/statusbar.h b/src/ui/statusbar.h
index 7d2c5ea0..c37f43f3 100644
--- a/src/ui/statusbar.h
+++ b/src/ui/statusbar.h
@@ -42,10 +42,6 @@ void status_bar_clear(void);
 void status_bar_clear_message(void);
 void status_bar_get_password(void);
 void status_bar_print_message(const char * const msg);
-void status_bar_inactive(const int win);
-void status_bar_active(const int win);
-void status_bar_new(const int win);
-void status_bar_set_all_inactive(void);
 void status_bar_current(int i);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ui/titlebar.c b/src/ui/titlebar.c
index 55710c7a..746d2782 100644
--- a/src/ui/titlebar.c
+++ b/src/ui/titlebar.c
@@ -44,7 +44,7 @@
 #include "ui/ui.h"
 #include "ui/titlebar.h"
 #include "ui/inputwin.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "ui/window.h"
 #include "roster_list.h"
 #include "chat_session.h"
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 29ee6bef..434fab24 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -38,7 +38,6 @@
 #include "config.h"
 
 #include <wchar.h>
-
 #include <glib.h>
 #ifdef HAVE_NCURSESW_NCURSES_H
 #include <ncursesw/ncurses.h>
@@ -48,8 +47,109 @@
 
 #include "contact.h"
 #include "jid.h"
-#include "ui/window.h"
 #include "xmpp/xmpp.h"
+#include "ui/buffer.h"
+#include "chat_state.h"
+#include "muc.h"
+
+#define LAYOUT_SPLIT_MEMCHECK       12345671
+#define PROFCHATWIN_MEMCHECK        22374522
+#define PROFMUCWIN_MEMCHECK         52345276
+#define PROFPRIVATEWIN_MEMCHECK     77437483
+#define PROFCONFWIN_MEMCHECK        64334685
+#define PROFXMLWIN_MEMCHECK         87333463
+
+#define NO_ME           1
+#define NO_DATE         2
+#define NO_EOL          4
+#define NO_COLOUR_FROM  8
+#define NO_COLOUR_DATE  16
+
+typedef enum {
+    LAYOUT_SIMPLE,
+    LAYOUT_SPLIT
+} layout_type_t;
+
+typedef struct prof_layout_t {
+    layout_type_t type;
+    WINDOW *win;
+    ProfBuff buffer;
+    int y_pos;
+    int paged;
+} ProfLayout;
+
+typedef struct prof_layout_simple_t {
+    ProfLayout base;
+} ProfLayoutSimple;
+
+typedef struct prof_layout_split_t {
+    ProfLayout base;
+    WINDOW *subwin;
+    int sub_y_pos;
+    unsigned long memcheck;
+} ProfLayoutSplit;
+
+typedef enum {
+    WIN_CONSOLE,
+    WIN_CHAT,
+    WIN_MUC,
+    WIN_MUC_CONFIG,
+    WIN_PRIVATE,
+    WIN_XML
+} win_type_t;
+
+typedef enum {
+    PROF_ENC_NONE,
+    PROF_ENC_OTR
+} prof_enc_t;
+
+typedef struct prof_win_t {
+    win_type_t type;
+    ProfLayout *layout;
+} ProfWin;
+
+typedef struct prof_console_win_t {
+    ProfWin window;
+} ProfConsoleWin;
+
+typedef struct prof_chat_win_t {
+    ProfWin window;
+    char *barejid;
+    int unread;
+    ChatState *state;
+    prof_enc_t enc_mode;
+    gboolean otr_is_trusted;
+    char *resource_override;
+    gboolean history_shown;
+    unsigned long memcheck;
+} ProfChatWin;
+
+typedef struct prof_muc_win_t {
+    ProfWin window;
+    char *roomjid;
+    int unread;
+    gboolean showjid;
+    unsigned long memcheck;
+} ProfMucWin;
+
+typedef struct prof_mucconf_win_t {
+    ProfWin window;
+    char *roomjid;
+    DataForm *form;
+    unsigned long memcheck;
+} ProfMucConfWin;
+
+typedef struct prof_private_win_t {
+    ProfWin window;
+    char *fulljid;
+    int unread;
+    unsigned long memcheck;
+} ProfPrivateWin;
+
+typedef struct prof_xml_win_t {
+    ProfWin window;
+    unsigned long memcheck;
+} ProfXMLWin;
 
 // ui startup and control
 void ui_init(void);
@@ -93,7 +193,6 @@ int ui_close_all_wins(void);
 int ui_close_read_wins(void);
 
 // current window actions
-void ui_clear_current(void);
 win_type_t ui_current_win_type(void);
 gboolean ui_current_win_is_otr(void);
 
@@ -224,6 +323,7 @@ void ui_page_up(void);
 void ui_page_down(void);
 void ui_subwin_page_up(void);
 void ui_subwin_page_down(void);
+void ui_clear_win(ProfWin *window);
 
 void ui_auto_away(void);
 void ui_end_auto_away(void);
@@ -332,12 +432,43 @@ void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *l
 void cons_show_contact_offline(PContact contact, char *resource, char *status);
 void cons_theme_colours(void);
 
+// status bar
+void status_bar_inactive(const int win);
+void status_bar_active(const int win);
+void status_bar_new(const int win);
+void status_bar_set_all_inactive(void);
+
 // roster window
 void rosterwin_roster(void);
 
 // occupants window
 void occupantswin_occupants(const char * const room);
 
+// window interface
+ProfWin* win_create_console(void);
+ProfWin* win_create_xmlconsole(void);
+ProfWin* win_create_chat(const char * const barejid);
+ProfWin* win_create_muc(const char * const roomjid);
+ProfWin* win_create_muc_config(const char * const title, DataForm *form);
+ProfWin* win_create_private(const char * const fulljid);
+
+void win_update_virtual(ProfWin *window);
+void win_free(ProfWin *window);
+int win_unread(ProfWin *window);
+void win_resize(ProfWin *window);
+void win_hide_subwin(ProfWin *window);
+void win_show_subwin(ProfWin *window);
+void win_refresh_without_subwin(ProfWin *window);
+void win_refresh_with_subwin(ProfWin *window);
+void win_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
+void win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
+char* win_get_title(ProfWin *window);
+void win_show_occupant(ProfWin *window, Occupant *occupant);
+void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant);
+void win_show_contact(ProfWin *window, PContact contact);
+void win_show_info(ProfWin *window, PContact contact);
+void win_println(ProfWin *window, const char * const message);
+
 // desktop notifier actions
 void notifier_initialise(void);
 void notifier_uninit(void);
diff --git a/src/ui/window.c b/src/ui/window.c
index 95b5e996..92db25fa 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -459,6 +459,46 @@ win_sub_page_up(ProfWin *window)
 }
 
 void
+win_clear(ProfWin *window)
+{
+    werase(window->layout->win);
+    win_update_virtual(window);
+}
+
+void
+win_resize(ProfWin *window)
+{
+    int subwin_cols = 0;
+    int cols = getmaxx(stdscr);
+
+    if (window->layout->type == LAYOUT_SPLIT) {
+        ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout;
+        if (layout->subwin) {
+            if (window->type == WIN_CONSOLE) {
+                subwin_cols = win_roster_cols();
+            } else if (window->type == WIN_MUC) {
+                subwin_cols = win_occpuants_cols();
+            }
+            wresize(layout->base.win, PAD_SIZE, cols - subwin_cols);
+            wresize(layout->subwin, PAD_SIZE, subwin_cols);
+            if (window->type == WIN_CONSOLE) {
+                rosterwin_roster();
+            } else if (window->type == WIN_MUC) {
+                ProfMucWin *mucwin = (ProfMucWin *)window;
+                assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+                occupantswin_occupants(mucwin->roomjid);
+            }
+        } else {
+            wresize(layout->base.win, PAD_SIZE, cols);
+        }
+    } else {
+        wresize(window->layout->win, PAD_SIZE, cols);
+    }
+
+    win_redraw(window);
+}
+
+void
 win_mouse(ProfWin *window, const wint_t ch, const int result)
 {
     int rows = getmaxy(stdscr);
@@ -531,6 +571,37 @@ win_update_virtual(ProfWin *window)
 }
 
 void
+win_refresh_without_subwin(ProfWin *window)
+{
+    int rows, cols;
+    getmaxyx(stdscr, rows, cols);
+
+    if ((window->type == WIN_MUC) || (window->type == WIN_CONSOLE)) {
+        pnoutrefresh(window->layout->win, window->layout->y_pos, 0, 1, 0, rows-3, cols-1);
+    }
+}
+
+void
+win_refresh_with_subwin(ProfWin *window)
+{
+    int rows, cols;
+    getmaxyx(stdscr, rows, cols);
+    int subwin_cols = 0;
+
+    if (window->type == WIN_MUC) {
+        ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout;
+        subwin_cols = win_occpuants_cols();
+        pnoutrefresh(layout->base.win, layout->base.y_pos, 0, 1, 0, rows-3, (cols-subwin_cols)-1);
+        pnoutrefresh(layout->subwin, layout->sub_y_pos, 0, 1, (cols-subwin_cols), rows-3, cols-1);
+    } else if (window->type == WIN_CONSOLE) {
+        ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout;
+        subwin_cols = win_roster_cols();
+        pnoutrefresh(layout->base.win, layout->base.y_pos, 0, 1, 0, rows-3, (cols-subwin_cols)-1);
+        pnoutrefresh(layout->subwin, layout->sub_y_pos, 0, 1, (cols-subwin_cols), rows-3, cols-1);
+    }
+}
+
+void
 win_move_to_end(ProfWin *window)
 {
     window->layout->paged = 0;
diff --git a/src/ui/window.h b/src/ui/window.h
index 06fbf7b5..4b11ade0 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -39,159 +39,42 @@
 
 #include <wchar.h>
 
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
-
 #include "contact.h"
 #include "muc.h"
+#include "ui/ui.h"
 #include "ui/buffer.h"
 #include "xmpp/xmpp.h"
 #include "chat_state.h"
 
-#define NO_ME           1
-#define NO_DATE         2
-#define NO_EOL          4
-#define NO_COLOUR_FROM  8
-#define NO_COLOUR_DATE  16
+#ifdef HAVE_NCURSESW_NCURSES_H
+#include <ncursesw/ncurses.h>
+#elif HAVE_NCURSES_H
+#include <ncurses.h>
+#endif
 
 #define PAD_SIZE 1000
 
-#define LAYOUT_SPLIT_MEMCHECK       12345671
-#define PROFCHATWIN_MEMCHECK        22374522
-#define PROFMUCWIN_MEMCHECK         52345276
-#define PROFPRIVATEWIN_MEMCHECK     77437483
-#define PROFCONFWIN_MEMCHECK        64334685
-#define PROFXMLWIN_MEMCHECK         87333463
-
-typedef enum {
-    LAYOUT_SIMPLE,
-    LAYOUT_SPLIT
-} layout_type_t;
-
-typedef struct prof_layout_t {
-    layout_type_t type;
-    WINDOW *win;
-    ProfBuff buffer;
-    int y_pos;
-    int paged;
-} ProfLayout;
-
-typedef struct prof_layout_simple_t {
-    ProfLayout base;
-} ProfLayoutSimple;
-
-typedef struct prof_layout_split_t {
-    ProfLayout base;
-    WINDOW *subwin;
-    int sub_y_pos;
-    unsigned long memcheck;
-} ProfLayoutSplit;
-
-typedef enum {
-    WIN_CONSOLE,
-    WIN_CHAT,
-    WIN_MUC,
-    WIN_MUC_CONFIG,
-    WIN_PRIVATE,
-    WIN_XML
-} win_type_t;
-
-typedef enum {
-    PROF_ENC_NONE,
-    PROF_ENC_OTR
-} prof_enc_t;
-
-typedef struct prof_win_t {
-    win_type_t type;
-    ProfLayout *layout;
-} ProfWin;
-
-typedef struct prof_console_win_t {
-    ProfWin window;
-} ProfConsoleWin;
-
-typedef struct prof_chat_win_t {
-    ProfWin window;
-    char *barejid;
-    int unread;
-    ChatState *state;
-    prof_enc_t enc_mode;
-    gboolean otr_is_trusted;
-    char *resource_override;
-    gboolean history_shown;
-    unsigned long memcheck;
-} ProfChatWin;
-
-typedef struct prof_muc_win_t {
-    ProfWin window;
-    char *roomjid;
-    int unread;
-    gboolean showjid;
-    unsigned long memcheck;
-} ProfMucWin;
-
-typedef struct prof_mucconf_win_t {
-    ProfWin window;
-    char *roomjid;
-    DataForm *form;
-    unsigned long memcheck;
-} ProfMucConfWin;
-
-typedef struct prof_private_win_t {
-    ProfWin window;
-    char *fulljid;
-    int unread;
-    unsigned long memcheck;
-} ProfPrivateWin;
-
-typedef struct prof_xml_win_t {
-    ProfWin window;
-    unsigned long memcheck;
-} ProfXMLWin;
-
-ProfWin* win_create_console(void);
-ProfWin* win_create_chat(const char * const barejid);
-ProfWin* win_create_muc(const char * const roomjid);
-ProfWin* win_create_muc_config(const char * const title, DataForm *form);
-ProfWin* win_create_private(const char * const fulljid);
-ProfWin* win_create_xmlconsole(void);
-
-char *win_get_title(ProfWin *window);
-
-void win_free(ProfWin *window);
-void win_update_virtual(ProfWin *window);
 void win_move_to_end(ProfWin *window);
-void win_show_contact(ProfWin *window, PContact contact);
-void win_show_occupant(ProfWin *window, Occupant *occupant);
 void win_show_status_string(ProfWin *window, const char * const from,
     const char * const show, const char * const status,
     GDateTime *last_activity, const char * const pre,
     const char * const default_show);
 void win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
     const char * const from, const char * const message);
-void win_show_info(ProfWin *window, PContact contact);
-void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant);
-void win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
-void win_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
 void win_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags,
     theme_item_t theme_item, const char * const from, const char * const message, char *id);
-void win_println(ProfWin *window, const char * const message);
 void win_newline(ProfWin *window);
 void win_redraw(ProfWin *window);
-void win_hide_subwin(ProfWin *window);
-void win_show_subwin(ProfWin *window);
 int win_roster_cols(void);
 int win_occpuants_cols(void);
 void win_printline_nowrap(WINDOW *win, char *msg);
 void win_mouse(ProfWin *current, const wint_t ch, const int result);
 void win_mark_received(ProfWin *window, const char * const id);
 
-int win_unread(ProfWin *window);
 gboolean win_has_active_subwin(ProfWin *window);
 
+void win_clear(ProfWin *window);
+
 void win_page_up(ProfWin *window);
 void win_page_down(ProfWin *window);
 void win_sub_page_down(ProfWin *window);
diff --git a/src/ui/windows.c b/src/window_list.c
index 2334efc8..ff040d63 100644
--- a/src/ui/windows.c
+++ b/src/window_list.c
@@ -1,5 +1,5 @@
 /*
- * windows.c
+ * window_list.c
  *
  * Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
  *
@@ -40,24 +40,16 @@
 
 #include <glib.h>
 
-#ifdef HAVE_NCURSESW_NCURSES_H
-#include <ncursesw/ncurses.h>
-#elif HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
-
 #include "common.h"
 #include "roster_list.h"
 #include "config/theme.h"
 #include "ui/ui.h"
 #include "ui/statusbar.h"
-#include "ui/window.h"
-#include "ui/windows.h"
+#include "window_list.h"
 #include "event/ui_events.h"
 
 static GHashTable *windows;
 static int current;
-static int max_cols;
 
 void
 wins_init(void)
@@ -65,7 +57,6 @@ wins_init(void)
     windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
         (GDestroyNotify)win_free);
 
-    max_cols = getmaxx(stdscr);
     ProfWin *console = win_create_console();
     g_hash_table_insert(windows, GINT_TO_POINTER(1), console);
 
@@ -386,14 +377,6 @@ wins_close_by_num(int i)
     }
 }
 
-void
-wins_clear_current(void)
-{
-    ProfWin *window = wins_get_current();
-    werase(window->layout->win);
-    win_update_virtual(window);
-}
-
 gboolean
 wins_is_current(ProfWin *window)
 {
@@ -480,39 +463,11 @@ wins_get_total_unread(void)
 void
 wins_resize_all(void)
 {
-    int cols = getmaxx(stdscr);
-
     GList *values = g_hash_table_get_values(windows);
     GList *curr = values;
     while (curr) {
         ProfWin *window = curr->data;
-        int subwin_cols = 0;
-
-        if (window->layout->type == LAYOUT_SPLIT) {
-            ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout;
-            if (layout->subwin) {
-                if (window->type == WIN_CONSOLE) {
-                    subwin_cols = win_roster_cols();
-                } else if (window->type == WIN_MUC) {
-                    subwin_cols = win_occpuants_cols();
-                }
-                wresize(layout->base.win, PAD_SIZE, cols - subwin_cols);
-                wresize(layout->subwin, PAD_SIZE, subwin_cols);
-                if (window->type == WIN_CONSOLE) {
-                    rosterwin_roster();
-                } else if (window->type == WIN_MUC) {
-                    ProfMucWin *mucwin = (ProfMucWin *)window;
-                    assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
-                    occupantswin_occupants(mucwin->roomjid);
-                }
-            } else {
-                wresize(layout->base.win, PAD_SIZE, cols);
-            }
-        } else {
-            wresize(window->layout->win, PAD_SIZE, cols);
-        }
-
-        win_redraw(window);
+        win_resize(window);
         curr = g_list_next(curr);
     }
     g_list_free(values);
@@ -524,38 +479,19 @@ wins_resize_all(void)
 void
 wins_hide_subwin(ProfWin *window)
 {
-    int rows, cols;
-    getmaxyx(stdscr, rows, cols);
-
     win_hide_subwin(window);
 
     ProfWin *current_win = wins_get_current();
-    if ((current_win->type == WIN_MUC) || (current_win->type == WIN_CONSOLE)) {
-        pnoutrefresh(current_win->layout->win, current_win->layout->y_pos, 0, 1, 0, rows-3, cols-1);
-    }
+    win_refresh_without_subwin(current_win);
 }
 
 void
 wins_show_subwin(ProfWin *window)
 {
-    int rows, cols;
-    getmaxyx(stdscr, rows, cols);
-    int subwin_cols = 0;
-
     win_show_subwin(window);
 
     ProfWin *current_win = wins_get_current();
-    if (current_win->type == WIN_MUC) {
-        ProfLayoutSplit *layout = (ProfLayoutSplit*)current_win->layout;
-        subwin_cols = win_occpuants_cols();
-        pnoutrefresh(layout->base.win, layout->base.y_pos, 0, 1, 0, rows-3, (cols-subwin_cols)-1);
-        pnoutrefresh(layout->subwin, layout->sub_y_pos, 0, 1, (cols-subwin_cols), rows-3, cols-1);
-    } else if (current_win->type == WIN_CONSOLE) {
-        ProfLayoutSplit *layout = (ProfLayoutSplit*)current_win->layout;
-        subwin_cols = win_roster_cols();
-        pnoutrefresh(layout->base.win, layout->base.y_pos, 0, 1, 0, rows-3, (cols-subwin_cols)-1);
-        pnoutrefresh(layout->subwin, layout->sub_y_pos, 0, 1, (cols-subwin_cols), rows-3, cols-1);
-    }
+    win_refresh_with_subwin(current_win);
 }
 
 ProfXMLWin *
diff --git a/src/ui/windows.h b/src/window_list.h
index 4cc527ca..8e8e72eb 100644
--- a/src/ui/windows.h
+++ b/src/window_list.h
@@ -1,5 +1,5 @@
 /*
- * windows.h
+ * window_list.h
  *
  * Copyright (C) 2012 - 2015 James Booth <boothj5@gmail.com>
  *
@@ -32,10 +32,10 @@
  *
  */
 
-#ifndef UI_WINDOWS_H
-#define UI_WINDOWS_H
+#ifndef WINDOW_LIST_H
+#define WINDOW_LIST_H
 
-#include "ui/window.h"
+#include "ui/ui.h"
 
 void wins_init(void);
 
@@ -68,7 +68,6 @@ int wins_get_num(ProfWin *window);
 int wins_get_current_num(void);
 void wins_close_current(void);
 void wins_close_by_num(int i);
-void wins_clear_current(void);
 gboolean wins_is_current(ProfWin *window);
 int wins_get_total_unread(void);
 void wins_resize_all(void);
diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c
index 1289aa4b..c94e17fd 100644
--- a/tests/unittests/ui/stub_ui.c
+++ b/tests/unittests/ui/stub_ui.c
@@ -176,6 +176,7 @@ void ui_page_up(void) {}
 void ui_page_down(void) {}
 void ui_subwin_page_up(void) {}
 void ui_subwin_page_down(void) {}
+void ui_clear_win(ProfWin *window) {}
 
 char * ui_ask_password(void)
 {
@@ -493,12 +494,68 @@ void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *l
 void cons_show_contact_offline(PContact contact, char *resource, char *status) {}
 void cons_theme_colours(void) {}
 
+// status bar
+void status_bar_inactive(const int win) {}
+void status_bar_active(const int win) {}
+void status_bar_new(const int win) {}
+void status_bar_set_all_inactive(void) {}
+
 // roster window
 void rosterwin_roster(void) {}
 
 // occupants window
 void occupantswin_occupants(const char * const room) {}
 
+// window interface
+ProfWin* win_create_console(void)
+{
+    return NULL;
+}
+ProfWin* win_create_xmlconsole(void)
+{
+    return NULL;
+}
+ProfWin* win_create_chat(const char * const barejid)
+{
+    return NULL;
+}
+ProfWin* win_create_muc(const char * const roomjid)
+{
+    return NULL;
+}
+ProfWin* win_create_muc_config(const char * const title, DataForm *form)
+{
+    return NULL;
+}
+ProfWin* win_create_private(const char * const fulljid)
+{
+    return NULL;
+}
+
+void win_update_virtual(ProfWin *window) {}
+void win_free(ProfWin *window) {}
+int win_unread(ProfWin *window)
+{
+    return 0;
+}
+
+void win_resize(ProfWin *window) {}
+void win_hide_subwin(ProfWin *window) {}
+void win_show_subwin(ProfWin *window) {}
+void win_refresh_without_subwin(ProfWin *window) {}
+void win_refresh_with_subwin(ProfWin *window) {}
+void win_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message) {}
+void win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...) {}
+char* win_get_title(ProfWin *window)
+{
+    return NULL;
+}
+void win_show_occupant(ProfWin *window, Occupant *occupant) {}
+void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant) {}
+void win_show_contact(ProfWin *window, PContact contact) {}
+void win_show_info(ProfWin *window, PContact contact) {}
+void win_println(ProfWin *window, const char * const message) {}
+
 // desktop notifier actions
 void notifier_uninit(void) {}
 
diff --git a/themes/boothj5 b/themes/boothj5
index 0a710889..3f591fc1 100644
--- a/themes/boothj5
+++ b/themes/boothj5
@@ -17,7 +17,7 @@ statusbar=blue
 statusbar.text=bold_white
 statusbar.brackets=white
 statusbar.active=bold_cyan
-statusbar.new=bold_green
+statusbar.new=bold_white
 main.text=white
 main.text.me=cyan
 main.text.them=bold_white