$ git clone http://tcclient.ion.nu/tc_client.git
commit 860613bab5fdcd6e4f5462cc1ddb353dbaf78ad8
Author: Alicia <...>
Date:   Mon Dec 5 20:19:40 2016 +0100

    tc_client-gtk: added an icon to mark moderators in the user list.

diff --git a/ChangeLog b/ChangeLog
index c3e9388..c2b7605 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,7 @@ tc_client-gtk: compatibility with older versions of libavformat.
 tc_client-gtk: build fixes for windows.
 tc_client-gtk: tweaks for windows compatibility.
 tc_client-gtk: bugfix: hiding your own camera caused a segfault.
+tc_client-gtk: added an icon to mark moderators in the user list.
 dist/appimage.sh: fix audio in appimages by building ffmpeg with support for nellymoser and speex, and depending on the system's libao and libpulse instead of including it in the appimage.
 libcamera(escapi): handle failure to open camera more gracefully.
 irchack: pass along "<user> cammed up" notifications.
diff --git a/Makefile b/Makefile
index 3b22e66..a88d056 100644
--- a/Makefile
+++ b/Makefile
@@ -132,12 +132,15 @@ camviewer: $(CAMVIEWER_OBJ)
 cursedchat: $(CURSEDCHAT_OBJ)
  $(CC) $(LDFLAGS) $^ $(LIBS) $(READLINE_LIBS) $(CURSES_LIBS) -o $@
 
-tc_client-gtk: $(TC_CLIENT_GTK_OBJ) camplaceholder.gif
+tc_client-gtk: $(TC_CLIENT_GTK_OBJ) camplaceholder.gif modicon.png
  $(CC) $(LDFLAGS) $(TC_CLIENT_GTK_OBJ) $(LIBS) $(GTK_LIBS) $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(AVRESAMPLE_LIBS) $(SWRESAMPLE_LIBS) $(AVFORMAT_LIBS) $(AO_LIBS) $(LIBV4L2_LIBS) $(LIBX11_LIBS) $(PULSE_LIBS) -o $@
 
 camplaceholder.gif: utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf
  utilities/gtk/gencamplaceholder.sh
 
+modicon.png: utilities/gtk/modicon.xcf
+ convert -background none $< -layers Merge -scale x20 $@
+
 libcamera.a: $(LIBCAMERA_OBJ)
  $(AR) cru $@ $^
  $(RANLIB) $@
@@ -151,7 +154,7 @@ SOURCES+=utilities/modbot/modbot.c utilities/modbot/queue.c utilities/modbot/que
 SOURCES+=utilities/camviewer/camviewer.c
 SOURCES+=utilities/cursedchat/cursedchat.c utilities/cursedchat/buffer.c utilities/cursedchat/buffer.h
 SOURCES+=utilities/gtk/camviewer.c utilities/gtk/userlist.c utilities/gtk/media.c utilities/gtk/compat.c utilities/gtk/configfile.c utilities/gtk/gui.c utilities/gtk/logging.c utilities/gtk/postproc.c utilities/gtk/inputhistory.c utilities/gtk/playmedia.c utilities/gtk/main.h utilities/gtk/userlist.h utilities/gtk/media.h utilities/gtk/compat.h utilities/gtk/configfile.h utilities/gtk/gui.h utilities/gtk/logging.h utilities/gtk/postproc.h utilities/gtk/inputhistory.h utilities/gtk/playmedia.h gtkgui.glade
-SOURCES+=utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf
+SOURCES+=utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf utilities/gtk/modicon.xcf
 SOURCES+=utilities/compat.c utilities/compat.h utilities/list.c utilities/list.h utilities/stringutils.c utilities/stringutils.h utilities/compat_av.c utilities/compat_av.h
 SOURCES+=utilities/libcamera/camera.c utilities/libcamera/camera.h utilities/libcamera/camera_v4l2.c utilities/libcamera/camera_v4l2.h utilities/libcamera/camera_img.c utilities/libcamera/camera_img.h utilities/libcamera/camera_escapi.cpp utilities/libcamera/camera_escapi.h utilities/libcamera/camera_x11.c utilities/libcamera/camera_x11.h
 tarball:
@@ -166,6 +169,7 @@ ifdef SWSCALE_LIBS
  install -m 755 -D tc_client-gtk "$(PREFIX)/bin/tc_client-gtk"
  install -D gtkgui.glade "$(PREFIX)/share/tc_client/gtkgui.glade"
  install -D camplaceholder.gif "$(PREFIX)/share/tc_client/camplaceholder.gif"
+ install -D modicon.png "$(PREFIX)/share/tc_client/modicon.png"
 endif
 endif
 endif
diff --git a/utilities/gtk/camviewer.c b/utilities/gtk/camviewer.c
index 8b9e342..b9bdcf7 100644
--- a/utilities/gtk/camviewer.c
+++ b/utilities/gtk/camviewer.c
@@ -496,19 +496,13 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer x)
   if(space && !strcmp(space, " is a moderator."))
   {
     space[0]=0;
-    struct user* user=finduser(buf);
-    if(user)
-    {
-      user->ismod=1;
-      renameuser(buf, buf); // Update the userlist label
-    }
+    usersetmod(buf, 1);
     return 1;
   }
   if(space && !strcmp(space, " is no longer a moderator."))
   {
     space[0]=0;
-    struct user* user=finduser(buf);
-    if(user){user->ismod=0;}
+    usersetmod(buf, 0);
     return 1;
   }
   // Start a stream when someone cams up
