diff options
author | James Booth <boothj5@gmail.com> | 2013-08-30 00:58:06 +0100 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2013-08-30 00:58:06 +0100 |
commit | 6b1c7da11fce79c666c1aa9e8bb3be6eda132c51 (patch) | |
tree | d2f156322ce2906e318cd02399a6134a9a9f5d7f | |
parent | 76b1d9b7c8359a05b0386f2074b5ef87e4d8c643 (diff) | |
parent | 4ae817cd8292f964ef1c45bfa3b70544ce23043f (diff) | |
download | profani-tty-6b1c7da11fce79c666c1aa9e8bb3be6eda132c51.tar.gz |
Merge branch 'master' into otr
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/command/command.c | 151 | ||||
-rw-r--r-- | src/common.c | 63 | ||||
-rw-r--r-- | src/common.h | 3 | ||||
-rw-r--r-- | src/ui/console.c | 348 | ||||
-rw-r--r-- | src/ui/core.c | 906 | ||||
-rw-r--r-- | src/ui/inputwin.c | 20 | ||||
-rw-r--r-- | src/ui/statusbar.c | 253 | ||||
-rw-r--r-- | src/ui/ui.h | 10 | ||||
-rw-r--r-- | src/ui/window.c | 4 | ||||
-rw-r--r-- | src/ui/window.h | 8 | ||||
-rw-r--r-- | src/ui/windows.c | 475 | ||||
-rw-r--r-- | src/ui/windows.h | 52 | ||||
-rw-r--r-- | tests/test_common.c | 296 |
14 files changed, 1681 insertions, 910 deletions
diff --git a/Makefile.am b/Makefile.am index fade94a3..fae529e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,7 @@ profanity_SOURCES = \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ + src/ui/windows.c src/ui/windows.h \ src/command/command.h src/command/command.c src/command/history.c \ src/command/history.h src/tools/parser.c \ src/tools/parser.h \ @@ -42,6 +43,7 @@ tests_testsuite_SOURCES = \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ + src/ui/windows.c src/ui/windows.h \ src/command/command.h src/command/command.c src/command/history.c \ src/command/history.h src/tools/parser.c \ src/tools/parser.h \ diff --git a/src/command/command.c b/src/command/command.c index 83f0e5b5..586cdb52 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -144,6 +144,7 @@ static gboolean _cmd_tiny(gchar **args, struct cmd_help_t help); static gboolean _cmd_titlebar(gchar **args, struct cmd_help_t help); static gboolean _cmd_vercheck(gchar **args, struct cmd_help_t help); static gboolean _cmd_who(gchar **args, struct cmd_help_t help); +static gboolean _cmd_win(gchar **args, struct cmd_help_t help); static gboolean _cmd_wins(gchar **args, struct cmd_help_t help); static gboolean _cmd_xa(gchar **args, struct cmd_help_t help); @@ -410,6 +411,14 @@ static struct cmd_t command_defs[] = "Example : /nick bob", NULL } } }, + { "/win", + _cmd_win, parse_args, 1, 1, NULL, + { "/win num", "View a window.", + { "/win num", + "------------------", + "Show the contents of a specific window in the main window area.", + NULL } } }, + { "/wins", _cmd_wins, parse_args, 0, 1, NULL, { "/wins [tidy|prune]", "List or tidy active windows.", @@ -1196,8 +1205,6 @@ cmd_execute_default(const char * const inp) break; } - free(recipient); - return TRUE; } @@ -1226,7 +1233,6 @@ _cmd_complete_parameters(char *input, int *size) if (ui_current_win_type() == WIN_MUC) { char *recipient = ui_current_recipient(); Autocomplete nick_ac = muc_get_roster_ac(recipient); - free(recipient); if (nick_ac != NULL) { gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ; @@ -1559,7 +1565,7 @@ _cmd_sub(gchar **args, struct cmd_help_t help) return TRUE; } - char *subcmd, *jid, *bare_jid; + char *subcmd, *jid; subcmd = args[0]; jid = args[1]; @@ -1583,49 +1589,47 @@ _cmd_sub(gchar **args, struct cmd_help_t help) return TRUE; } - if (jid != NULL) { - jid = strdup(jid); - } else { + if (jid == NULL) { jid = ui_current_recipient(); } - bare_jid = strtok(jid, "/"); + Jid *jidp = jid_create(jid); if (strcmp(subcmd, "allow") == 0) { - presence_subscription(bare_jid, PRESENCE_SUBSCRIBED); - cons_show("Accepted subscription for %s", bare_jid); - log_info("Accepted subscription for %s", bare_jid); + presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBED); + cons_show("Accepted subscription for %s", jidp->barejid); + log_info("Accepted subscription for %s", jidp->barejid); } else if (strcmp(subcmd, "deny") == 0) { - presence_subscription(bare_jid, PRESENCE_UNSUBSCRIBED); - cons_show("Deleted/denied subscription for %s", bare_jid); - log_info("Deleted/denied subscription for %s", bare_jid); + presence_subscription(jidp->barejid, PRESENCE_UNSUBSCRIBED); + cons_show("Deleted/denied subscription for %s", jidp->barejid); + log_info("Deleted/denied subscription for %s", jidp->barejid); } else if (strcmp(subcmd, "request") == 0) { - presence_subscription(bare_jid, PRESENCE_SUBSCRIBE); - cons_show("Sent subscription request to %s.", bare_jid); - log_info("Sent subscription request to %s.", bare_jid); + presence_subscription(jidp->barejid, PRESENCE_SUBSCRIBE); + cons_show("Sent subscription request to %s.", jidp->barejid); + log_info("Sent subscription request to %s.", jidp->barejid); } else if (strcmp(subcmd, "show") == 0) { - PContact contact = roster_get_contact(bare_jid); + PContact contact = roster_get_contact(jidp->barejid); if ((contact == NULL) || (p_contact_subscription(contact) == NULL)) { if (win_type == WIN_CHAT) { - ui_current_print_line("No subscription information for %s.", bare_jid); + ui_current_print_line("No subscription information for %s.", jidp->barejid); } else { - cons_show("No subscription information for %s.", bare_jid); + cons_show("No subscription information for %s.", jidp->barejid); } } else { if (win_type == WIN_CHAT) { if (p_contact_pending_out(contact)) { ui_current_print_line("%s subscription status: %s, request pending.", - bare_jid, p_contact_subscription(contact)); + jidp->barejid, p_contact_subscription(contact)); } else { - ui_current_print_line("%s subscription status: %s.", bare_jid, + ui_current_print_line("%s subscription status: %s.", jidp->barejid, p_contact_subscription(contact)); } } else { if (p_contact_pending_out(contact)) { cons_show("%s subscription status: %s, request pending.", - bare_jid, p_contact_subscription(contact)); + jidp->barejid, p_contact_subscription(contact)); } else { - cons_show("%s subscription status: %s.", bare_jid, + cons_show("%s subscription status: %s.", jidp->barejid, p_contact_subscription(contact)); } } @@ -1634,7 +1638,8 @@ _cmd_sub(gchar **args, struct cmd_help_t help) cons_show("Usage: %s", help.usage); } - free(jid); + jid_destroy(jidp); + return TRUE; } @@ -1673,6 +1678,19 @@ _cmd_wins(gchar **args, struct cmd_help_t help) return TRUE; } +static gboolean +_cmd_win(gchar **args, struct cmd_help_t help) +{ + int num = atoi(args[0]); + if (ui_win_exists(num)) { + ui_switch_win(num); + } else { + cons_show("Window %d does not exist.", num); + } + + return TRUE; +} + static gint _compare_commands(Command *a, Command *b) { @@ -1833,7 +1851,7 @@ _cmd_about(gchar **args, struct cmd_help_t help) cons_show(""); cons_about(); if (ui_current_win_type() != WIN_CONSOLE) { - status_bar_new(0); + status_bar_new(1); } return TRUE; } @@ -2016,8 +2034,6 @@ _cmd_who(gchar **args, struct cmd_help_t help) ui_room_roster(room, filtered, presence); } - free(room); - // not in groupchat window } else { cons_show(""); @@ -2137,7 +2153,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) } if (win_type != WIN_CONSOLE && win_type != WIN_MUC) { - status_bar_new(0); + status_bar_new(1); } return TRUE; @@ -2157,11 +2173,6 @@ _cmd_msg(gchar **args, struct cmd_help_t help) return TRUE; } - if (ui_windows_full()) { - cons_show_error("Windows all used, close a window and try again."); - return TRUE; - } - if (win_type == WIN_MUC) { char *room_name = ui_current_recipient(); if (muc_nick_in_roster(room_name, usr)) { @@ -2182,8 +2193,6 @@ _cmd_msg(gchar **args, struct cmd_help_t help) ui_current_print_line("No such participant \"%s\" in room.", usr); } - free(room_name); - return TRUE; } else { @@ -2421,11 +2430,6 @@ _cmd_duck(gchar **args, struct cmd_help_t help) return TRUE; } - if (ui_windows_full()) { - cons_show_error("Windows all used, close a window and try again."); - return TRUE; - } - // if no duck win open, create it and send a help command if (!ui_duck_exists()) { ui_create_duck_win(); @@ -2581,8 +2585,6 @@ _cmd_info(gchar **args, struct cmd_help_t help) break; } - free(recipient); - return TRUE; } @@ -2611,7 +2613,6 @@ _cmd_caps(gchar **args, struct cmd_help_t help) } else { cons_show("No such participant \"%s\" in room.", args[0]); } - free(recipient); } else { cons_show("No nickname supplied to /caps in chat room."); } @@ -2652,7 +2653,6 @@ _cmd_caps(gchar **args, struct cmd_help_t help) cons_show_caps(jid->resourcepart, resource); jid_destroy(jid); } - free(recipient); } break; default: @@ -2689,7 +2689,6 @@ _cmd_software(gchar **args, struct cmd_help_t help) } else { cons_show("No such participant \"%s\" in room.", args[0]); } - free(recipient); } else { cons_show("No nickname supplied to /software in chat room."); } @@ -2715,7 +2714,6 @@ _cmd_software(gchar **args, struct cmd_help_t help) } else { recipient = ui_current_recipient(); iq_send_software_version(recipient); - free(recipient); } break; default: @@ -2735,11 +2733,6 @@ _cmd_join(gchar **args, struct cmd_help_t help) return TRUE; } - if (ui_windows_full()) { - cons_show_error("Windows all used, close a window and try again."); - return TRUE; - } - Jid *room_arg = jid_create(args[0]); if (room_arg == NULL) { cons_show_error("Specified room has incorrect format"); @@ -2887,7 +2880,6 @@ _cmd_bookmark(gchar **args, struct cmd_help_t help) cons_show_bookmarks(bookmark_get_list()); } else { gboolean autojoin = FALSE; - gboolean jid_release = FALSE; gchar *jid = NULL; gchar *nick = NULL; int idx = 1; @@ -2913,7 +2905,6 @@ _cmd_bookmark(gchar **args, struct cmd_help_t help) if (win_type == WIN_MUC) { jid = ui_current_recipient(); - jid_release = TRUE; nick = muc_get_room_nick(jid); } else { cons_show("Usage: %s", help.usage); @@ -2928,10 +2919,6 @@ _cmd_bookmark(gchar **args, struct cmd_help_t help) } else { cons_show("Usage: %s", help.usage); } - - if (jid_release) { - free(jid); - } } return TRUE; @@ -3024,16 +3011,13 @@ _cmd_tiny(gchar **args, struct cmd_help_t help) } ui_outgoing_msg("me", recipient, tiny); - free(recipient); } else if (win_type == WIN_PRIVATE) { char *recipient = ui_current_recipient(); message_send(tiny, recipient); ui_outgoing_msg("me", recipient, tiny); - free(recipient); } else { // groupchat char *recipient = ui_current_recipient(); message_send_groupchat(tiny, recipient); - free(recipient); } free(tiny); } else { @@ -3058,21 +3042,12 @@ _cmd_close(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); int index = 0; - int curr = 0; int count = 0; if (args[0] == NULL) { index = ui_current_win_index(); } else if (strcmp(args[0], "all") == 0) { - for (curr = 1; curr <= 9; curr++) { - if (ui_win_exists(curr)) { - if (conn_status == JABBER_CONNECTED) { - ui_close_connected_win(curr); - } - ui_close_win(curr); - count++; - } - } + count = ui_close_all_wins(); if (count == 0) { cons_show("No windows to close."); } else if (count == 1) { @@ -3082,15 +3057,7 @@ _cmd_close(gchar **args, struct cmd_help_t help) } return TRUE; } else if (strcmp(args[0], "read") == 0) { - for (curr = 1; curr <= 9; curr++) { - if (ui_win_exists(curr) && (ui_win_unread(curr) == 0)) { - if (conn_status == JABBER_CONNECTED) { - ui_close_connected_win(curr); - } - ui_close_win(curr); - count++; - } - } + count = ui_close_read_wins(); if (count == 0) { cons_show("No windows to close."); } else if (count == 1) { @@ -3101,29 +3068,27 @@ _cmd_close(gchar **args, struct cmd_help_t help) return TRUE; } else { index = atoi(args[0]); - if (index == 0) { - index = 9; - } else if (index != 10) { - index--; - } } - if (index == 0) { - cons_show("Cannot close console window."); + if (index < 0 || index == 10) { + cons_show("No such window exists."); return TRUE; } - if (index > 9 || index < 0) { - cons_show("No such window exists."); + if (index == 1) { + cons_show("Cannot close console window."); return TRUE; } + if (index == 0) { + index = 10; + } + if (!ui_win_exists(index)) { cons_show("Window is not open."); return TRUE; } - // handle leaving rooms, or chat if (conn_status == JABBER_CONNECTED) { ui_close_connected_win(index); @@ -3131,11 +3096,7 @@ _cmd_close(gchar **args, struct cmd_help_t help) // close the window ui_close_win(index); - int ui_index = index + 1; - if (ui_index == 10) { - ui_index = 0; - } - cons_show("Closed window %d", ui_index); + cons_show("Closed window %d", index); return TRUE; } diff --git a/src/common.c b/src/common.c index c7ec7d0b..1131c4c9 100644 --- a/src/common.c +++ b/src/common.c @@ -399,6 +399,69 @@ get_unique_id(void) return result; } +int +cmp_win_num(gconstpointer a, gconstpointer b) +{ + int real_a = GPOINTER_TO_INT(a); + int real_b = GPOINTER_TO_INT(b); + + if (real_a == 0) { + real_a = 10; + } + + if (real_b == 0) { + real_b = 10; + } + + if (real_a < real_b) { + return -1; + } else if (real_a == real_b) { + return 0; + } else { + return 1; + } +} + +int +get_next_available_win_num(GList *used) +{ + int result = 0; + used = g_list_sort(used, cmp_win_num); + // only console used + if (g_list_length(used) == 1) { + return 2; + } else { + int last_num = 1; + GList *curr = used; + // skip console + curr = g_list_next(curr); + while (curr != NULL) { + int curr_num = GPOINTER_TO_INT(curr->data); + if (((last_num != 9) && ((last_num + 1) != curr_num)) || + ((last_num == 9) && (curr_num != 0))) { + result = last_num + 1; + if (result == 10) { + result = 0; + } + return (result); + } else { + last_num = curr_num; + if (last_num == 0) { + last_num = 10; + } + } + curr = g_list_next(curr); + } + result = last_num + 1; + if (result == 10) { + result = 0; + } + + return result; + } +} + + static size_t _data_callback(void *ptr, size_t size, size_t nmemb, void *data) { diff --git a/src/common.h b/src/common.h index f2b59413..b1b6834e 100644 --- a/src/common.h +++ b/src/common.h @@ -91,4 +91,7 @@ contact_presence_t contact_presence_from_resource_presence(resource_presence_t r char * get_unique_id(void); +int cmp_win_num(gconstpointer a, gconstpointer b); +int get_next_available_win_num(GList *used); + #endif diff --git a/src/ui/console.c b/src/ui/console.c index 42c4e080..92671a90 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -35,42 +35,34 @@ #include "config/theme.h" #include "ui/notifier.h" #include "ui/window.h" +#include "ui/windows.h" #include "ui/ui.h" #include "xmpp/xmpp.h" #include "xmpp/bookmark.h" -#define CONS_WIN_TITLE "_cons" - -static ProfWin* console; - static void _cons_splash_logo(void); void _show_roster_contacts(GSList *list, gboolean show_groups); -ProfWin * -cons_create(void) -{ - int cols = getmaxx(stdscr); - console = win_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); - return console; -} - void cons_show_time(void) { + ProfWin *console = wins_get_console(); win_print_time(console, '-'); - ui_console_dirty(); + wins_refresh_console(); } void cons_show_word(const char * const word) { + ProfWin *console = wins_get_console(); wprintw(console->win, "%s", word); - ui_console_dirty(); + wins_refresh_console(); } void cons_debug(const char * const msg, ...) { + ProfWin *console = wins_get_console(); if (strcmp(PACKAGE_STATUS, "development") == 0) { va_list arg; va_start(arg, msg); @@ -81,7 +73,7 @@ cons_debug(const char * const msg, ...) g_string_free(fmt_msg, TRUE); va_end(arg); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); ui_current_page_off(); @@ -92,6 +84,7 @@ cons_debug(const char * const msg, ...) void cons_show(const char * const msg, ...) { + ProfWin *console = wins_get_console(); va_list arg; va_start(arg, msg); GString *fmt_msg = g_string_new(NULL); @@ -100,12 +93,13 @@ cons_show(const char * const msg, ...) wprintw(console->win, "%s\n", fmt_msg->str); g_string_free(fmt_msg, TRUE); va_end(arg); - ui_console_dirty(); + wins_refresh_console(); } void cons_show_error(const char * const msg, ...) { + ProfWin *console = wins_get_console(); va_list arg; va_start(arg, msg); GString *fmt_msg = g_string_new(NULL); @@ -117,13 +111,14 @@ cons_show_error(const char * const msg, ...) g_string_free(fmt_msg, TRUE); va_end(arg); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_typing(const char * const barejid) { + ProfWin *console = wins_get_console(); PContact contact = roster_get_contact(barejid); const char * display_usr = NULL; if (p_contact_name(contact) != NULL) { @@ -137,14 +132,16 @@ cons_show_typing(const char * const barejid) wprintw(console->win, "!! %s is typing a message...\n", display_usr); wattroff(console->win, COLOUR_TYPING); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_incoming_message(const char * const short_from, const int win_index) { - int ui_index = win_index + 1; + ProfWin *console = wins_get_console(); + + int ui_index = win_index; if (ui_index == 10) { ui_index = 0; } @@ -153,13 +150,14 @@ cons_show_incoming_message(const char * const short_from, const int win_index) wprintw(console->win, "<< incoming from %s (%d)\n", short_from, ui_index); wattroff(console->win, COLOUR_INCOMING); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_about(void) { + ProfWin *console = wins_get_console(); int rows, cols; getmaxyx(stdscr, rows, cols); @@ -198,13 +196,14 @@ cons_about(void) prefresh(console->win, 0, 0, 1, 0, rows-3, cols-1); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_check_version(gboolean not_available_msg) { + ProfWin *console = wins_get_console(); char *latest_release = release_get_latest(); if (latest_release != NULL) { @@ -226,7 +225,7 @@ cons_check_version(gboolean not_available_msg) } } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } } @@ -235,6 +234,7 @@ cons_check_version(gboolean not_available_msg) void cons_show_login_success(ProfAccount *account) { + ProfWin *console = wins_get_console(); win_print_time(console, '-'); wprintw(console->win, "%s logged in successfully, ", account->jid); @@ -247,91 +247,28 @@ cons_show_login_success(ProfAccount *account) wprintw(console->win, " (priority %d)", accounts_get_priority_for_presence_type(account->name, presence)); wprintw(console->win, ".\n"); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_wins(void) { - int i = 0; - int count = 0; - int ui_index = 0; - + ProfWin *console = wins_get_console(); cons_show(""); cons_show("Active windows:"); - win_print_time(console, '-'); - wprintw(console->win, "1: Console\n"); - - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - count++; - } - } - - if (count != 0) { - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - ProfWin *window = windows[i]; - win_print_time(console, '-'); - ui_index = i + 1; - if (ui_index == 10) { - ui_index = 0; - } - - switch (window->type) - { - case WIN_CHAT: - wprintw(console->win, "%d: Chat %s", ui_index, window->from); - PContact contact = roster_get_contact(window->from); - - if (contact != NULL) { - if (p_contact_name(contact) != NULL) { - wprintw(console->win, " (%s)", p_contact_name(contact)); - } - wprintw(console->win, " - %s", p_contact_presence(contact)); - } - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - case WIN_PRIVATE: - wprintw(console->win, "%d: Private %s", ui_index, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; + GSList *window_strings = wins_create_summary(); - case WIN_MUC: - wprintw(console->win, "%d: Room %s", ui_index, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - case WIN_DUCK: - wprintw(console->win, "%d: DuckDuckGo search", ui_index); - - break; - - default: - break; - } - - wprintw(console->win, "\n"); - } - } + GSList *curr = window_strings; + while (curr != NULL) { + win_print_time(console, '-'); + wprintw(console->win, curr->data); + wprintw(console->win, "\n"); + curr = g_slist_next(curr); } cons_show(""); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -349,13 +286,14 @@ cons_show_room_invites(GSList *invites) } } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_info(PContact pcontact) { + ProfWin *console = wins_get_console(); const char *barejid = p_contact_barejid(pcontact); const char *name = p_contact_name(pcontact); const char *presence = p_contact_presence(pcontact); @@ -481,13 +419,14 @@ cons_show_info(PContact pcontact) ordered_resources = g_list_next(ordered_resources); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_caps(const char * const contact, Resource *resource) { + ProfWin *console = wins_get_console(); WINDOW *win = console->win; cons_show(""); const char *resource_presence = string_from_resource_presence(resource->presence); @@ -555,7 +494,7 @@ cons_show_caps(const char * const contact, Resource *resource) } } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -563,6 +502,7 @@ void cons_show_software_version(const char * const jid, const char * const presence, const char * const name, const char * const version, const char * const os) { + ProfWin *console = wins_get_console(); if ((name != NULL) || (version != NULL) || (os != NULL)) { cons_show(""); win_print_time(console, '-'); @@ -581,7 +521,7 @@ cons_show_software_version(const char * const jid, const char * const presence, cons_show("OS : %s", os); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -600,6 +540,9 @@ cons_show_received_subs(void) } g_slist_free_full(received, g_free); } + + wins_refresh_console(); + cons_alert(); } void @@ -619,11 +562,15 @@ cons_show_sent_subs(void) } else { cons_show("No pending requests sent."); } + + wins_refresh_console(); + cons_alert(); } void cons_show_room_list(GSList *rooms, const char * const conference_node) { + ProfWin *console = wins_get_console(); if ((rooms != NULL) && (g_slist_length(rooms) > 0)) { cons_show("Chat rooms at %s:", conference_node); while (rooms != NULL) { @@ -640,7 +587,7 @@ cons_show_room_list(GSList *rooms, const char * const conference_node) cons_show("No chat rooms at %s", conference_node); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -656,6 +603,8 @@ cons_show_bookmarks(const GList *list) while (list != NULL) { item = list->data; + ProfWin *console = wins_get_console(); + win_print_time(console, '-'); wprintw(console->win, " %s", item->jid); if (item->nick != NULL) { @@ -668,7 +617,7 @@ cons_show_bookmarks(const GList *list) list = g_list_next(list); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -710,7 +659,7 @@ cons_show_disco_info(const char *jid, GSList *identities, GSList *features) features = g_slist_next(features); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } } @@ -718,6 +667,7 @@ cons_show_disco_info(const char *jid, GSList *identities, GSList *features) void cons_show_disco_items(GSList *items, const char * const jid) { + ProfWin *console = wins_get_console(); if ((items != NULL) && (g_slist_length(items) > 0)) { cons_show(""); cons_show("Service discovery items for %s:", jid); @@ -735,13 +685,14 @@ cons_show_disco_items(GSList *items, const char * const jid) cons_show(""); cons_show("No service discovery items for %s", jid); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_status(const char * const barejid) { + ProfWin *console = wins_get_console(); PContact pcontact = roster_get_contact(barejid); if (pcontact != NULL) { @@ -749,7 +700,7 @@ cons_show_status(const char * const barejid) } else { cons_show("No such contact \"%s\" in roster.", barejid); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -786,13 +737,14 @@ cons_show_room_invite(const char * const invitor, const char * const room, free(display_from); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_account_list(gchar **accounts) { + ProfWin *console = wins_get_console(); int size = g_strv_length(accounts); if (size > 0) { cons_show("Accounts:"); @@ -815,13 +767,14 @@ cons_show_account_list(gchar **accounts) cons_show(""); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_account(ProfAccount *account) { + ProfWin *console = wins_get_console(); cons_show(""); cons_show("Account %s:", account->name); if (account->enabled) { @@ -928,7 +881,7 @@ cons_show_account(ProfAccount *account) } } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1021,7 +974,7 @@ cons_show_ui_prefs(void) cons_statuses_setting(); cons_titlebar_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1065,7 +1018,7 @@ cons_show_desktop_prefs(void) cons_show(""); cons_notify_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1129,7 +1082,7 @@ cons_show_chat_prefs(void) cons_gone_setting(); cons_history_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1166,7 +1119,7 @@ cons_show_log_prefs(void) cons_chlog_setting(); cons_grlog_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1202,7 +1155,7 @@ cons_show_presence_prefs(void) cons_show(""); cons_autoaway_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1247,7 +1200,7 @@ cons_show_connection_prefs(void) cons_reconnect_setting(); cons_autoping_setting(); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1266,7 +1219,7 @@ cons_show_themes(GSList *themes) } } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1287,7 +1240,7 @@ cons_prefs(void) cons_show_connection_prefs(); cons_show(""); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1310,7 +1263,7 @@ cons_help(void) cons_show("/help [command] - Detailed help on a specific command."); cons_show(""); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1332,86 +1285,11 @@ cons_navigation_help(void) cons_show("PAGE UP, PAGE DOWN : Page the main window."); cons_show(""); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void -_show_roster_contacts(GSList *list, gboolean show_groups) -{ - GSList *curr = list; - while(curr) { - - PContact contact = curr->data; - GString *title = g_string_new(" "); - title = g_string_append(title, p_contact_barejid(contact)); - if (p_contact_name(contact) != NULL) { - title = g_string_append(title, " ("); - title = g_string_append(title, p_contact_name(contact)); - title = g_string_append(title, ")"); - } - - const char *presence = p_contact_presence(contact); - win_print_time(console, '-'); - if (p_contact_subscribed(contact)) { - win_presence_colour_on(console, presence); - wprintw(console->win, "%s\n", title->str); - win_presence_colour_off(console, presence); - } else { - win_presence_colour_on(console, "offline"); - wprintw(console->win, "%s\n", title->str); - win_presence_colour_off(console, "offline"); - } - - g_string_free(title, TRUE); - - win_print_time(console, '-'); - wprintw(console->win, " Subscription : "); - GString *sub = g_string_new(""); - sub = g_string_append(sub, p_contact_subscription(contact)); - if (p_contact_pending_out(contact)) { - sub = g_string_append(sub, ", request sent"); - } - if (presence_sub_request_exists(p_contact_barejid(contact))) { - sub = g_string_append(sub, ", request received"); - } - if (p_contact_subscribed(contact)) { - wattron(console->win, COLOUR_SUBSCRIBED); - } else { - wattron(console->win, COLOUR_UNSUBSCRIBED); - } - wprintw(console->win, "%s\n", sub->str); - if (p_contact_subscribed(contact)) { - wattroff(console->win, COLOUR_SUBSCRIBED); - } else { - wattroff(console->win, COLOUR_UNSUBSCRIBED); - } - - g_string_free(sub, TRUE); - - if (show_groups) { - GSList *groups = p_contact_groups(contact); - if (groups != NULL) { - GString *groups_str = g_string_new(" Groups : "); - while (groups != NULL) { - g_string_append(groups_str, groups->data); - if (g_slist_next(groups) != NULL) { - g_string_append(groups_str, ", "); - } - groups = g_slist_next(groups); - } - - cons_show(groups_str->str); - g_string_free(groups_str, TRUE); - } - } - - curr = g_slist_next(curr); - } - -} - -void cons_show_roster_group(const char * const group, GSList *list) { cons_show(""); @@ -1423,7 +1301,7 @@ cons_show_roster_group(const char * const group, GSList *list) } _show_roster_contacts(list, FALSE); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1434,13 +1312,14 @@ cons_show_roster(GSList *list) cons_show("Roster:"); _show_roster_contacts(list, TRUE); - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } void cons_show_contacts(GSList *list) { + ProfWin *console = wins_get_console(); GSList *curr = list; while(curr) { @@ -1452,7 +1331,7 @@ cons_show_contacts(GSList *list) curr = g_slist_next(curr); } - ui_console_dirty(); + wins_refresh_console(); cons_alert(); } @@ -1460,13 +1339,14 @@ void cons_alert(void) { if (ui_current_win_type() != WIN_CONSOLE) { - status_bar_new(0); + status_bar_new(1); } } static void _cons_splash_logo(void) { + ProfWin *console = wins_get_console(); win_print_time(console, '-'); wprintw(console->win, "Welcome to\n"); @@ -1514,3 +1394,79 @@ _cons_splash_logo(void) wprintw(console->win, "Version %s\n", PACKAGE_VERSION); } } + +void +_show_roster_contacts(GSList *list, gboolean show_groups) +{ + ProfWin *console = wins_get_console(); + GSList *curr = list; + while(curr) { + + PContact contact = curr->data; + GString *title = g_string_new(" "); + title = g_string_append(title, p_contact_barejid(contact)); + if (p_contact_name(contact) != NULL) { + title = g_string_append(title, " ("); + title = g_string_append(title, p_contact_name(contact)); + title = g_string_append(title, ")"); + } + + const char *presence = p_contact_presence(contact); + win_print_time(console, '-'); + if (p_contact_subscribed(contact)) { + win_presence_colour_on(console, presence); + wprintw(console->win, "%s\n", title->str); + win_presence_colour_off(console, presence); + } else { + win_presence_colour_on(console, "offline"); + wprintw(console->win, "%s\n", title->str); + win_presence_colour_off(console, "offline"); + } + + g_string_free(title, TRUE); + + win_print_time(console, '-'); + wprintw(console->win, " Subscription : "); + GString *sub = g_string_new(""); + sub = g_string_append(sub, p_contact_subscription(contact)); + if (p_contact_pending_out(contact)) { + sub = g_string_append(sub, ", request sent"); + } + if (presence_sub_request_exists(p_contact_barejid(contact))) { + sub = g_string_append(sub, ", request received"); + } + if (p_contact_subscribed(contact)) { + wattron(console->win, COLOUR_SUBSCRIBED); + } else { + wattron(console->win, COLOUR_UNSUBSCRIBED); + } + wprintw(console->win, "%s\n", sub->str); + if (p_contact_subscribed(contact)) { + wattroff(console->win, COLOUR_SUBSCRIBED); + } else { + wattroff(console->win, COLOUR_UNSUBSCRIBED); + } + + g_string_free(sub, TRUE); + + if (show_groups) { + GSList *groups = p_contact_groups(contact); + if (groups != NULL) { + GString *groups_str = g_string_new(" Groups : "); + while (groups != NULL) { + g_string_append(groups_str, groups->data); + if (g_slist_next(groups) != NULL) { + g_string_append(groups_str, ", "); + } + groups = g_slist_next(groups); + } + + cons_show(groups_str->str); + g_string_free(groups_str, TRUE); + } + } + + curr = g_slist_next(curr); + } + +} diff --git a/src/ui/core.c b/src/ui/core.c index e73c0a67..2229d37c 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -46,19 +46,9 @@ #include "ui/notifier.h" #include "ui/ui.h" #include "ui/window.h" +#include "ui/windows.h" #include "xmpp/xmpp.h" -// the window currently being displayed -static int current_index = 0; -static ProfWin *current; -static ProfWin *console; - -// current window state -static gboolean current_win_dirty; - -// max columns for main windows, never resize below -static int max_cols = 0; - static char *win_title; #ifdef HAVE_LIBXSS @@ -67,10 +57,6 @@ static Display *display; static GTimer *ui_idle_time; -static void _set_current(int index); -static int _find_prof_win_index(const char * const contact); -static int _new_prof_win(const char * const contact, win_type_t type); -static void _current_window_refresh(void); static void _win_show_user(WINDOW *win, const char * const user, const int colour); static void _win_show_message(WINDOW *win, const char * const message); static void _win_show_error_msg(WINDOW *win, const char * const message); @@ -80,11 +66,9 @@ static void _show_status_string(ProfWin *window, const char * const from, const char * const default_show); static void _win_handle_switch(const wint_t * const ch); static void _win_handle_page(const wint_t * const ch); -static void _win_resize_all(void); static void _win_show_history(WINDOW *win, int win_index, const char * const contact); static void _ui_draw_win_title(void); -gboolean _tidy(void); void ui_init(void) @@ -101,45 +85,27 @@ ui_init(void) refresh(); create_title_bar(); create_status_bar(); - status_bar_active(0); + status_bar_active(1); create_input_window(); - max_cols = getmaxx(stdscr); - windows[0] = cons_create(); - console = windows[0]; - current = console; + wins_init(); cons_about(); notifier_init(); #ifdef HAVE_LIBXSS display = XOpenDisplay(0); #endif ui_idle_time = g_timer_new(); - current_win_dirty = TRUE; + wins_refresh_current(); } void ui_refresh(void) { _ui_draw_win_title(); - title_bar_refresh(); status_bar_refresh(); - - if (current_win_dirty) { - _current_window_refresh(); - current_win_dirty = FALSE; - } - inp_put_back(); } -void -ui_console_dirty(void) -{ - if (ui_current_win_type() == WIN_CONSOLE) { - current_win_dirty = TRUE; - } -} - unsigned long ui_get_idle_time(void) { @@ -169,6 +135,7 @@ void ui_close(void) { notifier_uninit(); + wins_destroy(); endwin(); } @@ -178,9 +145,9 @@ ui_resize(const int ch, const char * const input, const int size) log_info("Resizing UI"); title_bar_resize(); status_bar_resize(); - _win_resize_all(); + wins_resize_all(); inp_win_resize(input, size); - current_win_dirty = TRUE; + wins_refresh_current(); } void @@ -194,59 +161,41 @@ ui_load_colours(void) } gboolean -ui_windows_full(void) +ui_win_exists(int index) { - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] == NULL) { - return FALSE; - } - } - - return TRUE; -} - -gboolean ui_win_exists(int index) -{ - return (windows[index] != NULL); + ProfWin *window = wins_get_by_num(index); + return (window != NULL); } gboolean ui_duck_exists(void) { - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - if (windows[i]->type == WIN_DUCK) - return TRUE; - } - } - - return FALSE; + return wins_duck_exists(); } void ui_contact_typing(const char * const barejid) { - int win_index = _find_prof_win_index(barejid); + ProfWin *window = wins_get_by_recipient(barejid); if (prefs_get_boolean(PREF_INTYPE)) { // no chat window for user - if (win_index == NUM_WINS) { + if (window == NULL) { cons_show_typing(barejid); // have chat window but not currently in it - } else if (win_index != current_index) { + } else if (!wins_is_current(window)) { cons_show_typing(barejid); - current_win_dirty = TRUE; + wins_refresh_current(); // in chat window with user } else { title_bar_set_typing(TRUE); title_bar_draw(); - status_bar_active(win_index); - current_win_dirty = TRUE; + int num = wins_get_num(window); + status_bar_active(num); + wins_refresh_current(); } } @@ -265,26 +214,29 @@ ui_contact_typing(const char * const barejid) void ui_idle(void) { - int i; + GSList *recipients = wins_get_chat_recipients(); + GSList *curr = recipients; + while (curr != NULL) { + char *recipient = curr->data; + chat_session_no_activity(recipient); + + if (chat_session_is_gone(recipient) && + !chat_session_get_sent(recipient)) { + message_send_gone(recipient); + } else if (chat_session_is_inactive(recipient) && + !chat_session_get_sent(recipient)) { + message_send_inactive(recipient); + } else if (prefs_get_boolean(PREF_OUTTYPE) && + chat_session_is_paused(recipient) && + !chat_session_get_sent(recipient)) { + message_send_paused(recipient); + } - // loop through regular chat windows and update states - for (i = 1; i < NUM_WINS; i++) { - if ((windows[i] != NULL) && (windows[i]->type == WIN_CHAT)) { - char *recipient = windows[i]->from; - chat_session_no_activity(recipient); + curr = g_slist_next(curr); + } - if (chat_session_is_gone(recipient) && - !chat_session_get_sent(recipient)) { - message_send_gone(recipient); - } else if (chat_session_is_inactive(recipient) && - !chat_session_get_sent(recipient)) { - message_send_inactive(recipient); - } else if (prefs_get_boolean(PREF_OUTTYPE) && - chat_session_is_paused(recipient) && - !chat_session_get_sent(recipient)) { - message_send_paused(recipient); - } - } + if (recipients != NULL) { + g_slist_free(recipients); } } @@ -313,123 +265,87 @@ ui_incoming_msg(const char * const from, const char * const message, } } - int win_index = _find_prof_win_index(from); - if (win_index == NUM_WINS) { - win_index = _new_prof_win(from, win_type); + ProfWin *window = wins_get_by_recipient(from); + if (window == NULL) { + window = wins_new(from, win_type); win_created = TRUE; } - // no spare windows left - if (win_index == 0) { + int num = wins_get_num(window); + + // currently viewing chat window with sender + if (wins_is_current(window)) { if (tv_stamp == NULL) { - win_print_time(console, '-'); + win_print_time(window, '-'); } else { GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(console->win, COLOUR_TIME); - wprintw(console->win, "%s - ", date_fmt); - wattroff(console->win, COLOUR_TIME); + wattron(window->win, COLOUR_TIME); + wprintw(window->win, "%s - ", date_fmt); + wattroff(window->win, COLOUR_TIME); g_date_time_unref(time); g_free(date_fmt); } if (strncmp(message, "/me ", 4) == 0) { - wattron(console->win, COLOUR_THEM); - wprintw(console->win, "*%s ", display_from); - waddstr(console->win, message + 4); - wprintw(console->win, "\n"); - wattroff(console->win, COLOUR_THEM); - } else { - _win_show_user(console->win, display_from, 1); - _win_show_message(console->win, message); - } - - cons_show("Windows all used, close a window to respond."); - - if (current_index == 0) { - current_win_dirty = TRUE; + wattron(window->win, COLOUR_THEM); + wprintw(window->win, "*%s ", display_from); + waddstr(window->win, message + 4); + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_THEM); } else { - status_bar_new(0); + _win_show_user(window->win, display_from, 1); + _win_show_message(window->win, message); } + title_bar_set_typing(FALSE); + title_bar_draw(); + status_bar_active(num); + wins_refresh_current(); - // window found or created + // not currently viewing chat window with sender } else { - ProfWin *window = windows[win_index]; + status_bar_new(num); + cons_show_incoming_message(display_from, num); + if (prefs_get_boolean(PREF_FLASH)) + flash(); - // currently viewing chat window with sender - if (win_index == current_index) { - if (tv_stamp == NULL) { - win_print_time(window, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(window->win, COLOUR_TIME); - wprintw(window->win, "%s - ", date_fmt); - wattroff(window->win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(window->win, COLOUR_THEM); - wprintw(window->win, "*%s ", display_from); - waddstr(window->win, message + 4); - wprintw(window->win, "\n"); - wattroff(window->win, COLOUR_THEM); - } else { - _win_show_user(window->win, display_from, 1); - _win_show_message(window->win, message); - } - title_bar_set_typing(FALSE); - title_bar_draw(); - status_bar_active(win_index); - current_win_dirty = TRUE; + window->unread++; + if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { + _win_show_history(window->win, num, from); + } - // not currently viewing chat window with sender + if (tv_stamp == NULL) { + win_print_time(window, '-'); } else { - status_bar_new(win_index); - cons_show_incoming_message(display_from, win_index); - if (prefs_get_boolean(PREF_FLASH)) - flash(); - - windows[win_index]->unread++; - if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _win_show_history(window->win, win_index, from); - } - - if (tv_stamp == NULL) { - win_print_time(window, '-'); - } else { - // show users status first, when receiving message via delayed delivery - if (win_created) { - PContact pcontact = roster_get_contact(from); - if (pcontact != NULL) { - win_show_contact(window, pcontact); - } + // show users status first, when receiving message via delayed delivery + if (win_created) { + PContact pcontact = roster_get_contact(from); + if (pcontact != NULL) { + win_show_contact(window, pcontact); } - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(window->win, COLOUR_TIME); - wprintw(window->win, "%s - ", date_fmt); - wattroff(window->win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); } + GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(window->win, COLOUR_TIME); + wprintw(window->win, "%s - ", date_fmt); + wattroff(window->win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); + } - if (strncmp(message, "/me ", 4) == 0) { - wattron(window->win, COLOUR_THEM); - wprintw(window->win, "*%s ", display_from); - waddstr(window->win, message + 4); - wprintw(window->win, "\n"); - wattroff(window->win, COLOUR_THEM); - } else { - _win_show_user(window->win, display_from, 1); - _win_show_message(window->win, message); - } + if (strncmp(message, "/me ", 4) == 0) { + wattron(window->win, COLOUR_THEM); + wprintw(window->win, "*%s ", display_from); + waddstr(window->win, message + 4); + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_THEM); + } else { + _win_show_user(window->win, display_from, 1); + _win_show_message(window->win, message); } } - int ui_index = win_index + 1; + int ui_index = num; if (ui_index == 10) { ui_index = 0; } @@ -504,12 +420,12 @@ ui_contact_online(const char * const barejid, const char * const resource, g_string_append(display_str, ")"); } + ProfWin *console = wins_get_console(); _show_status_string(console, display_str->str, show, status, last_activity, "++", "online"); - int win_index = _find_prof_win_index(barejid); - if (win_index != NUM_WINS) { - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(barejid); + if (window != NULL) { _show_status_string(window, display_str->str, show, status, last_activity, "++", "online"); } @@ -517,8 +433,11 @@ ui_contact_online(const char * const barejid, const char * const resource, jid_destroy(jid); g_string_free(display_str, TRUE); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(console)) { + wins_refresh_current(); + } else if ((window != NULL) && (wins_is_current(window))) { + wins_refresh_current(); + } } void @@ -543,12 +462,12 @@ ui_contact_offline(const char * const from, const char * const show, g_string_append(display_str, ")"); } + ProfWin *console = wins_get_console(); _show_status_string(console, display_str->str, show, status, NULL, "--", "offline"); - int win_index = _find_prof_win_index(jidp->barejid); - if (win_index != NUM_WINS) { - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(jidp->barejid); + if (window != NULL) { _show_status_string(window, display_str->str, show, status, NULL, "--", "offline"); } @@ -556,30 +475,17 @@ ui_contact_offline(const char * const from, const char * const show, jid_destroy(jidp); g_string_free(display_str, TRUE); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(console)) { + wins_refresh_current(); + } else if ((window != NULL) && (wins_is_current(window))) { + wins_refresh_current(); + } } void ui_disconnected(void) { - int i; - // show message in all active chats - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - ProfWin *window = windows[i]; - win_print_time(window, '-'); - wattron(window->win, COLOUR_ERROR); - wprintw(window->win, "%s\n", "Lost connection."); - wattroff(window->win, COLOUR_ERROR); - - // if current win, set current_win_dirty - if (i == current_index) { - current_win_dirty = TRUE; - } - } - } - + wins_lost_connection(); title_bar_set_status(CONTACT_OFFLINE); status_bar_clear_message(); status_bar_refresh(); @@ -619,84 +525,122 @@ ui_close_connected_win(int index) } } +int +ui_close_all_wins(void) +{ + int count = 0; + jabber_conn_status_t conn_status = jabber_get_connection_status(); + + GList *win_nums = wins_get_nums(); + GList *curr = win_nums; + + while (curr != NULL) { + int num = GPOINTER_TO_INT(curr->data); + if (num != 1) { + if (conn_status == JABBER_CONNECTED) { + ui_close_connected_win(num); + } + ui_close_win(num); + count++; + } + curr = g_list_next(curr); + } + + g_list_free(curr); + g_list_free(win_nums); + + return count; +} + +int +ui_close_read_wins(void) +{ + int count = 0; + jabber_conn_status_t conn_status = jabber_get_connection_status(); + + GList *win_nums = wins_get_nums(); + GList *curr = win_nums; + + while (curr != NULL) { + int num = GPOINTER_TO_INT(curr->data); + if ((num != 1) && (ui_win_unread(num) == 0)) { + if (conn_status == JABBER_CONNECTED) { + ui_close_connected_win(num); + } + ui_close_win(num); + count++; + } + curr = g_list_next(curr); + } + + g_list_free(curr); + g_list_free(win_nums); + + return count; +} + void ui_switch_win(const int i) { ui_current_page_off(); - if (windows[i] != NULL) { - current_index = i; - current = windows[current_index]; + ProfWin *new_current = wins_get_by_num(i); + if (new_current != NULL) { + wins_set_current_by_num(i); ui_current_page_off(); - current->unread = 0; + new_current->unread = 0; - if (i == 0) { + if (i == 1) { title_bar_title(); - status_bar_active(0); + status_bar_active(1); } else { - PContact contact = roster_get_contact(current->from); + PContact contact = roster_get_contact(new_current->from); if (contact != NULL) { if (p_contact_name(contact) != NULL) { title_bar_set_recipient(p_contact_name(contact)); } else { - title_bar_set_recipient(current->from); + title_bar_set_recipient(new_current->from); } } else { - title_bar_set_recipient(current->from); + title_bar_set_recipient(new_current->from); } title_bar_draw();; status_bar_active(i); } + wins_refresh_current(); } - - current_win_dirty = TRUE; } void ui_clear_current(void) { - werase(current->win); - current_win_dirty = TRUE; + wins_clear_current(); } void ui_close_current(void) { - win_free(current); - windows[current_index] = NULL; - - // set it as inactive in the status bar + int current_index = wins_get_current_num(); status_bar_inactive(current_index); - - // go back to console window - _set_current(0); - status_bar_active(0); + wins_close_current(); + status_bar_active(1); title_bar_title(); - - current_win_dirty = TRUE; } void ui_close_win(int index) { - win_free(windows[index]); - windows[index] = NULL; - status_bar_inactive(index); - - if (index == current_index) { - _set_current(0); - } - - status_bar_active(0); + wins_close_by_num(index); + status_bar_active(1); title_bar_title(); - current_win_dirty = TRUE; + wins_refresh_current(); } void ui_tidy_wins(void) { - gboolean tidied = _tidy(); + gboolean tidied = wins_tidy(); if (tidied) { cons_show("Windows tidied."); @@ -709,23 +653,40 @@ void ui_prune_wins(void) { jabber_conn_status_t conn_status = jabber_get_connection_status(); - int curr = 0; gboolean pruned = FALSE; - for (curr = 1; curr <= 9; curr++) { - if (ui_win_exists(curr)) { - win_type_t win_type = windows[curr]->type; - if ((ui_win_unread(curr) == 0) && (win_type != WIN_MUC)) { - if (conn_status == JABBER_CONNECTED) { - ui_close_connected_win(curr); + GSList *recipients = wins_get_prune_recipients(); + if (recipients != NULL) { + pruned = TRUE; + } + GSList *curr = recipients; + while (curr != NULL) { + char *recipient = curr->data; + + if (conn_status == JABBER_CONNECTED) { + if (prefs_get_boolean(PREF_STATES)) { + + // 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); } - ui_close_win(curr); - pruned = TRUE; } } + + ProfWin *window = wins_get_by_recipient(recipient); + int num = wins_get_num(window); + ui_close_win(num); + + curr = g_slist_next(curr); + } + + if (recipients != NULL) { + g_slist_free(recipients); } - _tidy(); + wins_tidy(); if (pruned) { cons_show("Windows pruned."); } else { @@ -736,36 +697,41 @@ ui_prune_wins(void) win_type_t ui_current_win_type(void) { + ProfWin *current = wins_get_current(); return current->type; } int ui_current_win_index(void) { - return current_index; + return wins_get_current_num(); } win_type_t ui_win_type(int index) { - return windows[index]->type; + ProfWin *window = wins_get_by_num(index); + return window->type; } char * ui_recipient(int index) { - return strdup(windows[index]->from); + ProfWin *window = wins_get_by_num(index); + return window->from; } char * ui_current_recipient(void) { - return strdup(current->from); + ProfWin *current = wins_get_current(); + return current->from; } void ui_current_print_line(const char * const msg, ...) { + ProfWin *current = wins_get_current(); va_list arg; va_start(arg, msg); GString *fmt_msg = g_string_new(NULL); @@ -775,56 +741,51 @@ ui_current_print_line(const char * const msg, ...) g_string_free(fmt_msg, TRUE); va_end(arg); - current_win_dirty = TRUE; + wins_refresh_current(); } void ui_current_error_line(const char * const msg) { + ProfWin *current = wins_get_current(); win_print_time(current, '-'); wattron(current->win, COLOUR_ERROR); wprintw(current->win, "%s\n", msg); wattroff(current->win, COLOUR_ERROR); - current_win_dirty = TRUE; + wins_refresh_current(); } void ui_current_page_off(void) { - int rows = getmaxy(stdscr); - ProfWin *window = windows[current_index]; - - window->paged = 0; - - int y = getcury(window->win); + ProfWin *current = wins_get_current(); + current->paged = 0; + int rows = getmaxy(stdscr); + int y = getcury(current->win); int size = rows - 3; - window->y_pos = y - (size - 1); - if (window->y_pos < 0) - window->y_pos = 0; + current->y_pos = y - (size - 1); + if (current->y_pos < 0) { + current->y_pos = 0; + } - current_win_dirty = TRUE; + wins_refresh_current(); } void ui_print_error_from_recipient(const char * const from, const char *err_msg) { - int win_index; - ProfWin *window; - if (from == NULL || err_msg == NULL) return; - win_index = _find_prof_win_index(from); - // chat window exists - if (win_index < NUM_WINS) { - window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(from); + if (window != NULL) { win_print_time(window, '-'); _win_show_error_msg(window->win, err_msg); - if (win_index == current_index) { - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); } } } @@ -832,8 +793,7 @@ ui_print_error_from_recipient(const char * const from, const char *err_msg) void ui_print_system_msg_from_recipient(const char * const from, const char *message) { - int win_index; - ProfWin *window; + int num = 0; char from_cpy[strlen(from) + 1]; char *bare_jid; @@ -843,29 +803,31 @@ ui_print_system_msg_from_recipient(const char * const from, const char *message) strcpy(from_cpy, from); bare_jid = strtok(from_cpy, "/"); - win_index = _find_prof_win_index(bare_jid); - if (win_index == NUM_WINS) { - win_index = _new_prof_win(bare_jid, WIN_CHAT); - status_bar_active(win_index); - current_win_dirty = TRUE; + ProfWin *window = wins_get_by_recipient(bare_jid); + if (window == NULL) { + window = wins_new(bare_jid, WIN_CHAT); + if (window != NULL) { + num = wins_get_num(window); + status_bar_active(num); + } else { + num = 0; + window = wins_get_console(); + status_bar_active(1); + } } - window = windows[win_index]; win_print_time(window, '-'); wprintw(window->win, "*%s %s\n", bare_jid, message); // this is the current window - if (win_index == current_index) { - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); } } void ui_recipient_gone(const char * const barejid) { - int win_index; - ProfWin *window; - if (barejid == NULL) return; @@ -877,18 +839,16 @@ ui_recipient_gone(const char * const barejid) display_usr = barejid; } - win_index = _find_prof_win_index(barejid); - // chat window exists - if (win_index < NUM_WINS) { - window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(barejid); + if (window != NULL) { win_print_time(window, '!'); wattron(window->win, COLOUR_GONE); wprintw(window->win, "<- %s ", display_usr); wprintw(window->win, "has left the conversation."); wprintw(window->win, "\n"); wattroff(window->win, COLOUR_GONE); - if (win_index == current_index) { - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); } } } @@ -898,25 +858,24 @@ ui_new_chat_win(const char * const to) { // if the contact is offline, show a message PContact contact = roster_get_contact(to); - int win_index = _find_prof_win_index(to); - ProfWin *window = NULL; + ProfWin *window = wins_get_by_recipient(to); + int num = 0; // create new window - if (win_index == NUM_WINS) { + if (window == NULL) { Jid *jid = jid_create(to); if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); + window = wins_new(to, WIN_PRIVATE); } else { - win_index = _new_prof_win(to, WIN_CHAT); + window = wins_new(to, WIN_CHAT); } jid_destroy(jid); - - window = windows[win_index]; + num = wins_get_num(window); if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _win_show_history(window->win, win_index, to); + _win_show_history(window->win, num, to); } if (contact != NULL) { @@ -926,71 +885,71 @@ ui_new_chat_win(const char * const to) _show_status_string(window, to, show, status, NULL, "--", "offline"); } } - - // use existing window } else { - window = windows[win_index]; + num = wins_get_num(window); } - ui_switch_win(win_index); + ui_switch_win(num); } void ui_create_duck_win(void) { - int win_index = _new_prof_win("DuckDuckGo search", WIN_DUCK); - ui_switch_win(win_index); - win_print_time(windows[win_index], '-'); - wprintw(windows[win_index]->win, "Type ':help' to find out more.\n"); + ProfWin *window = wins_new("DuckDuckGo search", WIN_DUCK); + int num = wins_get_num(window); + ui_switch_win(num); + win_print_time(window, '-'); + wprintw(window->win, "Type ':help' to find out more.\n"); } void ui_open_duck_win(void) { - int win_index = _find_prof_win_index("DuckDuckGo search"); - if (win_index != NUM_WINS) { - ui_switch_win(win_index); + ProfWin *window = wins_get_by_recipient("DuckDuckGo search"); + if (window != NULL) { + int num = wins_get_num(window); + ui_switch_win(num); } } void ui_duck(const char * const query) { - int win_index = _find_prof_win_index("DuckDuckGo search"); - if (win_index != NUM_WINS) { - win_print_time(windows[win_index], '-'); - wprintw(windows[win_index]->win, "\n"); - win_print_time(windows[win_index], '-'); - wattron(windows[win_index]->win, COLOUR_ME); - wprintw(windows[win_index]->win, "Query : "); - wattroff(windows[win_index]->win, COLOUR_ME); - wprintw(windows[win_index]->win, query); - wprintw(windows[win_index]->win, "\n"); + ProfWin *window = wins_get_by_recipient("DuckDuckGo search"); + if (window != NULL) { + win_print_time(window, '-'); + wprintw(window->win, "\n"); + win_print_time(window, '-'); + wattron(window->win, COLOUR_ME); + wprintw(window->win, "Query : "); + wattroff(window->win, COLOUR_ME); + wprintw(window->win, query); + wprintw(window->win, "\n"); } } void ui_duck_result(const char * const result) { - int win_index = _find_prof_win_index("DuckDuckGo search"); + ProfWin *window = wins_get_by_recipient("DuckDuckGo search"); - if (win_index != NUM_WINS) { - win_print_time(windows[win_index], '-'); - wattron(windows[win_index]->win, COLOUR_THEM); - wprintw(windows[win_index]->win, "Result : "); - wattroff(windows[win_index]->win, COLOUR_THEM); + if (window != NULL) { + win_print_time(window, '-'); + wattron(window->win, COLOUR_THEM); + wprintw(window->win, "Result : "); + wattroff(window->win, COLOUR_THEM); glong offset = 0; while (offset < g_utf8_strlen(result, -1)) { gchar *ptr = g_utf8_offset_to_pointer(result, offset); gunichar unichar = g_utf8_get_char(ptr); if (unichar == '\n') { - wprintw(windows[win_index]->win, "\n"); - win_print_time(windows[win_index], '-'); + wprintw(window->win, "\n"); + win_print_time(window, '-'); } else { gchar *string = g_ucs4_to_utf8(&unichar, 1, NULL, NULL, NULL); if (string != NULL) { - wprintw(windows[win_index]->win, string); + wprintw(window->win, string); g_free(string); } } @@ -998,7 +957,7 @@ ui_duck_result(const char * const result) offset++; } - wprintw(windows[win_index]->win, "\n"); + wprintw(window->win, "\n"); } } @@ -1006,27 +965,25 @@ void ui_outgoing_msg(const char * const from, const char * const to, const char * const message) { - // if the contact is offline, show a message PContact contact = roster_get_contact(to); - int win_index = _find_prof_win_index(to); - ProfWin *window = NULL; + ProfWin *window = wins_get_by_recipient(to); + int num = 0; // create new window - if (win_index == NUM_WINS) { + if (window == NULL) { Jid *jid = jid_create(to); if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); + window = wins_new(to, WIN_PRIVATE); } else { - win_index = _new_prof_win(to, WIN_CHAT); + window = wins_new(to, WIN_CHAT); } jid_destroy(jid); - - window = windows[win_index]; + num = wins_get_num(window); if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _win_show_history(window->win, win_index, to); + _win_show_history(window->win, num, to); } if (contact != NULL) { @@ -1039,7 +996,7 @@ ui_outgoing_msg(const char * const from, const char * const to, // use existing window } else { - window = windows[win_index]; + num = wins_get_num(window); } win_print_time(window, '-'); @@ -1053,27 +1010,28 @@ ui_outgoing_msg(const char * const from, const char * const to, _win_show_user(window->win, from, 0); _win_show_message(window->win, message); } - ui_switch_win(win_index); + ui_switch_win(num); } void ui_room_join(Jid *jid) { - int win_index = _find_prof_win_index(jid->barejid); + ProfWin *window = wins_get_by_recipient(jid->barejid); + int num = 0; // create new window - if (win_index == NUM_WINS) { - win_index = _new_prof_win(jid->barejid, WIN_MUC); + if (window == NULL) { + window = wins_new(jid->barejid, WIN_MUC); } - ui_switch_win(win_index); + num = wins_get_num(window); + ui_switch_win(num); } void ui_room_roster(const char * const room, GList *roster, const char * const presence) { - int win_index = _find_prof_win_index(room); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); win_print_time(window, '!'); if ((roster == NULL) || (g_list_length(roster) == 0)) { @@ -1120,118 +1078,120 @@ ui_room_roster(const char * const room, GList *roster, const char * const presen wattroff(window->win, COLOUR_ONLINE); } - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_member_offline(const char * const room, const char * const nick) { - int win_index = _find_prof_win_index(room); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); win_print_time(window, '!'); wattron(window->win, COLOUR_OFFLINE); wprintw(window->win, "<- %s has left the room.\n", nick); wattroff(window->win, COLOUR_OFFLINE); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_member_online(const char * const room, const char * const nick, const char * const show, const char * const status) { - int win_index = _find_prof_win_index(room); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); win_print_time(window, '!'); wattron(window->win, COLOUR_ONLINE); wprintw(window->win, "-> %s has joined the room.\n", nick); wattroff(window->win, COLOUR_ONLINE); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_member_presence(const char * const room, const char * const nick, const char * const show, const char * const status) { - int win_index = _find_prof_win_index(room); - if (win_index != NUM_WINS) { - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); + + if (window != NULL) { _show_status_string(window, nick, show, status, NULL, "++", "online"); } - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_member_nick_change(const char * const room, const char * const old_nick, const char * const nick) { - int win_index = _find_prof_win_index(room); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); win_print_time(window, '!'); wattron(window->win, COLOUR_THEM); wprintw(window->win, "** %s is now known as %s\n", old_nick, nick); wattroff(window->win, COLOUR_THEM); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_nick_change(const char * const room, const char * const nick) { - int win_index = _find_prof_win_index(room); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room); win_print_time(window, '!'); wattron(window->win, COLOUR_ME); wprintw(window->win, "** You are now known as %s\n", nick); wattroff(window->win, COLOUR_ME); - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_history(const char * const room_jid, const char * const nick, GTimeVal tv_stamp, const char * const message) { - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; + ProfWin *window = wins_get_by_recipient(room_jid); GDateTime *time = g_date_time_new_from_timeval_utc(&tv_stamp); gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wprintw(win, "%s - ", date_fmt); + wprintw(window->win, "%s - ", date_fmt); g_date_time_unref(time); g_free(date_fmt); if (strncmp(message, "/me ", 4) == 0) { - wprintw(win, "*%s ", nick); - waddstr(win, message + 4); - wprintw(win, "\n"); + wprintw(window->win, "*%s ", nick); + waddstr(window->win, message + 4); + wprintw(window->win, "\n"); } else { - wprintw(win, "%s: ", nick); - _win_show_message(win, message); + wprintw(window->win, "%s: ", nick); + _win_show_message(window->win, message); } - if (win_index == current_index) - current_win_dirty = TRUE; + if (wins_is_current(window)) { + wins_refresh_current(); + } } void ui_room_message(const char * const room_jid, const char * const nick, const char * const message) { - int win_index = _find_prof_win_index(room_jid); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room_jid); + int num = wins_get_num(window); win_print_time(window, '-'); if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { @@ -1260,16 +1220,16 @@ ui_room_message(const char * const room_jid, const char * const nick, } // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - current_win_dirty = TRUE; + if (wins_is_current(window)) { + status_bar_active(num); + wins_refresh_current(); // not currenlty on groupchat window } else { - status_bar_new(win_index); - cons_show_incoming_message(nick, win_index); - if (current_index == 0) { - current_win_dirty = TRUE; + status_bar_new(num); + cons_show_incoming_message(nick, num); + if (wins_get_current_num() == 0) { + wins_refresh_current(); } if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { @@ -1278,10 +1238,10 @@ ui_room_message(const char * const room_jid, const char * const nick, } } - windows[win_index]->unread++; + window->unread++; } - int ui_index = win_index + 1; + int ui_index = num; if (ui_index == 10) { ui_index = 0; } @@ -1301,8 +1261,8 @@ ui_room_message(const char * const room_jid, const char * const nick, void ui_room_subject(const char * const room_jid, const char * const subject) { - int win_index = _find_prof_win_index(room_jid); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room_jid); + int num = wins_get_num(window); win_print_time(window, '!'); wattron(window->win, COLOUR_ROOMINFO); @@ -1311,21 +1271,21 @@ ui_room_subject(const char * const room_jid, const char * const subject) wprintw(window->win, "%s\n", subject); // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - current_win_dirty = TRUE; + if (wins_is_current(window)) { + status_bar_active(num); + wins_refresh_current(); // not currenlty on groupchat window } else { - status_bar_new(win_index); + status_bar_new(num); } } void ui_room_broadcast(const char * const room_jid, const char * const message) { - int win_index = _find_prof_win_index(room_jid); - ProfWin *window = windows[win_index]; + ProfWin *window = wins_get_by_recipient(room_jid); + int num = wins_get_num(window); win_print_time(window, '!'); wattron(window->win, COLOUR_ROOMINFO); @@ -1334,13 +1294,13 @@ ui_room_broadcast(const char * const room_jid, const char * const message) wprintw(window->win, "%s\n", message); // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - current_win_dirty = TRUE; + if (wins_is_current(window)) { + status_bar_active(num); + wins_refresh_current(); // not currenlty on groupchat window } else { - status_bar_new(win_index); + status_bar_new(num); } } @@ -1349,6 +1309,7 @@ ui_status(void) { char *recipient = ui_current_recipient(); PContact pcontact = roster_get_contact(recipient); + ProfWin *current = wins_get_current(); if (pcontact != NULL) { win_show_contact(current, pcontact); @@ -1361,8 +1322,8 @@ void ui_status_private(void) { Jid *jid = jid_create(ui_current_recipient()); - PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + ProfWin *current = wins_get_current(); if (pcontact != NULL) { win_show_contact(current, pcontact); @@ -1377,6 +1338,7 @@ void ui_status_room(const char * const contact) { PContact pcontact = muc_get_participant(ui_current_recipient(), contact); + ProfWin *current = wins_get_current(); if (pcontact != NULL) { win_show_contact(current, pcontact); @@ -1388,21 +1350,15 @@ ui_status_room(const char * const contact) gint ui_unread(void) { - int i; - gint result = 0; - for (i = 0; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - result += windows[i]->unread; - } - } - return result; + return wins_get_total_unread(); } int ui_win_unread(int index) { - if (windows[index] != NULL) { - return windows[index]->unread; + ProfWin *window = wins_get_by_num(index); + if (window != NULL) { + return window->unread; } else { return 0; } @@ -1450,38 +1406,6 @@ _ui_draw_win_title(void) } } -static int -_find_prof_win_index(const char * const contact) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if ((windows[i] != NULL) && (strcmp(windows[i]->from, contact) == 0)) { - break; - } - } - - return i; -} - -static int -_new_prof_win(const char * const contact, win_type_t type) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] == NULL) { - break; - } - } - - if (i != NUM_WINS) { - int cols = getmaxx(stdscr); - windows[i] = win_create(contact, cols, type); - return i; - } else { - return 0; - } -} - static void _win_show_user(WINDOW *win, const char * const user, const int colour) { @@ -1512,36 +1436,6 @@ _win_show_error_msg(WINDOW *win, const char * const message) } static void -_current_window_refresh(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); -} - -void -_win_resize_all(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - // only make the pads bigger, to avoid data loss on cropping - if (cols > max_cols) { - max_cols = cols; - - int i; - for (i = 0; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - wresize(windows[i]->win, PAD_SIZE, cols); - } - } - } - - prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); -} - -static void _show_status_string(ProfWin *window, const char * const from, const char * const show, const char * const status, GDateTime *last_activity, const char * const pre, @@ -1656,6 +1550,7 @@ _win_handle_switch(const wint_t * const ch) static void _win_handle_page(const wint_t * const ch) { + ProfWin *current = wins_get_current(); int rows = getmaxy(stdscr); int y = getcury(current->win); @@ -1684,7 +1579,7 @@ _win_handle_page(const wint_t * const ch) *page_start = y - page_space; current->paged = 1; - current_win_dirty = TRUE; + wins_refresh_current(); } else if (mouse_event.bstate & BUTTON4_PRESSED) { // mouse wheel up *page_start -= 4; @@ -1693,7 +1588,7 @@ _win_handle_page(const wint_t * const ch) *page_start = 0; current->paged = 1; - current_win_dirty = TRUE; + wins_refresh_current(); } } } @@ -1708,7 +1603,7 @@ _win_handle_page(const wint_t * const ch) *page_start = 0; current->paged = 1; - current_win_dirty = TRUE; + wins_refresh_current(); // page down } else if (*ch == KEY_NPAGE) { @@ -1723,14 +1618,15 @@ _win_handle_page(const wint_t * const ch) *page_start = y - page_space; current->paged = 1; - current_win_dirty = TRUE; + wins_refresh_current(); } } static void _win_show_history(WINDOW *win, int win_index, const char * const contact) { - if (!windows[win_index]->history_shown) { + ProfWin *window = wins_get_by_num(win_index); + if (!window->history_shown) { GSList *history = NULL; Jid *jid = jid_create(jabber_get_fulljid()); history = chat_log_get_previous(jid->barejid, contact, history); @@ -1739,48 +1635,8 @@ _win_show_history(WINDOW *win, int win_index, const char * const contact) wprintw(win, "%s\n", history->data); history = g_slist_next(history); } - windows[win_index]->history_shown = 1; + window->history_shown = 1; g_slist_free_full(history, free); } } - -void -_set_current(int index) -{ - current_index = index; - current = windows[current_index]; -} - -gboolean -_tidy(void) -{ - int gap = 1; - int filler = 1; - gboolean tidied = FALSE; - - for (gap = 1; gap < NUM_WINS; gap++) { - // if a gap - if (!ui_win_exists(gap)) { - - // find next used window and move into gap - for (filler = gap + 1; filler < NUM_WINS; filler++) { - if (ui_win_exists(filler)) { - windows[gap] = windows[filler]; - if (windows[gap]->unread > 0) { - status_bar_new(gap); - } else { - status_bar_active(gap); - } - windows[filler] = NULL; - status_bar_inactive(filler); - tidied = TRUE; - break; - } - } - } - } - - return tidied; -} - diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 0ab53131..b6162938 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -526,34 +526,34 @@ _handle_alt_key(char *input, int *size, int key) switch (key) { case '1': - ui_switch_win(0); + ui_switch_win(1); break; case '2': - ui_switch_win(1); + ui_switch_win(2); break; case '3': - ui_switch_win(2); + ui_switch_win(3); break; case '4': - ui_switch_win(3); + ui_switch_win(4); break; case '5': - ui_switch_win(4); + ui_switch_win(5); break; case '6': - ui_switch_win(5); + ui_switch_win(6); break; case '7': - ui_switch_win(6); + ui_switch_win(7); break; case '8': - ui_switch_win(7); + ui_switch_win(8); break; case '9': - ui_switch_win(8); + ui_switch_win(9); break; case '0': - ui_switch_win(9); + ui_switch_win(0); break; case 263: case 127: diff --git a/src/ui/statusbar.c b/src/ui/statusbar.c index 6e7eae30..e7456adc 100644 --- a/src/ui/statusbar.c +++ b/src/ui/statusbar.c @@ -37,13 +37,20 @@ static WINDOW *status_bar; static char *message = NULL; -static char _active[31] = "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]"; -static int is_active[10]; -static int is_new[10]; +// 1 2 3 4 5 6 7 8 9 0 > +static char _active[34] = "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]"; +static int is_active[12]; +static GHashTable *remaining_active; +static int is_new[12]; +static GHashTable *remaining_new; static int dirty; static GDateTime *last_time; static void _status_bar_update_time(void); +static void _update_win_statuses(void); +static void _mark_new(int num); +static void _mark_active(int num); +static void _mark_inactive(int num); void create_status_bar(void) @@ -51,17 +58,19 @@ create_status_bar(void) int rows, cols, i; getmaxyx(stdscr, rows, cols); - is_active[0] = TRUE; - is_new[0] = FALSE; - for (i = 1; i < 10; i++) { + is_active[1] = TRUE; + is_new[1] = FALSE; + for (i = 2; i < 12; i++) { is_active[i] = FALSE; is_new[i] = FALSE; } + remaining_active = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); + remaining_new = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); status_bar = newwin(1, cols, rows-2, 0); wbkgd(status_bar, COLOUR_STATUS_TEXT); wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); + mvwprintw(status_bar, 0, cols - 34, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); if (last_time != NULL) @@ -86,6 +95,7 @@ status_bar_refresh(void) if (dirty) { _status_bar_update_time(); + _update_win_statuses(); wrefresh(status_bar); inp_put_back(); dirty = FALSE; @@ -97,7 +107,7 @@ status_bar_refresh(void) void status_bar_resize(void) { - int rows, cols, i; + int rows, cols; getmaxyx(stdscr, rows, cols); mvwin(status_bar, rows-2, 0); @@ -105,15 +115,10 @@ status_bar_resize(void) wbkgd(status_bar, COLOUR_STATUS_TEXT); werase(status_bar); wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); + mvwprintw(status_bar, 0, cols - 34, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } + _update_win_statuses(); if (message != NULL) mvwprintw(status_bar, 0, 10, message); @@ -125,60 +130,114 @@ status_bar_resize(void) } void -status_bar_inactive(const int win) +status_bar_set_all_inactive(void) { - is_active[win] = FALSE; - is_new[win] = FALSE; - - int active_pos = 1 + (win * 3); + int i = 0; + for (i = 0; i < 12; i++) { + is_active[i] = FALSE; + is_new[i] = FALSE; + _mark_inactive(i); + } - int cols = getmaxx(stdscr); + g_hash_table_remove_all(remaining_active); + g_hash_table_remove_all(remaining_new); +} - mvwaddch(status_bar, 0, cols - 31 + active_pos, ' '); +void +status_bar_inactive(const int win) +{ + int true_win = win; + if (true_win == 0) { + true_win = 10; + } - dirty = TRUE; + // extra windows + if (true_win > 10) { + g_hash_table_remove(remaining_active, GINT_TO_POINTER(true_win)); + g_hash_table_remove(remaining_new, GINT_TO_POINTER(true_win)); + + // still have new windows + if (g_hash_table_size(remaining_new) != 0) { + is_active[11] = TRUE; + is_new[11] = TRUE; + _mark_new(11); + + // still have active winsows + } else if (g_hash_table_size(remaining_active) != 0) { + is_active[11] = TRUE; + is_new[11] = FALSE; + _mark_active(11); + + // no active or new windows + } else { + is_active[11] = FALSE; + is_new[11] = FALSE; + _mark_inactive(11); + } + + // visible window indicators + } else { + is_active[true_win] = FALSE; + is_new[true_win] = FALSE; + _mark_inactive(true_win); + } } void status_bar_active(const int win) { - is_active[win] = TRUE; - is_new[win] = FALSE; - - int active_pos = 1 + (win * 3); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_ACTIVE); - if (win+1 < 10) - mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); - else - mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); - wattroff(status_bar, COLOUR_STATUS_ACTIVE); + int true_win = win; + if (true_win == 0) { + true_win = 10; + } - dirty = TRUE; + // extra windows + if (true_win > 10) { + g_hash_table_add(remaining_active, GINT_TO_POINTER(true_win)); + g_hash_table_remove(remaining_new, GINT_TO_POINTER(true_win)); + + // still have new windows + if (g_hash_table_size(remaining_new) != 0) { + is_active[11] = TRUE; + is_new[11] = TRUE; + _mark_new(11); + + // only active windows + } else { + is_active[11] = TRUE; + is_new[11] = FALSE; + _mark_active(11); + } + + // visible winsow indicators + } else { + is_active[true_win] = TRUE; + is_new[true_win] = FALSE; + _mark_active(true_win); + } } void status_bar_new(const int win) { - is_active[win] = TRUE; - is_new[win] = TRUE; - - int active_pos = 1 + (win * 3); + int true_win = win; + if (true_win == 0) { + true_win = 10; + } - int cols = getmaxx(stdscr); + if (true_win > 10) { + g_hash_table_add(remaining_active, GINT_TO_POINTER(true_win)); + g_hash_table_add(remaining_new, GINT_TO_POINTER(true_win)); - wattron(status_bar, COLOUR_STATUS_NEW); - wattron(status_bar, A_BLINK); - if (win+1 < 10) - mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); - else - mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); - wattroff(status_bar, COLOUR_STATUS_NEW); - wattroff(status_bar, A_BLINK); + is_active[11] = TRUE; + is_new[11] = TRUE; + _mark_new(11); - dirty = TRUE; + } else { + is_active[true_win] = TRUE; + is_new[true_win] = TRUE; + _mark_new(true_win); + } } void @@ -203,17 +262,10 @@ status_bar_print_message(const char * const msg) int cols = getmaxx(stdscr); wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); + mvwprintw(status_bar, 0, cols - 34, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); - int i; - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } - + _update_win_statuses(); dirty = TRUE; } @@ -226,9 +278,9 @@ status_bar_clear(void) } int i; - is_active[0] = TRUE; - is_new[0] = FALSE; - for (i = 1; i < 10; i++) { + is_active[1] = TRUE; + is_new[1] = FALSE; + for (i = 2; i < 12; i++) { is_active[i] = FALSE; is_new[i] = FALSE; } @@ -238,7 +290,7 @@ status_bar_clear(void) int cols = getmaxx(stdscr); wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); + mvwprintw(status_bar, 0, cols - 34, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); dirty = TRUE; @@ -257,17 +309,10 @@ status_bar_clear_message(void) int cols = getmaxx(stdscr); wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); + mvwprintw(status_bar, 0, cols - 34, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); - int i; - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } - + _update_win_statuses(); dirty = TRUE; } @@ -289,3 +334,65 @@ _status_bar_update_time(void) dirty = TRUE; } + +static void +_update_win_statuses(void) +{ + int i; + for(i = 1; i < 12; i++) { + if (is_new[i]) { + _mark_new(i); + } + else if (is_active[i]) { + _mark_active(i); + } + else { + _mark_inactive(i); + } + } +} + +static void +_mark_new(int num) +{ + int active_pos = 1 + ((num-1) * 3); + int cols = getmaxx(stdscr); + wattron(status_bar, COLOUR_STATUS_NEW); + wattron(status_bar, A_BLINK); + if (num == 10) { + mvwprintw(status_bar, 0, cols - 34 + active_pos, "0"); + } else if (num > 10) { + mvwprintw(status_bar, 0, cols - 34 + active_pos, ">"); + } else { + mvwprintw(status_bar, 0, cols - 34 + active_pos, "%d", num); + } + wattroff(status_bar, COLOUR_STATUS_NEW); + wattroff(status_bar, A_BLINK); + dirty = TRUE; +} + +static void +_mark_active(int num) +{ + int active_pos = 1 + ((num-1) * 3); + int cols = getmaxx(stdscr); + wattron(status_bar, COLOUR_STATUS_ACTIVE); + if (num == 10) { + mvwprintw(status_bar, 0, cols - 34 + active_pos, "0"); + } else if (num > 10) { + mvwprintw(status_bar, 0, cols - 34 + active_pos, ">"); + } else { + mvwprintw(status_bar, 0, cols - 34 + active_pos, "%d", num); + } + wattroff(status_bar, COLOUR_STATUS_ACTIVE); + dirty = TRUE; +} + +static void +_mark_inactive(int num) +{ + int active_pos = 1 + ((num-1) * 3); + int cols = getmaxx(stdscr); + mvwaddch(status_bar, 0, cols - 34 + active_pos, ' '); + dirty = TRUE; +} diff --git a/src/ui/ui.h b/src/ui/ui.h index f0601753..fa74bed6 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -40,10 +40,6 @@ #include "xmpp/xmpp.h" #define INP_WIN_MAX 1000 -#define NUM_WINS 10 - -// holds console at index 0 and chat wins 1 through to 9 -ProfWin* windows[NUM_WINS]; // ui startup and control void ui_init(void); @@ -56,15 +52,15 @@ void ui_idle(void); void ui_handle_special_keys(const wint_t * const ch, const char * const inp, const int size); void ui_switch_win(const int i); -gboolean ui_windows_full(void); unsigned long ui_get_idle_time(void); void ui_reset_idle_time(void); void ui_new_chat_win(const char * const to); void ui_print_error_from_recipient(const char * const from, const char *err_msg); void ui_print_system_msg_from_recipient(const char * const from, const char *message); gint ui_unread(void); -void ui_console_dirty(void); void ui_close_connected_win(int index); +int ui_close_all_wins(void); +int ui_close_read_wins(void); // current window actions void ui_close_current(void); @@ -149,7 +145,6 @@ void title_bar_set_typing(gboolean is_typing); void title_bar_draw(void); // console window actions -ProfWin* cons_create(void); void cons_show(const char * const msg, ...); void cons_about(void); void cons_help(void); @@ -230,6 +225,7 @@ void status_bar_inactive(const int win); void status_bar_active(const int win); void status_bar_new(const int win); void status_bar_update_time(void); +void status_bar_set_all_inactive(void); // input window actions wint_t inp_get_char(char *input, int *size); diff --git a/src/ui/window.c b/src/ui/window.c index e2e03340..7c6f9266 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -35,8 +35,6 @@ #include "config/theme.h" #include "ui/window.h" -#define CONS_WIN_TITLE "_cons" - ProfWin* win_create(const char * const title, int cols, win_type_t type) { @@ -59,8 +57,6 @@ win_free(ProfWin* window) { delwin(window->win); free(window->from); - window->from = NULL; - window->win = NULL; free(window); window = NULL; } diff --git a/src/ui/window.h b/src/ui/window.h index 96c8f4af..a4421d1b 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -23,6 +23,14 @@ #ifndef WINDOW_H #define WINDOW_H +#include "config.h" + +#ifdef HAVE_NCURSESW_NCURSES_H +#include <ncursesw/ncurses.h> +#elif HAVE_NCURSES_H +#include <ncurses.h> +#endif + #include "contact.h" #define PAD_SIZE 1000 diff --git a/src/ui/windows.c b/src/ui/windows.c new file mode 100644 index 00000000..e956068c --- /dev/null +++ b/src/ui/windows.c @@ -0,0 +1,475 @@ +/* + * windows.c + * + * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "config.h" + +#include <string.h> + +#include <glib.h> + +#ifdef HAVE_NCURSESW_NCURSES_H +#include <ncursesw/ncurses.h> +#elif HAVE_NCURSES_H +#include <ncurses.h> +#endif + +#include "common.h" +#include "config/theme.h" +#include "ui/ui.h" +#include "ui/window.h" +#include "ui/windows.h" + +#define CONS_WIN_TITLE "_cons" + +static GHashTable *windows; +static int current; +static int max_cols; + +void +wins_init(void) +{ + windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify)win_free); + + max_cols = getmaxx(stdscr); + int cols = getmaxx(stdscr); + ProfWin *console = win_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); + g_hash_table_insert(windows, GINT_TO_POINTER(1), console); + + current = 1; +} + +ProfWin * +wins_get_console(void) +{ + return g_hash_table_lookup(windows, GINT_TO_POINTER(1)); +} + +ProfWin * +wins_get_current(void) +{ + return g_hash_table_lookup(windows, GINT_TO_POINTER(current)); +} + +GList * +wins_get_nums(void) +{ + return g_hash_table_get_keys(windows); +} + +void +wins_set_current_by_num(int i) +{ + if (g_hash_table_lookup(windows, GINT_TO_POINTER(i)) != NULL) { + current = i; + } +} + +ProfWin * +wins_get_by_num(int i) +{ + return g_hash_table_lookup(windows, GINT_TO_POINTER(i)); +} + +ProfWin * +wins_get_by_recipient(const char * const recipient) +{ + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + if (g_strcmp0(window->from, recipient) == 0) { + return window; + } + curr = g_list_next(curr); + } + + return NULL; +} + +int +wins_get_num(ProfWin *window) +{ + GList *keys = g_hash_table_get_keys(windows); + GList *curr = keys; + + 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) { + return GPOINTER_TO_INT(num_p); + } + curr = g_list_next(curr); + } + + return -1; +} + +int +wins_get_current_num(void) +{ + return current; +} + +void +wins_close_current(void) +{ + wins_close_by_num(current); +} + +void +wins_close_by_num(int i) +{ + if (i != 1) { + if (i == current) { + current = 1; + wins_refresh_current(); + } + g_hash_table_remove(windows, GINT_TO_POINTER(i)); + status_bar_inactive(i); + } +} + +void +wins_refresh_current(void) +{ + ProfWin *window = wins_get_current(); + int rows, cols; + getmaxyx(stdscr, rows, cols); + prefresh(window->win, window->y_pos, 0, 1, 0, rows-3, cols-1); +} + +void +wins_clear_current(void) +{ + ProfWin *window = wins_get_current(); + werase(window->win); + wins_refresh_current(); +} + +gboolean +wins_is_current(ProfWin *window) +{ + ProfWin *current_window = wins_get_current(); + + if (g_strcmp0(current_window->from, window->from) == 0) { + return TRUE; + } else { + return FALSE; + } +} + +ProfWin * +wins_new(const char * const from, win_type_t type) +{ + GList *keys = g_hash_table_get_keys(windows); + int result = get_next_available_win_num(keys); + int cols = getmaxx(stdscr); + ProfWin *new = win_create(from, cols, type); + g_hash_table_insert(windows, GINT_TO_POINTER(result), new); + return new; +} + +int +wins_get_total_unread(void) +{ + int result = 0; + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + result += window->unread; + curr = g_list_next(curr); + } + return result; +} + +void +wins_resize_all(void) +{ + int rows, cols; + getmaxyx(stdscr, rows, cols); + + // only make the pads bigger, to avoid data loss on cropping + if (cols > max_cols) { + max_cols = cols; + + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + wresize(window->win, PAD_SIZE, cols); + curr = g_list_next(curr); + } + } + + ProfWin *current_win = wins_get_current(); + + prefresh(current_win->win, current_win->y_pos, 0, 1, 0, rows-3, cols-1); +} + +void +wins_refresh_console(void) +{ + if (current == 0) { + wins_refresh_current(); + } +} + +gboolean +wins_duck_exists(void) +{ + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + if (window->type == WIN_DUCK) + return TRUE; + curr = g_list_next(curr); + } + + return FALSE; +} + +GSList * +wins_get_chat_recipients(void) +{ + GSList *result = NULL; + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + if (window->type == WIN_CHAT) { + result = g_slist_append(result, window->from); + } + curr = g_list_next(curr); + } + return result; +} + +GSList * +wins_get_prune_recipients(void) +{ + GSList *result = NULL; + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + if (window->unread == 0 && window->type != WIN_MUC && window->type != WIN_CONSOLE) { + result = g_slist_append(result, window->from); + } + curr = g_list_next(curr); + } + return result; +} + +void +wins_lost_connection(void) +{ + GList *values = g_hash_table_get_values(windows); + GList *curr = values; + + while (curr != NULL) { + ProfWin *window = curr->data; + if (window->type != WIN_CONSOLE) { + win_print_time(window, '-'); + wattron(window->win, COLOUR_ERROR); + wprintw(window->win, "%s\n", "Lost connection."); + wattroff(window->win, COLOUR_ERROR); + + // if current win, set current_win_dirty + if (wins_is_current(window)) { + wins_refresh_current(); + } + } + curr = g_list_next(curr); + } +} + +gboolean +wins_tidy(void) +{ + gboolean tidy_required = FALSE; + // check for gaps + GList *keys = g_hash_table_get_keys(windows); + keys = g_list_sort(keys, cmp_win_num); + + // get last used + GList *last = g_list_last(keys); + int last_num = GPOINTER_TO_INT(last->data); + + // find first free num TODO - Will sort again + int next_available = get_next_available_win_num(keys); + + // found gap (next available before last window) + if (cmp_win_num(GINT_TO_POINTER(next_available), GINT_TO_POINTER(last_num)) < 0) { + tidy_required = TRUE; + } + + if (tidy_required) { + status_bar_set_all_inactive(); + GHashTable *new_windows = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, (GDestroyNotify)win_free); + + int num = 1; + GList *curr = keys; + while (curr != NULL) { + ProfWin *window = g_hash_table_lookup(windows, curr->data); + if (num == 10) { + g_hash_table_insert(new_windows, GINT_TO_POINTER(0), window); + if (window->unread > 0) { + status_bar_new(0); + } else { + status_bar_active(0); + } + } else { + g_hash_table_insert(new_windows, GINT_TO_POINTER(num), window); + if (window->unread > 0) { + status_bar_new(num); + } else { + status_bar_active(num); + } + } + num++; + curr = g_list_next(curr); + } + + windows = new_windows; + return TRUE; + } else { + return FALSE; + } +} + +GSList * +wins_create_summary(void) +{ + GSList *result = NULL; + + GList *keys = g_hash_table_get_keys(windows); + keys = g_list_sort(keys, cmp_win_num); + GList *curr = keys; + + while (curr != NULL) { + ProfWin *window = g_hash_table_lookup(windows, curr->data); + int ui_index = GPOINTER_TO_INT(curr->data); + + GString *chat_string; + GString *priv_string; + GString *muc_string; + GString *duck_string; + + switch (window->type) + { + case WIN_CONSOLE: + result = g_slist_append(result, strdup("1: Console")); + break; + case WIN_CHAT: + chat_string = g_string_new(""); + g_string_printf(chat_string, "%d: Chat %s", ui_index, window->from); + PContact contact = roster_get_contact(window->from); + + if (contact != NULL) { + if (p_contact_name(contact) != NULL) { + GString *chat_name = g_string_new(""); + g_string_printf(chat_name, " (%s)", p_contact_name(contact)); + g_string_append(chat_string, chat_name->str); + g_string_free(chat_name, TRUE); + } + GString *chat_presence = g_string_new(""); + g_string_printf(chat_presence, " - %s", p_contact_presence(contact)); + g_string_append(chat_string, chat_presence->str); + g_string_free(chat_presence, TRUE); + } + + if (window->unread > 0) { + GString *chat_unread = g_string_new(""); + g_string_printf(chat_unread, ", %d unread", window->unread); + g_string_append(chat_string, chat_unread->str); + g_string_free(chat_unread, TRUE); + } + + result = g_slist_append(result, strdup(chat_string->str)); + g_string_free(chat_string, TRUE); + + break; + + case WIN_PRIVATE: + priv_string = g_string_new(""); + g_string_printf(priv_string, "%d: Private %s", ui_index, window->from); + + if (window->unread > 0) { + GString *priv_unread = g_string_new(""); + g_string_printf(priv_unread, ", %d unread", window->unread); + g_string_append(priv_string, priv_unread->str); + g_string_free(priv_unread, TRUE); + } + + result = g_slist_append(result, strdup(priv_string->str)); + g_string_free(priv_string, TRUE); + + break; + + case WIN_MUC: + muc_string = g_string_new(""); + g_string_printf(muc_string, "%d: Room %s", ui_index, window->from); + + if (window->unread > 0) { + GString *muc_unread = g_string_new(""); + g_string_printf(muc_unread, ", %d unread", window->unread); + g_string_append(muc_string, muc_unread->str); + g_string_free(muc_unread, TRUE); + } + + result = g_slist_append(result, strdup(muc_string->str)); + g_string_free(muc_string, TRUE); + + break; + + case WIN_DUCK: + duck_string = g_string_new(""); + g_string_printf(duck_string, "%d: DuckDuckGo search", ui_index); + result = g_slist_append(result, strdup(duck_string->str)); + g_string_free(duck_string, TRUE); + + break; + + default: + break; + } + curr = g_list_next(curr); + } + + return result; +} + +void +wins_destroy(void) +{ + g_hash_table_destroy(windows); +} diff --git a/src/ui/windows.h b/src/ui/windows.h new file mode 100644 index 00000000..6d93c434 --- /dev/null +++ b/src/ui/windows.h @@ -0,0 +1,52 @@ +/* + * windows.h + * + * Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef WINDOWS_H +#define WINDOWS_H + +void wins_init(void); +ProfWin * wins_get_console(void); +ProfWin * wins_get_current(void); +void wins_set_current_by_num(int i); +ProfWin * wins_get_by_num(int i); +ProfWin * wins_get_by_recipient(const char * const recipient); +int wins_get_num(ProfWin *window); +int wins_get_current_num(void); +void wins_close_current(void); +void wins_close_by_num(int i); +void wins_refresh_current(void); +void wins_refresh_console(void); +void wins_clear_current(void); +gboolean wins_is_current(ProfWin *window); +ProfWin * wins_new(const char * const from, win_type_t type); +int wins_get_total_unread(void); +void wins_resize_all(void); +gboolean wins_duck_exists(void); +GSList * wins_get_chat_recipients(void); +GSList * wins_get_prune_recipients(void); +void wins_lost_connection(void); +gboolean wins_tidy(void); +GSList * wins_create_summary(void); +void wins_destroy(void); +GList * wins_get_nums(void); + +#endif diff --git a/tests/test_common.c b/tests/test_common.c index 6bdcfb76..37dd37d2 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -146,6 +146,283 @@ void replace_when_new_null(void) assert_string_equals("hello", result); } +void compare_win_nums_less(void) +{ + gconstpointer a = GINT_TO_POINTER(2); + gconstpointer b = GINT_TO_POINTER(3); + + int result = cmp_win_num(a, b); + + assert_true(result < 0); +} + +void compare_win_nums_equal(void) +{ + gconstpointer a = GINT_TO_POINTER(5); + gconstpointer b = GINT_TO_POINTER(5); + + int result = cmp_win_num(a, b); + + assert_true(result == 0); +} + +void compare_win_nums_greater(void) +{ + gconstpointer a = GINT_TO_POINTER(7); + gconstpointer b = GINT_TO_POINTER(6); + + int result = cmp_win_num(a, b); + + assert_true(result > 0); +} + +void compare_0s_equal(void) +{ + gconstpointer a = GINT_TO_POINTER(0); + gconstpointer b = GINT_TO_POINTER(0); + + int result = cmp_win_num(a, b); + + assert_true(result == 0); +} + +void compare_0_greater_than_1(void) +{ + gconstpointer a = GINT_TO_POINTER(0); + gconstpointer b = GINT_TO_POINTER(1); + + int result = cmp_win_num(a, b); + + assert_true(result > 0); +} + +void compare_1_less_than_0(void) +{ + gconstpointer a = GINT_TO_POINTER(1); + gconstpointer b = GINT_TO_POINTER(0); + + int result = cmp_win_num(a, b); + + assert_true(result < 0); +} + +void compare_0_less_than_11(void) +{ + gconstpointer a = GINT_TO_POINTER(0); + gconstpointer b = GINT_TO_POINTER(11); + + int result = cmp_win_num(a, b); + + assert_true(result < 0); +} + +void compare_11_greater_than_0(void) +{ + gconstpointer a = GINT_TO_POINTER(11); + gconstpointer b = GINT_TO_POINTER(0); + + int result = cmp_win_num(a, b); + + assert_true(result > 0); +} + +void compare_0_greater_than_9(void) +{ + gconstpointer a = GINT_TO_POINTER(0); + gconstpointer b = GINT_TO_POINTER(9); + + int result = cmp_win_num(a, b); + + assert_true(result > 0); +} + +void compare_9_less_than_0(void) +{ + gconstpointer a = GINT_TO_POINTER(9); + gconstpointer b = GINT_TO_POINTER(0); + + int result = cmp_win_num(a, b); + + assert_true(result < 0); +} + +void next_available_when_only_console(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + + int result = get_next_available_win_num(used); + + assert_int_equals(2, result); +} + +void next_available_3_at_end(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + + int result = get_next_available_win_num(used); + + assert_int_equals(3, result); +} + +void next_available_9_at_end(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + + int result = get_next_available_win_num(used); + + assert_int_equals(9, result); +} + +void next_available_0_at_end(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + used = g_list_append(used, GINT_TO_POINTER(9)); + + int result = get_next_available_win_num(used); + + assert_int_equals(0, result); +} + +void next_available_2_in_first_gap(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(9)); + used = g_list_append(used, GINT_TO_POINTER(0)); + + int result = get_next_available_win_num(used); + + assert_int_equals(2, result); +} + +void next_available_9_in_first_gap(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + used = g_list_append(used, GINT_TO_POINTER(0)); + used = g_list_append(used, GINT_TO_POINTER(11)); + used = g_list_append(used, GINT_TO_POINTER(12)); + used = g_list_append(used, GINT_TO_POINTER(13)); + used = g_list_append(used, GINT_TO_POINTER(20)); + + int result = get_next_available_win_num(used); + + assert_int_equals(9, result); +} + +void next_available_0_in_first_gap(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + used = g_list_append(used, GINT_TO_POINTER(9)); + used = g_list_append(used, GINT_TO_POINTER(11)); + used = g_list_append(used, GINT_TO_POINTER(12)); + used = g_list_append(used, GINT_TO_POINTER(13)); + used = g_list_append(used, GINT_TO_POINTER(20)); + + int result = get_next_available_win_num(used); + + assert_int_equals(0, result); +} + +void next_available_11_in_first_gap(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + used = g_list_append(used, GINT_TO_POINTER(9)); + used = g_list_append(used, GINT_TO_POINTER(0)); + used = g_list_append(used, GINT_TO_POINTER(12)); + used = g_list_append(used, GINT_TO_POINTER(13)); + used = g_list_append(used, GINT_TO_POINTER(20)); + + int result = get_next_available_win_num(used); + + assert_int_equals(11, result); +} + +void next_available_24_first_big_gap(void) +{ + GList *used = NULL; + used = g_list_append(used, GINT_TO_POINTER(1)); + used = g_list_append(used, GINT_TO_POINTER(2)); + used = g_list_append(used, GINT_TO_POINTER(3)); + used = g_list_append(used, GINT_TO_POINTER(4)); + used = g_list_append(used, GINT_TO_POINTER(5)); + used = g_list_append(used, GINT_TO_POINTER(6)); + used = g_list_append(used, GINT_TO_POINTER(7)); + used = g_list_append(used, GINT_TO_POINTER(8)); + used = g_list_append(used, GINT_TO_POINTER(9)); + used = g_list_append(used, GINT_TO_POINTER(0)); + used = g_list_append(used, GINT_TO_POINTER(11)); + used = g_list_append(used, GINT_TO_POINTER(12)); + used = g_list_append(used, GINT_TO_POINTER(13)); + used = g_list_append(used, GINT_TO_POINTER(14)); + used = g_list_append(used, GINT_TO_POINTER(15)); + used = g_list_append(used, GINT_TO_POINTER(16)); + used = g_list_append(used, GINT_TO_POINTER(17)); + used = g_list_append(used, GINT_TO_POINTER(18)); + used = g_list_append(used, GINT_TO_POINTER(19)); + used = g_list_append(used, GINT_TO_POINTER(20)); + used = g_list_append(used, GINT_TO_POINTER(21)); + used = g_list_append(used, GINT_TO_POINTER(22)); + used = g_list_append(used, GINT_TO_POINTER(23)); + used = g_list_append(used, GINT_TO_POINTER(51)); + used = g_list_append(used, GINT_TO_POINTER(52)); + used = g_list_append(used, GINT_TO_POINTER(53)); + used = g_list_append(used, GINT_TO_POINTER(89)); + used = g_list_append(used, GINT_TO_POINTER(90)); + used = g_list_append(used, GINT_TO_POINTER(100)); + used = g_list_append(used, GINT_TO_POINTER(101)); + used = g_list_append(used, GINT_TO_POINTER(102)); + + int result = get_next_available_win_num(used); + + assert_int_equals(24, result); +} + void register_common_tests(void) { TEST_MODULE("common tests"); @@ -162,4 +439,23 @@ void register_common_tests(void) TEST(replace_when_sub_null); TEST(replace_when_new_empty); TEST(replace_when_new_null); + TEST(compare_win_nums_less); + TEST(compare_win_nums_equal); + TEST(compare_win_nums_greater); + TEST(compare_0s_equal); + TEST(compare_0_greater_than_1); + TEST(compare_1_less_than_0); + TEST(compare_0_less_than_11); + TEST(compare_11_greater_than_0); + TEST(compare_0_greater_than_9); + TEST(compare_9_less_than_0); + TEST(next_available_when_only_console); + TEST(next_available_3_at_end); + TEST(next_available_9_at_end); + TEST(next_available_0_at_end); + TEST(next_available_2_in_first_gap); + TEST(next_available_9_in_first_gap); + TEST(next_available_0_in_first_gap); + TEST(next_available_11_in_first_gap); + TEST(next_available_24_first_big_gap); } |