JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Reload colors in reset
[st.git] / st.c
diff --git a/st.c b/st.c
index 96111a0..362de23 100644 (file)
--- a/st.c
+++ b/st.c
@@ -77,6 +77,13 @@ char *argv0;
 #define IS_SET(flag) ((term.mode & (flag)) != 0)
 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000)
 
+#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
+#define IS_TRUECOL(x)    (1 << 24 & (x))
+#define TRUERED(x)       (((x) & 0xff0000) >> 8)
+#define TRUEGREEN(x)     (((x) & 0xff00))
+#define TRUEBLUE(x)      (((x) & 0xff) << 8)
+
+
 #define VT102ID "\033[?6c"
 
 enum glyph_attribute {
@@ -98,37 +105,37 @@ enum cursor_movement {
 enum cursor_state {
        CURSOR_DEFAULT  = 0,
        CURSOR_WRAPNEXT = 1,
-       CURSOR_ORIGIN   = 2
+       CURSOR_ORIGIN   = 2
 };
 
 enum term_mode {
-       MODE_WRAP        = 1,
+       MODE_WRAP        = 1,
        MODE_INSERT      = 2,
        MODE_APPKEYPAD   = 4,
        MODE_ALTSCREEN   = 8,
-       MODE_CRLF        = 16,
+       MODE_CRLF        = 16,
        MODE_MOUSEBTN    = 32,
        MODE_MOUSEMOTION = 64,
        MODE_REVERSE     = 128,
        MODE_KBDLOCK     = 256,
-       MODE_HIDE        = 512,
-       MODE_ECHO        = 1024,
-       MODE_APPCURSOR   = 2048,
+       MODE_HIDE        = 512,
+       MODE_ECHO        = 1024,
+       MODE_APPCURSOR   = 2048,
        MODE_MOUSESGR    = 4096,
-       MODE_8BIT        = 8192,
-       MODE_BLINK       = 16384,
-       MODE_FBLINK      = 32768,
-       MODE_FOCUS       = 65536,
-       MODE_MOUSEX10    = 131072,
+       MODE_8BIT        = 8192,
+       MODE_BLINK       = 16384,
+       MODE_FBLINK      = 32768,
+       MODE_FOCUS       = 65536,
+       MODE_MOUSEX10    = 131072,
        MODE_MOUSEMANY   = 262144,
        MODE_MOUSE       = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
-                          |MODE_MOUSEMANY,
+                         |MODE_MOUSEMANY,
 };
 
 enum escape_state {
        ESC_START      = 1,
-       ESC_CSI = 2,
-       ESC_STR = 4, /* DSC, OSC, PM, APC */
+       ESC_CSI        = 2,
+       ESC_STR        = 4,  /* DSC, OSC, PM, APC */
        ESC_ALTCHARSET = 8,
        ESC_STR_END    = 16, /* a final string was encountered */
        ESC_TEST       = 32, /* Enter in test mode */
@@ -150,26 +157,22 @@ enum selection_snap {
        SNAP_LINE = 2
 };
 
-/* bit macro */
-#undef B0
-enum { B0=1, B1=2, B2=4, B3=8, B4=16, B5=32, B6=64, B7=128 };
-
 typedef unsigned char uchar;
 typedef unsigned int uint;
 typedef unsigned long ulong;
 typedef unsigned short ushort;
 
 typedef struct {
-       char c[UTF_SIZ];     /* character code */
-       uchar mode;  /* attribute flags */
-       ushort fg;   /* foreground  */
-       ushort bg;   /* background  */
+       char c[UTF_SIZ]; /* character code */
+       uchar mode;      /* attribute flags */
+       ulong fg;        /* foreground  */
+       ulong bg;        /* background  */
 } Glyph;
 
 typedef Glyph *Line;
 
 typedef struct {
-       Glyph attr;      /* current char attributes */
+       Glyph attr; /* current char attributes */
        int x;
        int y;
        char state;
@@ -179,36 +182,36 @@ typedef struct {
 /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
 typedef struct {
        char buf[ESC_BUF_SIZ]; /* raw string */
-       int len;               /* raw string length */
+       int len;               /* raw string length */
        char priv;
        int arg[ESC_ARG_SIZ];
-       int narg;              /* nb of args */
+       int narg;              /* nb of args */
        char mode;
 } CSIEscape;
 
 /* STR Escape sequence structs */
 /* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */
 typedef struct {
-       char type;           /* ESC type ... */
+       char type;             /* ESC type ... */
        char buf[STR_BUF_SIZ]; /* raw string */
-       int len;               /* raw string length */
+       int len;               /* raw string length */
        char *args[STR_ARG_SIZ];
-       int narg;             /* nb of args */
+       int narg;              /* nb of args */
 } STREscape;
 
 /* Internal representation of the screen */
 typedef struct {
-       int row;        /* nb row */
-       int col;        /* nb col */
-       Line *line;     /* screen */
-       Line *alt;      /* alternate screen */
-       bool *dirty;    /* dirtyness of lines */
-       TCursor c;      /* cursor */
-       int top;        /* top    scroll limit */
-       int bot;        /* bottom scroll limit */
-       int mode;       /* terminal mode flags */
-       int esc;        /* escape state flags */
-       bool numlock;   /* lock numbers in keyboard */
+       int row;      /* nb row */
+       int col;      /* nb col */
+       Line *line;   /* screen */
+       Line *alt;    /* alternate screen */
+       bool *dirty;  /* dirtyness of lines */
+       TCursor c;    /* cursor */
+       int top;      /* top    scroll limit */
+       int bot;      /* bottom scroll limit */
+       int mode;     /* terminal mode flags */
+       int esc;      /* escape state flags */
+       bool numlock; /* lock numbers in keyboard */
        bool *tabs;
 } Term;
 
@@ -245,9 +248,9 @@ typedef struct {
        uint mask;
        char s[ESC_BUF_SIZ];
        /* three valued logic variables: 0 indifferent, 1 on, -1 off */
-       signed char appkey;             /* application keypad */
-       signed char appcursor;          /* application cursor */
-       signed char crlf;               /* crlf mode          */
+       signed char appkey;    /* application keypad */
+       signed char appcursor; /* application cursor */
+       signed char crlf;      /* crlf mode          */
 } Key;
 
 typedef struct {
@@ -358,7 +361,7 @@ static void tsetdirtattr(int);
 static void tsetmode(bool, bool, int *, int);
 static void tfulldirt(void);
 static void techo(char *, int);
-
+static ulong tdefcolor(int *, int *, int);
 static inline bool match(uint, uint);
 static void ttynew(void);
 static void ttyread(void);
@@ -466,17 +469,12 @@ enum {
 
 typedef struct {
        XftFont *font;
-       long c;
        int flags;
 } Fontcache;
 
-/*
- * Fontcache is a ring buffer, with frccur as current position and frclen as
- * the current length of used elements.
- */
-
-static Fontcache frc[1024];
-static int frccur = -1, frclen = 0;
+/* Fontcache is an array now. A new font will be appended to the array. */
+static Fontcache frc[16];
+static int frclen = 0;
 
 ssize_t
 xwrite(int fd, char *s, size_t len) {
@@ -527,17 +525,17 @@ utf8decode(char *s, long *u) {
 
        rtn = 1;
        c = *s;
-       if(~c & B7) { /* 0xxxxxxx */
+       if(~c & 0x80) { /* 0xxxxxxx */
                *u = c;
                return rtn;
-       } else if((c & (B7|B6|B5)) == (B7|B6)) { /* 110xxxxx */
-               *u = c&(B4|B3|B2|B1|B0);
+       } else if((c & 0xE0) == 0xC0) { /* 110xxxxx */
+               *u = c & 0x1F;
                n = 1;
-       } else if((c & (B7|B6|B5|B4)) == (B7|B6|B5)) { /* 1110xxxx */
-               *u = c&(B3|B2|B1|B0);
+       } else if((c & 0xF0) == 0xE0) { /* 1110xxxx */
+               *u = c & 0x0F;
                n = 2;
-       } else if((c & (B7|B6|B5|B4|B3)) == (B7|B6|B5|B4)) { /* 11110xxx */
-               *u = c & (B2|B1|B0);
+       } else if((c & 0xF8) == 0xF0) { /* 11110xxx */
+               *u = c & 0x07;
                n = 3;
        } else {
                goto invalid;
@@ -545,10 +543,10 @@ utf8decode(char *s, long *u) {
 
        for(i = n, ++s; i > 0; --i, ++rtn, ++s) {
                c = *s;
-               if((c & (B7|B6)) != B7) /* 10xxxxxx */
+               if((c & 0xC0) != 0x80) /* 10xxxxxx */
                        goto invalid;
                *u <<= 6;
-               *u |= c & (B5|B4|B3|B2|B1|B0);
+               *u |= c & 0x3F;
        }
 
        if((n == 1 && *u < 0x80) ||
@@ -577,20 +575,20 @@ utf8encode(long *u, char *s) {
                *sp = uc; /* 0xxxxxxx */
                return 1;
        } else if(*u < 0x800) {
-               *sp = (uc >> 6) | (B7|B6); /* 110xxxxx */
+               *sp = (uc >> 6) | 0xC0; /* 110xxxxx */
                n = 1;
        } else if(uc < 0x10000) {
-               *sp = (uc >> 12) | (B7|B6|B5); /* 1110xxxx */
+               *sp = (uc >> 12) | 0xE0; /* 1110xxxx */
                n = 2;
        } else if(uc <= 0x10FFFF) {
-               *sp = (uc >> 18) | (B7|B6|B5|B4); /* 11110xxx */
+               *sp = (uc >> 18) | 0xF0; /* 11110xxx */
                n = 3;
        } else {
                goto invalid;
        }
 
        for(i=n,++sp; i>0; --i,++sp)
-               *sp = ((uc >> 6*(i-1)) & (B5|B4|B3|B2|B1|B0)) | B7; /* 10xxxxxx */
+               *sp = ((uc >> 6*(i-1)) & 0x3F) | 0x80; /* 10xxxxxx */
 
        return n+1;
 invalid:
@@ -613,16 +611,16 @@ isfullutf8(char *s, int b) {
        c3 = (uchar *)++s;
        if(b < 1) {
                return 0;
-       } else if((*c1&(B7|B6|B5)) == (B7|B6) && b == 1) {
+       } else if((*c1 & 0xE0) == 0xC0 && b == 1) {
                return 0;
-       } else if((*c1&(B7|B6|B5|B4)) == (B7|B6|B5) &&
+       } else if((*c1 & 0xF0) == 0xE0 &&
            ((b == 1) ||
-           ((b == 2) && (*c2&(B7|B6)) == B7))) {
+           ((b == 2) && (*c2 & 0xC0) == 0x80))) {
                return 0;
-       } else if((*c1&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4) &&
+       } else if((*c1 & 0xF8) == 0xF0 &&
            ((b == 1) ||
-           ((b == 2) && (*c2&(B7|B6)) == B7) ||
-           ((b == 3) && (*c2&(B7|B6)) == B7 && (*c3&(B7|B6)) == B7))) {
+           ((b == 2) && (*c2 & 0xC0) == 0x80) ||
+           ((b == 3) && (*c2 & 0xC0) == 0x80 && (*c3 & 0xC0) == 0x80))) {
                return 0;
        } else {
                return 1;
@@ -633,11 +631,11 @@ int
 utf8size(char *s) {
        uchar c = *s;
 
-       if(~c&B7) {
+       if(~c & 0x80) {
                return 1;
-       } else if((c&(B7|B6|B5)) == (B7|B6)) {
+       } else if((c & 0xE0) == 0xC0) {
                return 2;
-       } else if((c&(B7|B6|B5|B4)) == (B7|B6|B5)) {
+       } else if((c & 0xF0) == 0xE0) {
                return 3;
        } else {
                return 4;
@@ -916,7 +914,6 @@ bpress(XEvent *e) {
                if(sel.snap != 0) {
                        sel.mode++;
                        tsetdirt(sel.nb.y, sel.ne.y);
-                       draw();
                }
                sel.tclick2 = sel.tclick1;
                sel.tclick1 = now;
@@ -1187,7 +1184,7 @@ sigchld(int a) {
        int stat = 0;
 
        if(waitpid(pid, &stat, 0) < 0)
-               die("Waiting for pid %hd failed: %s\n", pid, SERRNO);
+               die("Waiting for pid %hd failed: %s\n", pid, SERRNO);
 
        if(WIFEXITED(stat)) {
                exit(WEXITSTATUS(stat));
@@ -1628,9 +1625,58 @@ tdeleteline(int n) {
        tscrollup(term.c.y, n);
 }
 
+ulong
+tdefcolor(int *attr, int *npar, int l) {
+       long idx = -1;
+       uint r, g, b;
+
+       switch (attr[*npar + 1]) {
+       case 2: /* direct colour in RGB space */
+               if (*npar + 4 >= l) {
+                       fprintf(stderr,
+                               "erresc(38): Incorrect number of parameters (%d)\n",
+                               *npar);
+                       break;
+               }
+               r = attr[*npar + 2];
+               g = attr[*npar + 3];
+               b = attr[*npar + 4];
+               *npar += 4;
+               if(!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255))
+                       fprintf(stderr, "erresc: bad rgb color (%d,%d,%d)\n",
+                               r, g, b);
+               else
+                       idx = TRUECOLOR(r, g, b);
+               break;
+       case 5: /* indexed colour */
+               if (*npar + 2 >= l) {
+                       fprintf(stderr,
+                               "erresc(38): Incorrect number of parameters (%d)\n",
+                               *npar);
+                       break;
+               }
+               *npar += 2;
+               if(!BETWEEN(attr[*npar], 0, 255))
+                       fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]);
+               else
+                       idx = attr[*npar];
+               break;
+       case 0: /* implemented defined (only foreground) */
+       case 1: /* transparent */
+       case 3: /* direct colour in CMY space */
+       case 4: /* direct colour in CMYK space */
+       default:
+               fprintf(stderr,
+                       "erresc(38): gfx attr %d unknown\n", attr[*npar]);
+       }
+
+       return idx;
+}
+
 void
 tsetattr(int *attr, int l) {
        int i;
+       ulong idx;
 
        for(i = 0; i < l; i++) {
                switch(attr[i]) {
@@ -1675,39 +1721,15 @@ tsetattr(int *attr, int l) {
                        term.c.attr.mode &= ~ATTR_REVERSE;
                        break;
                case 38:
-                       if(i + 2 < l && attr[i + 1] == 5) {
-                               i += 2;
-                               if(BETWEEN(attr[i], 0, 255)) {
-                                       term.c.attr.fg = attr[i];
-                               } else {
-                                       fprintf(stderr,
-                                               "erresc: bad fgcolor %d\n",
-                                               attr[i]);
-                               }
-                       } else {
-                               fprintf(stderr,
-                                       "erresc(38): gfx attr %d unknown\n",
-                                       attr[i]);
-                       }
+                       if ((idx = tdefcolor(attr, &i, l)) >= 0)
+                               term.c.attr.fg = idx;
                        break;
                case 39:
                        term.c.attr.fg = defaultfg;
                        break;
                case 48:
-                       if(i + 2 < l && attr[i + 1] == 5) {
-                               i += 2;
-                               if(BETWEEN(attr[i], 0, 255)) {
-                                       term.c.attr.bg = attr[i];
-                               } else {
-                                       fprintf(stderr,
-                                               "erresc: bad bgcolor %d\n",
-                                               attr[i]);
-                               }
-                       } else {
-                               fprintf(stderr,
-                                       "erresc(48): gfx attr %d unknown\n",
-                                       attr[i]);
-                       }
+                       if ((idx = tdefcolor(attr, &i, l)) >= 0)
+                               term.c.attr.bg = idx;
                        break;
                case 49:
                        term.c.attr.bg = defaultbg;
@@ -1826,7 +1848,7 @@ tsetmode(bool priv, bool set, int *args, int narg) {
                                        tclearregion(0, 0, term.col-1,
                                                        term.row-1);
                                }
-                               if(set ^ alt)           /* set is always 1 or 0 */
+                               if(set ^ alt) /* set is always 1 or 0 */
                                        tswapscreen();
                                if(*args != 1049)
                                        break;
@@ -2189,10 +2211,10 @@ techo(char *buf, int len) {
        for(; len > 0; buf++, len--) {
                char c = *buf;
 
-               if(c == '\033') {               /* escape */
+               if(c == '\033') { /* escape */
                        tputc("^", 1);
                        tputc("[", 1);
-               } else if(c < '\x20') { /* control code */
+               } else if(c < '\x20') { /* control code */
                        if(c != '\n' && c != '\r' && c != '\t') {
                                c |= '\x40';
                                tputc("^", 1);
@@ -2263,31 +2285,31 @@ tputc(char *c, int len) {
         */
        if(control) {
                switch(ascii) {
-               case '\t':      /* HT */
+               case '\t':   /* HT */
                        tputtab(1);
                        return;
-               case '\b':      /* BS */
+               case '\b':   /* BS */
                        tmoveto(term.c.x-1, term.c.y);
                        return;
-               case '\r':      /* CR */
+               case '\r':   /* CR */
                        tmoveto(0, term.c.y);
                        return;
-               case '\f':      /* LF */
-               case '\v':      /* VT */
-               case '\n':      /* LF */
+               case '\f':   /* LF */
+               case '\v':   /* VT */
+               case '\n':   /* LF */
                        /* go to first col if the mode is set */
                        tnewline(IS_SET(MODE_CRLF));
                        return;
-               case '\a':      /* BEL */
+               case '\a':   /* BEL */
                        if(!(xw.state & WIN_FOCUSED))
                                xseturgency(1);
                        return;
-               case '\033':    /* ESC */
+               case '\033': /* ESC */
                        csireset();
                        term.esc = ESC_START;
                        return;
-               case '\016':    /* SO */
-               case '\017':    /* SI */
+               case '\016': /* SO */
+               case '\017': /* SI */
                        /*
                         * Different charsets are hard to handle. Applications
                         * should use the right alt charset escapes for the
@@ -2295,15 +2317,15 @@ tputc(char *c, int len) {
                         * rest is incompatible history st should not support.
                         */
                        return;
-               case '\032':    /* SUB */
-               case '\030':    /* CAN */
+               case '\032': /* SUB */
+               case '\030': /* CAN */
                        csireset();
                        return;
-               case '\005':    /* ENQ (IGNORED) */
-               case '\000':    /* NUL (IGNORED) */
-               case '\021':    /* XON (IGNORED) */
-               case '\023':    /* XOFF (IGNORED) */
-               case 0177:      /* DEL (IGNORED) */
+               case '\005': /* ENQ (IGNORED) */
+               case '\000': /* NUL (IGNORED) */
+               case '\021': /* XON (IGNORED) */
+               case '\023': /* XOFF (IGNORED) */
+               case 0177:   /* DEL (IGNORED) */
                        return;
                }
        } else if(term.esc & ESC_START) {
@@ -2406,6 +2428,7 @@ tputc(char *c, int len) {
                                treset();
                                term.esc = 0;
                                xresettitle();
+                               xloadcols();
                                break;
                        case '=': /* DECPAM -- Application keypad */
                                term.mode |= MODE_APPKEYPAD;
@@ -2567,6 +2590,13 @@ void
 xloadcols(void) {
        int i, r, g, b;
        XRenderColor color = { .alpha = 0xffff };
+       static bool loaded;
+       Colour *cp;
+
+       if(loaded) {
+               for (cp = dc.col; cp < dc.col + LEN(dc.col); ++cp)
+                       XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
+       }
 
        /* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */
        for(i = 0; i < LEN(colorname); i++) {
@@ -2599,6 +2629,7 @@ xloadcols(void) {
                        die("Could not allocate color %d\n", i);
                }
        }
+       loaded = true;
 }
 
 int
@@ -2786,18 +2817,12 @@ xunloadfont(Font *f) {
 
 void
 xunloadfonts(void) {
-       int i, ip;
+       int i;
 
-       /*
-        * Free the loaded fonts in the font cache. This is done backwards
-        * from the frccur.
-        */
-       for(i = 0, ip = frccur; i < frclen; i++, ip--) {
-               if(ip < 0)
-                       ip = LEN(frc) - 1;
-               XftFontClose(xw.dpy, frc[ip].font);
+       /* Free the loaded fonts in the font cache.  */
+       for(i = 0; i < frclen; i++) {
+               XftFontClose(xw.dpy, frc[i].font);
        }
-       frccur = -1;
        frclen = 0;
 
        xunloadfont(&dc.font);
@@ -2923,7 +2948,7 @@ void
 xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
        int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
            width = charlen * xw.cw, xp, i;
-       int frp, frcflags;
+       int frcflags;
        int u8fl, u8fblen, u8cblen, doesexist;
        char *u8c, *u8fs;
        long u8char;
@@ -2932,7 +2957,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
-       Colour *fg, *bg, *temp, revfg, revbg;
+       Colour *fg, *bg, *temp, revfg, revbg, truefg, truebg;
        XRenderColor colfg, colbg;
        Rectangle r;
 
@@ -2952,8 +2977,27 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                if(base.fg == defaultfg)
                        base.fg = defaultunderline;
        }
-       fg = &dc.col[base.fg];
-       bg = &dc.col[base.bg];
+       if(IS_TRUECOL(base.fg)) {
+               colfg.red = TRUERED(base.fg);
+               colfg.green = TRUEGREEN(base.fg);
+               colfg.blue = TRUEBLUE(base.fg);
+               XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg);
+               fg = &truefg;
+       } else {
+               fg = &dc.col[base.fg];
+       }
+
+       if(IS_TRUECOL(base.bg)) {
+               colbg.green = TRUEGREEN(base.bg);
+               colbg.red = TRUERED(base.bg);
+               colbg.blue = TRUEBLUE(base.bg);
+               XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg);
+               bg = &truebg;
+       } else {
+               bg = &dc.col[base.bg];
+       }
+
+
 
        if(base.mode & ATTR_BOLD) {
                if(BETWEEN(base.fg, 0, 7)) {
@@ -2968,9 +3012,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                }
                /*
                 * Those ranges will not be brightened:
-                *      8 - 15 – bright system colors
-                *      196 - 231 – highest 256 color cube
-                *      252 - 255 – brightest colors in greyscale
+                *    8 - 15 – bright system colors
+                *    196 - 231 – highest 256 color cube
+                *    252 - 255 – brightest colors in greyscale
                 */
                font = &dc.bfont;
                frcflags = FRC_BOLD;
@@ -3049,7 +3093,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                        s += u8cblen;
                        bytelen -= u8cblen;
 
-                       doesexist = XftCharIndex(xw.dpy, font->match, u8char);
+                       doesexist = XftCharExists(xw.dpy, font->match, u8char);
                        if(!doesexist || bytelen <= 0) {
                                if(bytelen <= 0) {
                                        if(doesexist) {
@@ -3076,14 +3120,10 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                if(doesexist)
                        break;
 
-               frp = frccur;
                /* Search the font cache. */
-               for(i = 0; i < frclen; i++, frp--) {
-                       if(frp <= 0)
-                               frp = LEN(frc) - 1;
-
-                       if(frc[frp].c == u8char
-                                       && frc[frp].flags == frcflags) {
+               for(i = 0; i < frclen; i++) {
+                       if(XftCharExists(xw.dpy, frc[i].font, u8char)
+                                       && frc[i].flags == frcflags) {
                                break;
                        }
                }
@@ -3118,28 +3158,24 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
                        /*
                         * Overwrite or create the new cache entry.
                         */
-                       frccur++;
-                       frclen++;
-                       if(frccur >= LEN(frc))
-                               frccur = 0;
-                       if(frclen > LEN(frc)) {
-                               frclen = LEN(frc);
-                               XftFontClose(xw.dpy, frc[frccur].font);
+                       if(frclen >= LEN(frc)) {
+                               frclen = LEN(frc) - 1;
+                               XftFontClose(xw.dpy, frc[frclen].font);
                        }
 
-                       frc[frccur].font = XftFontOpenPattern(xw.dpy,
+                       frc[frclen].font = XftFontOpenPattern(xw.dpy,
                                        fontpattern);
-                       frc[frccur].c = u8char;
-                       frc[frccur].flags = frcflags;
+                       frc[frclen].flags = frcflags;
+
+                       i = frclen;
+                       frclen++;
 
                        FcPatternDestroy(fcpattern);
                        FcCharSetDestroy(fccharset);
-
-                       frp = frccur;
                }
 
-               XftDrawStringUtf8(xw.draw, fg, frc[frp].font,
-                               xp, winy + frc[frp].font->ascent,
+               XftDrawStringUtf8(xw.draw, fg, frc[i].font,
+                               xp, winy + frc[i].font->ascent,
                                (FcChar8 *)u8c, u8cblen);
 
                xp += font->width;
@@ -3356,17 +3392,17 @@ focus(XEvent *ev) {
        }
 }
 
-inline bool
+static inline bool
 match(uint mask, uint state) {
-       state &= ~(ignoremod);
+       state &= ~ignoremod;
 
        if(mask == XK_NO_MOD && state)
                return false;
        if(mask != XK_ANY_MOD && mask != XK_NO_MOD && !state)
                return false;
-       if((state & mask) != state)
-               return false;
-       return true;
+       if(mask == XK_ANY_MOD)
+               return true;
+       return state == mask;
 }
 
 void
@@ -3376,7 +3412,6 @@ numlock(const Arg *dummy) {
 
 char*
 kmap(KeySym k, uint state) {
-       uint mask;
        Key *kp;
        int i;
 
@@ -3391,12 +3426,10 @@ kmap(KeySym k, uint state) {
        }
 
        for(kp = key; kp < key + LEN(key); kp++) {
-               mask = kp->mask;
-
                if(kp->k != k)
                        continue;
 
-               if(!match(mask, state))
+               if(!match(kp->mask, state))
                        continue;
 
                if(kp->appkey > 0) {
@@ -3460,7 +3493,7 @@ kpress(XEvent *ev) {
                if(len == 1 && e->state & Mod1Mask) {
                        if(IS_SET(MODE_8BIT)) {
                                if(*xstr < 0177) {
-                                       c = *xstr | B7;
+                                       c = *xstr | 0x80;
                                        ret = utf8encode(&c, cp);
                                        cp += ret;
                                        len = 0;
@@ -3528,10 +3561,28 @@ resize(XEvent *e) {
 void
 run(void) {
        XEvent ev;
+       int w = xw.w, h = xw.h;
        fd_set rfd;
        int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
        struct timeval drawtimeout, *tv = NULL, now, last, lastblink;
 
+       /* Waiting for window mapping */
+       while(1) {
+               XNextEvent(xw.dpy, &ev);
+               if(ev.type == ConfigureNotify) {
+                       w = ev.xconfigure.width;
+                       h = ev.xconfigure.height;
+               } else if(ev.type == MapNotify) {
+                       break;
+               }
+       }
+
+       if(!xw.isfixed)
+               cresize(w, h);
+       else
+               cresize(xw.fw, xw.fh);
+       ttynew();
+
        gettimeofday(&lastblink, NULL);
        gettimeofday(&last, NULL);
 
@@ -3681,10 +3732,7 @@ run:
        XSetLocaleModifiers("");
        tnew(80, 24);
        xinit();
-       ttynew();
        selinit();
-       if(xw.isfixed)
-               cresize(xw.h, xw.w);
        run();
 
        return 0;