diff --git a/utilities/gtk/gui.c b/utilities/gtk/gui.c
index 0f07fef..ad04b36 100644
--- a/utilities/gtk/gui.c
+++ b/utilities/gtk/gui.c
@@ -35,6 +35,7 @@ extern gboolean gui_greenscreen_preview(void* x);
 GdkCursor* gui_cursor_text;
 GdkCursor* gui_cursor_link;
 struct chatview* mainchat;
+GdkPixbuf* modicon=0;
 
 void settings_reset(GtkBuilder* gui)
 {
@@ -1067,6 +1068,8 @@ void gui_init(char frombuild)
     camplaceholder=gdk_pixbuf_animation_new_from_file(PREFIX "/share/tc_client/camplaceholder.gif", 0);
   }
   camplaceholder_iter=gdk_pixbuf_animation_get_iter(camplaceholder, 0);
+  // Load moderator icon
+  modicon=gdk_pixbuf_new_from_file(PREFIX "/share/tc_client/modicon.png", 0);
   // Populate saved channels
   GtkWidget* startbox=GTK_WIDGET(gtk_builder_get_object(gui, "startbox"));
   int channelcount=config_get_int("channelcount");
diff --git a/utilities/gtk/gui.h b/utilities/gtk/gui.h
index 1d71345..e75ed65 100644
--- a/utilities/gtk/gui.h
+++ b/utilities/gtk/gui.h
@@ -74,3 +74,4 @@ extern GtkBuilder* gui;
 extern GdkCursor* gui_cursor_text;
 extern GdkCursor* gui_cursor_link;
 extern struct chatview* mainchat;
+extern GdkPixbuf* modicon;
diff --git a/utilities/gtk/modicon.xcf b/utilities/gtk/modicon.xcf
new file mode 100644
index 0000000..78a50be
Binary files /dev/null and b/utilities/gtk/modicon.xcf differ
diff --git a/utilities/gtk/userlist.c b/utilities/gtk/userlist.c
index 1121749..463feea 100644
--- a/utilities/gtk/userlist.c
+++ b/utilities/gtk/userlist.c
@@ -52,6 +52,7 @@ struct user* adduser(const char* nick)
   userlist=realloc(userlist, sizeof(struct user)*usercount);
   userlist[usercount-1].nick=strdup(nick);
   userlist[usercount-1].label=gtk_label_new(nick); // TODO: some kind of menubutton for actions?
+  userlist[usercount-1].item=userlist[usercount-1].label;
   userlist[usercount-1].pm_tab=0;
   userlist[usercount-1].pm_tablabel=0;
   userlist[usercount-1].pm_chatview=0;
@@ -71,15 +72,7 @@ void renameuser(const char* old, const char* newnick)
   if(!user){return;}
   free(user->nick);
   user->nick=strdup(newnick);
-  if(user->ismod)
-  {
-    char newlabel[strlen(newnick)+2];
-    newlabel[0]='@';
-    strcpy(&newlabel[1], newnick);
-    gtk_label_set_text(GTK_LABEL(user->label), newlabel);
-  }else{
-    gtk_label_set_text(GTK_LABEL(user->label), newnick);
-  }
+  gtk_label_set_text(GTK_LABEL(user->label), newnick);
   if(user->pm_tablabel)
   {
     if(user->pm_highlight)
@@ -99,10 +92,32 @@ void removeuser(const char* nick)
     if(!strcmp(userlist[i].nick, nick))
     {
       free(userlist[i].nick);
-      gtk_widget_destroy(userlist[i].label);
+      gtk_widget_destroy(userlist[i].item);
       --usercount;
       memmove(&userlist[i], &userlist[i+1], (usercount-i)*sizeof(struct user));
       return;
     }
   }
 }
+
+void usersetmod(const char* nick, char mod)
+{
+  struct user* user=finduser(nick);
+  if(!user || mod==user->ismod){return;}
+  user->ismod=mod;
+  g_object_ref(user->label); // Keep label from getting destroyed
+  if(mod)
+  { // Add icon to symbolize being a moderator
+    gtk_container_remove(GTK_CONTAINER(userlistwidget), user->label);
+    user->item=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+    gtk_box_pack_start(GTK_BOX(user->item), user->label, 0, 0, 0);
+    gtk_box_pack_start(GTK_BOX(user->item), gtk_image_new_from_pixbuf(modicon), 0, 0, 0);
+    gtk_box_pack_start(GTK_BOX(userlistwidget), user->item, 0, 0, 0);
+    gtk_widget_show_all(user->item);
+  }else{
+    gtk_widget_destroy(user->item);
+    gtk_box_pack_start(GTK_BOX(userlistwidget), user->label, 0, 0, 0);
+    user->item=user->label;
+  }
+  g_object_unref(user->label);
+}
diff --git a/utilities/gtk/userlist.h b/utilities/gtk/userlist.h
index 0b58dbe..2c03fd2 100644
--- a/utilities/gtk/userlist.h
+++ b/utilities/gtk/userlist.h
@@ -18,6 +18,7 @@ struct user
 {
   char* nick;
   GtkWidget* label;
+  GtkWidget* item;
   char ismod;
   GtkWidget* pm_tab;
   GtkWidget* pm_tablabel;
@@ -34,3 +35,4 @@ extern struct user* user_find_by_tab(GtkWidget* tab);
 extern struct user* adduser(const char* nick);
 extern void renameuser(const char* old, const char* newnick);
 extern void removeuser(const char* nick);
+extern void usersetmod(const char* nick, char mod);