From badbc3003f1a6e2d6eecb166a36fef8bc66f9b17 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 15 Nov 2015 21:33:48 +0000 Subject: Show presence in roster WIP --- src/command/command.c | 10 ++++++++-- src/command/commands.c | 28 +++++++++++++++++++++++++++ src/config/preferences.c | 8 ++++++++ src/config/preferences.h | 2 ++ src/ui/rosterwin.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 2b8b4d8b..4241acb4 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -274,8 +274,8 @@ static struct cmd_t command_defs[] = CMD_SYN( "/roster", "/roster online", - "/roster show [offline|resource|empty]", - "/roster hide [offline|resource|empty]", + "/roster show [offline|resource|presence|status|empty]", + "/roster hide [offline|resource|presence|status|empty]", "/roster by group|presence|none", "/roster size ", "/roster add []", @@ -291,10 +291,14 @@ static struct cmd_t command_defs[] = { "show", "Show the roster panel." }, { "show offline", "Show offline contacts in the roster panel." }, { "show resource", "Show contact's connected resources in the roster panel." }, + { "show presence", "Show contact's presence in the roster panel." }, + { "show status", "Show contact's status message in the roster panel." }, { "show empty", "When grouping by presence, show empty presence groups." }, { "hide", "Hide the roster panel." }, { "hide offline", "Hide offline contacts in the roster panel." }, { "hide resource", "Hide contact's connected resources in the roster panel." }, + { "hide presence", "Hide contact's presence in the roster panel." }, + { "hide status", "Hide contact's status message in the roster panel." }, { "hide empty", "When grouping by presence, hide empty presence groups." }, { "by group", "Group contacts in the roster panel by roster group." }, { "by presence", "Group contacts in the roster panel by presence." }, @@ -2015,6 +2019,8 @@ cmd_init(void) roster_option_ac = autocomplete_new(); autocomplete_add(roster_option_ac, "offline"); autocomplete_add(roster_option_ac, "resource"); + autocomplete_add(roster_option_ac, "presence"); + autocomplete_add(roster_option_ac, "status"); autocomplete_add(roster_option_ac, "empty"); roster_by_ac = autocomplete_new(); diff --git a/src/command/commands.c b/src/command/commands.c index fe3c7045..40a041c9 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1773,6 +1773,20 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args) rosterwin_roster(); } return TRUE; + } else if (g_strcmp0(args[1], "presence") == 0) { + cons_show("Roster presence enabled"); + prefs_set_boolean(PREF_ROSTER_PRESENCE, TRUE); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; + } else if (g_strcmp0(args[1], "status") == 0) { + cons_show("Roster status enabled"); + prefs_set_boolean(PREF_ROSTER_STATUS, TRUE); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; } else if (g_strcmp0(args[1], "empty") == 0) { cons_show("Roster empty enabled"); prefs_set_boolean(PREF_ROSTER_EMPTY, TRUE); @@ -1806,6 +1820,20 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args) rosterwin_roster(); } return TRUE; + } else if (g_strcmp0(args[1], "presence") == 0) { + cons_show("Roster presence disabled"); + prefs_set_boolean(PREF_ROSTER_PRESENCE, FALSE); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; + } else if (g_strcmp0(args[1], "status") == 0) { + cons_show("Roster status disabled"); + prefs_set_boolean(PREF_ROSTER_STATUS, FALSE); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; } else if (g_strcmp0(args[1], "empty") == 0) { cons_show("Roster empty disabled"); prefs_set_boolean(PREF_ROSTER_EMPTY, FALSE); diff --git a/src/config/preferences.c b/src/config/preferences.c index c7196051..b8f6d607 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -597,6 +597,8 @@ _get_group(preference_t pref) case PREF_ROSTER: case PREF_ROSTER_OFFLINE: case PREF_ROSTER_RESOURCE: + case PREF_ROSTER_PRESENCE: + case PREF_ROSTER_STATUS: case PREF_ROSTER_EMPTY: case PREF_ROSTER_BY: case PREF_RESOURCE_TITLE: @@ -768,6 +770,10 @@ _get_key(preference_t pref) return "roster.offline"; case PREF_ROSTER_RESOURCE: return "roster.resource"; + case PREF_ROSTER_PRESENCE: + return "roster.presence"; + case PREF_ROSTER_STATUS: + return "roster.status"; case PREF_ROSTER_EMPTY: return "roster.empty"; case PREF_ROSTER_BY: @@ -823,6 +829,8 @@ _get_default_boolean(preference_t pref) case PREF_ROSTER: case PREF_ROSTER_OFFLINE: case PREF_ROSTER_RESOURCE: + case PREF_ROSTER_PRESENCE: + case PREF_ROSTER_STATUS: case PREF_ROSTER_EMPTY: case PREF_TLS_SHOW: case PREF_LASTACTIVITY: diff --git a/src/config/preferences.h b/src/config/preferences.h index 9aa6ff72..ff830cce 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -64,6 +64,8 @@ typedef enum { PREF_ROSTER_SIZE, PREF_ROSTER_OFFLINE, PREF_ROSTER_RESOURCE, + PREF_ROSTER_PRESENCE, + PREF_ROSTER_STATUS, PREF_ROSTER_EMPTY, PREF_ROSTER_BY, PREF_MUC_PRIVILEGES, diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c index d7d4012d..6201394d 100644 --- a/src/ui/rosterwin.c +++ b/src/ui/rosterwin.c @@ -47,6 +47,7 @@ _rosterwin_contact(ProfLayoutSplit *layout, PContact contact) { const char *name = p_contact_name_or_jid(contact); const char *presence = p_contact_presence(contact); + char *by = prefs_get_string(PREF_ROSTER_BY); if ((g_strcmp0(presence, "offline") != 0) || ((g_strcmp0(presence, "offline") == 0) && (prefs_get_boolean(PREF_ROSTER_OFFLINE)))) { @@ -74,9 +75,58 @@ _rosterwin_contact(ProfLayoutSplit *layout, PContact contact) g_string_free(msg, TRUE); wattroff(layout->subwin, theme_attrs(resource_presence_colour)); + if (prefs_get_boolean(PREF_ROSTER_PRESENCE)) { + gboolean by_presence = g_strcmp0(by, "presence") == 0; + gboolean has_status = resource->status != NULL; + gboolean show_status = prefs_get_boolean(PREF_ROSTER_STATUS); + if (!by_presence || (has_status && show_status)) { + wattron(layout->subwin, theme_attrs(resource_presence_colour)); + GString *msg = g_string_new(" "); + if (!by_presence) { + g_string_append(msg, resource_presence); + } + if (has_status && show_status) { + if (!by_presence) { + g_string_append(msg, ", \""); + } else { + g_string_append(msg, "\""); + } + g_string_append(msg, resource->status); + g_string_append(msg, "\""); + } + win_printline_nowrap(layout->subwin, msg->str); + g_string_free(msg, TRUE); + wattroff(layout->subwin, theme_attrs(resource_presence_colour)); + } + } + curr_resource = g_list_next(curr_resource); } g_list_free(resources); + } else if (prefs_get_boolean(PREF_ROSTER_PRESENCE)) { + gboolean by_presence = g_strcmp0(by, "presence") == 0; + gboolean has_status = p_contact_status(contact) != NULL; + gboolean show_status = prefs_get_boolean(PREF_ROSTER_STATUS); + if (!by_presence || (has_status && show_status)) { + wattron(layout->subwin, theme_attrs(presence_colour)); + GString *msg = g_string_new(" "); + if (!by_presence) { + g_string_append(msg, presence); + } + if (has_status && show_status) { + if (!by_presence) { + g_string_append(msg, ", \""); + } else { + g_string_append(msg, "\""); + } + const char *status = p_contact_status(contact); + g_string_append(msg, status); + g_string_append(msg, "\""); + } + win_printline_nowrap(layout->subwin, msg->str); + g_string_free(msg, TRUE); + wattroff(layout->subwin, theme_attrs(presence_colour)); + } } } } -- cgit 1.4.1-2-gfad0 00; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# We can't really do much with null-terminated kernel strings, and we don't
# want to. Let's turn them into regular length-prefixed strings at the first
# opportunity.

