$ git clone http://tcclient.ion.nu/tc_client.git
commit 5cc2c4bc1ad56dd99d8b8a2b799c302a2d219e5d
Author: Alicia <...>
Date:   Tue Apr 7 06:49:00 2015 +0200

    Version 0.6

diff --git a/ChangeLog b/ChangeLog
index adedc1a..59b2dd1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+0.6:
+Fixed a bug in the ID list that kept IDs from being removed correctly.
+Show colors using ANSI escape codes.
 0.5:
 Fixed a bug in irchack.c that sent the JOIN confirmation to the wrong file descriptor.
 Avoid sending empty lines.
diff --git a/Makefile b/Makefile
index 7f57a99..dce00d7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
-VERSION=0.5
+VERSION=0.6
 CFLAGS=-g3 -Wall $(shell curl-config --cflags)
 LIBS=-g3 $(shell curl-config --libs)
 
-tc_client: client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o
+tc_client: client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o
  $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
 
 clean:
- rm -f client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o tc_client
+ rm -f client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o tc_client
 
 tarball:
- tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h LICENSE README ChangeLog irchack.c
+ tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c colors.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h colors.h LICENSE README ChangeLog irchack.c
diff --git a/README b/README
index 9c4cb28..01fabe8 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 Some notes about tc_client in its current state (things that should be fixed):
-*there is no real user interface, to send a message you just type it and it might get cut off by incoming messages, it'll be ugly.
+*there is no real user interface, to send a message you just type it and it might get cut off by incoming messages, it'll be ugly. There is however the irchack program that lets you use an IRC client.
 *PMs can be sent by /msg <nickname> <message> and replies appear similarly. Note however that PMs sent this way are currently sent to everyone in the channel, but the flash client ignores them.
 *you can't log in with an account and thus not do mod stuff, I don't know how this works protocol-wise
 
diff --git a/client.c b/client.c
index 40f59af..ce84d08 100644
--- a/client.c
+++ b/client.c
@@ -31,6 +31,7 @@
 #include "numlist.h"
 #include "amfwriter.h"
 #include "idlist.h"
+#include "colors.h"
 
 struct writebuf
 {
@@ -253,28 +254,6 @@ int main(int argc, char** argv)
   close(f);
 */
 
-/* Disabled for now
-  char* colors[]={ // Sorted like a rainbow
-    "#821615,en",
-    "#c53332,en",
-    "#a08f23,en",
-    "#a78901,en",
-    "#919104,en",
-    "#7bb224,en",
-    "#7db257,en",
-    "#487d21,en",
-    "#00a990,en",
-    "#32a5d9,en",
-    "#1d82eb,en",
-    "#1965b6,en",
-    "#5c1a7a,en",
-    "#9d5bb5,en",
-    "#c356a3,en",
-    "#b9807f,en"
-  };
-  unsigned int currentcolor=0;
-*/
-
 //  int outnum=2; (Debugging, number for output filenames)
   struct pollfd pfd[2];
   pfd[0].fd=0;
@@ -359,10 +338,11 @@ int main(int argc, char** argv)
         amfsend(&amf, sock);
       }
       // Items for privmsg: 0=cmd, 2=channel, 3=msg, 4=color/lang, 5=nick
-      else if(amfin->itemcount>5 && amfin->items[0].type==AMF_STRING && amf_comparestrings_c(&amfin->items[0].string, "privmsg") && amfin->items[3].type==AMF_STRING && amfin->items[5].type==AMF_STRING)
+      else if(amfin->itemcount>5 && amfin->items[0].type==AMF_STRING && amf_comparestrings_c(&amfin->items[0].string, "privmsg") && amfin->items[3].type==AMF_STRING && amfin->items[4].type==AMF_STRING && amfin->items[5].type==AMF_STRING)
       {
         wchar_t* msg=fromnumlist(amfin->items[3].string.string);
-        printf("%s %s: %ls\n", timestamp(), amfin->items[5].string.string, msg);
+        const char* color=resolvecolor(amfin->items[4].string.string);
+        printf("%s \x1b[%sm%s: %ls\x1b[0m\n", timestamp(), color, amfin->items[5].string.string, msg);
         free(msg);
         fflush(stdout);
       }
