Archived
0
0
Fork 0

update st

This commit is contained in:
Daryl Ronningen 2023-05-06 23:20:03 -07:00
parent 9973cc2bdd
commit 50a72324cd
Signed by: Daryl Ronningen
GPG key ID: FD23F0C934A5EC6B
7 changed files with 193 additions and 183 deletions

84
hb.c
View file

@ -8,10 +8,10 @@
#include <hb-ft.h> #include <hb-ft.h>
#include "st.h" #include "st.h"
#include "hb.h"
#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } #define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END }
void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length);
hb_font_t *hbfindfont(XftFont *match); hb_font_t *hbfindfont(XftFont *match);
typedef struct { typedef struct {
@ -27,7 +27,7 @@ static HbFontMatch *hbfontcache = NULL;
* e. g. * e. g.
* FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
*/ */
hb_feature_t features[] = { }; hb_feature_t features[] = { 0 };
void void
hbunloadfonts() hbunloadfonts()
@ -66,70 +66,23 @@ hbfindfont(XftFont *match)
return font; return font;
} }
void void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) {
hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y) Rune rune;
{ ushort mode = USHRT_MAX;
int start = 0, length = 1, gstart = 0; unsigned int glyph_count;
hb_codepoint_t *codepoints = calloc((unsigned int)len, sizeof(hb_codepoint_t)); int i, end = start + length;
for (int idx = 1, specidx = 1; idx < len; idx++) {
if (glyphs[idx].mode & ATTR_WDUMMY) {
length += 1;
continue;
}
if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) {
hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
/* Reset the sequence. */
length = 1;
start = specidx;
gstart = idx;
} else {
length += 1;
}
specidx++;
}
/* EOL. */
hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
/* Apply the transformation to glyph specs. */
for (int i = 0, specidx = 0; i < len; i++) {
if (glyphs[i].mode & ATTR_WDUMMY)
continue;
if (glyphs[i].mode & ATTR_BOXDRAW) {
specidx++;
continue;
}
if (codepoints[i] != specs[specidx].glyph)
((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
specs[specidx++].glyph = codepoints[i];
}
free(codepoints);
}
void
hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length)
{
hb_font_t *font = hbfindfont(xfont); hb_font_t *font = hbfindfont(xfont);
if (font == NULL) if (font == NULL)
return; return;
Rune rune;
ushort mode = USHRT_MAX;
hb_buffer_t *buffer = hb_buffer_create(); hb_buffer_t *buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
/* Fill buffer with codepoints. */ /* Fill buffer with codepoints. */
for (int i = start; i < (start+length); i++) { for (i = start; i < end; i++) {
rune = string[i].u; rune = glyphs[i].u;
mode = string[i].mode; mode = glyphs[i].mode;
if (mode & ATTR_WDUMMY) if (mode & ATTR_WDUMMY)
rune = 0x0020; rune = 0x0020;
hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1); hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
@ -139,14 +92,17 @@ hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoin
hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t));
/* Get new glyph info. */ /* Get new glyph info. */
hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL); hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count);
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count);
/* Write new codepoints. */ /** Fill the output. */
for (int i = 0; i < length; i++) { data->buffer = buffer;
hb_codepoint_t gid = info[i].codepoint; data->glyphs = info;
codepoints[start+i] = gid; data->positions = pos;
data->count = glyph_count;
} }
/* Cleanup. */ void hbcleanup(HbTransformData *data) {
hb_buffer_destroy(buffer); hb_buffer_destroy(data->buffer);
memset(data, 0, sizeof(HbTransformData));
} }

10
hb.h
View file

@ -2,5 +2,13 @@
#include <hb.h> #include <hb.h>
#include <hb-ft.h> #include <hb-ft.h>
typedef struct {
hb_buffer_t *buffer;
hb_glyph_info_t *glyphs;
hb_glyph_position_t *positions;
unsigned int count;
} HbTransformData;
void hbunloadfonts(); void hbunloadfonts();
void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int); void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int);
void hbcleanup(HbTransformData *);

View file

