diff --git a/src/command/command.c b/src/command/command.c index c80ce2b4..367d3c29 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -284,6 +284,7 @@ static struct cmd_t command_defs[] = "/roster indent contact ", "/roster indent resource ", "/roster indent presence ", + "/roster resource join on|off", "/roster size ", "/roster wrap on|off", "/roster add []", @@ -326,6 +327,7 @@ static struct cmd_t command_defs[] = { "indent contact ", "Indent contact line by spaces (0 to 10)." }, { "indent resource ", "Indent resource line by spaces (0 to 10)." }, { "indent presence ", "Indent presence line by spaces (-1 to 10), a value of -1 will show presence on the previous line." }, + { "resource join on|off", "Join resource with previous line when only one available resource." }, { "size ", "Percentage of the screen taken up by the roster (1-99)." }, { "wrap on|off", "Enabled or disanle line wrapping in roster panel." }, { "add []", "Add a new item to the roster." }, @@ -1793,6 +1795,7 @@ static Autocomplete disco_ac; static Autocomplete close_ac; static Autocomplete wins_ac; static Autocomplete roster_ac; +static Autocomplete roster_resource_ac; static Autocomplete roster_char_ac; static Autocomplete roster_char_none_ac; static Autocomplete roster_indent_ac; @@ -2047,6 +2050,10 @@ cmd_init(void) autocomplete_add(roster_ac, "char"); autocomplete_add(roster_ac, "indent"); autocomplete_add(roster_ac, "wrap"); + autocomplete_add(roster_ac, "resource"); + + roster_resource_ac = autocomplete_new(); + autocomplete_add(roster_resource_ac, "join"); roster_char_ac = autocomplete_new(); autocomplete_add(roster_char_ac, "header"); @@ -2331,6 +2338,7 @@ cmd_uninit(void) autocomplete_free(close_ac); autocomplete_free(wins_ac); autocomplete_free(roster_ac); + autocomplete_free(roster_resource_ac); autocomplete_free(roster_char_ac); autocomplete_free(roster_char_none_ac); autocomplete_free(roster_indent_ac); @@ -2521,6 +2529,7 @@ cmd_reset_autocomplete(ProfWin *window) autocomplete_reset(close_ac); autocomplete_reset(wins_ac); autocomplete_reset(roster_ac); + autocomplete_reset(roster_resource_ac); autocomplete_reset(roster_char_ac); autocomplete_reset(roster_char_none_ac); autocomplete_reset(roster_indent_ac); @@ -2912,6 +2921,10 @@ static char* _roster_autocomplete(ProfWin *window, const char *const input) { char *result = NULL; + result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice); + if (result) { + return result; + } result = autocomplete_param_with_ac(input, "/roster char header", roster_char_none_ac, TRUE); if (result) { return result; @@ -2968,6 +2981,10 @@ _roster_autocomplete(ProfWin *window, const char *const input) if (result) { return result; } + result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE); + if (result) { + return result; + } result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE); if (result) { return result; diff --git a/src/command/commands.c b/src/command/commands.c index 4bc1f880..d352fd5a 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1761,6 +1761,17 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args) return res; } + // roster join with previous line + } else if (g_strcmp0(args[0], "resource") == 0) { + if (g_strcmp0(args[1], "join") == 0) { + int res = _cmd_set_boolean_preference(args[2], command, "Roster join", PREF_ROSTER_RESOURCE_JOIN); + rosterwin_roster(); + return res; + } else { + cons_bad_cmd_usage(command); + return TRUE; + } + // set header character } else if (g_strcmp0(args[0], "char") == 0) { if (g_strcmp0(args[1], "header") == 0) { diff --git a/src/config/preferences.c b/src/config/preferences.c index 3a261897..07985efc 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -767,6 +767,7 @@ _get_group(preference_t pref) case PREF_ROSTER_COUNT: case PREF_ROSTER_PRIORITY: case PREF_ROSTER_WRAP: + case PREF_ROSTER_RESOURCE_JOIN: case PREF_RESOURCE_TITLE: case PREF_RESOURCE_MESSAGE: case PREF_ENC_WARN: @@ -952,6 +953,8 @@ _get_key(preference_t pref) return "roster.priority"; case PREF_ROSTER_WRAP: return "roster.wrap"; + case PREF_ROSTER_RESOURCE_JOIN: + return "roster.resource.join"; case PREF_RESOURCE_TITLE: return "resource.title"; case PREF_RESOURCE_MESSAGE: @@ -1005,6 +1008,7 @@ _get_default_boolean(preference_t pref) case PREF_ROSTER_EMPTY: case PREF_ROSTER_COUNT: case PREF_ROSTER_PRIORITY: + case PREF_ROSTER_RESOURCE_JOIN: case PREF_TLS_SHOW: case PREF_LASTACTIVITY: return TRUE; diff --git a/src/config/preferences.h b/src/config/preferences.h index 9139e3b4..607a1abe 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -72,6 +72,7 @@ typedef enum { PREF_ROSTER_COUNT, PREF_ROSTER_PRIORITY, PREF_ROSTER_WRAP, + PREF_ROSTER_RESOURCE_JOIN, PREF_MUC_PRIVILEGES, PREF_PRESENCE, PREF_WRAP, diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c index ac5a642e..4dd1178b 100644 --- a/src/ui/rosterwin.c +++ b/src/ui/rosterwin.c @@ -128,45 +128,74 @@ _rosterwin_presence(ProfLayoutSplit *layout, theme_item_t colour, const char *pr static void _rosterwin_resources(ProfLayoutSplit *layout, PContact contact, int current_indent) { + gboolean join = prefs_get_boolean(PREF_ROSTER_RESOURCE_JOIN); + GList *resources = p_contact_get_available_resources(contact); if (resources) { - int resource_indent = prefs_get_roster_resource_indent(); - if (resource_indent > 0) { - current_indent += resource_indent; - } - - GList *curr_resource = resources; - while (curr_resource) { - Resource *resource = curr_resource->data; + if (join && (g_list_length(resources) == 1)) { + Resource *resource = resources->data; const char *resource_presence = string_from_resource_presence(resource->presence); theme_item_t resource_presence_colour = theme_main_presence_attrs(resource_presence); wattron(layout->subwin, theme_attrs(resource_presence_colour)); - GString *msg = g_string_new(" "); - int this_indent = current_indent; - while (this_indent > 0) { - g_string_append(msg, " "); - this_indent--; - } + GString *msg = g_string_new(""); char ch = prefs_get_roster_resource_char(); if (ch) { g_string_append_printf(msg, "%c", ch); + } else { + g_string_append(msg, " "); } g_string_append(msg, resource->name); if (prefs_get_boolean(PREF_ROSTER_PRIORITY)) { g_string_append_printf(msg, " %d", resource->priority); } - win_sub_newline_lazy(layout->subwin); gboolean wrap = prefs_get_boolean(PREF_ROSTER_WRAP); - win_sub_print(layout->subwin, msg->str, FALSE, wrap, current_indent); + win_sub_print(layout->subwin, msg->str, FALSE, wrap, 0); g_string_free(msg, TRUE); wattroff(layout->subwin, theme_attrs(resource_presence_colour)); if (prefs_get_boolean(PREF_ROSTER_PRESENCE) || prefs_get_boolean(PREF_ROSTER_STATUS)) { _rosterwin_presence(layout, resource_presence_colour, resource_presence, resource->status, current_indent); } + } else { + int resource_indent = prefs_get_roster_resource_indent(); + if (resource_indent > 0) { + current_indent += resource_indent; + } - curr_resource = g_list_next(curr_resource); + GList *curr_resource = resources; + while (curr_resource) { + Resource *resource = curr_resource->data; + const char *resource_presence = string_from_resource_presence(resource->presence); + theme_item_t resource_presence_colour = theme_main_presence_attrs(resource_presence); + + wattron(layout->subwin, theme_attrs(resource_presence_colour)); + GString *msg = g_string_new(" "); + int this_indent = current_indent; + while (this_indent > 0) { + g_string_append(msg, " "); + this_indent--; + } + char ch = prefs_get_roster_resource_char(); + if (ch) { + g_string_append_printf(msg, "%c", ch); + } + g_string_append(msg, resource->name); + if (prefs_get_boolean(PREF_ROSTER_PRIORITY)) { + g_string_append_printf(msg, " %d", resource->priority); + } + win_sub_newline_lazy(layout->subwin); + gboolean wrap = prefs_get_boolean(PREF_ROSTER_WRAP); + win_sub_print(layout->subwin, msg->str, FALSE, wrap, current_indent); + g_string_free(msg, TRUE); + wattroff(layout->subwin, theme_attrs(resource_presence_colour)); + + if (prefs_get_boolean(PREF_ROSTER_PRESENCE) || prefs_get_boolean(PREF_ROSTER_STATUS)) { + _rosterwin_presence(layout, resource_presence_colour, resource_presence, resource->status, current_indent); + } + + curr_resource = g_list_next(curr_resource); + } } } else if (prefs_get_boolean(PREF_ROSTER_PRESENCE) || prefs_get_boolean(PREF_ROSTER_STATUS)) { const char *presence = p_contact_presence(contact);