Introduction
Introduction Statistics Contact Development Disclaimer Help
support in-channel unicode - irc - Unnamed repository; edit this file 'descript…
git clone git://vernunftzentrum.de/irc.git
Log
Files
Refs
README
---
commit 734cc4f0e72259a8be86115c71dce0f112d6ff0b
parent 1c4a83b81f92884d7add4962151f16b74637a0c5
Author: Quentin Carbonneaux <[email protected]>
Date: Wed, 4 May 2016 22:17:19 -0400
support in-channel unicode
Diffstat:
Makefile | 2 +-
irc.c | 107 +++++++++++++++++++++++++++----
2 files changed, 96 insertions(+), 13 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
BIN = irc
CFLAGS = -std=c99 -Os -D_POSIX_C_SOURCE=201112 -D_GNU_SOURCE
-LDFLAGS = -lncurses
+LDFLAGS = -lncursesw
all: ${BIN}
diff --git a/irc.c b/irc.c
@@ -19,6 +19,7 @@
#include <netinet/tcp.h>
#include <netdb.h>
#include <locale.h>
+#include <wchar.h>
#undef CTRL
#define CTRL(x) (x & 037)
@@ -36,16 +37,20 @@ enum {
LineLen = 512,
MaxChans = 16,
BufSz = 2048,
- LogSz = 4096
+ LogSz = 4096,
+ UtfSz = 4,
+ RuneInvalid = 0xFFFD,
};
-struct {
+typedef unsigned int Rune;
+
+static struct {
int x;
int y;
WINDOW *sw, *mw, *iw;
} scr;
-struct Chan {
+static struct Chan {
char name[ChanLen];
char *buf, *eol;
int n; /* Scroll offset. */
@@ -54,13 +59,18 @@ struct Chan {
char new; /* New message. */
} chl[MaxChans];
-char nick[64];
-int quit, winchg;
-int sfd; /* Server file descriptor. */
-int nch, ch; /* Current number of channels, and current channel. */
-char outb[BufSz], *outp = outb; /* Output buffer. */
+static char nick[64];
+static int quit, winchg;
+static int sfd; /* Server file descriptor. */
+static int nch, ch; /* Current number of channels, and current channel. */
+static char outb[BufSz], *outp = outb; /* Output buffer. */
static FILE *logfp;
+static unsigned char utfbyte[UtfSz + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
+static unsigned char utfmask[UtfSz + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
+static Rune utfmin[UtfSz + 1] = { 0, 0, 0x80, 0x800, 0x10000};
+static Rune utfmax[UtfSz + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
+
static void scmd(char *, char *, char *, char *);
static void tdrawbar(void);
static void tredraw(void);
@@ -74,6 +84,71 @@ panic(const char *m)
exit(1);
}
+static size_t
+utf8validate(Rune *u, size_t i)
+{
+ if (*u < utfmin[i] || *u > utfmax[i] || (0xD800 <= *u && *u <= 0xDFFF))
+ *u = RuneInvalid;
+ for (i = 1; *u > utfmax[i]; ++i)
+ ;
+ return i;
+}
+
+static Rune
+utf8decodebyte(unsigned char c, size_t *i)
+{
+ for (*i = 0; *i < UtfSz + 1; ++(*i))
+ if ((c & utfmask[*i]) == utfbyte[*i])
+ return c & ~utfmask[*i];
+ return 0;
+}
+
+static size_t
+utf8decode(char *c, Rune *u, size_t clen)
+{
+ size_t i, j, len, type;
+ Rune udecoded;
+
+ *u = RuneInvalid;
+ if (!clen)
+ return 0;
+ udecoded = utf8decodebyte(c[0], &len);
+ if (len < 1 || len > UtfSz)
+ return 1;
+ for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
+ udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
+ if (type != 0)
+ return j;
+ }
+ if (j < len)
+ return 0;
+ *u = udecoded;
+ utf8validate(u, len);
+ return len;
+}
+
+static char
+utf8encodebyte(Rune u, size_t i)
+{
+ return utfbyte[i] | (u & ~utfmask[i]);
+}
+
+static size_t
+utf8encode(Rune u, char *c)
+{
+ size_t len, i;
+
+ len = utf8validate(&u, 0);
+ if (len > UtfSz)
+ return 0;
+ for (i = len - 1; i != 0; --i) {
+ c[i] = utf8encodebyte(u, 0);
+ u >>= 6;
+ }
+ c[0] = utf8encodebyte(u, len);
+ return len;
+}
+
static void
sndf(const char *fmt, ...)
{
@@ -206,10 +281,14 @@ pushl(char *p, char *e)
{
int x;
char *w;
+ Rune u;
+ cchar_t cc;
if ((w = memchr(p, '\n', e - p)))
e = w + 1;
- for (w = p, x = 0;; p++, x++) {
+ w = p;
+ x = 0;
+ for (;;) {
if (x >= scr.x) {
waddch(scr.mw, '\n');
for (x = 0; x < INDENT; x++)
@@ -219,11 +298,16 @@ pushl(char *p, char *e)
x += p - w;
}
if (p >= e || *p == ' ' || p - w + INDENT >= scr.x - 1) {
- for (; w < p; w++)
- waddch(scr.mw, *w);
+ while (w < p) {
+ w += utf8decode(w, &u, UtfSz);
+ setcchar(&cc, &u, 0, 0, 0);
+ wadd_wch(scr.mw, &cc);
+ }
if (p >= e)
return e;
}
+ p += utf8decode(p, &u, UtfSz);
+ x += wcwidth(u);
}
}
@@ -502,7 +586,6 @@ tdrawbar(void)
werase(scr.sw);
for (l = 0; fst < nch && l < scr.x; fst++) {
char *p = chl[fst].name;
-
if (fst == ch)
wattron(scr.sw, A_BOLD);
waddch(scr.sw, '['), l++;
You are viewing proxied material from vernunftzentrum.de. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.