aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-05 16:57:55 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-05 16:57:55 -0700
commit08d3749a636f9cd51f70ba1eed043be8e6c2eca9 (patch)
treec17cdff0796b73758a96977614d84f04d22c3bfb
parent2e80e18c190b737338f8000aafe685719b4899a1 (diff)
feat(term): added ligature support. some combining character help
-rw-r--r--sys/cmd/dwm/config.h2
-rw-r--r--sys/cmd/rules.mk4
-rw-r--r--sys/cmd/term/rules.mk6
-rw-r--r--sys/cmd/term/term.c47
-rw-r--r--sys/cmd/term/term.h8
-rw-r--r--sys/cmd/term/x.c36
-rw-r--r--sys/cmd/wm/client.c15
-rw-r--r--sys/cmd/wm/config.h4
-rw-r--r--sys/cmd/wm/input.c1
-rw-r--r--sys/cmd/wm/util.c1
-rw-r--r--sys/libn/string.c12
-rw-r--r--sys/rules.mk9
12 files changed, 99 insertions, 46 deletions
diff --git a/sys/cmd/dwm/config.h b/sys/cmd/dwm/config.h
index cb1ccdb..d14aded 100644
--- a/sys/cmd/dwm/config.h
+++ b/sys/cmd/dwm/config.h
@@ -93,6 +93,8 @@ static Key keys[] = {
{ MODKEY, XK_j, focusdirection, {.i = 'd'} },
{ MODKEY|ShiftMask, XK_h, setmfact, {.f = -0.05} },
{ MODKEY|ShiftMask, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY|ShiftMask, XK_k, rotatestack, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_j, rotatestack, {.i = -1 } },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_q, killclient, {0} },
diff --git a/sys/cmd/rules.mk b/sys/cmd/rules.mk
index 50d9274..dc0ca08 100644
--- a/sys/cmd/rules.mk
+++ b/sys/cmd/rules.mk
@@ -23,8 +23,8 @@ include $(DIR)/rules.mk
DIR := $(d)/term
include $(DIR)/rules.mk
-# DIR := $(d)/term2
-# include $(DIR)/rules.mk
+DIR := $(d)/term2
+include $(DIR)/rules.mk
DIR := $(d)/walk
include $(DIR)/rules.mk
diff --git a/sys/cmd/term/rules.mk b/sys/cmd/term/rules.mk
index 38acbf7..19fcdaf 100644
--- a/sys/cmd/term/rules.mk
+++ b/sys/cmd/term/rules.mk
@@ -2,7 +2,7 @@ include share/push.mk
# Iterate through subdirectory tree
# Local sources
-SRCS_$(d) := $(d)/term.c $(d)/x.c #$(d)/util.c
+SRCS_$(d) := $(d)/term.c $(d)/x.c $(d)/hb.c
BINS_$(d) := $(d)/term
include share/paths.mk
@@ -11,10 +11,12 @@ include share/paths.mk
include share/dynamic.mk
$(BINS_$(d)): TCFLAGS = \
`$(PKG) --cflags fontconfig` \
- `$(PKG) --cflags freetype2`
+ `$(PKG) --cflags freetype2` \
+ `$(PKG) --cflags harfbuzz`
$(BINS_$(d)): TCLIBS = \
`$(PKG) --libs fontconfig` \
`$(PKG) --libs freetype2` \
+ `$(PKG) --libs harfbuzz` \
-lm -lrt -lX11 -lutil -lXft -lXrender \
$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/libn/libn.a
diff --git a/sys/cmd/term/term.c b/sys/cmd/term/term.c
index f7687b9..77ed5c2 100644
--- a/sys/cmd/term/term.c
+++ b/sys/cmd/term/term.c
@@ -627,7 +627,7 @@ ttyread(void)
written = twrite(buf, buflen, 0);
buflen -= written;
/* keep any incomplete UTF-8 byte sequence for the next call */
- if (buflen > 0)
+ if(buflen > 0)
memmove(buf, buf + written, buflen);
return ret;
}
@@ -989,7 +989,7 @@ tsetchar(rune u, Letter *attr, int x, int y)
};
/*
- * The table is proudly stolen from rxvt.
+ * table is proudly stolen from rxvt.
*/
if (term.trantbl[term.charset] == CSgfx0 &&
BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41])
@@ -2082,6 +2082,7 @@ tputc(rune u)
char c[UTFmax];
int control;
int width, len;
+ rune nu;
Letter *gp;
control = ISCONTROL(u);
@@ -2090,10 +2091,30 @@ tputc(rune u)
width = len = 1;
} else {
len = utf8·runetobyte(c, &u);
- if (!control && (width = wcwidth(u)) == -1)
+ if(!control && (width = wcwidth(u)) == -1)
width = 1;
}
+ /* combining characters */
+ if(!width) {
+ if(term.c.x > 0)
+ gp = &term.line[term.c.y][term.c.x-1];
+ else if(term.c.y > 0)
+ gp = &term.line[term.c.y-1][term.col-1];
+ else
+ return;
+
+ printf("%d + %d\n", gp->u, u);
+
+ if(!hb_unicode_compose(hb_unicode_funcs_get_default(),gp->u, u, &nu)) {
+ assert(false);
+ return;
+ }
+
+ gp->u = nu;
+ return;
+ }
+
if (IS_SET(Tprint))
tprinter(c, len);
@@ -2103,7 +2124,7 @@ tputc(rune u)
* receives a ESC, a SUB, a ST or any other C1 control
* character.
*/
- if (term.esc & Xstr) {
+ if(term.esc & Xstr) {
if (u == '\a' || u == 030 || u == 032 || u == 033 ||
ISCONTROLC1(u)) {
term.esc &= ~(Xstart|Xstr|Xdcs);
@@ -2154,7 +2175,7 @@ check_control_code:
* because they can be embedded inside a control sequence, and
* they must not cause conflicts with sequences.
*/
- if (control) {
+ if(control) {
tcontrolcode(u);
/*
* control codes are not shown ever
@@ -2162,7 +2183,7 @@ check_control_code:
if (!term.esc)
term.lastc = 0;
return;
- } else if (term.esc & Xstart) {
+ } else if(term.esc & Xstart) {
if (term.esc & Xcsi) {
csiescseq.buf[csiescseq.len++] = u;
if (BETWEEN(u, 0x40, 0x7E)
@@ -2191,6 +2212,7 @@ check_control_code:
*/
return;
}
+
if (selected(term.c.x, term.c.y))
selclear();
@@ -2212,7 +2234,7 @@ check_control_code:
tsetchar(u, &term.c.attr, term.c.x, term.c.y);
term.lastc = u;
- if (width == 2) {
+ if(width == 2) {
gp->mode |= Gwrap;
if (term.c.x+1 < term.col) {
gp[1].u = '\0';
@@ -2234,16 +2256,16 @@ twrite(char *buf, int buflen, int show_ctrl)
int n;
for (n = 0; n < buflen; n += charsize) {
- if (IS_SET(Tutf8) && !IS_SET(Tsixel)) {
+ if(IS_SET(Tutf8) && !IS_SET(Tsixel)) {
/* process a complete utf8 char */
charsize = utf8·bytetorune(&u, buf + n);
- if (charsize == 0)
+ if(charsize == 0)
break;
} else {
u = buf[n] & 0xFF;
charsize = 1;
}
- if (show_ctrl && ISCONTROL(u)) {
+ if(show_ctrl && ISCONTROL(u)) {
if (u & 0x80) {
u &= 0x7f;
tputc('^');
@@ -2377,7 +2399,10 @@ draw(void)
cx--;
drawregion(0, 0, term.col, term.row);
- xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
+ xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
+ term.ocx, term.ocy, term.line[term.ocy][term.ocx],
+ term.line[term.ocy], term.col
+ );
term.ocx = cx;
term.ocy = term.c.y;
xfinishdraw();
diff --git a/sys/cmd/term/term.h b/sys/cmd/term/term.h
index 11c28c7..fd7b68c 100644
--- a/sys/cmd/term/term.h
+++ b/sys/cmd/term/term.h
@@ -10,6 +10,8 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <hb.h>
+
// -----------------------------------------------------------------------
// macros
@@ -17,7 +19,8 @@
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
-#define GLYPHCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg)
+#define GLYPHCMP(a, b) (((a).mode & (~Gwrap) & (~Gliga)) != ((b).mode & (~Gwrap) & (~Gliga)) || \
+ (a).fg != (b).fg || (a).bg != (b).bg)
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_nsec-t2.tv_nsec)/1E6)
#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))
#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
@@ -47,6 +50,7 @@ enum {
Gwrap = iota(8),
Gwide = iota(9),
Gwdummy = iota(10),
+ Gliga = iota(11),
Gboldfaint = Gbold | Gfaint,
};
@@ -251,7 +255,7 @@ union Arg {
void xbell(void);
void xclipcopy(void);
-void xdrawcursor(int, int, Letter, int, int, Letter);
+void xdrawcursor(int, int, Letter, int, int, Letter, Letter*, int);
void xdrawline(Letter*, int, int, int);
void xfinishdraw(void);
void xloadcols(void);
diff --git a/sys/cmd/term/x.c b/sys/cmd/term/x.c
index 308478f..3079f38 100644
--- a/sys/cmd/term/x.c
+++ b/sys/cmd/term/x.c
@@ -11,6 +11,10 @@
#include <X11/Xft/Xft.h>
#include <X11/XKBlib.h>
+/* harfbuzz additions */
+void hbunloadfonts();
+void hbtransform(XftGlyphFontSpec *, const Letter*, size_t, int, int);
+
/* types used in config.h */
typedef struct Shortcut Shortcut;
typedef struct MouseShortcut MouseShortcut;
@@ -1021,6 +1025,8 @@ xunloadfont(Font *f)
void
xunloadfonts(void)
{
+ hbunloadfonts();
+
/* Free the loaded fonts in the font cache. */
while (frclen > 0)
XftFontClose(xw.dpy, frc[--frclen].font);
@@ -1223,17 +1229,17 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int
FcCharSet *fccharset;
int i, f, numspecs = 0;
- 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. */
r = glyphs[i].u;
mode = glyphs[i].mode;
/* Skip dummy wide-character spacing. */
- if (mode == Gwdummy)
+ if(mode & Gwdummy)
continue;
/* Determine font for glyph if different from previous glyph. */
- if (prevmode != mode) {
+ if(prevmode != mode) {
prevmode = mode;
font = &dc.font;
frcflags = FRC_NORMAL;
@@ -1251,9 +1257,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int
yp = winy + font->ascent;
}
- /* Lookup character index with default font. */
+ /* lookup character index with default font. */
glyphidx = XftCharIndex(xw.dpy, font->match, r);
- if (glyphidx) {
+ if(glyphidx) {
specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx;
specs[numspecs].x = (short)xp;
@@ -1264,7 +1270,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int
}
/* 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, r);
/* Everything correct. */
if (glyphidx && frc[f].flags == frcflags)
@@ -1277,7 +1283,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int
}
/* Nothing was found. Use fontconfig to find matching font. */
- if (f >= frclen) {
+ if(f >= frclen) {
if (!font->set)
font->set = FcFontSort(0, font->pattern,
1, 0, &fcres);
@@ -1336,6 +1342,8 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int
numspecs++;
}
+ hbtransform(specs, glyphs, len, x, y);
+
return numspecs;
}
@@ -1474,16 +1482,16 @@ xdrawglyph(Letter g, int x, int y)
}
void
-xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og)
+xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og, Letter *line, int len)
{
Color drawcol;
/* remove the old cursor */
- if (selected(ox, oy))
+ if(selected(ox, oy))
og.mode ^= Greverse;
- xdrawglyph(og, ox, oy);
+ xdrawline(line, 0, oy, len);
- if (IS_SET(Whide))
+ if(IS_SET(Whide))
return;
/*
@@ -1491,7 +1499,7 @@ xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og)
*/
g.mode &= Gbold|Gitalic|Gunline|Gstruck|Gwide;
- if (IS_SET(Wreverse)) {
+ if(IS_SET(Wreverse)) {
g.mode |= Greverse;
g.bg = defaultfg;
if (selected(cx, cy)) {
@@ -1502,7 +1510,7 @@ xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og)
g.fg = defaultcs;
}
} else {
- if (selected(cx, cy)) {
+ if(selected(cx, cy)) {
g.fg = defaultfg;
g.bg = defaultrcs;
} else {
@@ -1520,7 +1528,7 @@ xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og)
}
drawnew:
- if (IS_SET(Wfocused)) {
+ if(IS_SET(Wfocused)) {
switch (win.cursor) {
case 7: /* st extension */
g.u = 0x2603; /* snowman (U+2603) */
diff --git a/sys/cmd/wm/client.c b/sys/cmd/wm/client.c
index 7c13545..5e0927a 100644
--- a/sys/cmd/wm/client.c
+++ b/sys/cmd/wm/client.c
@@ -64,11 +64,17 @@ resize_client(Arg *arg)
// -----------------------------------------------------------------------
// core
+static inline
+void
+activate(struct wlr_surface *surface, int state)
+{
+}
+
void
focus(Client *client, int lift)
{
- struct wlr_surface *old, *new;
struct wlr_xdg_surface *xdg;
+ struct wlr_surface *old, *new;
struct wlr_keyboard *keyboard;
if(!client) {
@@ -92,10 +98,11 @@ focus(Client *client, int lift)
server.monitor.selected = client->monitor;
client->isurgent = 0;
- // XXX: do we need for non-client case?
if(old) {
- xdg = wlr_xdg_surface_from_wlr_surface(old);
- wlr_xdg_toplevel_set_activated(xdg, false);
+ if(wlr_surface_is_xdg_surface(old)) {
+ xdg = wlr_xdg_surface_from_wlr_surface(old);
+ wlr_xdg_toplevel_set_activated(xdg, false);
+ }
}
keyboard = wlr_seat_get_keyboard(server.input.seat);
diff --git a/sys/cmd/wm/config.h b/sys/cmd/wm/config.h
index f80638f..1f5ba85 100644
--- a/sys/cmd/wm/config.h
+++ b/sys/cmd/wm/config.h
@@ -24,7 +24,7 @@ CONFIG(Rule*, endrule, arrend(cfg·rule));
/* commands */
CONFIG(char*, termcommand[], { "alacritty", nil });
-CONFIG(char*, menucommand[], { "bemenu-run", nil });
+CONFIG(char*, menucommand[], { "dmenu-wl_run", nil });
/* layouts */
CONFIG(Layout, layouts[], {
@@ -51,7 +51,7 @@ CONFIG(MonitorRule*, endmonitorrule, arrend(cfg·monitorrule));
CONFIG(Key, binding[], {
/* modifier key function argument */
{ MODKEY, KEY(Return), spawn, {.v = cfg·termcommand} },
- { MODKEY, KEY(D), spawn, {.v = cfg·menucommand} },
+ { MODKEY, KEY(d), spawn, {.v = cfg·menucommand} },
{ MODKEY|MOD(SHIFT), KEY(Q), quit, {.v = nil} },
});
CONFIG(Key*, endbinding, arrend(cfg·binding));
diff --git a/sys/cmd/wm/input.c b/sys/cmd/wm/input.c
index a91ecd8..4c6bfd4 100644
--- a/sys/cmd/wm/input.c
+++ b/sys/cmd/wm/input.c
@@ -18,6 +18,7 @@ int
keybinding(uint32 modifier, xkb_keysym_t sym)
{
Key *key;
+
for(key=cfg·binding; key!=cfg·endbinding; ++key) {
if(modifier == key->modifier && sym == key->sym && key->action){
key->action(&key->arg);
diff --git a/sys/cmd/wm/util.c b/sys/cmd/wm/util.c
index cf4f68a..7871d15 100644
--- a/sys/cmd/wm/util.c
+++ b/sys/cmd/wm/util.c
@@ -80,6 +80,7 @@ exclude(struct wlr_box *usable_area, uint32 anchor, int32 exclusive,
void
spawn(Arg *arg)
{
+ wlr_log(WLR_DEBUG, "spawning %s", ((char **)arg->v)[0]);
if(!fork()) {
dup2(2, 1);
setsid();
diff --git a/sys/libn/string.c b/sys/libn/string.c
index bf5d645..22a3359 100644
--- a/sys/libn/string.c
+++ b/sys/libn/string.c
@@ -40,26 +40,26 @@ utf8·bytetorune(rune* r, byte* s)
rune l;
c[0] = *(ubyte*)(s);
- if (c[0] < Tx) {
+ if(c[0] < Tx) {
*r = c[0];
return 1;
}
l = c[0];
- for (i = 1; i < UTFmax; i++) {
+ for(i = 1; i < UTFmax; i++) {
c[i] = *(ubyte*)(s+i);
c[i] ^= Tx;
if (c[i] & Testx) goto bad;
l = (l << Bitx) | c[i];
- if (c[0] < Tbyte(i + 2)) {
+ if(c[0] < Tbyte(i + 2)) {
l &= RuneX(i + 1);
if (i == 1) {
- if (c[0] < Tbyte(2) || l <= Rune1)
+ if (c[0] < Tbyte(2) || l <= Rune1)
goto bad;
- } else if (l <= RuneX(i) || l > RuneMax)
+ } else if (l <= RuneX(i) || l > RuneMax)
goto bad;
- if (i == 2 && SurrogateMin <= l && l <= SurrogateMax)
+ if (i == 2 && SurrogateMin <= l && l <= SurrogateMax)
goto bad;
*r = l;
diff --git a/sys/rules.mk b/sys/rules.mk
index 385c9ac..a45e8b3 100644
--- a/sys/rules.mk
+++ b/sys/rules.mk
@@ -2,12 +2,12 @@ include share/push.mk
# Iterate through subdirectory tree
-# DIR := $(d)/libc
-# include $(DIR)/rules.mk
-
DIR := $(d)/cmd
include $(DIR)/rules.mk
+# DIR := $(d)/libc
+# include $(DIR)/rules.mk
+
DIR := $(d)/libn
include $(DIR)/rules.mk
@@ -17,6 +17,9 @@ include $(DIR)/rules.mk
DIR := $(d)/libbio
include $(DIR)/rules.mk
+DIR := $(d)/libdraw
+include $(DIR)/rules.mk
+
# DIR := $(d)/libimage
# include $(DIR)/rules.mk