== code

kernel-string-to-string:  # ad: (addr allocation-descriptor), in: (addr kernel-string), out: (addr handle array byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    52/push-edx
    53/push-ebx
    56/push-esi
    57/push-edi
    # var len/ecx: int = length(in)
    (kernel-string-length *(ebp+0xc))
    89/<- %ecx 0/r32/eax
    # result = allocate-array(ad, len)
    (allocate-array *(ebp+8) %ecx *(ebp+0x10))
    # var c/edx: byte = 0
    ba/copy-to-edx 0/imm32
    # var src/esi: (addr byte) = in
    8b/-> *(ebp+0xc) 6/r32/esi
    # var dest/edi: (addr byte) = result->data
    8b/-> *(ebp+0x10) 7/r32/edi
    (lookup *edi *(edi+4))  # => eax
    8d/copy-address *(eax+4) 7/r32/edi
    {
$kernel-string-to-string:loop:
      # c = *src
      8a/byte-> *esi 2/r32/dl
      # if (c == 0) break
      81 7/subop/compare %edx 0/imm32
      74/jump-if-= break/disp8
      # *dest = c
      88/byte<- *edi 2/r32/dl
      # ++src
      46/increment-esi
      # ++dest
      47/increment-edi
      eb/jump loop/disp8
    }
$kernel-string-to-string:end:
    # . restore registers
    5f/pop-to-edi
    5e/pop-to-esi
    5b/pop-to-ebx
    5a/pop-to-edx
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

kernel-string-length:  # in: (addr kernel-string) -> result/eax: int
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    51/push-ecx
    52/push-edx
    # result = 0
    b8/copy-to-eax 0/imm32
    # var c/ecx: byte = 0
    b9/copy-to-ecx 0/imm32
    # var curr/edx: (addr byte) = in
    8b/-> *(ebp+8) 2/r32/edx
    {
$kernel-string-length:loop:
      # c = *curr
      8a/byte-> *edx 1/r32/ecx
      # if (c == 0) break
      81 7/subop/compare %ecx 0/imm32
      74/jump-if-= break/disp8
      # ++curr
      42/increment-edx
      # ++result
      40/increment-eax
      #
      eb/jump loop/disp8
    }
$kernel-string-length:end:
    # . restore registers
    5a/pop-to-edx
    59/pop-to-ecx
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return