diff mcabber/src/screen.c @ 1292:382ec54b584e

Muc nick coloring functionality
author Michal 'vorner' Vaner <vorner@ucw.cz>
date Tue, 28 Aug 2007 10:11:39 +0200
parents 9f64f548ac16
children 86caabe72f3a
line wrap: on
line diff
--- a/mcabber/src/screen.c	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/screen.c	Tue Aug 28 10:11:39 2007 +0200
@@ -28,6 +28,7 @@
 #include <locale.h>
 #include <langinfo.h>
 #include <config.h>
+#include <assert.h>
 
 #ifdef HAVE_ASPELL_H
 # include <aspell.h>
@@ -150,7 +151,17 @@
   GPatternSpec *compiled;
 } rostercolor;
 
-GSList *rostercolrules = NULL;
+static GSList *rostercolrules = NULL;
+
+static GHashTable *muccolors = NULL, *nickcolors = NULL;
+
+typedef struct {
+  bool manual;//Manually set?
+  int color;
+} nickcolor;
+
+static int nickcolcount = 0, *nickcols = NULL;
+static muccoltype glob_muccol = MC_OFF;
 
 /* Functions */
 
@@ -230,6 +241,90 @@
   return -1;
 }
 
+static void ensure_string_htable(GHashTable **table,
+    GDestroyNotify value_destroy_func)
+{
+  if (*table)//Have it already
+    return;
+  *table = g_hash_table_new_full(g_str_hash, g_str_equal,
+      g_free, value_destroy_func);
+}
+
+// Sets the coloring mode for given MUC
+// The MUC room does not need to be in the roster at that time
+// muc - the JID of room
+// type - the new type
+void scr_MucColor(const char *muc, muccoltype type)
+{
+  gchar *muclow = g_utf8_strdown(muc, -1);
+  if (type == MC_REMOVE) {//Remove it
+    if (strcmp(muc, "*")) {
+      if (muccolors && g_hash_table_lookup(muccolors, muclow))
+        g_hash_table_remove(muccolors, muclow);
+    } else {
+      scr_LogPrint(LPRINT_NORMAL, "Can not remove global coloring mode");
+    }
+    g_free(muclow);
+  } else {//Add or overwrite
+    if (strcmp(muc, "*")) {
+      ensure_string_htable(&muccolors, g_free);
+      muccoltype *value = g_new(muccoltype, 1);
+      *value = type;
+      g_hash_table_replace(muccolors, muclow, value);
+    } else {
+      glob_muccol = type;
+      g_free(muclow);
+    }
+  }
+  //Need to redraw?
+  if (chatmode && ((buddy_search_jid(muc) == current_buddy) || !strcmp(muc, "*")))
+    scr_UpdateBuddyWindow();
+}
+
+// Sets the color for nick in MUC
+// If color is "-", the color is marked as automaticly assigned and is
+// not used if the room is in the "preset" mode
+void scr_MucNickColor(const char *nick, const char *color)
+{
+  char *snick = g_strdup_printf("<%s>", nick), *mnick = g_strdup_printf("*%s ", nick);
+  bool need_update = false;
+  if (!strcmp(color, "-")) {//Remove the color
+    if (nickcolors) {
+      nickcolor *nc = g_hash_table_lookup(nickcolors, snick);
+      if (nc) {//Have this nick already
+        nc->manual = false;
+        nc = g_hash_table_lookup(nickcolors, mnick);
+        assert(nc);//Must have both at the same time
+        nc->manual = false;
+      }// Else -> no color saved, nothing to delete
+    }
+    g_free(snick);//They are not saved in the hash
+    g_free(mnick);
+    need_update = true;
+  } else {
+    int cl = color_to_color_fg(FindColorInternal(color));
+    if (cl < 0) {
+      scr_LogPrint(LPRINT_NORMAL, "No such color name");
+      g_free(snick);
+      g_free(mnick);
+    } else {
+      nickcolor *nc = g_new(nickcolor, 1);
+      ensure_string_htable(&nickcolors, NULL);
+      nc->manual = true;
+      nc->color = cl;
+      //Free the struct, if any there already
+      g_free(g_hash_table_lookup(nickcolors, mnick));
+      //Save the new ones
+      g_hash_table_replace(nickcolors, mnick, nc);
+      g_hash_table_replace(nickcolors, snick, nc);
+      need_update = true;
+    }
+  }
+  if (need_update && chatmode &&
+      (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_ROOM))
+    scr_UpdateBuddyWindow();
+}
+
 static void free_rostercolrule(rostercolor *col)
 {
   g_free(col->status);
@@ -404,6 +499,40 @@
     if (i >= COLOR_BLACK_BOLD_FG)
       COLOR_ATTRIB[i] = A_BOLD;
   }
