changeset 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 359e1c53552a
files mcabber/src/commands.c mcabber/src/roster.c mcabber/src/roster.h mcabber/src/screen.c mcabber/src/screen.h mcabber/src/utils.c mcabber/src/utils.h
diffstat 7 files changed, 217 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/src/commands.c	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/commands.c	Tue Aug 28 10:11:39 2007 +0200
@@ -257,6 +257,8 @@
 
   // Color category
   compl_add_category_word(COMPL_COLOR, "roster");
+  compl_add_category_word(COMPL_COLOR, "muc");
+  compl_add_category_word(COMPL_COLOR, "mucnick");
 }
 
 //  expandalias(line)
@@ -724,7 +726,7 @@
 
   if (!strcasecmp(subcmd, "roster")) {
     char **arglist = split_arg(arg, 3, 0);
-    char *status = *arglist, *wildcard = arglist[1], *color = arglist[2];
+    char *status = *arglist, *wildcard = to_utf8(arglist[1]), *color = arglist[2];
     if (status && !strcmp(status, "clear")) { // Not a color command, clear all
       scr_RosterClearColor();
       update_roster = TRUE;
@@ -737,6 +739,44 @@
       }
     }
     free_arg_lst(arglist);
+    g_free(wildcard);
+  } else if (!strcasecmp(subcmd, "muc")) {
+    char **arglist = split_arg(arg, 2, 0);
+    char *free_muc = to_utf8(*arglist);
+    const char *muc = free_muc, *mode = arglist[1];
+    if (!muc || !*muc)
+      scr_LogPrint(LPRINT_NORMAL, "What MUC?");
+    else {
+      if (!strcmp(muc, "."))
+        if (!(muc = CURRENT_JID))
+          scr_LogPrint(LPRINT_NORMAL, "No JID selected");
+      if (muc) {
+        if (check_jid_syntax(muc) && strcmp(muc, "*"))
+          scr_LogPrint(LPRINT_NORMAL, "Not a JID");
+        else {
+          if (!mode || !*mode || !strcasecmp(mode, "on"))
+            scr_MucColor(muc, MC_ALL);
+          else if (!strcasecmp(mode, "preset"))
+            scr_MucColor(muc, MC_PRESET);
+          else if (!strcasecmp(mode, "off"))
+            scr_MucColor(muc, MC_OFF);
+          else if (!strcmp(mode, "-"))
+            scr_MucColor(muc, MC_REMOVE);
+          else
+            scr_LogPrint(LPRINT_NORMAL, "Unknown coloring mode");
+        }
+      }
+    }
+    free_arg_lst(arglist);
+    g_free(free_muc);
+  } else if (!strcasecmp(subcmd, "mucnick")) {
+    char **arglist = split_arg(arg, 2, 0);
+    const char *nick = *arglist, *color = arglist[1];
+    if (!nick || !*nick || !color || !*color)
+      scr_LogPrint(LPRINT_NORMAL, "Missing argument");
+    else
+      scr_MucNickColor(nick, color);
+    free_arg_lst(arglist);
   } else
     scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!");
   free_arg_lst(paramlst);
--- a/mcabber/src/roster.c	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/roster.c	Tue Aug 28 10:11:39 2007 +0200
@@ -867,6 +867,8 @@
 
 const char *buddy_getjid(gpointer rosterdata)
 {
+  if (!rosterdata)
+    return NULL;
   roster *roster_usr = rosterdata;
   return roster_usr->jid;
 }
@@ -1270,7 +1272,7 @@
 // Look for a buddy with specified jid.
 // Search begins at buddylist; if no match is found in the the buddylist,
 // return NULL;
-GList *buddy_search_jid(char *jid)
+GList *buddy_search_jid(const char *jid)
 {
   GList *buddy;
   roster *roster_usr;
--- a/mcabber/src/roster.h	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/roster.h	Tue Aug 28 10:11:39 2007 +0200
@@ -193,7 +193,7 @@
 void    buddy_del_all_resources(gpointer rosterdata);
 void    buddy_setflags(gpointer rosterdata, guint flags, guint value);
 guint   buddy_getflags(gpointer rosterdata);
-GList  *buddy_search_jid(char *jid);
+GList  *buddy_search_jid(const char *jid);
 GList  *buddy_search(char *string);
 void    foreach_buddy(guint roster_type,
                       void (*pfunc)(gpointer rosterdata, void *param),
--- 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;
--- a/mcabber/src/screen.h	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/screen.h	Tue Aug 28 10:11:39 2007 +0200
@@ -92,6 +92,13 @@
   } mcode;
 } keycode;
 
+typedef enum {
+  MC_ALL,
+  MC_PRESET,
+  MC_OFF,
+  MC_REMOVE
+} muccoltype;
+
 void scr_init_bindings(void);
 
 void scr_Getch(keycode *kcode);
@@ -156,6 +163,8 @@
 void scr_BufferScrollUpDown(int updown, unsigned int nblines);
 bool scr_RosterColor(const char *status, const char *wildcard, const char *color);
 void scr_RosterClearColor(void);
+void scr_MucColor(const char *muc, muccoltype type);
+void scr_MucNickColor(const char *nick, const char *color);
 
 #ifdef DEBUG_ENABLE
 void scr_BufferList(void);
--- a/mcabber/src/utils.c	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/utils.c	Tue Aug 28 10:11:39 2007 +0200
@@ -317,10 +317,10 @@
  * Check if the full JID is valid
  * Return 0 if it is valid, non zero otherwise
  */
-int check_jid_syntax(char *fjid)
+int check_jid_syntax(const char *fjid)
 {
-  char *str;
-  char *domain, *resource;
+  const char *str;
+  const char *domain, *resource;
   int domlen;
 
   if (!fjid) return 1;
--- a/mcabber/src/utils.h	Sun Aug 26 22:23:30 2007 +0200
+++ b/mcabber/src/utils.h	Tue Aug 28 10:11:39 2007 +0200
@@ -28,7 +28,7 @@
 
 inline void safe_usleep(unsigned int usec); /* Only for delays < 1s */
 
-int check_jid_syntax(char *fjid);
+int check_jid_syntax(const char *fjid);
 
 inline void mc_strtolower(char *str);