diff --git a/colors.c b/colors.c
index 28969eb..8967326 100644
--- a/colors.c
+++ b/colors.c
@@ -1,7 +1,6 @@
 /*
     tc_client, a simple non-flash client for tinychat(.com)
-    Copyright (C) 2014-2015  alicia@ion.nu
-    Copyright (C) 2015  Pamela Hiatt
+    Copyright (C) 2014  alicia@ion.nu
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +18,7 @@
 #include "colors.h"
 
 // Sorted like rainbows
-const char* colors[COLORCOUNT]={ // The 16 colors accepted by the flash client
+const char* colors[]={
   "#821615,en",
   "#c53332,en",
   "#a08f23,en",
@@ -38,7 +37,7 @@ const char* colors[COLORCOUNT]={ // The 16 colors accepted by the flash client
   "#b9807f,en"
 };
 
-const char* termcolors[COLORCOUNT]={ // Equivalent color codes for ANSI escape sequences
+const char* termcolors[]={
   "31",
   "31;1",
   "33",
@@ -57,12 +56,10 @@ const char* termcolors[COLORCOUNT]={ // Equivalent color codes for ANSI escape s
   "35;1"
 };
 
-unsigned int currentcolor=COLORCOUNT;
-
 const char* resolvecolor(const char* tc_color)
 {
   int i;
-  for(i=0; i<COLORCOUNT; ++i)
+  for(i=0; i<16; ++i)
   {
     if(!strcmp(colors[i], tc_color)){return termcolors[i];}
   }
diff --git a/colors.h b/colors.h
index baa5d9b..76c1f29 100644
--- a/colors.h
+++ b/colors.h
@@ -1,6 +1,6 @@
 /*
     tc_client, a simple non-flash client for tinychat(.com)
-    Copyright (C) 2014-2015  alicia@ion.nu
+    Copyright (C) 2014  alicia@ion.nu
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
@@ -14,9 +14,7 @@
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#define COLORCOUNT 16
 extern const char* colors[];
 extern const char* termcolors[];
-extern unsigned int currentcolor;
 
 extern const char* resolvecolor(const char* tc_color);
diff --git a/idlist.c b/idlist.c
index 5e7c5f9..297f3b1 100644
--- a/idlist.c
+++ b/idlist.c
@@ -39,7 +39,7 @@ void idlist_remove(const char* name)
     {
       free((void*)idlist[i].name);
       --idlistlen;
-      memmove(idlist, &idlist[i+1], sizeof(struct idmap)*(idlistlen-i));
+      memmove(&idlist[i], &idlist[i+1], sizeof(struct idmap)*(idlistlen-i));
       return;
     }
   }
diff --git a/irchack.c b/irchack.c
index e64ae9d..4b022d9 100644
--- a/irchack.c
+++ b/irchack.c
@@ -22,16 +22,18 @@
 #include <stdio.h>
 #include <sys/socket.h>
 
-int main()
+int main(int argc, char** argv)
 {
+  int port=(argc>1?atoi(argv[1]):6667);
   struct sockaddr_in addr;
   memset(&addr, 0, sizeof(addr));
   addr.sin_family=AF_INET;
   addr.sin_addr.s_addr=0;
-  addr.sin_port=htons(6667);
+  addr.sin_port=htons(port);
   int lsock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   if(bind(lsock, (struct sockaddr*)&addr, sizeof(addr))){perror("bind"); return 1;}
   listen(lsock, 1);
+  printf("Done! Open an IRC client and connect to localhost on port %i\n", port);
   int sock=accept(lsock, 0, 0);
   close(lsock);
   char buf[2048];
@@ -140,6 +142,16 @@ printf("Got from tc_client: '%s'\n", buf);
         continue;
       }
       if(buf[0]!='['){continue;} // Beyond this we only care about timestamped lines
+      // Strip out ANSI escape codes (TODO: translate them to IRC color codes instead)
+      char* ansi;
+      while((ansi=strstr(buf, "\x1b[")))
+      {
+        int len;
+        for(len=0; ansi[len]&&ansi[len]!='m'; ++len);
+        if(ansi[len]=='m'){++len;}
+        memmove(ansi, &ansi[len], strlen(&ansi[len])+1);
+      }
+
       char* name=strchr(buf, ' ');
       if(!name){continue;}
       name[0]=0;
@@ -159,7 +171,7 @@ printf("Got from tc_client: '%s'\n", buf);
         }else{ // Regular channel message
           dprintf(sock, ":%s!user@host PRIVMSG #%s :%s\n", name, channel, msg);
         }
-      }else{ // action, TODO: parse the actions and send them as JOINs, NICKs and QUITs etc. instead
+      }else{ // action, parse the actions and send them as JOINs, NICKs and QUITs etc. instead
         msg[0]=0;
         msg=&msg[1];
         if(!strcmp(msg, "entered the channel"))