diff --git a/src/command/command.c b/src/command/command.c index 241865d5..7a87d828 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -278,6 +278,8 @@ static struct cmd_t command_defs[] = "/roster hide [offline|resource|presence|status|empty|count|priority]", "/roster by group|presence|none", "/roster order name|presence", + "/roster char header |none", + "/roster char contact |none", "/roster size ", "/roster add []", "/roster remove ", @@ -310,6 +312,10 @@ static struct cmd_t command_defs[] = { "by none", "No grouping in the roster panel." }, { "order name", "Order roster items by name only." }, { "order presence", "Order roster items by presence, and then by name." }, + { "char header ", "Prefix roster headers with specificed character." }, + { "char header none", "Remove roster header character prefix." }, + { "char contact ", "Prefix roster contacts with specificed character." }, + { "char contact none", "Remove roster contact character prefix." }, { "size ", "Percentage of the screen taken up by the roster (1-99)." }, { "add []", "Add a new item to the roster." }, { "remove ", "Removes an item from the roster." }, @@ -1776,6 +1782,8 @@ static Autocomplete disco_ac; static Autocomplete close_ac; static Autocomplete wins_ac; static Autocomplete roster_ac; +static Autocomplete roster_char_ac; +static Autocomplete roster_char_none_ac; static Autocomplete roster_option_ac; static Autocomplete roster_by_ac; static Autocomplete roster_order_ac; @@ -2024,6 +2032,14 @@ cmd_init(void) autocomplete_add(roster_ac, "by"); autocomplete_add(roster_ac, "order"); autocomplete_add(roster_ac, "size"); + autocomplete_add(roster_ac, "char"); + + roster_char_ac = autocomplete_new(); + autocomplete_add(roster_char_ac, "header"); + autocomplete_add(roster_char_ac, "contact"); + + roster_char_none_ac = autocomplete_new(); + autocomplete_add(roster_char_none_ac, "none"); roster_option_ac = autocomplete_new(); autocomplete_add(roster_option_ac, "offline"); @@ -2295,6 +2311,8 @@ cmd_uninit(void) autocomplete_free(close_ac); autocomplete_free(wins_ac); autocomplete_free(roster_ac); + autocomplete_free(roster_char_ac); + autocomplete_free(roster_char_none_ac); autocomplete_free(roster_option_ac); autocomplete_free(roster_by_ac); autocomplete_free(roster_order_ac); @@ -2482,6 +2500,8 @@ cmd_reset_autocomplete(ProfWin *window) autocomplete_reset(close_ac); autocomplete_reset(wins_ac); autocomplete_reset(roster_ac); + autocomplete_reset(roster_char_ac); + autocomplete_reset(roster_char_none_ac); autocomplete_reset(roster_option_ac); autocomplete_reset(roster_by_ac); autocomplete_reset(roster_order_ac); @@ -2870,6 +2890,14 @@ static char* _roster_autocomplete(ProfWin *window, const char *const input) { char *result = NULL; + result = autocomplete_param_with_ac(input, "/roster char header", roster_char_none_ac, TRUE); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/roster char contact", roster_char_none_ac, TRUE); + if (result) { + return result; + } result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete); if (result) { return result; @@ -2902,6 +2930,10 @@ _roster_autocomplete(ProfWin *window, const char *const input) if (result) { return result; } + result = autocomplete_param_with_ac(input, "/roster char", roster_char_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 92ca5daf..ca6a1003 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1750,6 +1750,37 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args) return TRUE; } + // set header character + } else if (g_strcmp0(args[0], "char") == 0) { + if (g_strcmp0(args[1], "header") == 0) { + if (!args[2]) { + cons_bad_cmd_usage(command); + } else if (g_strcmp0(args[2], "none") == 0) { + prefs_clear_roster_header_char(); + cons_show("Roster header char removed."); + rosterwin_roster(); + } else { + prefs_set_roster_header_char(args[2][0]); + cons_show("Roster header char set to %c.", args[2][0]); + rosterwin_roster(); + } + } else if (g_strcmp0(args[1], "contact") == 0) { + if (!args[2]) { + cons_bad_cmd_usage(command); + } else if (g_strcmp0(args[2], "none") == 0) { + prefs_clear_roster_contact_char(); + cons_show("Roster contact char removed."); + rosterwin_roster(); + } else { + prefs_set_roster_contact_char(args[2][0]); + cons_show("Roster contact char set to %c.", args[2][0]); + rosterwin_roster(); + } + } else { + cons_bad_cmd_usage(command); + } + return TRUE; + // show/hide roster } else if (g_strcmp0(args[0], "show") == 0) { if (args[1] == NULL) { diff --git a/src/config/preferences.c b/src/config/preferences.c index 0f5041bf..071b6646 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -444,6 +444,74 @@ prefs_set_pgp_char(char ch) _save_prefs(); } +char +prefs_get_roster_header_char(void) +{ + char result = 0; + + char *resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.header.char", NULL); + if (!resultstr) { + result = 0; + } else { + result = resultstr[0]; + } + free(resultstr); + + return result; +} + +void +prefs_set_roster_header_char(char ch) +{ + char str[2]; + str[0] = ch; + str[1] = '\0'; + + g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.header.char", str); + _save_prefs(); +} + +void +prefs_clear_roster_header_char(void) +{ + g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.header.char", NULL); + _save_prefs(); +} + +char +prefs_get_roster_contact_char(void) +{ + char result = 0; + + char *resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.contact.char", NULL); + if (!resultstr) { + result = 0; + } else { + result = resultstr[0]; + } + free(resultstr); + + return result; +} + +void +prefs_set_roster_contact_char(char ch) +{ + char str[2]; + str[0] = ch; + str[1] = '\0'; + + g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.contact.char", str); + _save_prefs(); +} + +void +prefs_clear_roster_contact_char(void) +{ + g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.contact.char", NULL); + _save_prefs(); +} + gboolean prefs_add_alias(const char *const name, const char *const value) { diff --git a/src/config/preferences.h b/src/config/preferences.h index c5f60469..da4eef88 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -165,6 +165,13 @@ void prefs_set_otr_char(char ch); char prefs_get_pgp_char(void); void prefs_set_pgp_char(char ch); +char prefs_get_roster_header_char(void); +void prefs_set_roster_header_char(char ch); +void prefs_clear_roster_header_char(void); +char prefs_get_roster_contact_char(void); +void prefs_set_roster_contact_char(char ch); +void prefs_clear_roster_contact_char(void); + void prefs_add_login(const char *jid); gboolean prefs_add_alias(const char *const name, const char *const value); diff --git a/src/config/theme.c b/src/config/theme.c index a6649e88..b875f46f 100644 --- a/src/config/theme.c +++ b/src/config/theme.c @@ -469,6 +469,20 @@ _load_preferences(void) gint roster_size = g_key_file_get_integer(theme, "ui", "roster.size", NULL); prefs_set_roster_size(roster_size); } + if (g_key_file_has_key(theme, "ui", "roster.header.char", NULL)) { + gchar *ch = g_key_file_get_string(theme, "ui", "roster.header.char", NULL); + if (ch && strlen(ch) > 0) { + prefs_set_roster_header_char(ch[0]); + g_free(ch); + } + } + if (g_key_file_has_key(theme, "ui", "roster.contact.char", NULL)) { + gchar *ch = g_key_file_get_string(theme, "ui", "roster.contact.char", NULL); + if (ch && strlen(ch) > 0) { + prefs_set_roster_contact_char(ch[0]); + g_free(ch); + } + } _set_boolean_preference("privileges", PREF_MUC_PRIVILEGES); diff --git a/src/ui/console.c b/src/ui/console.c index 64eff932..1beaa48a 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1242,6 +1242,18 @@ cons_roster_setting(void) int size = prefs_get_roster_size(); cons_show("Roster size (/roster) : %d", size); + + char header_ch = prefs_get_roster_header_char(); + if (header_ch) + cons_show("Roster header char (/roster) : %c", header_ch); + else + cons_show("Roster header char (/roster) : none"); + + char contact_ch = prefs_get_roster_contact_char(); + if (contact_ch) + cons_show("Roster contact char (/roster) : %c", contact_ch); + else + cons_show("Roster contact char (/roster) : none"); } void diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index fb224598..58fef4d1 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -32,6 +32,7 @@ * */ +#include #include #include "ui/win_types.h" diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c index 32d64543..64ce1f7f 100644 --- a/src/ui/rosterwin.c +++ b/src/ui/rosterwin.c @@ -139,6 +139,10 @@ _rosterwin_contact(ProfLayoutSplit *layout, PContact contact) wattron(layout->subwin, theme_attrs(presence_colour)); GString *msg = g_string_new(" "); + char ch = prefs_get_roster_contact_char(); + if (ch) { + g_string_append_printf(msg, "%c", ch); + } g_string_append(msg, name); win_printline_nowrap(layout->subwin, msg->str); g_string_free(msg, TRUE); @@ -159,7 +163,12 @@ _rosterwin_contacts_by_presence(ProfLayoutSplit *layout, const char *const prese // if this group has contacts, or if we want to show empty groups if (contacts || prefs_get_boolean(PREF_ROSTER_EMPTY)) { wattron(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); - GString *title_str = g_string_new(title); + GString *title_str = g_string_new(" "); + char ch = prefs_get_roster_header_char(); + if (ch) { + g_string_append_printf(title_str, "%c", ch); + } + g_string_append(title_str, title); if (prefs_get_boolean(PREF_ROSTER_COUNT)) { g_string_append_printf(title_str, " (%d)", g_slist_length(contacts)); } @@ -194,7 +203,11 @@ _rosterwin_contacts_by_group(ProfLayoutSplit *layout, char *group) if (contacts || prefs_get_boolean(PREF_ROSTER_EMPTY)) { wattron(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); - GString *title = g_string_new(" -"); + GString *title = g_string_new(" "); + char ch = prefs_get_roster_header_char(); + if (ch) { + g_string_append_printf(title, "%c", ch); + } g_string_append(title, group); if (prefs_get_boolean(PREF_ROSTER_COUNT)) { g_string_append_printf(title, " (%d)", g_slist_length(contacts)); @@ -228,7 +241,13 @@ _rosterwin_contacts_by_no_group(ProfLayoutSplit *layout) if (contacts || prefs_get_boolean(PREF_ROSTER_EMPTY)) { wattron(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); - GString *title = g_string_new(" -no group"); + GString *title = g_string_new(" "); + char ch = prefs_get_roster_header_char(); + if (ch) { + g_string_append_printf(title, "%c", ch); + } + g_string_append(title, "no group"); + if (prefs_get_boolean(PREF_ROSTER_COUNT)) { g_string_append_printf(title, " (%d)", g_slist_length(contacts)); } @@ -257,13 +276,13 @@ rosterwin_roster(void) char *by = prefs_get_string(PREF_ROSTER_BY); if (g_strcmp0(by, "presence") == 0) { werase(layout->subwin); - _rosterwin_contacts_by_presence(layout, "chat", " -Available for chat"); - _rosterwin_contacts_by_presence(layout, "online", " -Online"); - _rosterwin_contacts_by_presence(layout, "away", " -Away"); - _rosterwin_contacts_by_presence(layout, "xa", " -Extended Away"); - _rosterwin_contacts_by_presence(layout, "dnd", " -Do not disturb"); + _rosterwin_contacts_by_presence(layout, "chat", "Available for chat"); + _rosterwin_contacts_by_presence(layout, "online", "Online"); + _rosterwin_contacts_by_presence(layout, "away", "Away"); + _rosterwin_contacts_by_presence(layout, "xa", "Extended Away"); + _rosterwin_contacts_by_presence(layout, "dnd", "Do not disturb"); if (prefs_get_boolean(PREF_ROSTER_OFFLINE)) { - _rosterwin_contacts_by_presence(layout, "offline", " -Offline"); + _rosterwin_contacts_by_presence(layout, "offline", "Offline"); } } else if (g_strcmp0(by, "group") == 0) { werase(layout->subwin); @@ -289,7 +308,12 @@ rosterwin_roster(void) werase(layout->subwin); wattron(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); - GString *title = g_string_new(" -Roster"); + GString *title = g_string_new(" "); + char ch = prefs_get_roster_header_char(); + if (ch) { + g_string_append_printf(title, "%c", ch); + } + g_string_append(title, "Roster"); if (prefs_get_boolean(PREF_ROSTER_COUNT)) { g_string_append_printf(title, " (%d)", g_slist_length(contacts)); } diff --git a/theme_template b/theme_template index ae36cfd4..7eca6ff9 100644 --- a/theme_template +++ b/theme_template @@ -74,9 +74,16 @@ statuses.muc= roster= roster.offline= roster.resource= -roster.by= -roster.size= +roster.presence= +roster.status= roster.empty= +roster.by= +roster.order= +roster.count= +roster.priority= +roster.size= +roster.header.char= +roster.contact.char= occupants= occupants.size= occupants.jid= diff --git a/themes/boothj5 b/themes/boothj5 index 0b40fab5..48ada774 100644 --- a/themes/boothj5 +++ b/themes/boothj5 @@ -82,6 +82,8 @@ roster.order=presence roster.count=true roster.priority=true roster.size=25 +roster.header.char=@ +roster.contact.char=- occupants=true occupants.size=15 occupants.jid=false diff --git a/themes/complex b/themes/complex index c1abfc81..e2667944 100644 --- a/themes/complex +++ b/themes/complex @@ -29,6 +29,8 @@ roster.order=presence roster.count=true roster.priority=true roster.size=25 +roster.header.char=- +roster.contact.char=- privileges=true presence=true intype=true