@ -32,7 +32,6 @@ static KeySym mappedkeys[] = {
XK_X, XK_X,
XK_Y, XK_Y,
XK_Z, XK_Z,
XK_Z,
XK_0, XK_0,
XK_1, XK_1,
XK_2, XK_2,
@ -600,7 +599,6 @@ static Key key[] = {
{ XK_X, ControlMask|ShiftMask, "\033[88;6u", 0, 0}, { XK_X, ControlMask|ShiftMask, "\033[88;6u", 0, 0},
{ XK_Y, ControlMask|ShiftMask, "\033[89;6u", 0, 0}, { XK_Y, ControlMask|ShiftMask, "\033[89;6u", 0, 0},
{ XK_Z, ControlMask|ShiftMask, "\033[90;6u", 0, 0}, { XK_Z, ControlMask|ShiftMask, "\033[90;6u", 0, 0},
{ XK_Z, ControlMask|ShiftMask, "\033[90;6u", 0, 0},
{ XK_0, Mod1Mask|ControlMask, "\033[48;7u", 0, 0}, { XK_0, Mod1Mask|ControlMask, "\033[48;7u", 0, 0},
{ XK_1, ControlMask, "\033[49;5u", 0, 0}, { XK_1, ControlMask, "\033[49;5u", 0, 0},
{ XK_1, Mod1Mask|ControlMask, "\033[49;7u", 0, 0}, { XK_1, Mod1Mask|ControlMask, "\033[49;7u", 0, 0},

View file

@ -1,5 +0,0 @@
int
tisaltscr(void)
{
return IS_SET(MODE_ALTSCREEN);
}

View file

@ -1 +0,0 @@
int tisaltscr(void);

19
st.c
View file

@ -676,6 +676,7 @@ execsh(char *cmd, char **args)
setenv("SHELL", sh, 1); setenv("SHELL", sh, 1);
setenv("HOME", pw->pw_dir, 1); setenv("HOME", pw->pw_dir, 1);
setenv("TERM", termname, 1); setenv("TERM", termname, 1);
setenv("COLORTERM", "truecolor", 1);
signal(SIGCHLD, SIG_DFL); signal(SIGCHLD, SIG_DFL);
signal(SIGHUP, SIG_DFL); signal(SIGHUP, SIG_DFL);
@ -1859,11 +1860,18 @@ csihandle(void)
case 'm': /* SGR -- Terminal attribute (color) */ case 'm': /* SGR -- Terminal attribute (color) */
tsetattr(csiescseq.arg, csiescseq.narg); tsetattr(csiescseq.arg, csiescseq.narg);
break; break;
case 'n': /* DSR Device Status Report (cursor position) */ case 'n': /* DSR -- Device Status Report */
if (csiescseq.arg[0] == 6) { switch (csiescseq.arg[0]) {
case 5: /* Status Report "OK" `0n` */
ttywrite("\033[0n", sizeof("\033[0n") - 1, 0);
break;
case 6: /* Report Cursor Position (CPR) "<row>;<column>R" */
len = snprintf(buffer, sizeof(buffer), "\033[%i;%iR", len = snprintf(buffer, sizeof(buffer), "\033[%i;%iR",
term.c.y+1, term.c.x+1); term.c.y+1, term.c.x+1);
ttywrite(buffer, len, 0); ttywrite(buffer, len, 0);
break;
default:
goto unknown;
} }
break; break;
case 'r': /* DECSTBM -- Set Scrolling Region */ case 'r': /* DECSTBM -- Set Scrolling Region */
@ -2084,8 +2092,10 @@ strhandle(void)
if (p && !strcmp(p, "?")) if (p && !strcmp(p, "?"))
osc4_color_response(j); osc4_color_response(j);
else if (xsetcolorname(j, p)) { else if (xsetcolorname(j, p)) {
if (par == 104 && narg <= 1) if (par == 104 && narg <= 1) {
xloadcols();
return; /* color reset without parameter */ return; /* color reset without parameter */
}
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
j, p ? p : "(null)"); j, p ? p : "(null)");
} else { } else {
@ -2567,6 +2577,9 @@ check_control_code:
* they must not cause conflicts with sequences. * they must not cause conflicts with sequences.
*/ */
if (control) { if (control) {
/* in UTF-8 mode ignore handling C1 control characters */
if (IS_SET(MODE_UTF8) && ISCONTROLC1(u))
return;
tcontrolcode(u); tcontrolcode(u);
/* /*
* control codes are not shown ever * control codes are not shown ever

127
x.c
View file

@ -68,6 +68,7 @@ static void zoomreset(const Arg *);
static inline ushort sixd_to_16bit(int); static inline ushort sixd_to_16bit(int);
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, int); static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
static void xdrawglyph(Glyph, int, int); static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int); static void xclear(int, int, int, int);
static int xgeommasktogravity(int); static int xgeommasktogravity(int);
@ -1211,6 +1212,7 @@ xinit(int cols, int rows)
XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
PropModeReplace, (uchar *)&thispid, 1); PropModeReplace, (uchar *)&thispid, 1);
win.mode = MODE_NUMLOCK; win.mode = MODE_NUMLOCK;
resettitle(); resettitle();
xhints(); xhints();
@ -1228,6 +1230,22 @@ xinit(int cols, int rows)
boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis);
} }
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)
{ {
@ -1243,54 +1261,64 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
FcFontSet *fcsets[] = { NULL }; FcFontSet *fcsets[] = { NULL };
FcCharSet *fccharset; FcCharSet *fccharset;
int i, f, numspecs = 0; int i, f, numspecs = 0;
int length = 0, start = 0;
HbTransformData shaped = { 0 };
/* Initial values. */
mode = prevmode = glyphs[0].mode;
xresetfontsettings(mode, &font, &frcflags);
for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i)
{ {
/* Fetch rune and mode for current glyph. */ /* 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)
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 + win.cyo;
} }
if (mode & ATTR_BOXDRAW) { /* Shape the segment. */
hbtransform(&shaped, font->match, glyphs, start, length);
for (int code_idx = 0; code_idx < shaped.count; code_idx++) {
rune = glyphs[start + code_idx].u;
runewidth = win.cw * ((glyphs[start + code_idx].mode & ATTR_WIDE) ? 2.0f : 1.0f);
if (glyphs[start + code_idx].mode & ATTR_WDUMMY)
continue;
if (glyphs[start + code_idx].mode & ATTR_BOXDRAW) {
/* minor shoehorning: boxdraw uses only this ushort */ /* minor shoehorning: boxdraw uses only this ushort */
glyphidx = boxdrawindex(&glyphs[i]);
} else {
/* Lookup character index with default font. */
glyphidx = XftCharIndex(xw.dpy, font->match, rune);
}
if (glyphidx) {
specs[numspecs].font = font->match; specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx; specs[numspecs].glyph = boxdrawindex(&glyphs[start + code_idx]);
specs[numspecs].x = (short)xp; specs[numspecs].x = xp;
specs[numspecs].y = (short)yp; specs[numspecs].y = yp;
xp += runewidth; xp += runewidth;
numspecs++; numspecs++;
continue; } else
} if (shaped.glyphs[code_idx].codepoint != 0) {
/* If symbol is found, put it into the specs. */
/* Fallback on font cache, search the font cache for match. */ specs[numspecs].font = font->match;
specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint;
specs[numspecs].x = xp + (short)shaped.positions[code_idx].x_offset;
specs[numspecs].y = yp + (short)shaped.positions[code_idx].y_offset;
xp += runewidth;
numspecs++;
} else {
/* If it's not found, try to fetch it through the font cache. */
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. */
@ -1306,8 +1334,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
/* Nothing was found. Use fontconfig to find matching font. */ /* Nothing was found. Use fontconfig to find matching font. */
if (f >= frclen) { if (f >= frclen) {
if (!font->set) if (!font->set)
font->set = FcFontSort(0, font->pattern, font->set = FcFontSort(0, font->pattern, 1, 0, &fcres);
1, 0, &fcres);
fcsets[0] = font->set; fcsets[0] = font->set;
/* /*
@ -1321,10 +1348,11 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
fccharset = FcCharSetCreate(); fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, rune); FcCharSetAddChar(fccharset, rune);
FcPatternAddCharSet(fcpattern, FC_CHARSET, FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, 1); FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
FcConfigSubstitute(0, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern);
fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres);
@ -1334,8 +1362,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
frc = xrealloc(frc, frccap * sizeof(Fontcache)); frc = xrealloc(frc, frccap * sizeof(Fontcache));
} }
frc[frclen].font = XftFontOpenPattern(xw.dpy, frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern);
fontpattern);
if (!frc[frclen].font) if (!frc[frclen].font)
die("XftFontOpenPattern failed seeking fallback font: %s\n", die("XftFontOpenPattern failed seeking fallback font: %s\n",
strerror(errno)); strerror(errno));
@ -1358,9 +1385,20 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
xp += runewidth; xp += runewidth;
numspecs++; numspecs++;
} }
}
/* Harfbuzz transformation for ligatures. */ /* Cleanup and get ready for next segment. */
hbtransform(specs, glyphs, len, x, y); 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;
} }
@ -2330,7 +2368,7 @@ void
kpress(XEvent *ev) kpress(XEvent *ev)
{ {
XKeyEvent *e = &ev->xkey; XKeyEvent *e = &ev->xkey;
KeySym ksym; KeySym ksym = NoSymbol;
char buf[64], *customkey; char buf[64], *customkey;
int len, screen; int len, screen;
Rune c; Rune c;
@ -2352,10 +2390,13 @@ kpress(XEvent *ev)
if (IS_SET(MODE_KBDLOCK)) if (IS_SET(MODE_KBDLOCK))
return; return;
if (xw.ime.xic) if (xw.ime.xic) {
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
else if (status == XBufferOverflow)
return;
} else {
len = XLookupString(e, buf, sizeof buf, &ksym, NULL); len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
}
screen = tisaltscr() ? S_ALT : S_PRI; screen = tisaltscr() ? S_ALT : S_PRI;