diff --git a/Makefile.am b/Makefile.am index 697d2e6a..61aace12 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,8 +8,9 @@ profanity_SOURCES = src/contact.c src/contact.h src/log.c src/common.c \ src/xmpp/iq.c src/xmpp/message.c src/xmpp/presence.c src/xmpp/stanza.c \ src/xmpp/stanza.h src/xmpp/message.h src/xmpp/iq.h src/xmpp/presence.h \ src/xmpp/capabilities.h src/xmpp/connection.h \ - src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/windows.c \ + 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/command/command.h src/command/command.c src/command/history.c \ src/command/history.h src/command/parser.c \ src/command/parser.h \ diff --git a/src/command/command.c b/src/command/command.c index 1a0596b6..6cbfdac9 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -499,11 +499,14 @@ static struct cmd_t setting_commands[] = " : use 0 to disable.", "typing : Notifications when contacts are typing.", " : on|off", + "invite : Notifications for chat room invites.", + " : on|off", "", "Example : /notify message on (enable message notifications)", "Example : /notify remind 10 (remind every 10 seconds)", "Example : /notify remind 0 (switch off reminders)", "Example : /notify typing on (enable typing notifications)", + "Example : /notify invite on (enable chat room invite notifications)", NULL } } }, { "/flash", @@ -783,6 +786,7 @@ cmd_init(void) autocomplete_add(notify_ac, strdup("message")); autocomplete_add(notify_ac, strdup("typing")); autocomplete_add(notify_ac, strdup("remind")); + autocomplete_add(notify_ac, strdup("invite")); autocomplete_add(notify_ac, strdup("status")); sub_ac = autocomplete_new(); @@ -917,8 +921,8 @@ cmd_reset_autocomplete() autocomplete_reset(notify_ac); autocomplete_reset(sub_ac); - if (win_current_is_groupchat()) { - Autocomplete nick_ac = muc_get_roster_ac(win_current_get_recipient()); + if (ui_current_win_type() == WIN_MUC) { + Autocomplete nick_ac = muc_get_roster_ac(ui_current_recipient()); if (nick_ac != NULL) { autocomplete_reset(nick_ac); } @@ -989,10 +993,10 @@ cmd_execute(const char * const command, const char * const inp) gchar **args = cmd->parser(inp, cmd->min_args, cmd->max_args); if (args == NULL) { cons_show("Usage: %s", cmd->help.usage); - if (win_current_is_chat()) { + if (ui_current_win_type() == WIN_CHAT) { char usage[strlen(cmd->help.usage) + 8]; sprintf(usage, "Usage: %s", cmd->help.usage); - win_current_show(usage); + ui_current_print_line(usage); } return TRUE; } else { @@ -1008,35 +1012,54 @@ cmd_execute(const char * const command, const char * const inp) gboolean cmd_execute_default(const char * const inp) { - if (win_current_is_groupchat()) { - jabber_conn_status_t status = jabber_get_connection_status(); - if (status != JABBER_CONNECTED) { - win_current_show("You are not currently connected."); - } else { - char *recipient = win_current_get_recipient(); - message_send_groupchat(inp, recipient); - free(recipient); - } - } else if (win_current_is_chat() || win_current_is_private()) { - jabber_conn_status_t status = jabber_get_connection_status(); - if (status != JABBER_CONNECTED) { - win_current_show("You are not currently connected."); - } else { - char *recipient = win_current_get_recipient(); - message_send(inp, recipient); + win_type_t win_type = ui_current_win_type(); + jabber_conn_status_t status = jabber_get_connection_status(); + char *recipient = ui_current_recipient(); - if (win_current_is_chat() && prefs_get_boolean(PREF_CHLOG)) { - const char *jid = jabber_get_jid(); - Jid *jidp = jid_create(jid); - chat_log_chat(jidp->barejid, recipient, inp, PROF_OUT_LOG, NULL); - jid_destroy(jidp); + switch (win_type) + { + case WIN_MUC: + if (status != JABBER_CONNECTED) { + ui_current_print_line("You are not currently connected."); + } else { + message_send_groupchat(inp, recipient); + free(recipient); } + break; - win_show_outgoing_msg("me", recipient, inp); - free(recipient); - } - } else { - cons_bad_command(inp); + case WIN_CHAT: + if (status != JABBER_CONNECTED) { + ui_current_print_line("You are not currently connected."); + } else { + message_send(inp, recipient); + + if (prefs_get_boolean(PREF_CHLOG)) { + const char *jid = jabber_get_jid(); + Jid *jidp = jid_create(jid); + chat_log_chat(jidp->barejid, recipient, inp, PROF_OUT_LOG, NULL); + jid_destroy(jidp); + } + + ui_outgoing_msg("me", recipient, inp); + free(recipient); + } + break; + + case WIN_PRIVATE: + if (status != JABBER_CONNECTED) { + ui_current_print_line("You are not currently connected."); + } else { + message_send(inp, recipient); + ui_outgoing_msg("me", recipient, inp); + free(recipient); + } + break; + + case WIN_CONSOLE: + cons_show("Unknown command: %s", inp); + break; + default: + break; } return TRUE; @@ -1068,8 +1091,8 @@ _cmd_complete_parameters(char *input, int *size) _parameter_autocomplete(input, size, "/statuses", prefs_autocomplete_boolean_choice); - if (win_current_is_groupchat()) { - Autocomplete nick_ac = muc_get_roster_ac(win_current_get_recipient()); + if (ui_current_win_type() == WIN_MUC) { + Autocomplete nick_ac = muc_get_roster_ac(ui_current_recipient()); if (nick_ac != NULL) { _parameter_autocomplete_with_ac(input, size, "/msg", nick_ac); _parameter_autocomplete_with_ac(input, size, "/info", nick_ac); @@ -1149,7 +1172,7 @@ _cmd_connect(gchar **args, struct cmd_help_t help) } if (conn_status == JABBER_DISCONNECTED) { - cons_bad_show("Connection attempt for %s failed.", jid); + cons_show_error("Connection attempt for %s failed.", jid); log_debug("Connection attempt for %s failed", jid); } @@ -1333,6 +1356,7 @@ static gboolean _cmd_sub(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); if (conn_status != JABBER_CONNECTED) { cons_show("You are currently not connected."); @@ -1383,7 +1407,7 @@ _cmd_sub(gchar **args, struct cmd_help_t help) return TRUE; } - if (!win_current_is_chat() && (jid == NULL)) { + if ((win_type != WIN_CHAT) && (jid == NULL)) { cons_show("You must specify a contact."); return TRUE; } @@ -1391,7 +1415,7 @@ _cmd_sub(gchar **args, struct cmd_help_t help) if (jid != NULL) { jid = strdup(jid); } else { - jid = win_current_get_recipient(); + jid = ui_current_recipient(); } bare_jid = strtok(jid, "/"); @@ -1411,18 +1435,18 @@ _cmd_sub(gchar **args, struct cmd_help_t help) } else if (strcmp(subcmd, "show") == 0) { PContact contact = contact_list_get_contact(bare_jid); if ((contact == NULL) || (p_contact_subscription(contact) == NULL)) { - if (win_current_is_chat()) { - win_current_show("No subscription information for %s.", bare_jid); + if (win_type == WIN_CHAT) { + ui_current_print_line("No subscription information for %s.", bare_jid); } else { cons_show("No subscription information for %s.", bare_jid); } } else { - if (win_current_is_chat()) { + if (win_type == WIN_CHAT) { if (p_contact_pending_out(contact)) { - win_current_show("%s subscription status: %s, request pending.", + ui_current_print_line("%s subscription status: %s, request pending.", bare_jid, p_contact_subscription(contact)); } else { - win_current_show("%s subscription status: %s.", bare_jid, + ui_current_print_line("%s subscription status: %s.", bare_jid, p_contact_subscription(contact)); } } else { @@ -1550,6 +1574,9 @@ _cmd_about(gchar **args, struct cmd_help_t help) { cons_show(""); cons_about(); + if (ui_current_win_type() != WIN_CONSOLE) { + status_bar_new(0); + } return TRUE; } @@ -1620,6 +1647,7 @@ static gboolean _cmd_who(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); @@ -1640,13 +1668,13 @@ _cmd_who(gchar **args, struct cmd_help_t help) // valid arg } else { - if (win_current_is_groupchat()) { - char *room = win_current_get_recipient(); + if (win_type == WIN_MUC) { + char *room = ui_current_recipient(); GList *list = muc_get_roster(room); // no arg, show all contacts if (presence == NULL) { - win_show_room_roster(room, list, NULL); + ui_room_roster(room, list, NULL); // available } else if (strcmp("available", presence) == 0) { @@ -1660,7 +1688,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) list = g_list_next(list); } - win_show_room_roster(room, filtered, "available"); + ui_room_roster(room, filtered, "available"); // unavailable } else if (strcmp("unavailable", presence) == 0) { @@ -1674,7 +1702,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) list = g_list_next(list); } - win_show_room_roster(room, filtered, "unavailable"); + ui_room_roster(room, filtered, "unavailable"); // online, available resources } else if (strcmp("online", presence) == 0) { @@ -1688,7 +1716,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) list = g_list_next(list); } - win_show_room_roster(room, filtered, "online"); + ui_room_roster(room, filtered, "online"); // offline, no available resources } else if (strcmp("offline", presence) == 0) { @@ -1702,7 +1730,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) list = g_list_next(list); } - win_show_room_roster(room, filtered, "offline"); + ui_room_roster(room, filtered, "offline"); // show specific status } else { @@ -1716,7 +1744,7 @@ _cmd_who(gchar **args, struct cmd_help_t help) list = g_list_next(list); } - win_show_room_roster(room, filtered, presence); + ui_room_roster(room, filtered, presence); } // not in groupchat window @@ -1808,6 +1836,10 @@ _cmd_who(gchar **args, struct cmd_help_t help) } } + if (win_type != WIN_CONSOLE) { + status_bar_new(0); + } + return TRUE; } @@ -1818,6 +1850,7 @@ _cmd_msg(gchar **args, struct cmd_help_t help) char *msg = args[1]; jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); @@ -1825,12 +1858,12 @@ _cmd_msg(gchar **args, struct cmd_help_t help) } if (ui_windows_full()) { - cons_bad_show("Windows all used, close a window and try again."); + cons_show_error("Windows all used, close a window and try again."); return TRUE; } - if (win_current_is_groupchat()) { - char *room_name = win_current_get_recipient(); + if (win_type == WIN_MUC) { + char *room_name = ui_current_recipient(); if (muc_nick_in_roster(room_name, usr)) { GString *full_jid = g_string_new(room_name); g_string_append(full_jid, "/"); @@ -1838,15 +1871,15 @@ _cmd_msg(gchar **args, struct cmd_help_t help) if (msg != NULL) { message_send(msg, full_jid->str); - win_show_outgoing_msg("me", full_jid->str, msg); + ui_outgoing_msg("me", full_jid->str, msg); } else { - win_new_chat_win(full_jid->str); + ui_new_chat_win(full_jid->str); } g_string_free(full_jid, TRUE); } else { - win_current_show("No such participant \"%s\" in room.", usr); + ui_current_print_line("No such participant \"%s\" in room.", usr); } return TRUE; @@ -1854,9 +1887,9 @@ _cmd_msg(gchar **args, struct cmd_help_t help) } else { if (msg != NULL) { message_send(msg, usr); - win_show_outgoing_msg("me", usr, msg); + ui_outgoing_msg("me", usr, msg); - if (win_current_is_chat() && prefs_get_boolean(PREF_CHLOG)) { + if ((win_type == WIN_CHAT) && prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_jid(); Jid *jidp = jid_create(jid); chat_log_chat(jidp->barejid, usr, msg, PROF_OUT_LOG, NULL); @@ -1865,7 +1898,7 @@ _cmd_msg(gchar **args, struct cmd_help_t help) return TRUE; } else { - win_new_chat_win(usr); + ui_new_chat_win(usr); return TRUE; } } @@ -1877,35 +1910,45 @@ _cmd_status(gchar **args, struct cmd_help_t help) char *usr = args[0]; jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); - } else { - if (win_current_is_groupchat()) { + return TRUE; + } + + switch (win_type) + { + case WIN_MUC: if (usr != NULL) { - win_room_show_status(usr); + ui_status_room(usr); } else { - win_current_show("You must specify a nickname."); + ui_current_print_line("You must specify a nickname."); } - } else if (win_current_is_chat()) { + break; + case WIN_CHAT: if (usr != NULL) { - win_current_show("No parameter required when in chat."); + ui_current_print_line("No parameter required when in chat."); } else { - win_show_status(); + ui_status(); } - } else if (win_current_is_private()) { + break; + case WIN_PRIVATE: if (usr != NULL) { - win_current_show("No parameter required when in chat."); + ui_current_print_line("No parameter required when in chat."); } else { - win_private_show_status(); + ui_status_private(); } - } else { + break; + case WIN_CONSOLE: if (usr != NULL) { cons_show_status(usr); } else { cons_show("Usage: %s", help.usage); } - } + break; + default: + break; } return TRUE; @@ -1917,13 +1960,19 @@ _cmd_info(gchar **args, struct cmd_help_t help) char *usr = args[0]; jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); + PContact pcontact = NULL; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); - } else { - if (win_current_is_groupchat()) { + return TRUE; + } + + switch (win_type) + { + case WIN_MUC: if (usr != NULL) { - PContact pcontact = muc_get_participant(win_current_get_recipient(), usr); + pcontact = muc_get_participant(ui_current_recipient(), usr); if (pcontact != NULL) { cons_show_info(pcontact); } else { @@ -1932,25 +1981,25 @@ _cmd_info(gchar **args, struct cmd_help_t help) } else { cons_show("No nickname supplied to /info in chat room."); } - - } else if (win_current_is_chat()) { + break; + case WIN_CHAT: if (usr != NULL) { cons_show("No parameter required for /info in chat."); } else { - PContact pcontact = contact_list_get_contact(win_current_get_recipient()); + pcontact = contact_list_get_contact(ui_current_recipient()); if (pcontact != NULL) { cons_show_info(pcontact); } else { - cons_show("No such contact \"%s\" in roster.", win_current_get_recipient()); + cons_show("No such contact \"%s\" in roster.", ui_current_recipient()); } } - - } else if (win_current_is_private()) { + break; + case WIN_PRIVATE: if (usr != NULL) { - win_current_show("No parameter required when in chat."); + ui_current_print_line("No parameter required when in chat."); } else { - Jid *jid = jid_create(win_current_get_recipient()); - PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + Jid *jid = jid_create(ui_current_recipient()); + pcontact = muc_get_participant(jid->barejid, jid->resourcepart); if (pcontact != NULL) { cons_show_info(pcontact); } else { @@ -1958,9 +2007,10 @@ _cmd_info(gchar **args, struct cmd_help_t help) } jid_destroy(jid); } - } else { + break; + case WIN_CONSOLE: if (usr != NULL) { - PContact pcontact = contact_list_get_contact(usr); + pcontact = contact_list_get_contact(usr); if (pcontact != NULL) { cons_show_info(pcontact); } else { @@ -1969,7 +2019,9 @@ _cmd_info(gchar **args, struct cmd_help_t help) } else { cons_show("Usage: %s", help.usage); } - } + break; + default: + break; } return TRUE; @@ -1979,13 +2031,19 @@ static gboolean _cmd_caps(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); + PContact pcontact = NULL; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); - } else { - if (win_current_is_groupchat()) { + return TRUE; + } + + switch (win_type) + { + case WIN_MUC: if (args[0] != NULL) { - PContact pcontact = muc_get_participant(win_current_get_recipient(), args[0]); + pcontact = muc_get_participant(ui_current_recipient(), args[0]); if (pcontact != NULL) { Resource *resource = p_contact_get_resource(pcontact, args[0]); cons_show_caps(args[0], resource); @@ -1995,14 +2053,16 @@ _cmd_caps(gchar **args, struct cmd_help_t help) } else { cons_show("No nickname supplied to /caps in chat room."); } - } else if (win_current_is_chat() || win_current_is_console()) { + break; + case WIN_CHAT: + case WIN_CONSOLE: if (args[0] != NULL) { Jid *jid = jid_create(args[0]); if (jid->fulljid == NULL) { cons_show("You must provide a full jid to the /caps command."); } else { - PContact pcontact = contact_list_get_contact(jid->barejid); + pcontact = contact_list_get_contact(jid->barejid); if (pcontact == NULL) { cons_show("Contact not found in roster: %s", jid->barejid); } else { @@ -2017,16 +2077,19 @@ _cmd_caps(gchar **args, struct cmd_help_t help) } else { cons_show("You must provide a jid to the /caps command."); } - } else { // private chat + break; + case WIN_PRIVATE: if (args[0] != NULL) { cons_show("No parameter needed to /caps when in private chat."); } else { - Jid *jid = jid_create(win_current_get_recipient()); - PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + Jid *jid = jid_create(ui_current_recipient()); + pcontact = muc_get_participant(jid->barejid, jid->resourcepart); Resource *resource = p_contact_get_resource(pcontact, jid->resourcepart); cons_show_caps(jid->resourcepart, resource); } - } + break; + default: + break; } return TRUE; @@ -2037,15 +2100,21 @@ static gboolean _cmd_software(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); + PContact pcontact = NULL; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); - } else { - if (win_current_is_groupchat()) { + return TRUE; + } + + switch (win_type) + { + case WIN_MUC: if (args[0] != NULL) { - PContact pcontact = muc_get_participant(win_current_get_recipient(), args[0]); + pcontact = muc_get_participant(ui_current_recipient(), args[0]); if (pcontact != NULL) { - Jid *jid = jid_create_from_bare_and_resource(win_current_get_recipient(), args[0]); + Jid *jid = jid_create_from_bare_and_resource(ui_current_recipient(), args[0]); iq_send_software_version(jid->fulljid); jid_destroy(jid); } else { @@ -2054,7 +2123,9 @@ _cmd_software(gchar **args, struct cmd_help_t help) } else { cons_show("No nickname supplied to /software in chat room."); } - } else if (win_current_is_chat() || win_current_is_console()) { + break; + case WIN_CHAT: + case WIN_CONSOLE: if (args[0] != NULL) { Jid *jid = jid_create(args[0]); @@ -2066,13 +2137,16 @@ _cmd_software(gchar **args, struct cmd_help_t help) } else { cons_show("You must provide a jid to the /software command."); } - } else { // private chat + break; + case WIN_PRIVATE: if (args[0] != NULL) { cons_show("No parameter needed to /software when in private chat."); } else { - iq_send_software_version(win_current_get_recipient()); + iq_send_software_version(ui_current_recipient()); } - } + break; + default: + break; } return TRUE; @@ -2089,7 +2163,7 @@ _cmd_join(gchar **args, struct cmd_help_t help) } if (ui_windows_full()) { - cons_bad_show("Windows all used, close a window and try again."); + cons_show_error("Windows all used, close a window and try again."); return TRUE; } @@ -2126,7 +2200,7 @@ _cmd_join(gchar **args, struct cmd_help_t help) if (!muc_room_is_active(room_jid)) { presence_join_room(room_jid); } - win_join_chat(room_jid); + ui_room_join(room_jid); jid_destroy(room_jid); jid_destroy(my_jid); @@ -2148,12 +2222,12 @@ _cmd_invite(gchar **args, struct cmd_help_t help) return TRUE; } - if (!win_current_is_groupchat()) { + if (ui_current_win_type() != WIN_MUC) { cons_show("You must be in a chat room to send an invite."); return TRUE; } - room = win_current_get_recipient(); + room = ui_current_recipient(); message_send_invite(room, contact, reason); if (reason != NULL) { cons_show("Room invite sent, contact: %s, room: %s, reason: \"%s\".", @@ -2229,12 +2303,12 @@ _cmd_nick(gchar **args, struct cmd_help_t help) cons_show("You are not currently connected."); return TRUE; } - if (!win_current_is_groupchat()) { + if (ui_current_win_type() != WIN_MUC) { cons_show("You can only change your nickname in a chat room window."); return TRUE; } - char *room = win_current_get_recipient(); + char *room = ui_current_recipient(); char *nick = args[0]; presence_change_room_nick(room, nick); @@ -2245,21 +2319,22 @@ static gboolean _cmd_tiny(gchar **args, struct cmd_help_t help) { char *url = args[0]; + win_type_t win_type = ui_current_win_type(); if (!tinyurl_valid(url)) { GString *error = g_string_new("/tiny, badly formed URL: "); g_string_append(error, url); - cons_bad_show(error->str); - if (!win_current_is_console()) { - win_current_bad_show(error->str); + cons_show_error(error->str); + if (win_type != WIN_CONSOLE) { + ui_current_error_line(error->str); } g_string_free(error, TRUE); - } else if (!win_current_is_console()) { + } else if (win_type != WIN_CONSOLE) { char *tiny = tinyurl_get(url); if (tiny != NULL) { - if (win_current_is_chat()) { - char *recipient = win_current_get_recipient(); + if (win_type == WIN_CHAT) { + char *recipient = ui_current_recipient(); message_send(tiny, recipient); if (prefs_get_boolean(PREF_CHLOG)) { @@ -2269,21 +2344,21 @@ _cmd_tiny(gchar **args, struct cmd_help_t help) jid_destroy(jidp); } - win_show_outgoing_msg("me", recipient, tiny); + ui_outgoing_msg("me", recipient, tiny); free(recipient); - } else if (win_current_is_private()) { - char *recipient = win_current_get_recipient(); + } else if (win_type == WIN_PRIVATE) { + char *recipient = ui_current_recipient(); message_send(tiny, recipient); - win_show_outgoing_msg("me", recipient, tiny); + ui_outgoing_msg("me", recipient, tiny); free(recipient); } else { // groupchat - char *recipient = win_current_get_recipient(); + char *recipient = ui_current_recipient(); message_send_groupchat(tiny, recipient); free(recipient); } free(tiny); } else { - cons_bad_show("Couldn't get tinyurl."); + cons_show_error("Couldn't get tinyurl."); } } else { cons_show("/tiny can only be used in chat windows"); @@ -2295,7 +2370,7 @@ _cmd_tiny(gchar **args, struct cmd_help_t help) static gboolean _cmd_clear(gchar **args, struct cmd_help_t help) { - win_current_clear(); + ui_clear_current(); return TRUE; } @@ -2303,22 +2378,23 @@ static gboolean _cmd_close(gchar **args, struct cmd_help_t help) { jabber_conn_status_t conn_status = jabber_get_connection_status(); + win_type_t win_type = ui_current_win_type(); // cannot close console window - if (win_current_is_console()) { + if (win_type == WIN_CONSOLE) { cons_show("Cannot close console window."); return TRUE; } // handle leaving rooms, or chat if (conn_status == JABBER_CONNECTED) { - if (win_current_is_groupchat()) { - char *room_jid = win_current_get_recipient(); + if (win_type == WIN_MUC) { + char *room_jid = ui_current_recipient(); presence_leave_chat_room(room_jid); - } else if (win_current_is_chat() || win_current_is_private()) { + } else if ((win_type == WIN_CHAT) || (win_type == WIN_PRIVATE)) { if (prefs_get_boolean(PREF_STATES)) { - char *recipient = win_current_get_recipient(); + char *recipient = ui_current_recipient(); // send chat state before closing if (chat_session_get_recipient_supports(recipient)) { @@ -2331,7 +2407,7 @@ _cmd_close(gchar **args, struct cmd_help_t help) } // close the window - win_current_close(); + ui_close_current(); return TRUE; } @@ -2415,7 +2491,7 @@ _cmd_set_notify(gchar **args, struct cmd_help_t help) // bad kind if ((strcmp(kind, "message") != 0) && (strcmp(kind, "typing") != 0) && - (strcmp(kind, "remind") != 0)) { + (strcmp(kind, "remind") != 0) && (strcmp(kind, "invite") != 0)) { cons_show("Usage: %s", help.usage); // set message setting @@ -2442,6 +2518,18 @@ _cmd_set_notify(gchar **args, struct cmd_help_t help) cons_show("Usage: /notify typing on|off"); } + // set invite setting + } else if (strcmp(kind, "invite") == 0) { + if (strcmp(value, "on") == 0) { + cons_show("Chat room invite notifications enabled."); + prefs_set_boolean(PREF_NOTIFY_INVITE, TRUE); + } else if (strcmp(value, "off") == 0) { + cons_show("Chat room invite notifications disabled."); + prefs_set_boolean(PREF_NOTIFY_INVITE, FALSE); + } else { + cons_show("Usage: /notify invite on|off"); + } + // set remind setting } else if (strcmp(kind, "remind") == 0) { gint period = atoi(value); diff --git a/src/common.c b/src/common.c index 641151db..94b2872c 100644 --- a/src/common.c +++ b/src/common.c @@ -19,6 +19,7 @@ * along with Profanity. If not, see . * */ +#include "config.h" #include #include @@ -260,6 +261,32 @@ release_get_latest() } } +gboolean +release_is_new(char *found_version) +{ + int curr_maj, curr_min, curr_patch, found_maj, found_min, found_patch; + + int parse_curr = sscanf(PACKAGE_VERSION, "%d.%d.%d", &curr_maj, &curr_min, + &curr_patch); + int parse_found = sscanf(found_version, "%d.%d.%d", &found_maj, &found_min, + &found_patch); + + if (parse_found == 3 && parse_curr == 3) { + if (found_maj > curr_maj) { + return TRUE; + } else if (found_maj == curr_maj && found_min > curr_min) { + return TRUE; + } else if (found_maj == curr_maj && found_min == curr_min + && found_patch > curr_patch) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + gboolean valid_resource_presence_string(const char * const str) { diff --git a/src/common.h b/src/common.h index 59307b35..96c5d08c 100644 --- a/src/common.h +++ b/src/common.h @@ -83,6 +83,7 @@ char* encode_xml(const char * const xml); char * prof_getline(FILE *stream); int octet_compare(unsigned char *str1, unsigned char *str2); char* release_get_latest(void); +gboolean release_is_new(char *found_version); gchar * xdg_get_config_home(void); gchar * xdg_get_data_home(void); diff --git a/src/config/preferences.c b/src/config/preferences.c index 1abab5f6..d6d37234 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -299,6 +299,7 @@ _get_group(preference_t pref) return "chatstates"; case PREF_NOTIFY_TYPING: case PREF_NOTIFY_MESSAGE: + case PREF_NOTIFY_INVITE: return "notifications"; case PREF_CHLOG: return "logging"; @@ -344,6 +345,8 @@ _get_key(preference_t pref) return "typing"; case PREF_NOTIFY_MESSAGE: return "message"; + case PREF_NOTIFY_INVITE: + return "invite"; case PREF_CHLOG: return "chlog"; case PREF_AUTOAWAY_CHECK: diff --git a/src/config/preferences.h b/src/config/preferences.h index 70254e25..bdfe7a95 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -50,6 +50,7 @@ typedef enum { PREF_OUTTYPE, PREF_NOTIFY_TYPING, PREF_NOTIFY_MESSAGE, + PREF_NOTIFY_INVITE, PREF_CHLOG, PREF_AUTOAWAY_CHECK, PREF_AUTOAWAY_MODE, diff --git a/src/profanity.c b/src/profanity.c index 2d37b817..052575a9 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -42,6 +42,7 @@ #include "log.h" #include "muc.h" #include "resource.h" +#include "ui/notifier.h" #include "ui/ui.h" #include "xmpp/xmpp.h" @@ -102,15 +103,15 @@ prof_run(const int disable_tls, char *log_level) void prof_handle_typing(char *from) { - ui_show_typing(from); - win_current_page_off(); + ui_contact_typing(from); + ui_current_page_off(); } void prof_handle_incoming_message(char *from, char *message, gboolean priv) { - ui_show_incoming_msg(from, message, NULL, priv); - win_current_page_off(); + ui_incoming_msg(from, message, NULL, priv); + ui_current_page_off(); if (prefs_get_boolean(PREF_CHLOG) && !priv) { Jid *from_jid = jid_create(from); @@ -126,8 +127,8 @@ void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp, gboolean priv) { - ui_show_incoming_msg(from, message, &tv_stamp, priv); - win_current_page_off(); + ui_incoming_msg(from, message, &tv_stamp, priv); + ui_current_page_off(); if (prefs_get_boolean(PREF_CHLOG) && !priv) { Jid *from_jid = jid_create(from); @@ -142,19 +143,20 @@ prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp, void prof_handle_error_message(const char *from, const char *err_msg) { + win_type_t win_type = ui_current_win_type(); if (err_msg == NULL) { - cons_bad_show("Unknown error received from service."); + cons_show_error("Unknown error received from service."); } else if (strcmp(err_msg, "conflict") == 0) { - if (win_current_is_groupchat()) { - win_current_show("Nickname already in use."); + if (win_type == WIN_MUC) { + ui_current_print_line("Nickname already in use."); } else { - cons_bad_show("Error received from server: %s", err_msg); + cons_show_error("Error received from server: %s", err_msg); } } else { - cons_bad_show("Error received from server: %s", err_msg); + cons_show_error("Error received from server: %s", err_msg); } - win_show_error_msg(from, err_msg); + ui_print_error_from_recipient(from, err_msg); } void @@ -165,20 +167,20 @@ prof_handle_subscription(const char *from, jabber_subscr_t type) /* TODO: auto-subscribe if needed */ cons_show("Received authorization request from %s", from); log_info("Received authorization request from %s", from); - win_show_system_msg(from, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject"); - win_current_page_off(); + ui_print_system_msg_from_recipient(from, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject"); + ui_current_page_off(); break; case PRESENCE_SUBSCRIBED: cons_show("Subscription received from %s", from); log_info("Subscription received from %s", from); - win_show_system_msg(from, "Subscribed"); - win_current_page_off(); + ui_print_system_msg_from_recipient(from, "Subscribed"); + ui_current_page_off(); break; case PRESENCE_UNSUBSCRIBED: cons_show("%s deleted subscription", from); log_info("%s deleted subscription", from); - win_show_system_msg(from, "Unsubscribed"); - win_current_page_off(); + ui_print_system_msg_from_recipient(from, "Unsubscribed"); + ui_current_page_off(); break; default: /* unknown type */ @@ -195,7 +197,7 @@ prof_handle_login_account_success(char *account_name) cons_show_login_success(account); title_bar_set_status(contact_presence); log_info("%s logged in successfully", account->jid); - win_current_page_off(); + ui_current_page_off(); status_bar_print_message(account->jid); status_bar_refresh(); @@ -205,26 +207,26 @@ prof_handle_login_account_success(char *account_name) void prof_handle_gone(const char * const from) { - win_show_gone(from); - win_current_page_off(); + ui_recipient_gone(from); + ui_current_page_off(); } void prof_handle_failed_login(void) { - cons_bad_show("Login failed."); + cons_show_error("Login failed."); log_info("Login failed"); - win_current_page_off(); + ui_current_page_off(); } void prof_handle_lost_connection(void) { - cons_bad_show("Lost connection."); + cons_show_error("Lost connection."); contact_list_clear(); chat_sessions_clear(); ui_disconnected(); - win_current_page_off(); + ui_current_page_off(); } void @@ -235,38 +237,38 @@ prof_handle_disconnect(const char * const jid) contact_list_clear(); chat_sessions_clear(); ui_disconnected(); - win_current_page_off(); + ui_current_page_off(); } void prof_handle_room_history(const char * const room_jid, const char * const nick, GTimeVal tv_stamp, const char * const message) { - win_show_room_history(room_jid, nick, tv_stamp, message); - win_current_page_off(); + ui_room_history(room_jid, nick, tv_stamp, message); + ui_current_page_off(); } void prof_handle_room_message(const char * const room_jid, const char * const nick, const char * const message) { - win_show_room_message(room_jid, nick, message); - win_current_page_off(); + ui_room_message(room_jid, nick, message); + ui_current_page_off(); } void prof_handle_room_subject(const char * const room_jid, const char * const subject) { - win_show_room_subject(room_jid, subject); - win_current_page_off(); + ui_room_subject(room_jid, subject); + ui_current_page_off(); } void prof_handle_room_broadcast(const char *const room_jid, const char * const message) { - win_show_room_broadcast(room_jid, message); - win_current_page_off(); + ui_room_broadcast(room_jid, message); + ui_current_page_off(); } void @@ -274,8 +276,8 @@ prof_handle_room_roster_complete(const char * const room) { muc_set_roster_received(room); GList *roster = muc_get_roster(room); - win_show_room_roster(room, roster, NULL); - win_current_page_off(); + ui_room_roster(room, roster, NULL); + ui_current_page_off(); } void @@ -286,8 +288,8 @@ prof_handle_room_member_presence(const char * const room, gboolean updated = muc_add_to_roster(room, nick, show, status, caps_str); if (updated) { - win_show_room_member_presence(room, nick, show, status); - win_current_page_off(); + ui_room_member_presence(room, nick, show, status); + ui_current_page_off(); } } @@ -297,8 +299,8 @@ prof_handle_room_member_online(const char * const room, const char * const nick, const char * const caps_str) { muc_add_to_roster(room, nick, show, status, caps_str); - win_show_room_member_online(room, nick, show, status); - win_current_page_off(); + ui_room_member_online(room, nick, show, status); + ui_current_page_off(); } void @@ -306,8 +308,8 @@ prof_handle_room_member_offline(const char * const room, const char * const nick const char * const show, const char * const status) { muc_remove_from_roster(room, nick); - win_show_room_member_offline(room, nick); - win_current_page_off(); + ui_room_member_offline(room, nick); + ui_current_page_off(); } void @@ -321,7 +323,7 @@ void prof_handle_room_invite(jabber_invite_t invite_type, const char * const reason) { cons_show_room_invite(invitor, room, reason); - win_current_page_off(); + ui_current_page_off(); } void @@ -336,7 +338,7 @@ prof_handle_contact_online(char *contact, Resource *resource, if (strcmp(p_contact_subscription(result), "none") != 0) { const char *show = string_from_resource_presence(resource->presence); ui_contact_online(contact, resource->name, show, resource->status, last_activity); - win_current_page_off(); + ui_current_page_off(); } } } @@ -353,7 +355,7 @@ prof_handle_contact_offline(char *contact, char *resource, char *status) if (p_contact_subscription(result) != NULL) { if (strcmp(p_contact_subscription(result), "none") != 0) { ui_contact_offline(jid->fulljid, "offline", status); - win_current_page_off(); + ui_current_page_off(); } } jid_destroy(jid); @@ -364,16 +366,16 @@ void prof_handle_room_member_nick_change(const char * const room, const char * const old_nick, const char * const nick) { - win_show_room_member_nick_change(room, old_nick, nick); - win_current_page_off(); + ui_room_member_nick_change(room, old_nick, nick); + ui_current_page_off(); } void prof_handle_room_nick_change(const char * const room, const char * const nick) { - win_show_room_nick_change(room, nick); - win_current_page_off(); + ui_room_nick_change(room, nick); + ui_current_page_off(); } void @@ -388,15 +390,15 @@ prof_handle_idle(void) void prof_handle_activity(void) { + win_type_t win_type = ui_current_win_type(); jabber_conn_status_t status = jabber_get_connection_status(); - if (status == JABBER_CONNECTED) { - if (win_current_is_chat()) { - char *recipient = win_current_get_recipient(); - chat_session_set_composing(recipient); - if (!chat_session_get_sent(recipient) || - chat_session_is_paused(recipient)) { - message_send_composing(recipient); - } + + if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) { + char *recipient = ui_current_recipient(); + chat_session_set_composing(recipient); + if (!chat_session_get_sent(recipient) || + chat_session_is_paused(recipient)) { + message_send_composing(recipient); } } } @@ -406,28 +408,28 @@ prof_handle_version_result(const char * const jid, const char * const presence, const char * const name, const char * const version, const char * const os) { cons_show_software_version(jid, presence, name, version, os); - win_current_page_off(); + ui_current_page_off(); } void prof_handle_room_list(GSList *rooms, const char *conference_node) { cons_show_room_list(rooms, conference_node); - win_current_page_off(); + ui_current_page_off(); } void prof_handle_disco_items(GSList *items, const char *jid) { cons_show_disco_items(items, jid); - win_current_page_off(); + ui_current_page_off(); } void prof_handle_disco_info(const char *from, GSList *identities, GSList *features) { cons_show_disco_info(from, identities, features); - win_current_page_off(); + ui_current_page_off(); } /* @@ -464,7 +466,7 @@ _process_input(char *inp) inp_win_reset(); contact_list_reset_search_attempts(); - win_current_page_off(); + ui_current_page_off(); return result; } @@ -489,7 +491,7 @@ _handle_idle_time() cons_show("Idle for %d minutes, status set to away (priority %d), \"%s\".", prefs_get_autoaway_time(), pri, prefs_get_string(PREF_AUTOAWAY_MESSAGE)); title_bar_set_status(CONTACT_AWAY); - win_current_page_off(); + ui_current_page_off(); } else { int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), @@ -497,7 +499,7 @@ _handle_idle_time() cons_show("Idle for %d minutes, status set to away (priority %d).", prefs_get_autoaway_time(), pri); title_bar_set_status(CONTACT_AWAY); - win_current_page_off(); + ui_current_page_off(); } // handle idle mode @@ -520,7 +522,7 @@ _handle_idle_time() RESOURCE_ONLINE); cons_show("No longer idle, status set to online (priority %d).", pri); title_bar_set_status(CONTACT_ONLINE); - win_current_page_off(); + ui_current_page_off(); } else if (strcmp(prefs_get_string(PREF_AUTOAWAY_MODE), "idle") == 0) { presence_update(RESOURCE_ONLINE, NULL, 0); title_bar_set_status(CONTACT_ONLINE); diff --git a/src/ui/console.c b/src/ui/console.c new file mode 100644 index 00000000..36358635 --- /dev/null +++ b/src/ui/console.c @@ -0,0 +1,1250 @@ +/* + * console.c + * + * Copyright (C) 2012, 2013 James Booth + * + * 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 . + * + */ + +#include +#include + +#ifdef HAVE_NCURSESW_NCURSES_H +#include +#elif HAVE_NCURSES_H +#include +#endif + +#include "command/command.h" +#include "common.h" +#include "config/preferences.h" +#include "contact_list.h" +#include "config/theme.h" +#include "ui/notifier.h" +#include "ui/window.h" +#include "ui/ui.h" + +#define CONS_WIN_TITLE "_cons" + +static ProfWin* console; + +static void _cons_splash_logo(void); +static void _cons_show_basic_help(void); +static void _cons_alert(void); + +ProfWin * +cons_create(void) +{ + int cols = getmaxx(stdscr); + console = win_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); + return console; +} + +void +cons_show_time(void) +{ + win_print_time(console, '-'); + ui_console_dirty(); +} + +void +cons_show_word(const char * const word) +{ + wprintw(console->win, "%s", word); + ui_console_dirty(); +} + +void +cons_debug(const char * const msg, ...) +{ + if (strcmp(PACKAGE_STATUS, "development") == 0) { + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + win_print_time(console, '-'); + wprintw(console->win, "%s\n", fmt_msg->str); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + ui_console_dirty(); + _cons_alert(); + + ui_current_page_off(); + ui_refresh(); + } +} + +void +cons_show(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + win_print_time(console, '-'); + wprintw(console->win, "%s\n", fmt_msg->str); + g_string_free(fmt_msg, TRUE); + va_end(arg); + ui_console_dirty(); +} + +void +cons_show_error(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + win_print_time(console, '-'); + wattron(console->win, COLOUR_ERROR); + wprintw(console->win, "%s\n", fmt_msg->str); + wattroff(console->win, COLOUR_ERROR); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_typing(const char * const short_from) +{ + win_print_time(console, '-'); + wattron(console->win, COLOUR_TYPING); + wprintw(console->win, "!! %s is typing a message...\n", short_from); + wattroff(console->win, COLOUR_TYPING); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_incoming_message(const char * const short_from, const int win_index) +{ + win_print_time(console, '-'); + wattron(console->win, COLOUR_INCOMING); + wprintw(console->win, "<< incoming from %s (%d)\n", short_from, win_index + 1); + wattroff(console->win, COLOUR_INCOMING); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_about(void) +{ + int rows, cols; + getmaxyx(stdscr, rows, cols); + + if (prefs_get_boolean(PREF_SPLASH)) { + _cons_splash_logo(); + } else { + win_print_time(console, '-'); + + if (strcmp(PACKAGE_STATUS, "development") == 0) { + wprintw(console->win, "Welcome to Profanity, version %sdev\n", PACKAGE_VERSION); + } else { + wprintw(console->win, "Welcome to Profanity, version %s\n", PACKAGE_VERSION); + } + } + + win_print_time(console, '-'); + wprintw(console->win, "Copyright (C) 2012, 2013 James Booth <%s>.\n", PACKAGE_BUGREPORT); + win_print_time(console, '-'); + wprintw(console->win, "License GPLv3+: GNU GPL version 3 or later \n"); + win_print_time(console, '-'); + wprintw(console->win, "\n"); + win_print_time(console, '-'); + wprintw(console->win, "This is free software; you are free to change and redistribute it.\n"); + win_print_time(console, '-'); + wprintw(console->win, "There is NO WARRANTY, to the extent permitted by law.\n"); + win_print_time(console, '-'); + wprintw(console->win, "\n"); + win_print_time(console, '-'); + wprintw(console->win, "Type '/help' to show complete help.\n"); + win_print_time(console, '-'); + wprintw(console->win, "\n"); + + if (prefs_get_boolean(PREF_VERCHECK)) { + cons_check_version(FALSE); + } + + prefresh(console->win, 0, 0, 1, 0, rows-3, cols-1); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_check_version(gboolean not_available_msg) +{ + char *latest_release = release_get_latest(); + + if (latest_release != NULL) { + gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0); + + if (relase_valid) { + if (release_is_new(latest_release)) { + win_print_time(console, '-'); + wprintw(console->win, "A new version of Profanity is available: %s", latest_release); + win_print_time(console, '-'); + wprintw(console->win, "Check for details.\n"); + free(latest_release); + win_print_time(console, '-'); + wprintw(console->win, "\n"); + } else { + if (not_available_msg) { + cons_show("No new version available."); + cons_show(""); + } + } + + ui_console_dirty(); + _cons_alert(); + } + } +} + +void +cons_show_login_success(ProfAccount *account) +{ + win_print_time(console, '-'); + wprintw(console->win, "%s logged in successfully, ", account->jid); + + resource_presence_t presence = accounts_get_login_presence(account->name); + const char *presence_str = string_from_resource_presence(presence); + + win_presence_colour_on(console, presence_str); + wprintw(console->win, "%s", presence_str); + win_presence_colour_off(console, presence_str); + wprintw(console->win, " (priority %d)", + accounts_get_priority_for_presence_type(account->name, presence)); + wprintw(console->win, ".\n"); + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_wins(void) +{ + int i = 0; + int count = 0; + + 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, '-'); + + switch (window->type) + { + case WIN_CHAT: + wprintw(console->win, "%d: chat %s", i + 1, window->from); + PContact contact = contact_list_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", i + 1, window->from); + + if (window->unread > 0) { + wprintw(console->win, ", %d unread", window->unread); + } + + break; + + case WIN_MUC: + wprintw(console->win, "%d: room %s", i + 1, window->from); + + if (window->unread > 0) { + wprintw(console->win, ", %d unread", window->unread); + } + + break; + + default: + break; + } + + wprintw(console->win, "\n"); + } + } + } + + cons_show(""); + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_info(PContact pcontact) +{ + const char *barejid = p_contact_barejid(pcontact); + const char *name = p_contact_name(pcontact); + const char *presence = p_contact_presence(pcontact); + const char *sub = p_contact_subscription(pcontact); + GList *resources = p_contact_get_available_resources(pcontact); + GList *ordered_resources = NULL; + GDateTime *last_activity = p_contact_last_activity(pcontact); + WINDOW *win = console->win; + + win_print_time(console, '-'); + wprintw(win, "\n"); + win_print_time(console, '-'); + win_presence_colour_on(console, presence); + wprintw(win, "%s", barejid); + if (name != NULL) { + wprintw(win, " (%s)", name); + } + win_presence_colour_off(console, presence); + wprintw(win, ":\n"); + + if (sub != NULL) { + win_print_time(console, '-'); + wprintw(win, "Subscription: %s\n", sub); + } + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + win_print_time(console, '-'); + wprintw(win, "Last activity: "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(win, "%ds", seconds); + + wprintw(win, "\n"); + + g_date_time_unref(now); + } + + if (resources != NULL) { + win_print_time(console, '-'); + wprintw(win, "Resources:\n"); + + // sort in order of availabiltiy + while (resources != NULL) { + Resource *resource = resources->data; + ordered_resources = g_list_insert_sorted(ordered_resources, + resource, (GCompareFunc)resource_compare_availability); + resources = g_list_next(resources); + } + } + + while (ordered_resources != NULL) { + Resource *resource = ordered_resources->data; + const char *resource_presence = string_from_resource_presence(resource->presence); + win_print_time(console, '-'); + win_presence_colour_on(console, resource_presence); + wprintw(win, " %s (%d), %s", resource->name, resource->priority, resource_presence); + if (resource->status != NULL) { + wprintw(win, ", \"%s\"", resource->status); + } + wprintw(win, "\n"); + win_presence_colour_off(console, resource_presence); + + if (resource->caps_str != NULL) { + Capabilities *caps = caps_get(resource->caps_str); + if (caps != NULL) { + // show identity + if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { + win_print_time(console, '-'); + wprintw(win, " Identity: "); + if (caps->name != NULL) { + wprintw(win, "%s", caps->name); + if ((caps->category != NULL) || (caps->type != NULL)) { + wprintw(win, " "); + } + } + if (caps->type != NULL) { + wprintw(win, "%s", caps->type); + if (caps->category != NULL) { + wprintw(win, " "); + } + } + if (caps->category != NULL) { + wprintw(win, "%s", caps->category); + } + wprintw(win, "\n"); + } + if (caps->software != NULL) { + win_print_time(console, '-'); + wprintw(win, " Software: %s", caps->software); + } + if (caps->software_version != NULL) { + wprintw(win, ", %s", caps->software_version); + } + if ((caps->software != NULL) || (caps->software_version != NULL)) { + wprintw(win, "\n"); + } + if (caps->os != NULL) { + win_print_time(console, '-'); + wprintw(win, " OS: %s", caps->os); + } + if (caps->os_version != NULL) { + wprintw(win, ", %s", caps->os_version); + } + if ((caps->os != NULL) || (caps->os_version != NULL)) { + wprintw(win, "\n"); + } + } + } + + ordered_resources = g_list_next(ordered_resources); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_caps(const char * const contact, Resource *resource) +{ + WINDOW *win = console->win; + cons_show(""); + const char *resource_presence = string_from_resource_presence(resource->presence); + win_print_time(console, '-'); + win_presence_colour_on(console, resource_presence); + wprintw(console->win, "%s", contact); + win_presence_colour_off(console, resource_presence); + wprintw(win, ":\n"); + + if (resource->caps_str != NULL) { + Capabilities *caps = caps_get(resource->caps_str); + if (caps != NULL) { + // show identity + if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { + win_print_time(console, '-'); + wprintw(win, "Identity: "); + if (caps->name != NULL) { + wprintw(win, "%s", caps->name); + if ((caps->category != NULL) || (caps->type != NULL)) { + wprintw(win, " "); + } + } + if (caps->type != NULL) { + wprintw(win, "%s", caps->type); + if (caps->category != NULL) { + wprintw(win, " "); + } + } + if (caps->category != NULL) { + wprintw(win, "%s", caps->category); + } + wprintw(win, "\n"); + } + if (caps->software != NULL) { + win_print_time(console, '-'); + wprintw(win, "Software: %s", caps->software); + } + if (caps->software_version != NULL) { + wprintw(win, ", %s", caps->software_version); + } + if ((caps->software != NULL) || (caps->software_version != NULL)) { + wprintw(win, "\n"); + } + if (caps->os != NULL) { + win_print_time(console, '-'); + wprintw(win, "OS: %s", caps->os); + } + if (caps->os_version != NULL) { + wprintw(win, ", %s", caps->os_version); + } + if ((caps->os != NULL) || (caps->os_version != NULL)) { + wprintw(win, "\n"); + } + + if (caps->features != NULL) { + win_print_time(console, '-'); + wprintw(win, "Features:\n"); + GSList *feature = caps->features; + while (feature != NULL) { + win_print_time(console, '-'); + wprintw(win, " %s\n", feature->data); + feature = g_slist_next(feature); + } + } + } + } + + ui_console_dirty(); + _cons_alert(); +} + +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) +{ + if ((name != NULL) || (version != NULL) || (os != NULL)) { + cons_show(""); + win_print_time(console, '-'); + win_presence_colour_on(console, presence); + wprintw(console->win, "%s", jid); + win_presence_colour_off(console, presence); + wprintw(console->win, ":\n"); + } + if (name != NULL) { + cons_show("Name : %s", name); + } + if (version != NULL) { + cons_show("Version : %s", version); + } + if (os != NULL) { + cons_show("OS : %s", os); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_room_list(GSList *rooms, const char * const conference_node) +{ + if ((rooms != NULL) && (g_slist_length(rooms) > 0)) { + cons_show("Chat rooms at %s:", conference_node); + while (rooms != NULL) { + DiscoItem *room = rooms->data; + win_print_time(console, '-'); + wprintw(console->win, " %s", room->jid); + if (room->name != NULL) { + wprintw(console->win, ", (%s)", room->name); + } + wprintw(console->win, "\n"); + rooms = g_slist_next(rooms); + } + } else { + cons_show("No chat rooms at %s", conference_node); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_disco_info(const char *jid, GSList *identities, GSList *features) +{ + if (((identities != NULL) && (g_slist_length(identities) > 0)) || + ((features != NULL) && (g_slist_length(features) > 0))) { + cons_show(""); + cons_show("Service disovery info for %s", jid); + + if (identities != NULL) { + cons_show(" Identities"); + } + while (identities != NULL) { + DiscoIdentity *identity = identities->data; // anme trpe, cat + GString *identity_str = g_string_new(" "); + if (identity->name != NULL) { + identity_str = g_string_append(identity_str, strdup(identity->name)); + identity_str = g_string_append(identity_str, " "); + } + if (identity->type != NULL) { + identity_str = g_string_append(identity_str, strdup(identity->type)); + identity_str = g_string_append(identity_str, " "); + } + if (identity->category != NULL) { + identity_str = g_string_append(identity_str, strdup(identity->category)); + } + cons_show(identity_str->str); + g_string_free(identity_str, FALSE); + identities = g_slist_next(identities); + } + + if (features != NULL) { + cons_show(" Features:"); + } + while (features != NULL) { + cons_show(" %s", features->data); + features = g_slist_next(features); + } + + ui_console_dirty(); + _cons_alert(); + } +} + +void +cons_show_disco_items(GSList *items, const char * const jid) +{ + if ((items != NULL) && (g_slist_length(items) > 0)) { + cons_show(""); + cons_show("Service discovery items for %s:", jid); + while (items != NULL) { + DiscoItem *item = items->data; + win_print_time(console, '-'); + wprintw(console->win, " %s", item->jid); + if (item->name != NULL) { + wprintw(console->win, ", (%s)", item->name); + } + wprintw(console->win, "\n"); + items = g_slist_next(items); + } + } else { + cons_show(""); + cons_show("No service discovery items for %s", jid); + } + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_status(const char * const contact) +{ + PContact pcontact = contact_list_get_contact(contact); + + if (pcontact != NULL) { + win_show_contact(console, pcontact); + } else { + cons_show("No such contact \"%s\" in roster.", contact); + } + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_room_invite(const char * const invitor, const char * const room, + const char * const reason) +{ + char *display_room = NULL; + char *domain = strdup(jabber_get_domain()); + Jid *room_jid = jid_create(room); + GString *default_service = g_string_new("conference."); + g_string_append(default_service, domain); + + cons_show(""); + cons_show("Chat room invite received:"); + cons_show(" From : %s", invitor); + cons_show(" Room : %s", room); + + if (reason != NULL) { + cons_show(" Message: %s", reason); + } + + if (strcmp(room_jid->domainpart, default_service->str) == 0) { + display_room = room_jid->localpart; + } else { + display_room = room_jid->barejid; + } + + cons_show("Type \"/join %s\" to accept the invitation", display_room); + + if (prefs_get_boolean(PREF_NOTIFY_INVITE)) { + notify_invite(invitor, room); + } + + jid_destroy(room_jid); + g_string_free(default_service, TRUE); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_account_list(gchar **accounts) +{ + int size = g_strv_length(accounts); + if (size > 0) { + cons_show("Accounts:"); + int i = 0; + for (i = 0; i < size; i++) { + if ((jabber_get_connection_status() == JABBER_CONNECTED) && + (g_strcmp0(jabber_get_account_name(), accounts[i]) == 0)) { + resource_presence_t presence = accounts_get_last_presence(accounts[i]); + win_print_time(console, '-'); + win_presence_colour_on(console, string_from_resource_presence(presence)); + wprintw(console->win, "%s\n", accounts[i]); + win_presence_colour_off(console, string_from_resource_presence(presence)); + } else { + cons_show(accounts[i]); + } + } + cons_show(""); + } else { + cons_show("No accounts created yet."); + cons_show(""); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_account(ProfAccount *account) +{ + cons_show(""); + cons_show("Account %s:", account->name); + if (account->enabled) { + cons_show ("enabled : TRUE"); + } else { + cons_show ("enabled : FALSE"); + } + cons_show ("jid : %s", account->jid); + if (account->resource != NULL) { + cons_show ("resource : %s", account->resource); + } + if (account->server != NULL) { + cons_show ("server : %s", account->server); + } + if (account->last_presence != NULL) { + cons_show ("Last presence : %s", account->last_presence); + } + if (account->login_presence != NULL) { + cons_show ("Login presence : %s", account->login_presence); + } + cons_show ("Priority : chat:%d, online:%d, away:%d, xa:%d, dnd:%d", + account->priority_chat, account->priority_online, account->priority_away, + account->priority_xa, account->priority_dnd); + + if ((jabber_get_connection_status() == JABBER_CONNECTED) && + (g_strcmp0(jabber_get_account_name(), account->name) == 0)) { + GList *resources = jabber_get_available_resources(); + GList *ordered_resources = NULL; + + WINDOW *win = console->win; + if (resources != NULL) { + win_print_time(console, '-'); + wprintw(win, "Resources:\n"); + + // sort in order of availabiltiy + while (resources != NULL) { + Resource *resource = resources->data; + ordered_resources = g_list_insert_sorted(ordered_resources, + resource, (GCompareFunc)resource_compare_availability); + resources = g_list_next(resources); + } + } + + while (ordered_resources != NULL) { + Resource *resource = ordered_resources->data; + const char *resource_presence = string_from_resource_presence(resource->presence); + win_print_time(console, '-'); + win_presence_colour_on(console, resource_presence); + wprintw(win, " %s (%d), %s", resource->name, resource->priority, resource_presence); + if (resource->status != NULL) { + wprintw(win, ", \"%s\"", resource->status); + } + wprintw(win, "\n"); + win_presence_colour_off(console, resource_presence); + + if (resource->caps_str != NULL) { + Capabilities *caps = caps_get(resource->caps_str); + if (caps != NULL) { + // show identity + if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { + win_print_time(console, '-'); + wprintw(win, " Identity: "); + if (caps->name != NULL) { + wprintw(win, "%s", caps->name); + if ((caps->category != NULL) || (caps->type != NULL)) { + wprintw(win, " "); + } + } + if (caps->type != NULL) { + wprintw(win, "%s", caps->type); + if (caps->category != NULL) { + wprintw(win, " "); + } + } + if (caps->category != NULL) { + wprintw(win, "%s", caps->category); + } + wprintw(win, "\n"); + } + if (caps->software != NULL) { + win_print_time(console, '-'); + wprintw(win, " Software: %s", caps->software); + } + if (caps->software_version != NULL) { + wprintw(win, ", %s", caps->software_version); + } + if ((caps->software != NULL) || (caps->software_version != NULL)) { + wprintw(win, "\n"); + } + if (caps->os != NULL) { + win_print_time(console, '-'); + wprintw(win, " OS: %s", caps->os); + } + if (caps->os_version != NULL) { + wprintw(win, ", %s", caps->os_version); + } + if ((caps->os != NULL) || (caps->os_version != NULL)) { + wprintw(win, "\n"); + } + } + } + + ordered_resources = g_list_next(ordered_resources); + } + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_ui_prefs(void) +{ + cons_show("UI preferences:"); + cons_show(""); + + gchar *theme = prefs_get_string(PREF_THEME); + if (theme == NULL) { + cons_show("Theme (/theme) : default"); + } else { + cons_show("Theme (/theme) : %s", theme); + } + + if (prefs_get_boolean(PREF_BEEP)) + cons_show("Terminal beep (/beep) : ON"); + else + cons_show("Terminal beep (/beep) : OFF"); + + if (prefs_get_boolean(PREF_FLASH)) + cons_show("Terminal flash (/flash) : ON"); + else + cons_show("Terminal flash (/flash) : OFF"); + + if (prefs_get_boolean(PREF_INTYPE)) + cons_show("Show typing (/intype) : ON"); + else + cons_show("Show typing (/intype) : OFF"); + + if (prefs_get_boolean(PREF_SPLASH)) + cons_show("Splash screen (/splash) : ON"); + else + cons_show("Splash screen (/splash) : OFF"); + + if (prefs_get_boolean(PREF_HISTORY)) + cons_show("Chat history (/history) : ON"); + else + cons_show("Chat history (/history) : OFF"); + + if (prefs_get_boolean(PREF_VERCHECK)) + cons_show("Version checking (/vercheck) : ON"); + else + cons_show("Version checking (/vercheck) : OFF"); + + if (prefs_get_boolean(PREF_MOUSE)) + cons_show("Mouse handling (/mouse) : ON"); + else + cons_show("Mouse handling (/mouse) : OFF"); + + if (prefs_get_boolean(PREF_STATUSES)) + cons_show("Status (/statuses) : ON"); + else + cons_show("Status (/statuses) : OFF"); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_desktop_prefs(void) +{ + cons_show("Desktop notification preferences:"); + cons_show(""); + + if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) + cons_show("Messages (/notify message) : ON"); + else + cons_show("Messages (/notify message) : OFF"); + + if (prefs_get_boolean(PREF_NOTIFY_TYPING)) + cons_show("Composing (/notify typing) : ON"); + else + cons_show("Composing (/notify typing) : OFF"); + + if (prefs_get_boolean(PREF_NOTIFY_INVITE)) + cons_show("Room invites (/notify invite) : ON"); + else + cons_show("Room invites (/notify invite) : OFF"); + + gint remind_period = prefs_get_notify_remind(); + if (remind_period == 0) { + cons_show("Reminder period (/notify remind) : OFF"); + } else if (remind_period == 1) { + cons_show("Reminder period (/notify remind) : 1 second"); + } else { + cons_show("Reminder period (/notify remind) : %d seconds", remind_period); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_chat_prefs(void) +{ + cons_show("Chat preferences:"); + cons_show(""); + + if (prefs_get_boolean(PREF_STATES)) + cons_show("Send chat states (/states) : ON"); + else + cons_show("Send chat states (/states) : OFF"); + + if (prefs_get_boolean(PREF_OUTTYPE)) + cons_show("Send composing (/outtype) : ON"); + else + cons_show("Send composing (/outtype) : OFF"); + + gint gone_time = prefs_get_gone(); + if (gone_time == 0) { + cons_show("Leave conversation (/gone) : OFF"); + } else if (gone_time == 1) { + cons_show("Leave conversation (/gone) : 1 minute"); + } else { + cons_show("Leave conversation (/gone) : %d minutes", gone_time); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_log_prefs(void) +{ + cons_show("Logging preferences:"); + cons_show(""); + + cons_show("Max log size (/log maxsize) : %d bytes", prefs_get_max_log_size()); + + if (prefs_get_boolean(PREF_CHLOG)) + cons_show("Chat logging (/chlog) : ON"); + else + cons_show("Chat logging (/chlog) : OFF"); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_presence_prefs(void) +{ + cons_show("Presence preferences:"); + cons_show(""); + + if (strcmp(prefs_get_string(PREF_AUTOAWAY_MODE), "off") == 0) { + cons_show("Autoaway (/autoaway mode) : OFF"); + } else { + cons_show("Autoaway (/autoaway mode) : %s", prefs_get_string(PREF_AUTOAWAY_MODE)); + } + + cons_show("Autoaway minutes (/autoaway time) : %d minutes", prefs_get_autoaway_time()); + + if ((prefs_get_string(PREF_AUTOAWAY_MESSAGE) == NULL) || + (strcmp(prefs_get_string(PREF_AUTOAWAY_MESSAGE), "") == 0)) { + cons_show("Autoaway message (/autoaway message) : OFF"); + } else { + cons_show("Autoaway message (/autoaway message) : \"%s\"", prefs_get_string(PREF_AUTOAWAY_MESSAGE)); + } + + if (prefs_get_boolean(PREF_AUTOAWAY_CHECK)) { + cons_show("Autoaway check (/autoaway check) : ON"); + } else { + cons_show("Autoaway check (/autoaway check) : OFF"); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_connection_prefs(void) +{ + cons_show("Connection preferences:"); + cons_show(""); + + gint reconnect_interval = prefs_get_reconnect(); + if (reconnect_interval == 0) { + cons_show("Reconnect interval (/reconnect) : OFF"); + } else if (reconnect_interval == 1) { + cons_show("Reconnect interval (/reconnect) : 1 second"); + } else { + cons_show("Reconnect interval (/reconnect) : %d seconds", reconnect_interval); + } + + gint autoping_interval = prefs_get_autoping(); + if (autoping_interval == 0) { + cons_show("Autoping interval (/autoping) : OFF"); + } else if (autoping_interval == 1) { + cons_show("Autoping interval (/autoping) : 1 second"); + } else { + cons_show("Autoping interval (/autoping) : %d seconds", autoping_interval); + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_themes(GSList *themes) +{ + cons_show(""); + + if (themes == NULL) { + cons_show("No available themes."); + } else { + cons_show("Available themes:"); + while (themes != NULL) { + cons_show(themes->data); + themes = g_slist_next(themes); + } + } + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_prefs(void) +{ + cons_show(""); + cons_show_ui_prefs(); + cons_show(""); + cons_show_desktop_prefs(); + cons_show(""); + cons_show_chat_prefs(); + cons_show(""); + cons_show_log_prefs(); + cons_show(""); + cons_show_presence_prefs(); + cons_show(""); + cons_show_connection_prefs(); + cons_show(""); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_help(void) +{ + cons_show(""); + cons_show("Choose a help option:"); + cons_show(""); + cons_show("/help list - List all commands."); + cons_show("/help basic - Summary of basic usage commands."); + cons_show("/help presence - Summary of online status change commands."); + cons_show("/help settings - Summary of commands for changing Profanity settings."); + cons_show("/help navigation - How to navigate around Profanity."); + cons_show("/help [command] - Detailed help on a specific command."); + cons_show(""); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_basic_help(void) +{ + cons_show(""); + cons_show("Basic Commands:"); + _cons_show_basic_help(); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_settings_help(void) +{ + cons_show(""); + cons_show("Settings:"); + cons_show(""); + + GSList *settings_helpers = cmd_get_settings_help(); + while (settings_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)settings_helpers->data; + cons_show("%-27s: %s", help->usage, help->short_help); + settings_helpers = g_slist_next(settings_helpers); + } + + cons_show(""); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_presence_help(void) +{ + cons_show(""); + cons_show("Presence changes:"); + cons_show(""); + + GSList *presence_helpers = cmd_get_presence_help(); + while (presence_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)presence_helpers->data; + cons_show("%-25s: %s", help->usage, help->short_help); + presence_helpers = g_slist_next(presence_helpers); + } + + cons_show(""); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_navigation_help(void) +{ + cons_show(""); + cons_show("Navigation:"); + cons_show(""); + cons_show("Alt-1 : This console window."); + cons_show("Alt-2..Alt-0 : Chat windows."); + cons_show("F1 : This console window."); + cons_show("F2..F10 : Chat windows."); + cons_show("UP, DOWN : Navigate input history."); + cons_show("LEFT, RIGHT, HOME, END : Edit current input."); + cons_show("ESC : Clear current input."); + cons_show("TAB : Autocomplete command/recipient/login."); + cons_show("PAGE UP, PAGE DOWN : Page the main window."); + cons_show(""); + + ui_console_dirty(); + _cons_alert(); +} + +void +cons_show_contacts(GSList *list) +{ + GSList *curr = list; + + while(curr) { + PContact contact = curr->data; + if (strcmp(p_contact_subscription(contact), "none") != 0) { + win_show_contact(console, contact); + } + curr = g_slist_next(curr); + } + + ui_console_dirty(); + _cons_alert(); +} + +static void +_cons_splash_logo(void) +{ + win_print_time(console, '-'); + wprintw(console->win, "Welcome to\n"); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " ___ _ \n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " / __) (_)_ \n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " ____ ____ ___ | |__ ____ ____ _| |_ _ _ \n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |\n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| | | | | | |_| | | ( ( | | | | | | |_| |_| |\n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |\n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "|_| (____/ \n"); + wattroff(console->win, COLOUR_SPLASH); + + win_print_time(console, '-'); + wprintw(console->win, "\n"); + win_print_time(console, '-'); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + wprintw(console->win, "Version %sdev\n", PACKAGE_VERSION); + } else { + wprintw(console->win, "Version %s\n", PACKAGE_VERSION); + } +} + +static void +_cons_show_basic_help(void) +{ + cons_show(""); + + GSList *basic_helpers = cmd_get_basic_help(); + while (basic_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)basic_helpers->data; + cons_show("%-30s: %s", help->usage, help->short_help); + basic_helpers = g_slist_next(basic_helpers); + } + + cons_show(""); + ui_console_dirty(); + _cons_alert(); +} + +static void +_cons_alert(void) +{ + if (ui_current_win_type() != WIN_CONSOLE) { + status_bar_new(0); + } +} + diff --git a/src/ui/core.c b/src/ui/core.c new file mode 100644 index 00000000..b936b59b --- /dev/null +++ b/src/ui/core.c @@ -0,0 +1,1432 @@ +/* + * core.c + * + * Copyright (C) 2012, 2013 James Booth + * + * 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 . + * + */ + +#include "config.h" + +#include +#include +#ifdef HAVE_LIBXSS +#include +#endif +#include +#ifdef HAVE_NCURSESW_NCURSES_H +#include +#elif HAVE_NCURSES_H +#include +#endif + +#include "chat_session.h" +#include "command/command.h" +#include "common.h" +#include "config/preferences.h" +#include "config/theme.h" +#include "contact.h" +#include "contact_list.h" +#include "jid.h" +#include "log.h" +#include "muc.h" +#include "ui/notifier.h" +#include "ui/ui.h" +#include "ui/window.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 +static Display *display; +#endif + +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); +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, + 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); + +void +ui_init(void) +{ + log_info("Initialising UI"); + initscr(); + raw(); + keypad(stdscr, TRUE); + if (prefs_get_boolean(PREF_MOUSE)) { + mousemask(ALL_MOUSE_EVENTS, NULL); + mouseinterval(5); + } + ui_load_colours(); + refresh(); + create_title_bar(); + create_status_bar(); + status_bar_active(0); + create_input_window(); + max_cols = getmaxx(stdscr); + windows[0] = cons_create(); + console = windows[0]; + current = console; + cons_about(); + notifier_init(); +#ifdef HAVE_LIBXSS + display = XOpenDisplay(0); +#endif + ui_idle_time = g_timer_new(); + current_win_dirty = TRUE; +} + +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) +{ +// if compiled with libxss, get the x sessions idle time +#ifdef HAVE_LIBXSS + XScreenSaverInfo *info = XScreenSaverAllocInfo(); + if (info != NULL && display != NULL) { + XScreenSaverQueryInfo(display, DefaultRootWindow(display), info); + unsigned long result = info->idle; + XFree(info); + return result; + } +// if no libxss or xss idle time failed, use profanity idle time +#endif + gdouble seconds_elapsed = g_timer_elapsed(ui_idle_time, NULL); + unsigned long ms_elapsed = seconds_elapsed * 1000.0; + return ms_elapsed; +} + +void +ui_reset_idle_time(void) +{ + g_timer_start(ui_idle_time); +} + +void +ui_close(void) +{ + notifier_uninit(); + endwin(); +} + +void +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(); + inp_win_resize(input, size); + current_win_dirty = TRUE; +} + +void +ui_load_colours(void) +{ + if (has_colors()) { + use_default_colors(); + start_color(); + theme_init_colours(); + } +} + +gboolean +ui_windows_full(void) +{ + int i; + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] == NULL) { + return FALSE; + } + } + + return TRUE; +} + +void +ui_contact_typing(const char * const from) +{ + int win_index = _find_prof_win_index(from); + + if (prefs_get_boolean(PREF_INTYPE)) { + // no chat window for user + if (win_index == NUM_WINS) { + cons_show_typing(from); + + // have chat window but not currently in it + } else if (win_index != current_index) { + cons_show_typing(from); + current_win_dirty = TRUE; + + // in chat window with user + } else { + title_bar_set_typing(TRUE); + title_bar_draw(); + + status_bar_active(win_index); + current_win_dirty = TRUE; + } + } + + if (prefs_get_boolean(PREF_NOTIFY_TYPING)) + notify_typing(from); +} + +void +ui_idle(void) +{ + int i; + + // 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); + + 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); + } + } + } +} + +void +ui_incoming_msg(const char * const from, const char * const message, + GTimeVal *tv_stamp, gboolean priv) +{ + char *display_from; + win_type_t win_type; + if (priv) { + win_type = WIN_PRIVATE; + display_from = get_nick_from_full_jid(from); + } else { + win_type = WIN_CHAT; + display_from = strdup(from); + } + + int win_index = _find_prof_win_index(from); + if (win_index == NUM_WINS) + win_index = _new_prof_win(from, win_type); + + // no spare windows left + if (win_index == 0) { + if (tv_stamp == NULL) { + win_print_time(console, '-'); + } 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); + g_date_time_unref(time); + g_free(date_fmt); + } + + if (strncmp(message, "/me ", 4) == 0) { + wattron(console->win, COLOUR_THEM); + wprintw(console->win, "*%s ", from); + wprintw(console->win, "%s", message + 4); + wprintw(console->win, "\n"); + wattroff(console->win, COLOUR_THEM); + } else { + _win_show_user(console->win, 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; + } else { + status_bar_new(0); + } + + // window found or created + } else { + ProfWin *window = windows[win_index]; + + // 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); + wprintw(window->win, "%s", 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; + + // not currently viewing chat window with sender + } else { + status_bar_new(win_index); + cons_show_incoming_message(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 { + 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); + wprintw(window->win, "%s", 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 (prefs_get_boolean(PREF_BEEP)) + beep(); + if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) + notify_message(display_from); + + g_free(display_from); +} + +void +ui_contact_online(const char * const barejid, const char * const resource, + const char * const show, const char * const status, GDateTime *last_activity) +{ + Jid *jid = jid_create_from_bare_and_resource(barejid, resource); + char *display_str = NULL; + + if (strcmp(jid->resourcepart, "__prof_default") == 0) { + display_str = jid->barejid; + } else { + display_str = jid->fulljid; + } + + _show_status_string(console, display_str, show, status, last_activity, "++", + "online"); + + int win_index = _find_prof_win_index(barejid); + if (win_index != NUM_WINS) { + ProfWin *window = windows[win_index]; + _show_status_string(window, display_str, show, status, last_activity, "++", + "online"); + } + + jid_destroy(jid); + + if (win_index == current_index) + current_win_dirty = TRUE; +} + +void +ui_contact_offline(const char * const from, const char * const show, + const char * const status) +{ + Jid *jidp = jid_create(from); + char *display_str = NULL; + + if (strcmp(jidp->resourcepart, "__prof_default") == 0) { + display_str = jidp->barejid; + } else { + display_str = jidp->fulljid; + } + + _show_status_string(console, display_str, show, status, NULL, "--", "offline"); + + int win_index = _find_prof_win_index(from); + if (win_index != NUM_WINS) { + ProfWin *window = windows[win_index]; + _show_status_string(window, display_str, show, status, NULL, "--", "offline"); + } + + if (win_index == current_index) + current_win_dirty = TRUE; +} + +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; + } + } + } + + title_bar_set_status(CONTACT_OFFLINE); + status_bar_clear_message(); + status_bar_refresh(); +} + +void +ui_handle_special_keys(const wint_t * const ch, const char * const inp, + const int size) +{ + _win_handle_switch(ch); + _win_handle_page(ch); + if (*ch == KEY_RESIZE) { + ui_resize(*ch, inp, size); + } + +} + +void +ui_switch_win(const int i) +{ + ui_current_page_off(); + if (windows[i] != NULL) { + current_index = i; + current = windows[current_index]; + ui_current_page_off(); + + current->unread = 0; + + if (i == 0) { + title_bar_title(); + status_bar_active(0); + } else { + title_bar_set_recipient(current->from); + title_bar_draw();; + status_bar_active(i); + } + } + + current_win_dirty = TRUE; +} + +void +ui_clear_current(void) +{ + werase(current->win); + current_win_dirty = TRUE; +} + +void +ui_close_current(void) +{ + win_free(current); + windows[current_index] = NULL; + + // set it as inactive in the status bar + status_bar_inactive(current_index); + + // go back to console window + _set_current(0); + status_bar_active(0); + title_bar_title(); + + current_win_dirty = TRUE; +} + +win_type_t +ui_current_win_type(void) +{ + return current->type; +} + +char * +ui_current_recipient(void) +{ + return strdup(current->from); +} + +void +ui_current_print_line(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + win_print_time(current, '-'); + wprintw(current->win, "%s\n", fmt_msg->str); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + current_win_dirty = TRUE; +} + +void +ui_current_error_line(const char * const msg) +{ + win_print_time(current, '-'); + wattron(current->win, COLOUR_ERROR); + wprintw(current->win, "%s\n", msg); + wattroff(current->win, COLOUR_ERROR); + + current_win_dirty = TRUE; +} + +void +ui_current_page_off(void) +{ + int rows = getmaxy(stdscr); + ProfWin *window = windows[current_index]; + + window->paged = 0; + + int y = getcury(window->win); + + int size = rows - 3; + + window->y_pos = y - (size - 1); + if (window->y_pos < 0) + window->y_pos = 0; + + current_win_dirty = TRUE; +} + +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]; + win_print_time(window, '-'); + _win_show_error_msg(window->win, err_msg); + if (win_index == current_index) { + current_win_dirty = TRUE; + } + } +} + +void +ui_print_system_msg_from_recipient(const char * const from, const char *message) +{ + int win_index; + ProfWin *window; + char from_cpy[strlen(from) + 1]; + char *bare_jid; + + if (from == NULL || message == NULL) + return; + + 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; + } + 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; + } +} + +void +ui_recipient_gone(const char * const from) +{ + int win_index; + ProfWin *window; + + if (from == NULL) + return; + + win_index = _find_prof_win_index(from); + // chat window exists + if (win_index < NUM_WINS) { + window = windows[win_index]; + win_print_time(window, '-'); + wattron(window->win, COLOUR_GONE); + wprintw(window->win, "*%s ", from); + 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; + } + } +} + +void +ui_new_chat_win(const char * const to) +{ + // if the contact is offline, show a message + PContact contact = contact_list_get_contact(to); + int win_index = _find_prof_win_index(to); + ProfWin *window = NULL; + + // create new window + if (win_index == NUM_WINS) { + Jid *jid = jid_create(to); + + if (muc_room_is_active(jid)) { + win_index = _new_prof_win(to, WIN_PRIVATE); + } else { + win_index = _new_prof_win(to, WIN_CHAT); + } + + jid_destroy(jid); + + window = windows[win_index]; + + if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { + _win_show_history(window->win, win_index, to); + } + + if (contact != NULL) { + if (strcmp(p_contact_presence(contact), "offline") == 0) { + const char const *show = p_contact_presence(contact); + const char const *status = p_contact_status(contact); + _show_status_string(window, to, show, status, NULL, "--", "offline"); + } + } + + // use existing window + } else { + window = windows[win_index]; + } + + ui_switch_win(win_index); +} + +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 = contact_list_get_contact(to); + int win_index = _find_prof_win_index(to); + ProfWin *window = NULL; + + // create new window + if (win_index == NUM_WINS) { + Jid *jid = jid_create(to); + + if (muc_room_is_active(jid)) { + win_index = _new_prof_win(to, WIN_PRIVATE); + } else { + win_index = _new_prof_win(to, WIN_CHAT); + } + + jid_destroy(jid); + + window = windows[win_index]; + + if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { + _win_show_history(window->win, win_index, to); + } + + if (contact != NULL) { + if (strcmp(p_contact_presence(contact), "offline") == 0) { + const char const *show = p_contact_presence(contact); + const char const *status = p_contact_status(contact); + _show_status_string(window, to, show, status, NULL, "--", "offline"); + } + } + + // use existing window + } else { + window = windows[win_index]; + } + + win_print_time(window, '-'); + if (strncmp(message, "/me ", 4) == 0) { + wattron(window->win, COLOUR_ME); + wprintw(window->win, "*%s ", from); + wprintw(window->win, "%s", message + 4); + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_ME); + } else { + _win_show_user(window->win, from, 0); + _win_show_message(window->win, message); + } + ui_switch_win(win_index); +} + +void +ui_room_join(Jid *jid) +{ + int win_index = _find_prof_win_index(jid->barejid); + + // create new window + if (win_index == NUM_WINS) { + win_index = _new_prof_win(jid->barejid, WIN_MUC); + } + + ui_switch_win(win_index); +} + +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]; + + win_print_time(window, '!'); + if ((roster == NULL) || (g_list_length(roster) == 0)) { + wattron(window->win, COLOUR_ROOMINFO); + if (presence == NULL) { + wprintw(window->win, "Room is empty.\n"); + } else { + wprintw(window->win, "No participants are %s.\n", presence); + } + wattroff(window->win, COLOUR_ROOMINFO); + } else { + wattron(window->win, COLOUR_ROOMINFO); + if (presence == NULL) { + wprintw(window->win, "Participants: "); + } else { + wprintw(window->win, "Participants (%s): ", presence); + } + wattroff(window->win, COLOUR_ROOMINFO); + wattron(window->win, COLOUR_ONLINE); + + while (roster != NULL) { + PContact member = roster->data; + const char const *nick = p_contact_barejid(member); + const char const *show = p_contact_presence(member); + + win_presence_colour_on(window, show); + wprintw(window->win, "%s", nick); + win_presence_colour_off(window, show); + + if (roster->next != NULL) { + wprintw(window->win, ", "); + } + + roster = g_list_next(roster); + } + + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_ONLINE); + } + + if (win_index == current_index) + current_win_dirty = TRUE; +} + +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]; + + 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; +} + +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]; + + 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; +} + +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]; + _show_status_string(window, nick, show, status, NULL, "++", "online"); + } + + if (win_index == current_index) + current_win_dirty = TRUE; +} + +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]; + + 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; +} + +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]; + + 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; +} + +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; + + 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); + g_date_time_unref(time); + g_free(date_fmt); + + if (strncmp(message, "/me ", 4) == 0) { + wprintw(win, "*%s ", nick); + wprintw(win, "%s", message + 4); + wprintw(win, "\n"); + } else { + wprintw(win, "%s: ", nick); + _win_show_message(win, message); + } + + if (win_index == current_index) + current_win_dirty = TRUE; +} + +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]; + + win_print_time(window, '-'); + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (strncmp(message, "/me ", 4) == 0) { + wattron(window->win, COLOUR_THEM); + wprintw(window->win, "*%s ", nick); + wprintw(window->win, "%s", message + 4); + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_THEM); + } else { + _win_show_user(window->win, nick, 1); + _win_show_message(window->win, message); + } + + } else { + if (strncmp(message, "/me ", 4) == 0) { + wattron(window->win, COLOUR_ME); + wprintw(window->win, "*%s ", nick); + wprintw(window->win, "%s", message + 4); + wprintw(window->win, "\n"); + wattroff(window->win, COLOUR_ME); + } else { + _win_show_user(window->win, nick, 0); + _win_show_message(window->win, message); + } + } + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + current_win_dirty = TRUE; + + // 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; + } + + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (prefs_get_boolean(PREF_FLASH)) { + flash(); + } + } + + windows[win_index]->unread++; + } + + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (prefs_get_boolean(PREF_BEEP)) { + beep(); + } + if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) { + notify_message(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]; + + win_print_time(window, '!'); + wattron(window->win, COLOUR_ROOMINFO); + wprintw(window->win, "Room subject: "); + wattroff(window->win, COLOUR_ROOMINFO); + wprintw(window->win, "%s\n", subject); + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + current_win_dirty = TRUE; + + // not currenlty on groupchat window + } else { + status_bar_new(win_index); + } +} + +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]; + + win_print_time(window, '!'); + wattron(window->win, COLOUR_ROOMINFO); + wprintw(window->win, "Room message: "); + wattroff(window->win, COLOUR_ROOMINFO); + wprintw(window->win, "%s\n", message); + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + current_win_dirty = TRUE; + + // not currenlty on groupchat window + } else { + status_bar_new(win_index); + } +} + +void +ui_status(void) +{ + char *recipient = ui_current_recipient(); + PContact pcontact = contact_list_get_contact(recipient); + + if (pcontact != NULL) { + win_show_contact(current, pcontact); + } else { + ui_current_print_line("Error getting contact info."); + } +} + +void +ui_status_private(void) +{ + Jid *jid = jid_create(ui_current_recipient()); + + PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + + if (pcontact != NULL) { + win_show_contact(current, pcontact); + } else { + ui_current_print_line("Error getting contact info."); + } + + jid_destroy(jid); +} + +void +ui_status_room(const char * const contact) +{ + PContact pcontact = muc_get_participant(ui_current_recipient(), contact); + + if (pcontact != NULL) { + win_show_contact(current, pcontact); + } else { + ui_current_print_line("No such participant \"%s\" in room.", 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; +} + +static void +_ui_draw_win_title(void) +{ + char new_win_title[100]; + + GString *version_str = g_string_new(""); + + if (prefs_get_boolean(PREF_TITLEBARVERSION)) { + g_string_append(version_str, " "); + g_string_append(version_str, PACKAGE_VERSION); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + g_string_append(version_str, "dev"); + } + } + + jabber_conn_status_t status = jabber_get_connection_status(); + + if (status == JABBER_CONNECTED) { + const char * const jid = jabber_get_jid(); + gint unread = ui_unread(); + + if (unread != 0) { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s (%d) - %s%c", '\033', "Profanity", version_str->str, unread, jid, '\007'); + } else { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s - %s%c", '\033', "Profanity", version_str->str, jid, '\007'); + } + } else { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s%c", '\033', "Profanity", version_str->str, '\007'); + } + + g_string_free(version_str, TRUE); + + if (g_strcmp0(win_title, new_win_title) != 0) { + // print to x-window title bar + printf("%s", new_win_title); + if (win_title != NULL) { + free(win_title); + } + win_title = strdup(new_win_title); + } +} + +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) +{ + if (colour) + wattron(win, COLOUR_THEM); + else + wattron(win, COLOUR_ME); + wprintw(win, "%s: ", user); + if (colour) + wattroff(win, COLOUR_THEM); + else + wattroff(win, COLOUR_ME); +} + +static void +_win_show_message(WINDOW *win, const char * const message) +{ + wprintw(win, "%s\n", message); +} + +static void +_win_show_error_msg(WINDOW *win, const char * const message) +{ + wattron(win, COLOUR_ERROR); + wprintw(win, "%s\n", message); + wattroff(win, COLOUR_ERROR); +} + +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, + const char * const default_show) +{ + WINDOW *win = window->win; + + if (!prefs_get_boolean(PREF_STATUSES)) + return; + + win_print_time(window, '-'); + + if (show != NULL) { + if (strcmp(show, "away") == 0) { + wattron(win, COLOUR_AWAY); + } else if (strcmp(show, "chat") == 0) { + wattron(win, COLOUR_CHAT); + } else if (strcmp(show, "dnd") == 0) { + wattron(win, COLOUR_DND); + } else if (strcmp(show, "xa") == 0) { + wattron(win, COLOUR_XA); + } else if (strcmp(show, "online") == 0) { + wattron(win, COLOUR_ONLINE); + } else { + wattron(win, COLOUR_OFFLINE); + } + } else if (strcmp(default_show, "online") == 0) { + wattron(win, COLOUR_ONLINE); + } else { + wattron(win, COLOUR_OFFLINE); + } + + wprintw(win, "%s %s", pre, from); + + if (show != NULL) + wprintw(win, " is %s", show); + else + wprintw(win, " is %s", default_show); + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + wprintw(win, ", idle "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(win, "%ds", seconds); + } + + if (status != NULL) + wprintw(win, ", \"%s\"", status); + + wprintw(win, "\n"); + + if (show != NULL) { + if (strcmp(show, "away") == 0) { + wattroff(win, COLOUR_AWAY); + } else if (strcmp(show, "chat") == 0) { + wattroff(win, COLOUR_CHAT); + } else if (strcmp(show, "dnd") == 0) { + wattroff(win, COLOUR_DND); + } else if (strcmp(show, "xa") == 0) { + wattroff(win, COLOUR_XA); + } else if (strcmp(show, "online") == 0) { + wattroff(win, COLOUR_ONLINE); + } else { + wattroff(win, COLOUR_OFFLINE); + } + } else if (strcmp(default_show, "online") == 0) { + wattroff(win, COLOUR_ONLINE); + } else { + wattroff(win, COLOUR_OFFLINE); + } +} + +static void +_win_handle_switch(const wint_t * const ch) +{ + if (*ch == KEY_F(1)) { + ui_switch_win(0); + } else if (*ch == KEY_F(2)) { + ui_switch_win(1); + } else if (*ch == KEY_F(3)) { + ui_switch_win(2); + } else if (*ch == KEY_F(4)) { + ui_switch_win(3); + } else if (*ch == KEY_F(5)) { + ui_switch_win(4); + } else if (*ch == KEY_F(6)) { + ui_switch_win(5); + } else if (*ch == KEY_F(7)) { + ui_switch_win(6); + } else if (*ch == KEY_F(8)) { + ui_switch_win(7); + } else if (*ch == KEY_F(9)) { + ui_switch_win(8); + } else if (*ch == KEY_F(10)) { + ui_switch_win(9); + } +} + +static void +_win_handle_page(const wint_t * const ch) +{ + int rows = getmaxy(stdscr); + int y = getcury(current->win); + + int page_space = rows - 4; + int *page_start = &(current->y_pos); + + if (prefs_get_boolean(PREF_MOUSE)) { + MEVENT mouse_event; + + if (*ch == KEY_MOUSE) { + if (getmouse(&mouse_event) == OK) { + +#ifdef PLATFORM_CYGWIN + if (mouse_event.bstate & BUTTON5_PRESSED) { // mouse wheel down +#else + if (mouse_event.bstate & BUTTON2_PRESSED) { // mouse wheel down +#endif + *page_start += 4; + + // only got half a screen, show full screen + if ((y - (*page_start)) < page_space) + *page_start = y - page_space; + + // went past end, show full screen + else if (*page_start >= y) + *page_start = y - page_space; + + current->paged = 1; + current_win_dirty = TRUE; + } else if (mouse_event.bstate & BUTTON4_PRESSED) { // mouse wheel up + *page_start -= 4; + + // went past beginning, show first page + if (*page_start < 0) + *page_start = 0; + + current->paged = 1; + current_win_dirty = TRUE; + } + } + } + } + + // page up + if (*ch == KEY_PPAGE) { + *page_start -= page_space; + + // went past beginning, show first page + if (*page_start < 0) + *page_start = 0; + + current->paged = 1; + current_win_dirty = TRUE; + + // page down + } else if (*ch == KEY_NPAGE) { + *page_start += page_space; + + // only got half a screen, show full screen + if ((y - (*page_start)) < page_space) + *page_start = y - page_space; + + // went past end, show full screen + else if (*page_start >= y) + *page_start = y - page_space; + + current->paged = 1; + current_win_dirty = TRUE; + } +} + +static void +_win_show_history(WINDOW *win, int win_index, const char * const contact) +{ + if (!windows[win_index]->history_shown) { + GSList *history = NULL; + Jid *jid = jid_create(jabber_get_jid()); + history = chat_log_get_previous(jid->barejid, contact, history); + jid_destroy(jid); + while (history != NULL) { + wprintw(win, "%s\n", history->data); + history = g_slist_next(history); + } + windows[win_index]->history_shown = 1; + + g_slist_free_full(history, free); + } +} + +void +_set_current(int index) +{ + current_index = index; + current = windows[current_index]; +} + diff --git a/src/ui/notifier.c b/src/ui/notifier.c new file mode 100644 index 00000000..5bf4defb --- /dev/null +++ b/src/ui/notifier.c @@ -0,0 +1,152 @@ +/* + * notifier.c + * + * Copyright (C) 2012, 2013 James Booth + * + * 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 . + * + */ +#include "config.h" + +#include +#include + +#include +#ifdef HAVE_LIBNOTIFY +#include +#endif +#ifdef PLATFORM_CYGWIN +#include +#endif + +#include "log.h" +#include "ui/ui.h" + +static void _notify(const char * const message, int timeout, + const char * const category); + +void +notifier_init(void) +{ +#ifdef HAVE_LIBNOTIFY + notify_init("Profanity"); +#endif +} + +void +notifier_uninit(void) +{ +#ifdef HAVE_LIBNOTIFY + if (notify_is_initted()) { + notify_uninit(); + } +#endif +} + +void +notify_typing(const char * const from) +{ + char message[strlen(from) + 1 + 11]; + sprintf(message, "%s: typing...", from); + + _notify(message, 10000, "Incoming message"); +} + +void +notify_invite(const char * const from, const char * const room) +{ + GString *message = g_string_new("Room invite\nfrom: "); + g_string_append(message, from); + g_string_append(message, "\nto: "); + g_string_append(message, room); + + _notify(message->str, 10000, "Incoming message"); + + g_string_free(message, FALSE); +} + +void +notify_message(const char * const short_from) +{ + char message[strlen(short_from) + 1 + 10]; + sprintf(message, "%s: message.", short_from); + + _notify(message, 10000, "Incoming message"); +} + +void +notify_remind(void) +{ + gint unread = ui_unread(); + if (unread > 0) { + char message[20]; + if (unread == 1) { + sprintf(message, "1 unread message"); + } else { + snprintf(message, sizeof(message), "%d unread messages", unread); + } + + _notify(message, 5000, "Incoming message"); + } +} + +static void +_notify(const char * const message, int timeout, + const char * const category) +{ +#ifdef HAVE_LIBNOTIFY + + if (notify_is_initted()) { + NotifyNotification *notification; + notification = notify_notification_new("Profanity", message, NULL); + notify_notification_set_timeout(notification, timeout); + notify_notification_set_category(notification, category); + notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); + + GError *error = NULL; + gboolean notify_success = notify_notification_show(notification, &error); + + if (!notify_success) { + log_error("Error sending desktop notification:"); + log_error(" -> Message : %s", message); + log_error(" -> Error : %s", error->message); + } + } else { + log_error("Libnotify initialisation error."); + } +#endif +#ifdef PLATFORM_CYGWIN + NOTIFYICONDATA nid; + nid.cbSize = sizeof(NOTIFYICONDATA); + //nid.hWnd = hWnd; + nid.uID = 100; + nid.uVersion = NOTIFYICON_VERSION; + //nid.uCallbackMessage = WM_MYMESSAGE; + nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); + strcpy(nid.szTip, "Tray Icon"); + nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + Shell_NotifyIcon(NIM_ADD, &nid); + + // For a Ballon Tip + nid.uFlags = NIF_INFO; + strcpy(nid.szInfoTitle, "Profanity"); // Title + strcpy(nid.szInfo, message); // Copy Tip + nid.uTimeout = timeout; // 3 Seconds + nid.dwInfoFlags = NIIF_INFO; + + Shell_NotifyIcon(NIM_MODIFY, &nid); +#endif +} diff --git a/src/ui/notifier.h b/src/ui/notifier.h new file mode 100644 index 00000000..60b2e337 --- /dev/null +++ b/src/ui/notifier.h @@ -0,0 +1,29 @@ +/* + * notifier.h + * + * Copyright (C) 2012, 2013 James Booth + * + * 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 . + * + */ + +void notifier_init(void); +void notifier_uninit(void); + +void notify_typing(const char * const from); +void notify_message(const char * const short_from); +void notify_remind(void); +void notify_invite(const char * const from, const char * const room); diff --git a/src/ui/ui.h b/src/ui/ui.h index 226dadbd..4dbde5ee 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -36,51 +36,79 @@ #include "contact.h" #include "jid.h" +#include "ui/window.h" #include "xmpp/xmpp.h" #define INP_WIN_MAX 1000 -#define PAD_SIZE 1000 +#define NUM_WINS 10 -typedef enum { - WIN_UNUSED, - WIN_CONSOLE, - WIN_CHAT, - WIN_MUC, - WIN_PRIVATE -} win_type_t; +// holds console at index 0 and chat wins 1 through to 9 +ProfWin* windows[NUM_WINS]; -struct prof_win { - char from[100]; - WINDOW *win; - win_type_t type; - int y_pos; - int paged; - int unread; - int history_shown; -}; - -// gui startup and shutdown, resize +// ui startup and control void ui_init(void); void ui_load_colours(void); void ui_refresh(void); void ui_close(void); void ui_resize(const int ch, const char * const input, const int size); -void ui_show_typing(const char * const from); void ui_idle(void); -void ui_show_incoming_msg(const char * const from, const char * const message, - GTimeVal *tv_stamp, gboolean priv); -void ui_contact_online(const char * const barejid, const char * const resource, - const char * const show, const char * const status, GDateTime *last_activity); -void ui_contact_offline(const char * const from, const char * const show, - const char * const status); -void ui_disconnected(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); + +// current window actions +void ui_close_current(void); +void ui_clear_current(void); +win_type_t ui_current_win_type(void); +char* ui_current_recipient(void); +void ui_current_print_line(const char * const msg, ...); +void ui_current_error_line(const char * const msg); +void ui_current_page_off(void); + +// ui events +void ui_contact_typing(const char * const from); +void ui_incoming_msg(const char * const from, const char * const message, + GTimeVal *tv_stamp, gboolean priv); +void ui_contact_online(const char * const barejid, const char * const resource, + const char * const show, const char * const status, GDateTime *last_activity); +void ui_contact_offline(const char * const from, const char * const show, + const char * const status); +void ui_disconnected(void); +void ui_recipient_gone(const char * const from); +void ui_outgoing_msg(const char * const from, const char * const to, + const char * const message); +void ui_room_join(Jid *jid); +void ui_room_roster(const char * const room, GList *roster, const char * const presence); +void ui_room_history(const char * const room_jid, const char * const nick, + GTimeVal tv_stamp, const char * const message); +void ui_room_message(const char * const room_jid, const char * const nick, + const char * const message); +void ui_room_subject(const char * const room_jid, + const char * const subject); +void ui_room_broadcast(const char * const room_jid, + const char * const message); +void ui_room_member_offline(const char * const room, const char * const nick); +void ui_room_member_online(const char * const room, + const char * const nick, const char * const show, const char * const status); +void ui_room_member_nick_change(const char * const room, + const char * const old_nick, const char * const nick); +void ui_room_nick_change(const char * const room, const char * const nick); +void ui_room_member_presence(const char * const room, + const char * const nick, const char * const show, const char * const status); + +// contact status functions +void ui_status_room(const char * const contact); +void ui_status(void); +void ui_status_private(void); // create windows void create_title_bar(void); @@ -97,49 +125,9 @@ void title_bar_set_recipient(char *from); void title_bar_set_typing(gboolean is_typing); void title_bar_draw(void); -// current window actions -void win_current_close(void); -void win_current_clear(void); -int win_current_is_console(void); -int win_current_is_chat(void); -int win_current_is_groupchat(void); -int win_current_is_private(void); -char* win_current_get_recipient(void); -void win_current_show(const char * const msg, ...); -void win_current_bad_show(const char * const msg); -void win_current_page_off(void); - -void win_show_error_msg(const char * const from, const char *err_msg); -void win_show_gone(const char * const from); -void win_show_system_msg(const char * const from, const char *message); -void win_show_outgoing_msg(const char * const from, const char * const to, - const char * const message); -void win_new_chat_win(const char * const to); - -void win_join_chat(Jid *jid); -void win_show_room_roster(const char * const room, GList *roster, const char * const presence); -void win_show_room_history(const char * const room_jid, const char * const nick, - GTimeVal tv_stamp, const char * const message); -void win_show_room_message(const char * const room_jid, const char * const nick, - const char * const message); -void win_show_room_subject(const char * const room_jid, - const char * const subject); -void win_show_room_broadcast(const char * const room_jid, - const char * const message); -void win_show_room_member_offline(const char * const room, const char * const nick); -void win_show_room_member_online(const char * const room, - const char * const nick, const char * const show, const char * const status); -void win_show_room_member_nick_change(const char * const room, - const char * const old_nick, const char * const nick); -void win_show_room_nick_change(const char * const room, const char * const nick); -void win_show_room_member_presence(const char * const room, - const char * const nick, const char * const show, const char * const status); -void win_room_show_status(const char * const contact); -void win_room_show_info(const char * const contact); -void win_show_status(void); -void win_private_show_status(void); - // console window actions +ProfWin* cons_create(void); +void cons_show(const char * const msg, ...); void cons_about(void); void cons_help(void); void cons_basic_help(void); @@ -154,15 +142,12 @@ void cons_show_log_prefs(void); void cons_show_presence_prefs(void); void cons_show_connection_prefs(void); void cons_show_account(ProfAccount *account); -void cons_bad_command(const char * const cmd); -void cons_show(const char * const cmd, ...); void cons_debug(const char * const msg, ...); void cons_show_time(void); void cons_show_word(const char * const word); -void cons_bad_show(const char * const cmd, ...); +void cons_show_error(const char * const cmd, ...); void cons_highlight_show(const char * const cmd); void cons_show_contacts(GSList * list); -void cons_check_version(gboolean not_available_msg); void cons_show_wins(void); void cons_show_status(const char * const contact); void cons_show_info(PContact pcontact); @@ -178,6 +163,9 @@ void cons_show_disco_items(GSList *items, const char * const jid); void cons_show_disco_info(const char *from, GSList *identities, GSList *features); void cons_show_room_invite(const char * const invitor, const char * const room, const char * const reason); +void cons_check_version(gboolean not_available_msg); +void cons_show_typing(const char * const short_from); +void cons_show_incoming_message(const char * const short_from, const int win_index); // status bar actions void status_bar_refresh(void); @@ -201,5 +189,4 @@ void inp_block(void); void inp_get_password(char *passwd); void inp_replace_input(char *input, const char * const new_input, int *size); -void notify_remind(void); #endif diff --git a/src/ui/window.c b/src/ui/window.c index 85648814..5ef23b84 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -38,7 +38,7 @@ #define CONS_WIN_TITLE "_cons" ProfWin* -window_create(const char * const title, int cols, win_type_t type) +win_create(const char * const title, int cols, win_type_t type) { ProfWin *new_win = malloc(sizeof(struct prof_win_t)); new_win->from = strdup(title); @@ -55,7 +55,7 @@ window_create(const char * const title, int cols, win_type_t type) } void -window_free(ProfWin* window) +win_free(ProfWin* window) { delwin(window->win); free(window->from); @@ -64,3 +64,98 @@ window_free(ProfWin* window) free(window); window = NULL; } + +void +win_print_time(ProfWin* window, char show_char) +{ + GDateTime *time = g_date_time_new_now_local(); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(window->win, COLOUR_TIME); + wprintw(window->win, "%s %c ", date_fmt, show_char); + wattroff(window->win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); +} + +void +win_presence_colour_on(ProfWin *window, const char * const presence) +{ + if (g_strcmp0(presence, "online") == 0) { + wattron(window->win, COLOUR_ONLINE); + } else if (g_strcmp0(presence, "away") == 0) { + wattron(window->win, COLOUR_AWAY); + } else if (g_strcmp0(presence, "chat") == 0) { + wattron(window->win, COLOUR_CHAT); + } else if (g_strcmp0(presence, "dnd") == 0) { + wattron(window->win, COLOUR_DND); + } else if (g_strcmp0(presence, "xa") == 0) { + wattron(window->win, COLOUR_XA); + } else { + wattron(window->win, COLOUR_OFFLINE); + } +} + +void +win_presence_colour_off(ProfWin *window, const char * const presence) +{ + if (g_strcmp0(presence, "online") == 0) { + wattroff(window->win, COLOUR_ONLINE); + } else if (g_strcmp0(presence, "away") == 0) { + wattroff(window->win, COLOUR_AWAY); + } else if (g_strcmp0(presence, "chat") == 0) { + wattroff(window->win, COLOUR_CHAT); + } else if (g_strcmp0(presence, "dnd") == 0) { + wattroff(window->win, COLOUR_DND); + } else if (g_strcmp0(presence, "xa") == 0) { + wattroff(window->win, COLOUR_XA); + } else { + wattroff(window->win, COLOUR_OFFLINE); + } +} + +void +win_show_contact(ProfWin *window, PContact contact) +{ + const char *barejid = p_contact_barejid(contact); + const char *name = p_contact_name(contact); + const char *presence = p_contact_presence(contact); + const char *status = p_contact_status(contact); + GDateTime *last_activity = p_contact_last_activity(contact); + + win_print_time(window, '-'); + win_presence_colour_on(window, presence); + wprintw(window->win, "%s", barejid); + + if (name != NULL) { + wprintw(window->win, " (%s)", name); + } + + wprintw(window->win, " is %s", presence); + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + wprintw(window->win, ", idle "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(window->win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(window->win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(window->win, "%ds", seconds); + } + + if (status != NULL) { + wprintw(window->win, ", \"%s\"", p_contact_status(contact)); + } + + wprintw(window->win, "\n"); + win_presence_colour_off(window, presence); +} diff --git a/src/ui/window.h b/src/ui/window.h index ce980dd6..933d4e66 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -23,7 +23,17 @@ #ifndef WINDOW_H #define WINDOW_H -#include "ui/ui.h" +#include "contact.h" + +#define PAD_SIZE 1000 + +typedef enum { + WIN_UNUSED, + WIN_CONSOLE, + WIN_CHAT, + WIN_MUC, + WIN_PRIVATE +} win_type_t; typedef struct prof_win_t { char *from; @@ -35,8 +45,12 @@ typedef struct prof_win_t { int history_shown; } ProfWin; +ProfWin* win_create(const char * const title, int cols, win_type_t type); +void win_free(ProfWin *window); -ProfWin* window_create(const char * const title, int cols, win_type_t type); -void window_free(ProfWin *window); +void win_print_time(ProfWin *window, char show_char); +void win_presence_colour_on(ProfWin *window, const char * const presence); +void win_presence_colour_off(ProfWin *window, const char * const presence); +void win_show_contact(ProfWin *window, PContact contact); #endif diff --git a/src/ui/windows.c b/src/ui/windows.c deleted file mode 100644 index 62d16167..00000000 --- a/src/ui/windows.c +++ /dev/null @@ -1,2881 +0,0 @@ -/* - * windows.c - * - * Copyright (C) 2012, 2013 James Booth - * - * 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 . - * - */ - -#include "config.h" - -#include -#include -#ifdef HAVE_LIBXSS -#include -#endif -#include -#ifdef HAVE_LIBNOTIFY -#include -#endif -#ifdef PLATFORM_CYGWIN -#include -#endif -#ifdef HAVE_NCURSESW_NCURSES_H -#include -#elif HAVE_NCURSES_H -#include -#endif - -#include "chat_session.h" -#include "command/command.h" -#include "common.h" -#include "config/preferences.h" -#include "config/theme.h" -#include "contact.h" -#include "contact_list.h" -#include "jid.h" -#include "log.h" -#include "muc.h" -#include "ui/ui.h" -#include "ui/window.h" - -#define CONS_WIN_TITLE "_cons" -#define NUM_WINS 10 - -// holds console at index 0 and chat wins 1 through to 9 -static ProfWin* windows[NUM_WINS]; - -// the window currently being displayed -static int current_index = 0; -static ProfWin *current; -static ProfWin *console; - -// current window state -static int dirty; - -// max columns for main windows, never resize below -static int max_cols = 0; - -static char *win_title; - -#ifdef HAVE_LIBXSS -static Display *display; -#endif - -static GTimer *ui_idle_time; - -static void _set_current(int index); -static void _create_windows(void); -static void _cons_splash_logo(void); -static void _cons_show_basic_help(void); -static void _win_show_contact(ProfWin *window, PContact contact); -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_time(WINDOW *win, char showchar); -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); -static void _show_status_string(WINDOW *win, const char * const from, - const char * const show, const char * const status, - GDateTime *last_activity, const char * const pre, - const char * const default_show); -static void _cons_show_typing(const char * const short_from); -static void _cons_show_incoming_message(const char * const short_from, - const int win_index); -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 gint _win_get_unread(void); -static void _win_show_history(WINDOW *win, int win_index, - const char * const contact); -static void _win_show_info(WINDOW *win, PContact pcontact); -static gboolean _new_release(char *found_version); -static void _ui_draw_win_title(void); -static void _presence_colour_on(WINDOW *win, const char * const presence); -static void _presence_colour_off(WINDOW *win, const char * const presence); - -static void _notify(const char * const message, int timeout, - const char * const category); -static void _notify_remind(gint unread); -static void _notify_message(const char * const short_from); -static void _notify_typing(const char * const from); - -void -ui_init(void) -{ - log_info("Initialising UI"); - initscr(); - raw(); - keypad(stdscr, TRUE); - if (prefs_get_boolean(PREF_MOUSE)) { - mousemask(ALL_MOUSE_EVENTS, NULL); - mouseinterval(5); - } - ui_load_colours(); - refresh(); - create_title_bar(); - create_status_bar(); - status_bar_active(0); - create_input_window(); - _create_windows(); -#ifdef HAVE_LIBXSS - display = XOpenDisplay(0); -#endif - ui_idle_time = g_timer_new(); - dirty = TRUE; -} - -void -ui_refresh(void) -{ - _ui_draw_win_title(); - - title_bar_refresh(); - status_bar_refresh(); - - if (dirty) { - _current_window_refresh(); - dirty = FALSE; - } - - inp_put_back(); -} - -static void -_ui_draw_win_title(void) -{ - char new_win_title[100]; - - GString *version_str = g_string_new(""); - - if (prefs_get_boolean(PREF_TITLEBARVERSION)) { - g_string_append(version_str, " "); - g_string_append(version_str, PACKAGE_VERSION); - if (strcmp(PACKAGE_STATUS, "development") == 0) { - g_string_append(version_str, "dev"); - } - } - - jabber_conn_status_t status = jabber_get_connection_status(); - - if (status == JABBER_CONNECTED) { - const char * const jid = jabber_get_jid(); - gint unread = _win_get_unread(); - - if (unread != 0) { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s (%d) - %s%c", '\033', "Profanity", version_str->str, unread, jid, '\007'); - } else { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s - %s%c", '\033', "Profanity", version_str->str, jid, '\007'); - } - } else { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s%c", '\033', "Profanity", version_str->str, '\007'); - } - - g_string_free(version_str, TRUE); - - if (g_strcmp0(win_title, new_win_title) != 0) { - // print to x-window title bar - printf("%s", new_win_title); - if (win_title != NULL) { - free(win_title); - } - win_title = strdup(new_win_title); - } -} - -unsigned long -ui_get_idle_time(void) -{ -// if compiled with libxss, get the x sessions idle time -#ifdef HAVE_LIBXSS - XScreenSaverInfo *info = XScreenSaverAllocInfo(); - if (info != NULL && display != NULL) { - XScreenSaverQueryInfo(display, DefaultRootWindow(display), info); - unsigned long result = info->idle; - XFree(info); - return result; - } -// if no libxss or xss idle time failed, use profanity idle time -#endif - gdouble seconds_elapsed = g_timer_elapsed(ui_idle_time, NULL); - unsigned long ms_elapsed = seconds_elapsed * 1000.0; - return ms_elapsed; -} - -void -ui_reset_idle_time(void) -{ - g_timer_start(ui_idle_time); -} - -void -ui_close(void) -{ -#ifdef HAVE_LIBNOTIFY - if (notify_is_initted()) { - notify_uninit(); - } -#endif - endwin(); -} - -void -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(); - inp_win_resize(input, size); - dirty = TRUE; -} - -void -ui_load_colours(void) -{ - if (has_colors()) { - use_default_colors(); - start_color(); - theme_init_colours(); - } -} - -gboolean -ui_windows_full(void) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] == NULL) { - return FALSE; - } - } - - return TRUE; -} - -void -ui_show_typing(const char * const from) -{ - int win_index = _find_prof_win_index(from); - - if (prefs_get_boolean(PREF_INTYPE)) { - // no chat window for user - if (win_index == NUM_WINS) { - _cons_show_typing(from); - - // have chat window but not currently in it - } else if (win_index != current_index) { - _cons_show_typing(from); - dirty = TRUE; - - // in chat window with user - } else { - title_bar_set_typing(TRUE); - title_bar_draw(); - - status_bar_active(win_index); - dirty = TRUE; - } - } - - if (prefs_get_boolean(PREF_NOTIFY_TYPING)) - _notify_typing(from); -} - -void -ui_idle(void) -{ - int i; - - // 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); - - 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); - } - } - } -} - -void -ui_show_incoming_msg(const char * const from, const char * const message, - GTimeVal *tv_stamp, gboolean priv) -{ - char *display_from; - win_type_t win_type; - if (priv) { - win_type = WIN_PRIVATE; - display_from = get_nick_from_full_jid(from); - } else { - win_type = WIN_CHAT; - display_from = strdup(from); - } - - int win_index = _find_prof_win_index(from); - if (win_index == NUM_WINS) - win_index = _new_prof_win(from, win_type); - - // no spare windows left - if (win_index == 0) { - if (tv_stamp == NULL) { - _win_show_time(console->win, '-'); - } 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); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(console->win, COLOUR_THEM); - wprintw(console->win, "*%s ", from); - wprintw(console->win, "%s", message + 4); - wprintw(console->win, "\n"); - wattroff(console->win, COLOUR_THEM); - } else { - _win_show_user(console->win, from, 1); - _win_show_message(console->win, message); - } - - cons_bad_show("Windows all used, close a window to respond."); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } - - // window found or created - } else { - WINDOW *win = windows[win_index]->win; - - // currently viewing chat window with sender - if (win_index == current_index) { - if (tv_stamp == NULL) { - _win_show_time(win, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s - ", date_fmt); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", display_from); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, display_from, 1); - _win_show_message(win, message); - } - title_bar_set_typing(FALSE); - title_bar_draw(); - status_bar_active(win_index); - dirty = TRUE; - - // not currently viewing chat window with sender - } else { - status_bar_new(win_index); - _cons_show_incoming_message(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(win, win_index, from); - } - - if (tv_stamp == NULL) { - _win_show_time(win, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s - ", date_fmt); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", display_from); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, display_from, 1); - _win_show_message(win, message); - } - } - } - - if (prefs_get_boolean(PREF_BEEP)) - beep(); - if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) - _notify_message(display_from); - - g_free(display_from); -} - -void -ui_contact_online(const char * const barejid, const char * const resource, - const char * const show, const char * const status, GDateTime *last_activity) -{ - Jid *jid = jid_create_from_bare_and_resource(barejid, resource); - char *display_str = NULL; - - if (strcmp(jid->resourcepart, "__prof_default") == 0) { - display_str = jid->barejid; - } else { - display_str = jid->fulljid; - } - - _show_status_string(console->win, display_str, show, status, last_activity, "++", - "online"); - - int win_index = _find_prof_win_index(barejid); - if (win_index != NUM_WINS) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, display_str, show, status, last_activity, "++", - "online"); - } - - jid_destroy(jid); - - if (win_index == current_index) - dirty = TRUE; -} - -void -ui_contact_offline(const char * const from, const char * const show, - const char * const status) -{ - Jid *jidp = jid_create(from); - char *display_str = NULL; - - if (strcmp(jidp->resourcepart, "__prof_default") == 0) { - display_str = jidp->barejid; - } else { - display_str = jidp->fulljid; - } - - _show_status_string(console->win, display_str, show, status, NULL, "--", "offline"); - - int win_index = _find_prof_win_index(from); - if (win_index != NUM_WINS) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, display_str, show, status, NULL, "--", "offline"); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -ui_disconnected(void) -{ - int i; - // show message in all active chats - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - WINDOW *win = windows[i]->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", "Lost connection."); - wattroff(win, COLOUR_ERROR); - - // if current win, set dirty - if (i == current_index) { - dirty = TRUE; - } - } - } - - title_bar_set_status(CONTACT_OFFLINE); - status_bar_clear_message(); - status_bar_refresh(); -} - -void -ui_handle_special_keys(const wint_t * const ch, const char * const inp, - const int size) -{ - _win_handle_switch(ch); - _win_handle_page(ch); - if (*ch == KEY_RESIZE) { - ui_resize(*ch, inp, size); - } - -} - -void -ui_switch_win(const int i) -{ - win_current_page_off(); - if (windows[i] != NULL) { - current_index = i; - current = windows[current_index]; - win_current_page_off(); - - current->unread = 0; - - if (i == 0) { - title_bar_title(); - status_bar_active(0); - } else { - title_bar_set_recipient(current->from); - title_bar_draw();; - status_bar_active(i); - } - } - - dirty = TRUE; -} - -void -win_current_clear(void) -{ - werase(current->win); - dirty = TRUE; -} - -void -win_current_close(void) -{ - window_free(current); - windows[current_index] = NULL; - - // set it as inactive in the status bar - status_bar_inactive(current_index); - - // go back to console window - _set_current(0); - status_bar_active(0); - title_bar_title(); - - dirty = TRUE; -} - -int -win_current_is_console(void) -{ - return (current->type == WIN_CONSOLE); -} - -int -win_current_is_chat(void) -{ - return (current->type == WIN_CHAT); -} - -int -win_current_is_groupchat(void) -{ - return (current->type == WIN_MUC); -} - -int -win_current_is_private(void) -{ - return (current->type == WIN_PRIVATE); -} - -char * -win_current_get_recipient(void) -{ - return strdup(current->from); -} - -void -win_current_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(current->win, '-'); - wprintw(current->win, "%s\n", fmt_msg->str); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - dirty = TRUE; -} - -void -win_current_bad_show(const char * const msg) -{ - WINDOW *win = current->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", msg); - wattroff(win, COLOUR_ERROR); - - dirty = TRUE; -} - -void -win_current_page_off(void) -{ - int rows = getmaxy(stdscr); - ProfWin *window = windows[current_index]; - - window->paged = 0; - - int y = getcury(window->win); - - int size = rows - 3; - - window->y_pos = y - (size - 1); - if (window->y_pos < 0) - window->y_pos = 0; - - dirty = TRUE; -} - -void -win_show_error_msg(const char * const from, const char *err_msg) -{ - int win_index; - WINDOW *win; - - if (from == NULL || err_msg == NULL) - return; - - win_index = _find_prof_win_index(from); - // chat window exists - if (win_index < NUM_WINS) { - win = windows[win_index]->win; - _win_show_time(win, '-'); - _win_show_error_msg(win, err_msg); - if (win_index == current_index) { - dirty = TRUE; - } - } -} - -void -win_show_system_msg(const char * const from, const char *message) -{ - int win_index; - WINDOW *win; - char from_cpy[strlen(from) + 1]; - char *bare_jid; - - if (from == NULL || message == NULL) - return; - - 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); - dirty = TRUE; - } - win = windows[win_index]->win; - - _win_show_time(win, '-'); - wprintw(win, "*%s %s\n", bare_jid, message); - - // this is the current window - if (win_index == current_index) { - dirty = TRUE; - } -} - -void -win_show_gone(const char * const from) -{ - int win_index; - WINDOW *win; - - if (from == NULL) - return; - - win_index = _find_prof_win_index(from); - // chat window exists - if (win_index < NUM_WINS) { - win = windows[win_index]->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_GONE); - wprintw(win, "*%s ", from); - wprintw(win, "has left the conversation."); - wprintw(win, "\n"); - wattroff(win, COLOUR_GONE); - if (win_index == current_index) { - dirty = TRUE; - } - } -} - -void -win_new_chat_win(const char * const to) -{ - // if the contact is offline, show a message - PContact contact = contact_list_get_contact(to); - int win_index = _find_prof_win_index(to); - WINDOW *win = NULL; - - // create new window - if (win_index == NUM_WINS) { - Jid *jid = jid_create(to); - - if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); - } else { - win_index = _new_prof_win(to, WIN_CHAT); - } - - jid_destroy(jid); - - win = windows[win_index]->win; - - if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _win_show_history(win, win_index, to); - } - - if (contact != NULL) { - if (strcmp(p_contact_presence(contact), "offline") == 0) { - const char const *show = p_contact_presence(contact); - const char const *status = p_contact_status(contact); - _show_status_string(win, to, show, status, NULL, "--", "offline"); - } - } - - // use existing window - } else { - win = windows[win_index]->win; - } - - ui_switch_win(win_index); -} - -void -win_show_outgoing_msg(const char * const from, const char * const to, - const char * const message) -{ - // if the contact is offline, show a message - PContact contact = contact_list_get_contact(to); - int win_index = _find_prof_win_index(to); - WINDOW *win = NULL; - - // create new window - if (win_index == NUM_WINS) { - Jid *jid = jid_create(to); - - if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); - } else { - win_index = _new_prof_win(to, WIN_CHAT); - } - - jid_destroy(jid); - - win = windows[win_index]->win; - - if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) { - _win_show_history(win, win_index, to); - } - - if (contact != NULL) { - if (strcmp(p_contact_presence(contact), "offline") == 0) { - const char const *show = p_contact_presence(contact); - const char const *status = p_contact_status(contact); - _show_status_string(win, to, show, status, NULL, "--", "offline"); - } - } - - // use existing window - } else { - win = windows[win_index]->win; - } - - _win_show_time(win, '-'); - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_ME); - wprintw(win, "*%s ", from); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_ME); - } else { - _win_show_user(win, from, 0); - _win_show_message(win, message); - } - ui_switch_win(win_index); -} - -void -win_join_chat(Jid *jid) -{ - int win_index = _find_prof_win_index(jid->barejid); - - // create new window - if (win_index == NUM_WINS) { - win_index = _new_prof_win(jid->barejid, WIN_MUC); - } - - ui_switch_win(win_index); -} - -void -win_show_room_roster(const char * const room, GList *roster, const char * const presence) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - if ((roster == NULL) || (g_list_length(roster) == 0)) { - wattron(win, COLOUR_ROOMINFO); - if (presence == NULL) { - wprintw(win, "Room is empty.\n"); - } else { - wprintw(win, "No participants are %s.\n", presence); - } - wattroff(win, COLOUR_ROOMINFO); - } else { - wattron(win, COLOUR_ROOMINFO); - if (presence == NULL) { - wprintw(win, "Participants: "); - } else { - wprintw(win, "Participants (%s): ", presence); - } - wattroff(win, COLOUR_ROOMINFO); - wattron(win, COLOUR_ONLINE); - - while (roster != NULL) { - PContact member = roster->data; - const char const *nick = p_contact_barejid(member); - const char const *show = p_contact_presence(member); - - _presence_colour_on(win, show); - wprintw(win, "%s", nick); - _presence_colour_off(win, show); - - if (roster->next != NULL) { - wprintw(win, ", "); - } - - roster = g_list_next(roster); - } - - wprintw(win, "\n"); - wattroff(win, COLOUR_ONLINE); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_member_offline(const char * const room, const char * const nick) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_OFFLINE); - wprintw(win, "<- %s has left the room.\n", nick); - wattroff(win, COLOUR_OFFLINE); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_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); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ONLINE); - wprintw(win, "-> %s has joined the room.\n", nick); - wattroff(win, COLOUR_ONLINE); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_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) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, nick, show, status, NULL, "++", "online"); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_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); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_THEM); - wprintw(win, "** %s is now known as %s\n", old_nick, nick); - wattroff(win, COLOUR_THEM); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_nick_change(const char * const room, const char * const nick) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ME); - wprintw(win, "** You are now known as %s\n", nick); - wattroff(win, COLOUR_ME); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_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; - - 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); - g_date_time_unref(time); - g_free(date_fmt); - - if (strncmp(message, "/me ", 4) == 0) { - wprintw(win, "*%s ", nick); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - } else { - wprintw(win, "%s: ", nick); - _win_show_message(win, message); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_message(const char * const room_jid, const char * const nick, - const char * const message) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '-'); - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", nick); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, nick, 1); - _win_show_message(win, message); - } - - } else { - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_ME); - wprintw(win, "*%s ", nick); - wprintw(win, "%s", message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_ME); - } else { - _win_show_user(win, nick, 0); - _win_show_message(win, message); - } - } - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - _cons_show_incoming_message(nick, win_index); - if (current_index == 0) { - dirty = TRUE; - } - - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (prefs_get_boolean(PREF_FLASH)) { - flash(); - } - } - - windows[win_index]->unread++; - } - - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (prefs_get_boolean(PREF_BEEP)) { - beep(); - } - if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) { - _notify_message(nick); - } - } -} - -void -win_show_room_subject(const char * const room_jid, const char * const subject) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ROOMINFO); - wprintw(win, "Room subject: "); - wattroff(win, COLOUR_ROOMINFO); - wprintw(win, "%s\n", subject); - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - } -} - -void -win_show_room_broadcast(const char * const room_jid, const char * const message) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ROOMINFO); - wprintw(win, "Room message: "); - wattroff(win, COLOUR_ROOMINFO); - wprintw(win, "%s\n", message); - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - } -} - -void -cons_show_login_success(ProfAccount *account) -{ - _win_show_time(console->win, '-'); - wprintw(console->win, "%s logged in successfully, ", account->jid); - - resource_presence_t presence = accounts_get_login_presence(account->name); - const char *presence_str = string_from_resource_presence(presence); - - _presence_colour_on(console->win, presence_str); - wprintw(console->win, "%s", presence_str); - _presence_colour_off(console->win, presence_str); - wprintw(console->win, " (priority %d)", - accounts_get_priority_for_presence_type(account->name, presence)); - wprintw(console->win, ".\n"); -} - - -void -cons_show_wins(void) -{ - int i = 0; - int count = 0; - - cons_show(""); - cons_show("Active windows:"); - _win_show_time(console->win, '-'); - 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_show_time(console->win, '-'); - - switch (window->type) - { - case WIN_CHAT: - wprintw(console->win, "%d: chat %s", i + 1, window->from); - PContact contact = contact_list_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", i + 1, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - case WIN_MUC: - wprintw(console->win, "%d: room %s", i + 1, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - default: - break; - } - - wprintw(console->win, "\n"); - } - } - } - - cons_show(""); -} - -void -cons_show_info(PContact pcontact) -{ - _win_show_info(console->win, pcontact); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_caps(const char * const contact, Resource *resource) -{ - WINDOW *win = console->win; - cons_show(""); - const char *resource_presence = string_from_resource_presence(resource->presence); - _win_show_time(win, '-'); - _presence_colour_on(win, resource_presence); - wprintw(win, "%s", contact); - _presence_colour_off(win, resource_presence); - wprintw(win, ":\n"); - - if (resource->caps_str != NULL) { - log_debug("Getting caps, caps_str: %s", resource->caps_str); - Capabilities *caps = caps_get(resource->caps_str); - if (caps != NULL) { - // show identity - if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { - _win_show_time(win, '-'); - wprintw(win, "Identity: "); - if (caps->name != NULL) { - wprintw(win, "%s", caps->name); - if ((caps->category != NULL) || (caps->type != NULL)) { - wprintw(win, " "); - } - } - if (caps->type != NULL) { - wprintw(win, "%s", caps->type); - if (caps->category != NULL) { - wprintw(win, " "); - } - } - if (caps->category != NULL) { - wprintw(win, "%s", caps->category); - } - wprintw(win, "\n"); - } - if (caps->software != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Software: %s", caps->software); - } - if (caps->software_version != NULL) { - wprintw(win, ", %s", caps->software_version); - } - if ((caps->software != NULL) || (caps->software_version != NULL)) { - wprintw(win, "\n"); - } - if (caps->os != NULL) { - _win_show_time(win, '-'); - wprintw(win, "OS: %s", caps->os); - } - if (caps->os_version != NULL) { - wprintw(win, ", %s", caps->os_version); - } - if ((caps->os != NULL) || (caps->os_version != NULL)) { - wprintw(win, "\n"); - } - - if (caps->features != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Features:\n"); - GSList *feature = caps->features; - while (feature != NULL) { - _win_show_time(win, '-'); - wprintw(win, " %s\n", feature->data); - feature = g_slist_next(feature); - } - } - } - } else { - log_debug("No caps string found in resource"); - } - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -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) -{ - if ((name != NULL) || (version != NULL) || (os != NULL)) { - cons_show(""); - _win_show_time(console->win, '-'); - _presence_colour_on(console->win, presence); - wprintw(console->win, "%s", jid); - _presence_colour_off(console->win, presence); - wprintw(console->win, ":\n"); - } - if (name != NULL) { - cons_show("Name : %s", name); - } - if (version != NULL) { - cons_show("Version : %s", version); - } - if (os != NULL) { - cons_show("OS : %s", os); - } -} - -void -cons_show_room_list(GSList *rooms, const char * const conference_node) -{ - if ((rooms != NULL) && (g_slist_length(rooms) > 0)) { - cons_show("Chat rooms at %s:", conference_node); - while (rooms != NULL) { - DiscoItem *room = rooms->data; - _win_show_time(console->win, '-'); - wprintw(console->win, " %s", room->jid); - if (room->name != NULL) { - wprintw(console->win, ", (%s)", room->name); - } - wprintw(console->win, "\n"); - rooms = g_slist_next(rooms); - } - } else { - cons_show("No chat rooms at %s", conference_node); - } -} - -void -cons_show_disco_info(const char *jid, GSList *identities, GSList *features) -{ - if (((identities != NULL) && (g_slist_length(identities) > 0)) || - ((features != NULL) && (g_slist_length(features) > 0))) { - cons_show(""); - cons_show("Service disovery info for %s", jid); - - if (identities != NULL) { - cons_show(" Identities"); - } - while (identities != NULL) { - DiscoIdentity *identity = identities->data; // anme trpe, cat - GString *identity_str = g_string_new(" "); - if (identity->name != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->name)); - identity_str = g_string_append(identity_str, " "); - } - if (identity->type != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->type)); - identity_str = g_string_append(identity_str, " "); - } - if (identity->category != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->category)); - } - cons_show(identity_str->str); - g_string_free(identity_str, FALSE); - identities = g_slist_next(identities); - } - - if (features != NULL) { - cons_show(" Features:"); - } - while (features != NULL) { - cons_show(" %s", features->data); - features = g_slist_next(features); - } - } -} - -void -cons_show_disco_items(GSList *items, const char * const jid) -{ - if ((items != NULL) && (g_slist_length(items) > 0)) { - cons_show(""); - cons_show("Service discovery items for %s:", jid); - while (items != NULL) { - DiscoItem *item = items->data; - _win_show_time(console->win, '-'); - wprintw(console->win, " %s", item->jid); - if (item->name != NULL) { - wprintw(console->win, ", (%s)", item->name); - } - wprintw(console->win, "\n"); - items = g_slist_next(items); - } - } else { - cons_show(""); - cons_show("No service discovery items for %s", jid); - } -} - -void -cons_show_status(const char * const contact) -{ - PContact pcontact = contact_list_get_contact(contact); - - if (pcontact != NULL) { - _win_show_contact(console, pcontact); - } else { - cons_show("No such contact \"%s\" in roster.", contact); - } -} - -void -cons_show_room_invite(const char * const invitor, const char * const room, - const char * const reason) -{ - char *display_room = NULL; - char *domain = strdup(jabber_get_domain()); - Jid *room_jid = jid_create(room); - GString *default_service = g_string_new("conference."); - g_string_append(default_service, domain); - - cons_show(""); - cons_show("Chat room invite received:"); - cons_show(" From : %s", invitor); - cons_show(" Room : %s", room); - - if (reason != NULL) { - cons_show(" Message: %s", reason); - } - - if (strcmp(room_jid->domainpart, default_service->str) == 0) { - display_room = room_jid->localpart; - } else { - display_room = room_jid->barejid; - } - - cons_show("Type \"/join %s\" to accept the invitation", display_room); - - jid_destroy(room_jid); - g_string_free(default_service, TRUE); -} - -void -cons_show_account_list(gchar **accounts) -{ - int size = g_strv_length(accounts); - if (size > 0) { - cons_show("Accounts:"); - int i = 0; - for (i = 0; i < size; i++) { - if ((jabber_get_connection_status() == JABBER_CONNECTED) && - (g_strcmp0(jabber_get_account_name(), accounts[i]) == 0)) { - resource_presence_t presence = accounts_get_last_presence(accounts[i]); - _win_show_time(console->win, '-'); - _presence_colour_on(console->win, string_from_resource_presence(presence)); - wprintw(console->win, "%s\n", accounts[i]); - _presence_colour_off(console->win, string_from_resource_presence(presence)); - } else { - cons_show(accounts[i]); - } - } - cons_show(""); - } else { - cons_show("No accounts created yet."); - cons_show(""); - } -} - -void -cons_show_account(ProfAccount *account) -{ - cons_show(""); - cons_show("Account %s:", account->name); - if (account->enabled) { - cons_show ("enabled : TRUE"); - } else { - cons_show ("enabled : FALSE"); - } - cons_show ("jid : %s", account->jid); - if (account->resource != NULL) { - cons_show ("resource : %s", account->resource); - } - if (account->server != NULL) { - cons_show ("server : %s", account->server); - } - if (account->last_presence != NULL) { - cons_show ("Last presence : %s", account->last_presence); - } - if (account->login_presence != NULL) { - cons_show ("Login presence : %s", account->login_presence); - } - cons_show ("Priority : chat:%d, online:%d, away:%d, xa:%d, dnd:%d", - account->priority_chat, account->priority_online, account->priority_away, - account->priority_xa, account->priority_dnd); - - if ((jabber_get_connection_status() == JABBER_CONNECTED) && - (g_strcmp0(jabber_get_account_name(), account->name) == 0)) { - GList *resources = jabber_get_available_resources(); - GList *ordered_resources = NULL; - - WINDOW *win = console->win; - if (resources != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Resources:\n"); - - // sort in order of availabiltiy - while (resources != NULL) { - Resource *resource = resources->data; - ordered_resources = g_list_insert_sorted(ordered_resources, - resource, (GCompareFunc)resource_compare_availability); - resources = g_list_next(resources); - } - } - - while (ordered_resources != NULL) { - Resource *resource = ordered_resources->data; - const char *resource_presence = string_from_resource_presence(resource->presence); - _win_show_time(win, '-'); - _presence_colour_on(win, resource_presence); - wprintw(win, " %s (%d), %s", resource->name, resource->priority, resource_presence); - if (resource->status != NULL) { - wprintw(win, ", \"%s\"", resource->status); - } - wprintw(win, "\n"); - _presence_colour_off(win, resource_presence); - - if (resource->caps_str != NULL) { - Capabilities *caps = caps_get(resource->caps_str); - if (caps != NULL) { - // show identity - if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { - _win_show_time(win, '-'); - wprintw(win, " Identity: "); - if (caps->name != NULL) { - wprintw(win, "%s", caps->name); - if ((caps->category != NULL) || (caps->type != NULL)) { - wprintw(win, " "); - } - } - if (caps->type != NULL) { - wprintw(win, "%s", caps->type); - if (caps->category != NULL) { - wprintw(win, " "); - } - } - if (caps->category != NULL) { - wprintw(win, "%s", caps->category); - } - wprintw(win, "\n"); - } - if (caps->software != NULL) { - _win_show_time(win, '-'); - wprintw(win, " Software: %s", caps->software); - } - if (caps->software_version != NULL) { - wprintw(win, ", %s", caps->software_version); - } - if ((caps->software != NULL) || (caps->software_version != NULL)) { - wprintw(win, "\n"); - } - if (caps->os != NULL) { - _win_show_time(win, '-'); - wprintw(win, " OS: %s", caps->os); - } - if (caps->os_version != NULL) { - wprintw(win, ", %s", caps->os_version); - } - if ((caps->os != NULL) || (caps->os_version != NULL)) { - wprintw(win, "\n"); - } - } - } - - ordered_resources = g_list_next(ordered_resources); - } - } -} - -void -win_show_status(void) -{ - char *recipient = win_current_get_recipient(); - PContact pcontact = contact_list_get_contact(recipient); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("Error getting contact info."); - } -} - -void -win_private_show_status(void) -{ - Jid *jid = jid_create(win_current_get_recipient()); - - PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("Error getting contact info."); - } - - jid_destroy(jid); -} - -void -win_room_show_status(const char * const contact) -{ - PContact pcontact = muc_get_participant(win_current_get_recipient(), contact); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("No such participant \"%s\" in room.", contact); - } -} - -void -cons_show_ui_prefs(void) -{ - cons_show("UI preferences:"); - cons_show(""); - - gchar *theme = prefs_get_string(PREF_THEME); - if (theme == NULL) { - cons_show("Theme (/theme) : default"); - } else { - cons_show("Theme (/theme) : %s", theme); - } - - if (prefs_get_boolean(PREF_BEEP)) - cons_show("Terminal beep (/beep) : ON"); - else - cons_show("Terminal beep (/beep) : OFF"); - - if (prefs_get_boolean(PREF_FLASH)) - cons_show("Terminal flash (/flash) : ON"); - else - cons_show("Terminal flash (/flash) : OFF"); - - if (prefs_get_boolean(PREF_INTYPE)) - cons_show("Show typing (/intype) : ON"); - else - cons_show("Show typing (/intype) : OFF"); - - if (prefs_get_boolean(PREF_SPLASH)) - cons_show("Splash screen (/splash) : ON"); - else - cons_show("Splash screen (/splash) : OFF"); - - if (prefs_get_boolean(PREF_HISTORY)) - cons_show("Chat history (/history) : ON"); - else - cons_show("Chat history (/history) : OFF"); - - if (prefs_get_boolean(PREF_VERCHECK)) - cons_show("Version checking (/vercheck) : ON"); - else - cons_show("Version checking (/vercheck) : OFF"); - - if (prefs_get_boolean(PREF_MOUSE)) - cons_show("Mouse handling (/mouse) : ON"); - else - cons_show("Mouse handling (/mouse) : OFF"); - - if (prefs_get_boolean(PREF_STATUSES)) - cons_show("Status (/statuses) : ON"); - else - cons_show("Status (/statuses) : OFF"); -} - -void -cons_show_desktop_prefs(void) -{ - cons_show("Desktop notification preferences:"); - cons_show(""); - - if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) - cons_show("Messages (/notify message) : ON"); - else - cons_show("Messages (/notify message) : OFF"); - - if (prefs_get_boolean(PREF_NOTIFY_TYPING)) - cons_show("Composing (/notify typing) : ON"); - else - cons_show("Composing (/notify typing) : OFF"); - - gint remind_period = prefs_get_notify_remind(); - if (remind_period == 0) { - cons_show("Reminder period (/notify remind) : OFF"); - } else if (remind_period == 1) { - cons_show("Reminder period (/notify remind) : 1 second"); - } else { - cons_show("Reminder period (/notify remind) : %d seconds", remind_period); - } -} - -void -cons_show_chat_prefs(void) -{ - cons_show("Chat preferences:"); - cons_show(""); - - if (prefs_get_boolean(PREF_STATES)) - cons_show("Send chat states (/states) : ON"); - else - cons_show("Send chat states (/states) : OFF"); - - if (prefs_get_boolean(PREF_OUTTYPE)) - cons_show("Send composing (/outtype) : ON"); - else - cons_show("Send composing (/outtype) : OFF"); - - gint gone_time = prefs_get_gone(); - if (gone_time == 0) { - cons_show("Leave conversation (/gone) : OFF"); - } else if (gone_time == 1) { - cons_show("Leave conversation (/gone) : 1 minute"); - } else { - cons_show("Leave conversation (/gone) : %d minutes", gone_time); - } -} - -void -cons_show_log_prefs(void) -{ - cons_show("Logging preferences:"); - cons_show(""); - - cons_show("Max log size (/log maxsize) : %d bytes", prefs_get_max_log_size()); - - if (prefs_get_boolean(PREF_CHLOG)) - cons_show("Chat logging (/chlog) : ON"); - else - cons_show("Chat logging (/chlog) : OFF"); -} - -void -cons_show_presence_prefs(void) -{ - cons_show("Presence preferences:"); - cons_show(""); - - if (strcmp(prefs_get_string(PREF_AUTOAWAY_MODE), "off") == 0) { - cons_show("Autoaway (/autoaway mode) : OFF"); - } else { - cons_show("Autoaway (/autoaway mode) : %s", prefs_get_string(PREF_AUTOAWAY_MODE)); - } - - cons_show("Autoaway minutes (/autoaway time) : %d minutes", prefs_get_autoaway_time()); - - if ((prefs_get_string(PREF_AUTOAWAY_MESSAGE) == NULL) || - (strcmp(prefs_get_string(PREF_AUTOAWAY_MESSAGE), "") == 0)) { - cons_show("Autoaway message (/autoaway message) : OFF"); - } else { - cons_show("Autoaway message (/autoaway message) : \"%s\"", prefs_get_string(PREF_AUTOAWAY_MESSAGE)); - } - - if (prefs_get_boolean(PREF_AUTOAWAY_CHECK)) { - cons_show("Autoaway check (/autoaway check) : ON"); - } else { - cons_show("Autoaway check (/autoaway check) : OFF"); - } -} - -void -cons_show_connection_prefs(void) -{ - cons_show("Connection preferences:"); - cons_show(""); - - gint reconnect_interval = prefs_get_reconnect(); - if (reconnect_interval == 0) { - cons_show("Reconnect interval (/reconnect) : OFF"); - } else if (reconnect_interval == 1) { - cons_show("Reconnect interval (/reconnect) : 1 second"); - } else { - cons_show("Reconnect interval (/reconnect) : %d seconds", reconnect_interval); - } - - gint autoping_interval = prefs_get_autoping(); - if (autoping_interval == 0) { - cons_show("Autoping interval (/autoping) : OFF"); - } else if (autoping_interval == 1) { - cons_show("Autoping interval (/autoping) : 1 second"); - } else { - cons_show("Autoping interval (/autoping) : %d seconds", autoping_interval); - } -} - -void -cons_show_themes(GSList *themes) -{ - cons_show(""); - - if (themes == NULL) { - cons_show("No available themes."); - } else { - cons_show("Available themes:"); - while (themes != NULL) { - cons_show(themes->data); - themes = g_slist_next(themes); - } - } -} - -void -cons_prefs(void) -{ - cons_show(""); - cons_show_ui_prefs(); - cons_show(""); - cons_show_desktop_prefs(); - cons_show(""); - cons_show_chat_prefs(); - cons_show(""); - cons_show_log_prefs(); - cons_show(""); - cons_show_presence_prefs(); - cons_show(""); - cons_show_connection_prefs(); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -static void -_cons_show_basic_help(void) -{ - cons_show(""); - - GSList *basic_helpers = cmd_get_basic_help(); - while (basic_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)basic_helpers->data; - cons_show("%-30s: %s", help->usage, help->short_help); - basic_helpers = g_slist_next(basic_helpers); - } - - cons_show(""); -} - -void -cons_help(void) -{ - cons_show(""); - cons_show("Choose a help option:"); - cons_show(""); - cons_show("/help list - List all commands."); - cons_show("/help basic - Summary of basic usage commands."); - cons_show("/help presence - Summary of online status change commands."); - cons_show("/help settings - Summary of commands for changing Profanity settings."); - cons_show("/help navigation - How to navigate around Profanity."); - cons_show("/help [command] - Detailed help on a specific command."); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_basic_help(void) -{ - cons_show(""); - cons_show("Basic Commands:"); - _cons_show_basic_help(); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_settings_help(void) -{ - cons_show(""); - cons_show("Settings:"); - cons_show(""); - - GSList *settings_helpers = cmd_get_settings_help(); - while (settings_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)settings_helpers->data; - cons_show("%-27s: %s", help->usage, help->short_help); - settings_helpers = g_slist_next(settings_helpers); - } - - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_presence_help(void) -{ - cons_show(""); - cons_show("Presence changes:"); - cons_show(""); - - GSList *presence_helpers = cmd_get_presence_help(); - while (presence_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)presence_helpers->data; - cons_show("%-25s: %s", help->usage, help->short_help); - presence_helpers = g_slist_next(presence_helpers); - } - - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_navigation_help(void) -{ - cons_show(""); - cons_show("Navigation:"); - cons_show(""); - cons_show("Alt-1 : This console window."); - cons_show("Alt-2..Alt-0 : Chat windows."); - cons_show("F1 : This console window."); - cons_show("F2..F10 : Chat windows."); - cons_show("UP, DOWN : Navigate input history."); - cons_show("LEFT, RIGHT, HOME, END : Edit current input."); - cons_show("ESC : Clear current input."); - cons_show("TAB : Autocomplete command/recipient/login."); - cons_show("PAGE UP, PAGE DOWN : Page the main window."); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_contacts(GSList *list) -{ - GSList *curr = list; - - while(curr) { - PContact contact = curr->data; - if (strcmp(p_contact_subscription(contact), "none") != 0) { - _win_show_contact(console, contact); - } - curr = g_slist_next(curr); - } -} - -void -cons_bad_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_ERROR); - wprintw(console->win, "%s\n", fmt_msg->str); - wattroff(console->win, COLOUR_ERROR); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_time(void) -{ - _win_show_time(console->win, '-'); -} - -void -cons_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(console->win, '-'); - wprintw(console->win, "%s\n", fmt_msg->str); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_debug(const char * const msg, ...) -{ - if (strcmp(PACKAGE_STATUS, "development") == 0) { - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(console->win, '-'); - wprintw(console->win, "%s\n", fmt_msg->str); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } - - win_current_page_off(); - ui_refresh(); - } -} - -void -cons_show_word(const char * const word) -{ - wprintw(console->win, "%s", word); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_bad_command(const char * const cmd) -{ - _win_show_time(console->win, '-'); - wprintw(console->win, "Unknown command: %s\n", cmd); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_about(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - if (prefs_get_boolean(PREF_SPLASH)) { - _cons_splash_logo(); - } else { - _win_show_time(console->win, '-'); - - if (strcmp(PACKAGE_STATUS, "development") == 0) { - wprintw(console->win, "Welcome to Profanity, version %sdev\n", PACKAGE_VERSION); - } else { - wprintw(console->win, "Welcome to Profanity, version %s\n", PACKAGE_VERSION); - } - } - - _win_show_time(console->win, '-'); - wprintw(console->win, "Copyright (C) 2012, 2013 James Booth <%s>.\n", PACKAGE_BUGREPORT); - _win_show_time(console->win, '-'); - wprintw(console->win, "License GPLv3+: GNU GPL version 3 or later \n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "This is free software; you are free to change and redistribute it.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "There is NO WARRANTY, to the extent permitted by law.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "Type '/help' to show complete help.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - - if (prefs_get_boolean(PREF_VERCHECK)) { - cons_check_version(FALSE); - } - - prefresh(console->win, 0, 0, 1, 0, rows-3, cols-1); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_check_version(gboolean not_available_msg) -{ - char *latest_release = release_get_latest(); - - if (latest_release != NULL) { - gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0); - - if (relase_valid) { - if (_new_release(latest_release)) { - _win_show_time(console->win, '-'); - wprintw(console->win, "A new version of Profanity is available: %s", latest_release); - _win_show_time(console->win, '-'); - wprintw(console->win, "Check for details.\n"); - free(latest_release); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - } else { - if (not_available_msg) { - cons_show("No new version available."); - cons_show(""); - } - } - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } - } - } -} - -void -notify_remind(void) -{ - gint unread = _win_get_unread(); - if (unread > 0) { - _notify_remind(unread); - } -} - -static void -_notify(const char * const message, int timeout, - const char * const category) -{ -#ifdef HAVE_LIBNOTIFY - gboolean notify_initted = notify_is_initted(); - - if (!notify_initted) { - notify_initted = notify_init("Profanity"); - } - - if (notify_initted) { - NotifyNotification *notification; - notification = notify_notification_new("Profanity", message, NULL); - notify_notification_set_timeout(notification, timeout); - notify_notification_set_category(notification, category); - notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); - - GError *error = NULL; - gboolean notify_success = notify_notification_show(notification, &error); - - if (!notify_success) { - log_error("Error sending desktop notification:"); - log_error(" -> Message : %s", message); - log_error(" -> Error : %s", error->message); - } - } else { - log_error("Libnotify initialisation error."); - } -#endif -#ifdef PLATFORM_CYGWIN - NOTIFYICONDATA nid; - nid.cbSize = sizeof(NOTIFYICONDATA); - //nid.hWnd = hWnd; - nid.uID = 100; - nid.uVersion = NOTIFYICON_VERSION; - //nid.uCallbackMessage = WM_MYMESSAGE; - nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); - strcpy(nid.szTip, "Tray Icon"); - nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - Shell_NotifyIcon(NIM_ADD, &nid); - - // For a Ballon Tip - nid.uFlags = NIF_INFO; - strcpy(nid.szInfoTitle, "Profanity"); // Title - strcpy(nid.szInfo, message); // Copy Tip - nid.uTimeout = timeout; // 3 Seconds - nid.dwInfoFlags = NIIF_INFO; - - Shell_NotifyIcon(NIM_MODIFY, &nid); -#endif -} - -static void -_notify_remind(gint unread) -{ - char message[20]; - if (unread == 1) { - sprintf(message, "1 unread message"); - } else { - snprintf(message, sizeof(message), "%d unread messages", unread); - } - - _notify(message, 5000, "Incoming message"); -} - -static void -_notify_message(const char * const short_from) -{ - char message[strlen(short_from) + 1 + 10]; - sprintf(message, "%s: message.", short_from); - - _notify(message, 10000, "Incoming message"); -} - -static void -_notify_typing(const char * const from) -{ - char message[strlen(from) + 1 + 11]; - sprintf(message, "%s: typing...", from); - - _notify(message, 10000, "Incoming message"); -} - -static void -_create_windows(void) -{ - int cols = getmaxx(stdscr); - max_cols = cols; - windows[0] = window_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); - console = windows[0]; - current = console; - cons_about(); -} - -static gboolean -_new_release(char *found_version) -{ - int curr_maj, curr_min, curr_patch, found_maj, found_min, found_patch; - - int parse_curr = sscanf(PACKAGE_VERSION, "%d.%d.%d", &curr_maj, &curr_min, - &curr_patch); - int parse_found = sscanf(found_version, "%d.%d.%d", &found_maj, &found_min, - &found_patch); - - if (parse_found == 3 && parse_curr == 3) { - if (found_maj > curr_maj) { - return TRUE; - } else if (found_maj == curr_maj && found_min > curr_min) { - return TRUE; - } else if (found_maj == curr_maj && found_min == curr_min - && found_patch > curr_patch) { - return TRUE; - } else { - return FALSE; - } - } else { - return FALSE; - } -} - -static void -_cons_splash_logo(void) -{ - _win_show_time(console->win, '-'); - wprintw(console->win, "Welcome to\n"); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " ___ _ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " / __) (_)_ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " ____ ____ ___ | |__ ____ ____ _| |_ _ _ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| | | | | | |_| | | ( ( | | | | | | |_| |_| |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "|_| (____/ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - if (strcmp(PACKAGE_STATUS, "development") == 0) { - wprintw(console->win, "Version %sdev\n", PACKAGE_VERSION); - } else { - wprintw(console->win, "Version %s\n", PACKAGE_VERSION); - } -} - -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] = window_create(contact, cols, type); - return i; - } else { - return 0; - } -} - -static void -_win_show_time(WINDOW *win, char showchar) -{ - GDateTime *time = g_date_time_new_now_local(); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s %c ", date_fmt, showchar); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); -} - -static void -_win_show_user(WINDOW *win, const char * const user, const int colour) -{ - if (colour) - wattron(win, COLOUR_THEM); - else - wattron(win, COLOUR_ME); - wprintw(win, "%s: ", user); - if (colour) - wattroff(win, COLOUR_THEM); - else - wattroff(win, COLOUR_ME); -} - -static void -_win_show_message(WINDOW *win, const char * const message) -{ - wprintw(win, "%s\n", message); -} - -static void -_win_show_error_msg(WINDOW *win, const char * const message) -{ - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", message); - wattroff(win, COLOUR_ERROR); -} - -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 -_presence_colour_on(WINDOW *win, const char * const presence) -{ - if (g_strcmp0(presence, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else if (g_strcmp0(presence, "away") == 0) { - wattron(win, COLOUR_AWAY); - } else if (g_strcmp0(presence, "chat") == 0) { - wattron(win, COLOUR_CHAT); - } else if (g_strcmp0(presence, "dnd") == 0) { - wattron(win, COLOUR_DND); - } else if (g_strcmp0(presence, "xa") == 0) { - wattron(win, COLOUR_XA); - } else { - wattron(win, COLOUR_OFFLINE); - } -} - -static void -_presence_colour_off(WINDOW *win, const char * const presence) -{ - if (g_strcmp0(presence, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else if (g_strcmp0(presence, "away") == 0) { - wattroff(win, COLOUR_AWAY); - } else if (g_strcmp0(presence, "chat") == 0) { - wattroff(win, COLOUR_CHAT); - } else if (g_strcmp0(presence, "dnd") == 0) { - wattroff(win, COLOUR_DND); - } else if (g_strcmp0(presence, "xa") == 0) { - wattroff(win, COLOUR_XA); - } else { - wattroff(win, COLOUR_OFFLINE); - } -} - -static void -_show_status_string(WINDOW *win, const char * const from, - const char * const show, const char * const status, - GDateTime *last_activity, const char * const pre, - const char * const default_show) -{ - if (!prefs_get_boolean(PREF_STATUSES)) - return; - - _win_show_time(win, '-'); - - if (show != NULL) { - if (strcmp(show, "away") == 0) { - wattron(win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattron(win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattron(win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattron(win, COLOUR_XA); - } else if (strcmp(show, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else { - wattron(win, COLOUR_OFFLINE); - } - } else if (strcmp(default_show, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else { - wattron(win, COLOUR_OFFLINE); - } - - wprintw(win, "%s %s", pre, from); - - if (show != NULL) - wprintw(win, " is %s", show); - else - wprintw(win, " is %s", default_show); - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - wprintw(win, ", idle "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(win, "%ds", seconds); - } - - if (status != NULL) - wprintw(win, ", \"%s\"", status); - - wprintw(win, "\n"); - - if (show != NULL) { - if (strcmp(show, "away") == 0) { - wattroff(win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattroff(win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattroff(win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattroff(win, COLOUR_XA); - } else if (strcmp(show, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else { - wattroff(win, COLOUR_OFFLINE); - } - } else if (strcmp(default_show, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else { - wattroff(win, COLOUR_OFFLINE); - } -} - -static void -_cons_show_typing(const char * const short_from) -{ - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_TYPING); - wprintw(console->win, "!! %s is typing a message...\n", short_from); - wattroff(console->win, COLOUR_TYPING); -} - -static void -_cons_show_incoming_message(const char * const short_from, const int win_index) -{ - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_INCOMING); - wprintw(console->win, "<< incoming from %s (%d)\n", short_from, win_index + 1); - wattroff(console->win, COLOUR_INCOMING); -} - -static void -_win_show_contact(ProfWin *window, PContact contact) -{ - const char *barejid = p_contact_barejid(contact); - const char *name = p_contact_name(contact); - const char *presence = p_contact_presence(contact); - const char *status = p_contact_status(contact); - GDateTime *last_activity = p_contact_last_activity(contact); - - _win_show_time(window->win, '-'); - _presence_colour_on(window->win, presence); - wprintw(window->win, "%s", barejid); - - if (name != NULL) { - wprintw(window->win, " (%s)", name); - } - - wprintw(window->win, " is %s", presence); - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - wprintw(window->win, ", idle "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(window->win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(window->win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(window->win, "%ds", seconds); - } - - if (status != NULL) { - wprintw(window->win, ", \"%s\"", p_contact_status(contact)); - } - - wprintw(window->win, "\n"); - _presence_colour_off(window->win, presence); -} - -static void -_win_handle_switch(const wint_t * const ch) -{ - if (*ch == KEY_F(1)) { - ui_switch_win(0); - } else if (*ch == KEY_F(2)) { - ui_switch_win(1); - } else if (*ch == KEY_F(3)) { - ui_switch_win(2); - } else if (*ch == KEY_F(4)) { - ui_switch_win(3); - } else if (*ch == KEY_F(5)) { - ui_switch_win(4); - } else if (*ch == KEY_F(6)) { - ui_switch_win(5); - } else if (*ch == KEY_F(7)) { - ui_switch_win(6); - } else if (*ch == KEY_F(8)) { - ui_switch_win(7); - } else if (*ch == KEY_F(9)) { - ui_switch_win(8); - } else if (*ch == KEY_F(10)) { - ui_switch_win(9); - } -} - -static void -_win_handle_page(const wint_t * const ch) -{ - int rows = getmaxy(stdscr); - int y = getcury(current->win); - - int page_space = rows - 4; - int *page_start = &(current->y_pos); - - if (prefs_get_boolean(PREF_MOUSE)) { - MEVENT mouse_event; - - if (*ch == KEY_MOUSE) { - if (getmouse(&mouse_event) == OK) { - -#ifdef PLATFORM_CYGWIN - if (mouse_event.bstate & BUTTON5_PRESSED) { // mouse wheel down -#else - if (mouse_event.bstate & BUTTON2_PRESSED) { // mouse wheel down -#endif - *page_start += 4; - - // only got half a screen, show full screen - if ((y - (*page_start)) < page_space) - *page_start = y - page_space; - - // went past end, show full screen - else if (*page_start >= y) - *page_start = y - page_space; - - current->paged = 1; - dirty = TRUE; - } else if (mouse_event.bstate & BUTTON4_PRESSED) { // mouse wheel up - *page_start -= 4; - - // went past beginning, show first page - if (*page_start < 0) - *page_start = 0; - - current->paged = 1; - dirty = TRUE; - } - } - } - } - - // page up - if (*ch == KEY_PPAGE) { - *page_start -= page_space; - - // went past beginning, show first page - if (*page_start < 0) - *page_start = 0; - - current->paged = 1; - dirty = TRUE; - - // page down - } else if (*ch == KEY_NPAGE) { - *page_start += page_space; - - // only got half a screen, show full screen - if ((y - (*page_start)) < page_space) - *page_start = y - page_space; - - // went past end, show full screen - else if (*page_start >= y) - *page_start = y - page_space; - - current->paged = 1; - dirty = TRUE; - } -} - -static gint -_win_get_unread(void) -{ - int i; - gint result = 0; - for (i = 0; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - result += windows[i]->unread; - } - } - return result; -} - -static void -_win_show_history(WINDOW *win, int win_index, const char * const contact) -{ - if (!windows[win_index]->history_shown) { - GSList *history = NULL; - Jid *jid = jid_create(jabber_get_jid()); - history = chat_log_get_previous(jid->barejid, contact, history); - jid_destroy(jid); - while (history != NULL) { - wprintw(win, "%s\n", history->data); - history = g_slist_next(history); - } - windows[win_index]->history_shown = 1; - - g_slist_free_full(history, free); - } -} - -static void -_win_show_info(WINDOW *win, PContact pcontact) -{ - const char *barejid = p_contact_barejid(pcontact); - const char *name = p_contact_name(pcontact); - const char *presence = p_contact_presence(pcontact); - const char *sub = p_contact_subscription(pcontact); - GList *resources = p_contact_get_available_resources(pcontact); - GList *ordered_resources = NULL; - GDateTime *last_activity = p_contact_last_activity(pcontact); - - _win_show_time(win, '-'); - wprintw(win, "\n"); - _win_show_time(win, '-'); - _presence_colour_on(win, presence); - wprintw(win, "%s", barejid); - if (name != NULL) { - wprintw(win, " (%s)", name); - } - _presence_colour_off(win, presence); - wprintw(win, ":\n"); - - if (sub != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Subscription: %s\n", sub); - } - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - _win_show_time(win, '-'); - wprintw(win, "Last activity: "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(win, "%ds", seconds); - - wprintw(win, "\n"); - - g_date_time_unref(now); - } - - if (resources != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Resources:\n"); - - // sort in order of availabiltiy - while (resources != NULL) { - Resource *resource = resources->data; - ordered_resources = g_list_insert_sorted(ordered_resources, - resource, (GCompareFunc)resource_compare_availability); - resources = g_list_next(resources); - } - } - - while (ordered_resources != NULL) { - Resource *resource = ordered_resources->data; - const char *resource_presence = string_from_resource_presence(resource->presence); - _win_show_time(win, '-'); - _presence_colour_on(win, resource_presence); - wprintw(win, " %s (%d), %s", resource->name, resource->priority, resource_presence); - if (resource->status != NULL) { - wprintw(win, ", \"%s\"", resource->status); - } - wprintw(win, "\n"); - _presence_colour_off(win, resource_presence); - - if (resource->caps_str != NULL) { - Capabilities *caps = caps_get(resource->caps_str); - if (caps != NULL) { - // show identity - if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { - _win_show_time(win, '-'); - wprintw(win, " Identity: "); - if (caps->name != NULL) { - wprintw(win, "%s", caps->name); - if ((caps->category != NULL) || (caps->type != NULL)) { - wprintw(win, " "); - } - } - if (caps->type != NULL) { - wprintw(win, "%s", caps->type); - if (caps->category != NULL) { - wprintw(win, " "); - } - } - if (caps->category != NULL) { - wprintw(win, "%s", caps->category); - } - wprintw(win, "\n"); - } - if (caps->software != NULL) { - _win_show_time(win, '-'); - wprintw(win, " Software: %s", caps->software); - } - if (caps->software_version != NULL) { - wprintw(win, ", %s", caps->software_version); - } - if ((caps->software != NULL) || (caps->software_version != NULL)) { - wprintw(win, "\n"); - } - if (caps->os != NULL) { - _win_show_time(win, '-'); - wprintw(win, " OS: %s", caps->os); - } - if (caps->os_version != NULL) { - wprintw(win, ", %s", caps->os_version); - } - if ((caps->os != NULL) || (caps->os_version != NULL)) { - wprintw(win, "\n"); - } - } - } - - ordered_resources = g_list_next(ordered_resources); - } -} - -void -_set_current(int index) -{ - current_index = index; - current = windows[current_index]; -} -