+  char *ncolors = g_strdup(settings_opt_get("nick_colors")),
+      *ncolor_start = ncolors;
+  if (ncolors) {
+    while (*ncolors) {
+      if ((*ncolors == ' ') || (*ncolors == '\t')) {
+        ncolors ++;
+      } else {
+        char *end = ncolors;
+        bool ended = false;
+        while (*end && (*end != ' ') && (*end != '\t'))
+          end++;
+        if (!end)
+          ended = true;
+        *end = '\0';
+        int cl = color_to_color_fg(FindColorInternal(ncolors));
+        if (cl < 0) {
+          scr_LogPrint(LPRINT_NORMAL, "Unknown color %s", ncolors);
+        } else {
+          nickcols = g_realloc(nickcols, (++nickcolcount) * sizeof *nickcols);
+          nickcols[nickcolcount-1] = cl;
+        }
+        if (ended)
+          ncolors = NULL;
+        else
+          ncolors = end+1;
+      }
+    }
+    g_free(ncolor_start);
+  }
+  if (!nickcols) {//Fallback to have something
+    nickcolcount = 1;
+    nickcols = g_new(int, 1);
+    *nickcols = COLOR_GENERAL;
+  }
 }
 
 static void init_keycodes(void)
@@ -910,10 +1039,37 @@
       if (line->mucnicklen && (line->flags & HBB_PREFIX_IN)) {
         //Store the char after the nick
         char tmp = line->text[line->mucnicklen];
-        //TODO choose the color in proper way
-        wattrset(win_entry->win, get_color(COLOR_RED_BOLD_FG));
+        muccoltype type = glob_muccol, *typetmp;
         //Terminate the string after the nick
         line->text[line->mucnicklen] = '\0';
+        char *mucjid = g_utf8_strdown(CURRENT_JID, -1);
+        if (muccolors) {
+          typetmp = g_hash_table_lookup(muccolors, mucjid);
+          if (typetmp)
+            type = *typetmp;
+        }
+        g_free(mucjid);
+        nickcolor *actual = NULL;
+        // Need to generate some random color?
+        if ((type == MC_ALL) && (!nickcolors ||
+            !g_hash_table_lookup(nickcolors, line->text))) {
+          ensure_string_htable(&nickcolors, NULL);
+          char *snick = g_strdup(line->text), *mnick = g_strdup(line->text);
+          nickcolor *nc = g_new(nickcolor, 1);
+          nc->color = nickcols[random() % nickcolcount];
+          nc->manual = false;
+          *snick = '<';
+          snick[strlen(snick)-1] = '>';
+          *mnick = '*';
+          mnick[strlen(mnick)-1] = ' ';
+          //Insert them
+          g_hash_table_insert(nickcolors, snick, nc);
+          g_hash_table_insert(nickcolors, mnick, nc);
+        }
+        if (nickcolors)
+          actual = g_hash_table_lookup(nickcolors, line->text);
+        if (actual && ((type == MC_ALL) || (actual->manual)))
+          wattrset(win_entry->win, get_color(actual->color));
         wprintw(win_entry->win, "%s", line->text);
         //Return the char
         line->text[line->mucnicklen] = tmp;