]> git.armaanb.net Git - st.git/blobdiff - x.c
Switch to zenburn theme
[st.git] / x.c
diff --git a/x.c b/x.c
index 120e495df49c650856251a785e9716acf90d6a39..9b26b96fba538e627738e74a3415b089fd19d73e 100644 (file)
--- a/x.c
+++ b/x.c
@@ -19,6 +19,7 @@ char *argv0;
 #include "arg.h"
 #include "st.h"
 #include "win.h"
+#include "hb.h"
 
 /* types used in config.h */
 typedef struct {
@@ -156,7 +157,7 @@ static void xresize(int, int);
 static void xhints(void);
 static int xloadcolor(int, const char *, Color *);
 static int xloadfont(Font *, FcPattern *);
-static void xloadfonts(char *, double);
+static void xloadfonts(const char *, double);
 static void xunloadfont(Font *);
 static void xunloadfonts(void);
 static void xsetenv(void);
@@ -253,6 +254,7 @@ static char *opt_name  = NULL;
 static char *opt_title = NULL;
 
 static int oldbutton = 3; /* button event on startup: 3 = release */
+static int cursorblinks = 0;
 
 void
 clipcopy(const Arg *dummy)
@@ -387,7 +389,9 @@ mousereport(XEvent *e)
                        button = 3;
                } else {
                        button -= Button1;
-                       if (button >= 3)
+                       if (button >= 7)
+                               button += 128 - 7;
+                       else if (button >= 3)
                                button += 64 - 3;
                }
                if (e->xbutton.type == ButtonPress) {
@@ -950,7 +954,7 @@ xloadfont(Font *f, FcPattern *pattern)
 }
 
 void
-xloadfonts(char *fontstr, double fontsize)
+xloadfonts(const char *fontstr, double fontsize)
 {
        FcPattern *pattern;
        double fontval;
@@ -958,7 +962,7 @@ xloadfonts(char *fontstr, double fontsize)
        if (fontstr[0] == '-')
                pattern = XftXlfdParse(fontstr, False, False);
        else
-               pattern = FcNameParse((FcChar8 *)fontstr);
+               pattern = FcNameParse((const FcChar8 *)fontstr);
 
        if (!pattern)
                die("can't open font %s\n", fontstr);
@@ -1031,6 +1035,9 @@ xunloadfont(Font *f)
 void
 xunloadfonts(void)
 {
+       /* Clear Harfbuzz font cache. */
+       hbunloadfonts();
+
        /* Free the loaded fonts in the font cache.  */
        while (frclen > 0)
                XftFontClose(xw.dpy, frc[--frclen].font);
@@ -1230,7 +1237,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
                mode = glyphs[i].mode;
 
                /* Skip dummy wide-character spacing. */
-               if (mode == ATTR_WDUMMY)
+               if (mode & ATTR_WDUMMY)
                        continue;
 
                /* Determine font for glyph if different from previous glyph. */
@@ -1337,6 +1344,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
                numspecs++;
        }
 
+       /* Harfbuzz transformation for ligatures. */
+       hbtransform(specs, glyphs, len, x, y);
+
        return numspecs;
 }
 
@@ -1486,14 +1496,17 @@ xdrawglyph(Glyph g, int x, int y)
 }
 
 void
-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
+xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
 {
        Color drawcol;
 
        /* remove the old cursor */
        if (selected(ox, oy))
                og.mode ^= ATTR_REVERSE;
-       xdrawglyph(og, ox, oy);
+
+       /* Redraw the line where cursor was previously.
+        * It will restore the ligatures broken by the cursor. */
+       xdrawline(line, 0, oy, len);
 
        if (IS_SET(MODE_HIDE))
                return;
@@ -1527,16 +1540,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
        /* draw the new one */
        if (IS_SET(MODE_FOCUSED)) {
                switch (win.cursor) {
-               case 7: /* st extension */
-                       g.u = 0x2603; /* snowman (U+2603) */
+               case 0: /* Blinking block */
+               case 1: /* Blinking block (default) */
+                       if (IS_SET(MODE_BLINK))
+                               break;
                        /* FALLTHROUGH */
-               case 0: /* Blinking Block */
-               case 1: /* Blinking Block (Default) */
-               case 2: /* Steady Block */
+               case 2: /* Steady block */
                        xdrawglyph(g, cx, cy);
                        break;
-               case 3: /* Blinking Underline */
-               case 4: /* Steady Underline */
+               case 3: /* Blinking underline */
+                       if (IS_SET(MODE_BLINK))
+                               break;
+                       /* FALLTHROUGH */
+               case 4: /* Steady underline */
                        XftDrawRect(xw.draw, &drawcol,
                                        borderpx + cx * win.cw,
                                        borderpx + (cy + 1) * win.ch - \
@@ -1544,12 +1560,23 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
                                        win.cw, cursorthickness);
                        break;
                case 5: /* Blinking bar */
+                       if (IS_SET(MODE_BLINK))
+                               break;
+                       /* FALLTHROUGH */
                case 6: /* Steady bar */
                        XftDrawRect(xw.draw, &drawcol,
                                        borderpx + cx * win.cw,
                                        borderpx + cy * win.ch,
                                        cursorthickness, win.ch);
                        break;
+               case 7: /* Blinking st cursor */
+                       if (IS_SET(MODE_BLINK))
+                               break;
+                       /* FALLTHROUGH */
+               case 8: /* Steady st cursor */
+                       g.u = stcursor;
+                       xdrawglyph(g, cx, cy);
+                       break;
                }
        } else {
                XftDrawRect(xw.draw, &drawcol,
@@ -1704,9 +1731,12 @@ xsetmode(int set, unsigned int flags)
 int
 xsetcursor(int cursor)
 {
-       if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
+       if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
                return 1;
        win.cursor = cursor;
+       cursorblinks = win.cursor == 0 || win.cursor == 1 ||
+                      win.cursor == 3 || win.cursor == 5 ||
+                      win.cursor == 7;
        return 0;
 }
 
@@ -1950,6 +1980,10 @@ run(void)
                if (FD_ISSET(ttyfd, &rfd) || xev) {
                        if (!drawing) {
                                trigger = now;
+                               if (IS_SET(MODE_BLINK)) {
+                                       win.mode ^= MODE_BLINK;
+                               }
+                               lastblink = now;
                                drawing = 1;
                        }
                        timeout = (maxlatency - TIMEDIFF(now, trigger)) \
@@ -1960,7 +1994,7 @@ run(void)
 
                /* idle detected or maxlatency exhausted -> draw */
                timeout = -1;
-               if (blinktimeout && tattrset(ATTR_BLINK)) {
+               if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
                        timeout = blinktimeout - TIMEDIFF(now, lastblink);
                        if (timeout <= 0) {
                                if (-timeout > blinktimeout) /* start visible */
@@ -1996,7 +2030,7 @@ main(int argc, char *argv[])
 {
        xw.l = xw.t = 0;
        xw.isfixed = False;
-       xsetcursor(cursorshape);
+       xsetcursor(cursorstyle);
 
        ARGBEGIN {
        case 'a':