Compare commits

...

4 Commits

4 changed files with 873 additions and 379 deletions

View File

@ -265,6 +265,8 @@ static Shortcut shortcuts[] = {
{ TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} },
{ ShiftMask, XK_Insert, selpaste, {.i = 0} }, { ShiftMask, XK_Insert, selpaste, {.i = 0} },
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
}; };
/* /*

924
st.c

File diff suppressed because it is too large Load Diff

27
st.h
View File

@ -23,18 +23,20 @@
enum glyph_attribute { enum glyph_attribute {
ATTR_NULL = 0, ATTR_NULL = 0,
ATTR_BOLD = 1 << 0, ATTR_SET = 1 << 0,
ATTR_FAINT = 1 << 1, ATTR_BOLD = 1 << 1,
ATTR_ITALIC = 1 << 2, ATTR_FAINT = 1 << 2,
ATTR_UNDERLINE = 1 << 3, ATTR_ITALIC = 1 << 3,
ATTR_BLINK = 1 << 4, ATTR_UNDERLINE = 1 << 4,
ATTR_REVERSE = 1 << 5, ATTR_BLINK = 1 << 5,
ATTR_INVISIBLE = 1 << 6, ATTR_REVERSE = 1 << 6,
ATTR_STRUCK = 1 << 7, ATTR_INVISIBLE = 1 << 7,
ATTR_WRAP = 1 << 8, ATTR_STRUCK = 1 << 8,
ATTR_WIDE = 1 << 9, ATTR_WRAP = 1 << 9,
ATTR_WDUMMY = 1 << 10, ATTR_WIDE = 1 << 10,
ATTR_WDUMMY = 1 << 11,
ATTR_BOXDRAW = 1 << 11, ATTR_BOXDRAW = 1 << 11,
ATTR_SELECTED = 1 << 12,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
ATTR_DIRTYUNDERLINE = 1 << 15, ATTR_DIRTYUNDERLINE = 1 << 15,
}; };
@ -92,6 +94,8 @@ void die(const char *, ...);
void redraw(void); void redraw(void);
void draw(void); void draw(void);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void printscreen(const Arg *); void printscreen(const Arg *);
void printsel(const Arg *); void printsel(const Arg *);
void sendbreak(const Arg *); void sendbreak(const Arg *);
@ -99,6 +103,7 @@ void toggleprinter(const Arg *);
int tattrset(int); int tattrset(int);
void tnew(int, int); void tnew(int, int);
int tisaltscreen(void);
void tresize(int, int); void tresize(int, int);
void tsetdirtattr(int); void tsetdirtattr(int);
void ttyhangup(void); void ttyhangup(void);

141
x.c
View File

@ -20,6 +20,7 @@ char *argv0;
#include "arg.h" #include "arg.h"
#include "st.h" #include "st.h"
#include "win.h" #include "win.h"
#include "hb.h"
/* types used in config.h */ /* types used in config.h */
typedef struct { typedef struct {
@ -167,6 +168,7 @@ typedef struct {
} DC; } DC;
static inline ushort sixd_to_16bit(int); static inline ushort sixd_to_16bit(int);
static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
static void xdrawglyph(Glyph, int, int); static void xdrawglyph(Glyph, int, int);
@ -796,7 +798,7 @@ xresize(int col, int row)
xclear(0, 0, win.w, win.h); xclear(0, 0, win.w, win.h);
/* resize to new width */ /* resize to new width */
xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4);
} }
ushort ushort
@ -1108,6 +1110,9 @@ xunloadfont(Font *f)
void void
xunloadfonts(void) xunloadfonts(void)
{ {
/* Clear Harfbuzz font cache. */
hbunloadfonts();
/* Free the loaded fonts in the font cache. */ /* Free the loaded fonts in the font cache. */
while (frclen > 0) while (frclen > 0)
XftFontClose(xw.dpy, frc[--frclen].font); XftFontClose(xw.dpy, frc[--frclen].font);
@ -1239,7 +1244,7 @@ xinit(int cols, int rows)
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
/* font spec buffer */ /* font spec buffer */
xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4);
/* Xft rendering context */ /* Xft rendering context */
xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
@ -1293,6 +1298,22 @@ xinit(int cols, int rows)
xsel.xtarget = XA_STRING; xsel.xtarget = XA_STRING;
} }
void
xresetfontsettings(ushort mode, Font **font, int *frcflags)
{
*font = &dc.font;
if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
*font = &dc.ibfont;
*frcflags = FRC_ITALICBOLD;
} else if (mode & ATTR_ITALIC) {
*font = &dc.ifont;
*frcflags = FRC_ITALIC;
} else if (mode & ATTR_BOLD) {
*font = &dc.bfont;
*frcflags = FRC_BOLD;
}
}
int int
xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
{ {
@ -1307,49 +1328,65 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
FcPattern *fcpattern, *fontpattern; FcPattern *fcpattern, *fontpattern;
FcFontSet *fcsets[] = { NULL }; FcFontSet *fcsets[] = { NULL };
FcCharSet *fccharset; FcCharSet *fccharset;
int i, f, numspecs = 0; int i, f, length = 0, start = 0, numspecs = 0;
float cluster_xp = xp, cluster_yp = yp;
HbTransformData shaped = { 0 };
/* Initial values. */
mode = prevmode = glyphs[0].mode;
xresetfontsettings(mode, &font, &frcflags);
for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
/* Fetch rune and mode for current glyph. */
rune = glyphs[i].u;
mode = glyphs[i].mode; mode = glyphs[i].mode;
/* Skip dummy wide-character spacing. */ /* Skip dummy wide-character spacing. */
if (mode == ATTR_WDUMMY) if (mode & ATTR_WDUMMY && i < (len - 1))
continue; continue;
/* Determine font for glyph if different from previous glyph. */ if (
if (prevmode != mode) { prevmode != mode
prevmode = mode; || ATTRCMP(glyphs[start], glyphs[i])
font = &dc.font; || selected(x + i, y) != selected(x + start, y)
frcflags = FRC_NORMAL; || i == (len - 1)
runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); ) {
if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { /* Handle 1-character wide segments and end of line */
font = &dc.ibfont; length = i - start;
frcflags = FRC_ITALICBOLD; if (i == start) {
} else if (mode & ATTR_ITALIC) { length = 1;
font = &dc.ifont; } else if (i == (len - 1)) {
frcflags = FRC_ITALIC; length = (i - start + 1);
} else if (mode & ATTR_BOLD) {
font = &dc.bfont;
frcflags = FRC_BOLD;
}
yp = winy + font->ascent;
} }
/* Lookup character index with default font. */ /* Shape the segment. */
glyphidx = XftCharIndex(xw.dpy, font->match, rune); hbtransform(&shaped, font->match, glyphs, start, length);
if (glyphidx) { runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f);
specs[numspecs].font = font->match; cluster_xp = xp; cluster_yp = yp;
specs[numspecs].glyph = glyphidx; for (int code_idx = 0; code_idx < shaped.count; code_idx++) {
specs[numspecs].x = (short)xp; int idx = shaped.glyphs[code_idx].cluster;
specs[numspecs].y = (short)yp;
if (glyphs[start + idx].mode & ATTR_WDUMMY)
continue;
/* Advance the drawing cursor if we've moved to a new cluster */
if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) {
xp += runewidth; xp += runewidth;
numspecs++; cluster_xp = xp;
continue; cluster_yp = yp;
runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f);
} }
/* Fallback on font cache, search the font cache for match. */ if (shaped.glyphs[code_idx].codepoint != 0) {
/* If symbol is found, put it into the specs. */
specs[numspecs].font = font->match;
specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint;
specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.);
specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.);
cluster_xp += shaped.positions[code_idx].x_advance / 64.;
cluster_yp += shaped.positions[code_idx].y_advance / 64.;
numspecs++;
} else {
/* If it's not found, try to fetch it through the font cache. */
rune = glyphs[start + idx].u;
for (f = 0; f < frclen; f++) { for (f = 0; f < frclen; f++) {
glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
/* Everything correct. */ /* Everything correct. */
@ -1418,9 +1455,22 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
specs[numspecs].glyph = glyphidx; specs[numspecs].glyph = glyphidx;
specs[numspecs].x = (short)xp; specs[numspecs].x = (short)xp;
specs[numspecs].y = (short)yp; specs[numspecs].y = (short)yp;
xp += runewidth;
numspecs++; numspecs++;
} }
}
/* Cleanup and get ready for next segment. */
hbcleanup(&shaped);
start = i;
/* Determine font for glyph if different from previous glyph. */
if (prevmode != mode) {
prevmode = mode;
xresetfontsettings(mode, &font, &frcflags);
yp = winy + font->ascent;
}
}
}
return numspecs; return numspecs;
} }
@ -1962,7 +2012,7 @@ xdrawglyph(Glyph g, int x, int y)
} }
void 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; Color drawcol;
XRenderColor colbg; XRenderColor colbg;
@ -1970,7 +2020,10 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
/* remove the old cursor */ /* remove the old cursor */
if (selected(ox, oy)) if (selected(ox, oy))
og.mode ^= ATTR_REVERSE; 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)) if (IS_SET(MODE_HIDE))
return; return;
@ -2110,18 +2163,16 @@ xdrawline(Line line, int x1, int y1, int x2)
Glyph base, new; Glyph base, new;
XftGlyphFontSpec *specs = xw.specbuf; XftGlyphFontSpec *specs = xw.specbuf;
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
i = ox = 0; i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) { for (x = x1; x < x2; x++) {
new = line[x]; new = line[x];
if (new.mode == ATTR_WDUMMY) if (new.mode == ATTR_WDUMMY)
continue; continue;
if (selected(x, y1)) if (selected(x, y1))
new.mode ^= ATTR_REVERSE; new.mode ^= ATTR_REVERSE;
if (i > 0 && ATTRCMP(base, new)) { if ((i > 0) && ATTRCMP(base, new)) {
xdrawglyphfontspecs(specs, base, i, ox, y1); numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1);
specs += i; xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
numspecs -= i;
i = 0; i = 0;
} }
if (i == 0) { if (i == 0) {
@ -2130,8 +2181,10 @@ xdrawline(Line line, int x1, int y1, int x2)
} }
i++; i++;
} }
if (i > 0) if (i > 0) {
xdrawglyphfontspecs(specs, base, i, ox, y1); numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1);
xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
}
} }
void void