Compare commits

..

No commits in common. "0fb63d30a36dde89f48aa6a2b3dc808fef3669f1" and "b9f99cf7f1e0a0c3c2551b26ca2d8ddd0379b315" have entirely different histories.

4 changed files with 379 additions and 873 deletions

View File

@ -265,8 +265,6 @@ 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} },
}; };
/* /*

920
st.c

File diff suppressed because it is too large Load Diff

27
st.h
View File

@ -23,20 +23,18 @@
enum glyph_attribute { enum glyph_attribute {
ATTR_NULL = 0, ATTR_NULL = 0,
ATTR_SET = 1 << 0, ATTR_BOLD = 1 << 0,
ATTR_BOLD = 1 << 1, ATTR_FAINT = 1 << 1,
ATTR_FAINT = 1 << 2, ATTR_ITALIC = 1 << 2,
ATTR_ITALIC = 1 << 3, ATTR_UNDERLINE = 1 << 3,
ATTR_UNDERLINE = 1 << 4, ATTR_BLINK = 1 << 4,
ATTR_BLINK = 1 << 5, ATTR_REVERSE = 1 << 5,
ATTR_REVERSE = 1 << 6, ATTR_INVISIBLE = 1 << 6,
ATTR_INVISIBLE = 1 << 7, ATTR_STRUCK = 1 << 7,
ATTR_STRUCK = 1 << 8, ATTR_WRAP = 1 << 8,
ATTR_WRAP = 1 << 9, ATTR_WIDE = 1 << 9,
ATTR_WIDE = 1 << 10, ATTR_WDUMMY = 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,
}; };
@ -94,8 +92,6 @@ 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 *);
@ -103,7 +99,6 @@ 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);

143
x.c
View File

@ -20,7 +20,6 @@ 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 {
@ -168,7 +167,6 @@ 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);
@ -798,7 +796,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) * 4); xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
} }
ushort ushort
@ -1110,9 +1108,6 @@ 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);
@ -1244,7 +1239,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) * 4); xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
/* 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);
@ -1298,22 +1293,6 @@ 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)
{ {
@ -1328,65 +1307,49 @@ 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, length = 0, start = 0, numspecs = 0; int i, f, 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 && i < (len - 1)) if (mode == ATTR_WDUMMY)
continue; continue;
if ( /* Determine font for glyph if different from previous glyph. */
prevmode != mode if (prevmode != mode) {
|| ATTRCMP(glyphs[start], glyphs[i]) prevmode = mode;
|| selected(x + i, y) != selected(x + start, y) font = &dc.font;
|| i == (len - 1) frcflags = FRC_NORMAL;
) { runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f);
/* Handle 1-character wide segments and end of line */ if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
length = i - start; font = &dc.ibfont;
if (i == start) { frcflags = FRC_ITALICBOLD;
length = 1; } else if (mode & ATTR_ITALIC) {
} else if (i == (len - 1)) { font = &dc.ifont;
length = (i - start + 1); frcflags = FRC_ITALIC;
} else if (mode & ATTR_BOLD) {
font = &dc.bfont;
frcflags = FRC_BOLD;
}
yp = winy + font->ascent;
} }
/* Shape the segment. */ /* Lookup character index with default font. */
hbtransform(&shaped, font->match, glyphs, start, length); glyphidx = XftCharIndex(xw.dpy, font->match, rune);
runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f); if (glyphidx) {
cluster_xp = xp; cluster_yp = yp;
for (int code_idx = 0; code_idx < shaped.count; code_idx++) {
int idx = shaped.glyphs[code_idx].cluster;
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;
cluster_xp = xp;
cluster_yp = yp;
runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f);
}
if (shaped.glyphs[code_idx].codepoint != 0) {
/* If symbol is found, put it into the specs. */
specs[numspecs].font = font->match; specs[numspecs].font = font->match;
specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; specs[numspecs].glyph = glyphidx;
specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.); specs[numspecs].x = (short)xp;
specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.); specs[numspecs].y = (short)yp;
cluster_xp += shaped.positions[code_idx].x_advance / 64.; xp += runewidth;
cluster_yp += shaped.positions[code_idx].y_advance / 64.;
numspecs++; numspecs++;
} else { continue;
/* If it's not found, try to fetch it through the font cache. */ }
rune = glyphs[start + idx].u;
/* Fallback on font cache, search the font cache for match. */
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. */
@ -1455,22 +1418,9 @@ 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;
} }
@ -2012,7 +1962,7 @@ xdrawglyph(Glyph g, int x, int y)
} }
void void
xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
{ {
Color drawcol; Color drawcol;
XRenderColor colbg; XRenderColor colbg;
@ -2020,10 +1970,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
/* 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;
@ -2163,16 +2110,18 @@ 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; x++) { for (x = x1; x < x2 && i < numspecs; 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)) {
numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); xdrawglyphfontspecs(specs, base, i, ox, y1);
xdrawglyphfontspecs(specs, base, numspecs, ox, y1); specs += i;
numspecs -= i;
i = 0; i = 0;
} }
if (i == 0) { if (i == 0) {
@ -2181,10 +2130,8 @@ xdrawline(Line line, int x1, int y1, int x2)
} }
i++; i++;
} }
if (i > 0) { if (i > 0)
numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); xdrawglyphfontspecs(specs, base, i, ox, y1);
xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
}
} }
void void