changeset 1272:033576acac4c

Add configurable roster colors (Michal 'vorner' Vaner)
author Mikael Berthe <mikael@lilotux.net>
date Tue, 21 Aug 2007 20:49:03 +0200
parents f8a874ff453a
children b17ab2782ce5
files mcabber/mcabberrc.example mcabber/src/commands.c mcabber/src/compl.h mcabber/src/screen.c mcabber/src/screen.h mcabber/src/settings.c
diffstat 6 files changed, 224 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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);
--- 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)
--- 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);
--- 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++;