# HG changeset patch # User Mikael Berthe # Date 1187722143 -7200 # Node ID 033576acac4c924a33986f907440011d4fdd2478 # Parent f8a874ff453a3d406e36cfa1d25b8fc423d8c2ee Add configurable roster colors (Michal 'vorner' Vaner) diff -r f8a874ff453a -r 033576acac4c mcabber/mcabberrc.example --- a/mcabber/mcabberrc.example Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/mcabberrc.example Tue Aug 21 20:49:03 2007 +0200 @@ -279,6 +279,13 @@ #set color_rosterselmsg = red #set color_rosternewmsg = red +#You can color roster items by their status and JID. For example, to have all +#roster items white, just all contacts from jabber.org that are away, not +#available or do not disturb yellow, you do this: +# +#color roster * * white +#color roster adn *@jabber.org yellow + # Style # Note: the "log_win_height" and "roster_width" values below can be set # in real time when mcabber is running. Refresh the screen (Ctrl-l) to diff -r f8a874ff453a -r 033576acac4c mcabber/src/commands.c --- a/mcabber/src/commands.c Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/src/commands.c Tue Aug 21 20:49:03 2007 +0200 @@ -77,6 +77,7 @@ static void do_screen_refresh(char *arg); static void do_chat_disable(char *arg); static void do_source(char *arg); +static void do_color(char *arg); // Global variable for the commands list static GSList *Commands; @@ -147,6 +148,7 @@ cmd_add("status_to", "Show or set your status for one recipient", COMPL_JID, COMPL_STATUS, &do_status_to); cmd_add("version", "Show mcabber version", 0, 0, &do_version); + cmd_add("color", "Set coloring options", COMPL_COLOR, 0, &do_color); // Status category compl_add_category_word(COMPL_STATUS, "online"); @@ -252,6 +254,9 @@ compl_add_category_word(COMPL_PGP, "force"); compl_add_category_word(COMPL_PGP, "info"); compl_add_category_word(COMPL_PGP, "setkey"); + + // Color category + compl_add_category_word(COMPL_COLOR, "roster"); } // expandalias(line) @@ -702,6 +707,41 @@ free_arg_lst(paramlst); } +void do_color(char *arg) +{ + char **paramlst; + char *subcmd; + + paramlst = split_arg(arg, 2, 1); // subcmd, arg + subcmd = *paramlst; + arg = *(paramlst+1); + + if (!subcmd || !*subcmd) { + scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); + free_arg_lst(paramlst); + return; + } + + if (!strcasecmp(subcmd, "roster")) { + char **arglist = split_arg(arg, 3, 0); + char *status = *arglist, *wildcard = arglist[1], *color = arglist[2]; + if (status && !strcmp(status, "clear")) { // Not a color command, clear all + scr_RosterClearColor(); + update_roster = TRUE; + } else { + if (!status || !*status || !wildcard || !*wildcard || !color || !*color) { + scr_LogPrint(LPRINT_NORMAL, "Missing argument"); + } else { + update_roster = scr_RosterColor(status, wildcard, color) + || update_roster; + } + } + free_arg_lst(arglist); + } else + scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); + free_arg_lst(paramlst); +} + // setstatus(recipient, arg) // Set your Jabber status. // - if recipient is not NULL, the status is sent to this contact only diff -r f8a874ff453a -r 033576acac4c mcabber/src/compl.h --- a/mcabber/src/compl.h Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/src/compl.h Tue Aug 21 20:49:03 2007 +0200 @@ -21,6 +21,7 @@ #define COMPL_EVENTS (1U<<15) #define COMPL_EVENTSID (1U<<16) #define COMPL_PGP (1U<<17) +#define COMPL_COLOR (1U<<18) void compl_add_category_word(guint, const char *command); void compl_del_category_word(guint categ, const char *word); diff -r f8a874ff453a -r 033576acac4c mcabber/src/screen.c --- a/mcabber/src/screen.c Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/src/screen.c Tue Aug 21 20:49:03 2007 +0200 @@ -143,9 +143,59 @@ AspellSpeller *spell_checker; #endif +typedef struct { + char *status, *wildcard; + int color; + GPatternSpec *compiled; +} rostercolor; + +GSList *rostercolrules = NULL; + /* Functions */ -static int FindColor(const char *name) +static int color_conv_table[] = { + COLOR_BLACK, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW, + COLOR_BLUE, + COLOR_MAGENTA, + COLOR_CYAN, + COLOR_WHITE +}; + +static int color_conv_table_fg[] = { + COLOR_BLACK_FG, + COLOR_RED_FG, + COLOR_GREEN_FG, + COLOR_YELLOW_FG, + COLOR_BLUE_FG, + COLOR_MAGENTA_FG, + COLOR_CYAN_FG, + COLOR_WHITE_FG +}; + +static int color_to_color_fg(int color) +{ + unsigned i = 0; + for ( ; i < sizeof color_conv_table / sizeof *color_conv_table; i++) + if (color == color_conv_table[i]) + return color_conv_table_fg[i]; + return -1; +} + +static int color_fg_to_color(int color) +{ + unsigned i = 0; + if (color >= COLOR_BLACK_BOLD_FG) + color -= COLOR_BLACK_BOLD_FG - COLOR_BLACK_FG; + for ( ; i < sizeof color_conv_table_fg / sizeof *color_conv_table_fg; i++) + if (color == color_conv_table_fg[i]) + return color_conv_table[i]; + return -1; +} + +static int FindColorInternal(const char *name) { if (!strcmp(name, "default")) return -1; @@ -166,10 +216,87 @@ if (!strcmp(name, "white")) return COLOR_WHITE; + return -2; +} + +static int FindColor(const char *name) +{ + int result = FindColorInternal(name); + if (result != -2) + return result; + scr_LogPrint(LPRINT_LOGNORM, "ERROR: Wrong color: %s", name); return -1; } +static void free_rostercolrule(rostercolor *col) +{ + g_free(col->status); + g_free(col->wildcard); + g_pattern_spec_free(col->compiled); + g_free(col); +} + +void scr_RosterClearColor(void) +{ + GSList *head; + for (head = rostercolrules; head; head = g_slist_next(head)) { + free_rostercolrule(head->data); + } + g_slist_free(rostercolrules); + rostercolrules = NULL; +} + +bool scr_RosterColor(const char *status, const char *wildcard, + const char *color) +{ + GSList *head; + GSList *found = NULL; + for (head = rostercolrules; head; head = g_slist_next(head)) { + rostercolor *rc = head->data; + if ((!strcmp(status, rc->status)) && (!strcmp(wildcard, rc->wildcard))) { + found = head; + break; + } + } + if (!strcmp(color,"-")) {//Delete the rule + if (found) { + free_rostercolrule(found->data); + rostercolrules = g_slist_delete_link(rostercolrules, found); + return TRUE; + } else { + scr_LogPrint(LPRINT_NORMAL, "No such color rule, nothing removed"); + return FALSE; + } + } else { + bool isbright = false; + int cl; + if (!strncmp(color, "bright", 6)) { + isbright = true; + color += 6; + } + cl = color_to_color_fg(FindColorInternal(color)); + if (isbright) + cl += COLOR_BLACK_BOLD_FG - COLOR_BLACK_FG; + if (cl < 0 ) { + scr_LogPrint(LPRINT_NORMAL, "No such color name"); + return FALSE; + } + if (found) { + rostercolor *rc = found->data; + rc->color = cl; + } else { + rostercolor *rc = g_new(rostercolor, 1); + rc->status = g_strdup(status); + rc->wildcard = g_strdup(wildcard); + rc->compiled = g_pattern_spec_new(wildcard); + rc->color = cl; + rostercolrules = g_slist_prepend(rostercolrules, rc); + } + return TRUE; + } +} + static void ParseColors(void) { const char *colors[] = { @@ -263,6 +390,11 @@ break; } } + for (i = COLOR_BLACK_FG; i < COLOR_max; i++) { + init_pair(i, color_fg_to_color(i), FindColor(background)); + if (i >= COLOR_BLACK_BOLD_FG) + COLOR_ATTRIB[i] = A_BOLD; + } } static void init_keycodes(void) @@ -1429,8 +1561,22 @@ } else { if (pending == '#') wattrset(rosterWnd, get_color(COLOR_ROSTERNMSG)); - else - wattrset(rosterWnd, get_color(COLOR_ROSTER)); + else { + int color = get_color(COLOR_ROSTER); + if ((!isspe) && (!isgrp)) {//Look for color rules + GSList *head; + const char *jid = buddy_getjid(BUDDATA(buddy)); + for (head = rostercolrules; head; head = g_slist_next(head)) { + rostercolor *rc = head->data; + if (g_pattern_match_string(rc->compiled, jid) && + (!strcmp("*", rc->status) || strchr(rc->status, status))) { + color = get_color(rc->color); + break; + } + } + } + wattrset(rosterWnd, color); + } } if (Roster_Width > 7) diff -r f8a874ff453a -r 033576acac4c mcabber/src/screen.h --- a/mcabber/src/screen.h Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/src/screen.h Tue Aug 21 20:49:03 2007 +0200 @@ -48,6 +48,25 @@ COLOR_ROSTERNMSG, COLOR_INFO, COLOR_MSGIN, + //Foreground color on usual backgroud + //curses do not allow telling color only -> + //needs colorpairs + COLOR_BLACK_FG, + COLOR_RED_FG, + COLOR_GREEN_FG, + COLOR_YELLOW_FG, + COLOR_BLUE_FG, + COLOR_MAGENTA_FG, + COLOR_CYAN_FG, + COLOR_WHITE_FG, + COLOR_BLACK_BOLD_FG, + COLOR_RED_BOLD_FG, + COLOR_GREEN_BOLD_FG, + COLOR_YELLOW_BOLD_FG, + COLOR_BLUE_BOLD_FG, + COLOR_MAGENTA_BOLD_FG, + COLOR_CYAN_BOLD_FG, + COLOR_WHITE_BOLD_FG, COLOR_max }; @@ -139,6 +158,8 @@ void scr_RosterUnreadMessage(int); void scr_RosterJumpAlternate(void); void scr_BufferScrollUpDown(int updown, unsigned int nblines); +bool scr_RosterColor(const char *status, const char *wildcard, const char *color); +void scr_RosterClearColor(void); #ifdef DEBUG_ENABLE void scr_BufferList(void); diff -r f8a874ff453a -r 033576acac4c mcabber/src/settings.c --- a/mcabber/src/settings.c Mon Aug 20 21:30:16 2007 +0200 +++ b/mcabber/src/settings.c Tue Aug 21 20:49:03 2007 +0200 @@ -153,15 +153,18 @@ if ((*line == '\n') || (*line == '\0') || (*line == '#')) continue; - // We only allow assignments line, except for commands "pgp" and "source" + // We only allow assignments line, except for commands "pgp", "source" + // and "color" if ((strchr(line, '=') != NULL) || - startswith(line, "pgp ", FALSE) || startswith(line, "source ", FALSE)) { + startswith(line, "pgp ", FALSE) || startswith(line, "source ", FALSE) || + startswith(line, "color ", FALSE)) { // Only accept the set, alias, bind, pgp and source commands if (!startswith(line, "set ", FALSE) && !startswith(line, "bind ", FALSE) && !startswith(line, "alias ", FALSE) && !startswith(line, "pgp ", FALSE) && - !startswith(line, "source ", FALSE)) { + !startswith(line, "source ", FALSE) && + !startswith(line, "color ", FALSE)) { scr_LogPrint(LPRINT_LOGNORM, "Error in configuration file (l. %d): bad command", ln); err++;