diff options
author | ZachIR <zachir@librem.one> | 2025-07-08 20:39:57 -0500 |
---|---|---|
committer | ZachIR <zachir@librem.one> | 2025-07-08 20:39:57 -0500 |
commit | 38d2f7ba589e8ee0ee5ded7915952ed094e3a51a (patch) | |
tree | b98c891bcd03dcbc6a9ebae038d154a472febe8a | |
parent | 8cda47f8e8b2db37f5c69b4cdb748ac31a2e6e23 (diff) |
Start from scratch on version 0.9.2
39 files changed, 416 insertions, 8220 deletions
@@ -4,16 +4,10 @@ include config.mk -SRC = st.c x.c boxdraw.c +SRC = st.c x.c OBJ = $(SRC:.c=.o) -all: options st - -options: - @echo st build options: - @echo "CFLAGS = $(STCFLAGS)" - @echo "LDFLAGS = $(STLDFLAGS)" - @echo "CC = $(CC)" +all: st config.h: cp config.def.h config.h @@ -23,7 +17,6 @@ config.h: st.o: config.h st.h win.h x.o: arg.h config.h st.h win.h -boxdraw.o: config.h st.h boxdraw_data.h $(OBJ): config.h config.mk @@ -50,12 +43,9 @@ install: st chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 tic -sx st.info @echo Please see the README file regarding the terminfo entry of st. - mkdir -p $(DESTDIR)$(ICONPREFIX) - [ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || : uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/st rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 - rm -f $(DESTDIR)$(ICONPREFIX)/$(ICONNAME) -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall diff --git a/boxdraw.c b/boxdraw.c deleted file mode 100644 index 28a92d0..0000000 --- a/boxdraw.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih - * MIT/X Consortium License - */ - -#include <X11/Xft/Xft.h> -#include "st.h" -#include "boxdraw_data.h" - -/* Rounded non-negative integers division of n / d */ -#define DIV(n, d) (((n) + (d) / 2) / (d)) - -static Display *xdpy; -static Colormap xcmap; -static XftDraw *xd; -static Visual *xvis; - -static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); -static void drawboxlines(int, int, int, int, XftColor *, ushort); - -/* public API */ - -void -boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) -{ - xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; -} - -int -isboxdraw(Rune u) -{ - Rune block = u & ~0xff; - return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || - (boxdraw_braille && block == 0x2800); -} - -/* the "index" is actually the entire shape data encoded as ushort */ -ushort -boxdrawindex(const Glyph *g) -{ - if (boxdraw_braille && (g->u & ~0xff) == 0x2800) - return BRL | (uint8_t)g->u; - if (boxdraw_bold && (g->mode & ATTR_BOLD)) - return BDB | boxdata[(uint8_t)g->u]; - return boxdata[(uint8_t)g->u]; -} - -void -drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, - const XftGlyphFontSpec *specs, int len) -{ - for ( ; len-- > 0; x += cw, specs++) - drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); -} - -/* implementation */ - -void -drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) -{ - ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ - if (bd & (BDL | BDA)) { - /* lines (light/double/heavy/arcs) */ - drawboxlines(x, y, w, h, fg, bd); - - } else if (cat == BBD) { - /* lower (8-X)/8 block */ - int d = DIV((uint8_t)bd * h, 8); - XftDrawRect(xd, fg, x, y + d, w, h - d); - - } else if (cat == BBU) { - /* upper X/8 block */ - XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); - - } else if (cat == BBL) { - /* left X/8 block */ - XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); - - } else if (cat == BBR) { - /* right (8-X)/8 block */ - int d = DIV((uint8_t)bd * w, 8); - XftDrawRect(xd, fg, x + d, y, w - d, h); - - } else if (cat == BBQ) { - /* Quadrants */ - int w2 = DIV(w, 2), h2 = DIV(h, 2); - if (bd & TL) - XftDrawRect(xd, fg, x, y, w2, h2); - if (bd & TR) - XftDrawRect(xd, fg, x + w2, y, w - w2, h2); - if (bd & BL) - XftDrawRect(xd, fg, x, y + h2, w2, h - h2); - if (bd & BR) - XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); - - } else if (bd & BBS) { - /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ - int d = (uint8_t)bd; - XftColor xfc; - XRenderColor xrc = { .alpha = 0xffff }; - - xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); - xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); - xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); - - XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); - XftDrawRect(xd, &xfc, x, y, w, h); - XftColorFree(xdpy, xvis, xcmap, &xfc); - - } else if (cat == BRL) { - /* braille, each data bit corresponds to one dot at 2x4 grid */ - int w1 = DIV(w, 2); - int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); - - if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); - if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); - if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); - if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); - if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); - if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); - if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); - if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); - - } -} - -void -drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) -{ - /* s: stem thickness. width/8 roughly matches underscore thickness. */ - /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ - /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ - int mwh = MIN(w, h); - int base_s = MAX(1, DIV(mwh, 8)); - int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ - int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; - int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); - /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ - /* The base length (per direction till edge) includes this square. */ - - int light = bd & (LL | LU | LR | LD); - int double_ = bd & (DL | DU | DR | DD); - - if (light) { - /* d: additional (negative) length to not-draw the center */ - /* texel - at arcs and avoid drawing inside (some) doubles */ - int arc = bd & BDA; - int multi_light = light & (light - 1); - int multi_double = double_ & (double_ - 1); - /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ - int d = arc || (multi_double && !multi_light) ? -s : 0; - - if (bd & LL) - XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); - if (bd & LU) - XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); - if (bd & LR) - XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); - if (bd & LD) - XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); - } - - /* double lines - also align with light to form heavy when combined */ - if (double_) { - /* - * going clockwise, for each double-ray: p is additional length - * to the single-ray nearer to the previous direction, and n to - * the next. p and n adjust from the base length to lengths - * which consider other doubles - shorter to avoid intersections - * (p, n), or longer to draw the far-corner texel (n). - */ - int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; - if (dl) { - int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; - XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); - XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); - } - if (du) { - int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; - XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); - XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); - } - if (dr) { - int p = du ? -s : 0, n = dd ? -s : du ? s : 0; - XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); - XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); - } - if (dd) { - int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; - XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); - XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); - } - } -} diff --git a/boxdraw_data.h b/boxdraw_data.h deleted file mode 100644 index 7890500..0000000 --- a/boxdraw_data.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih - * MIT/X Consortium License - */ - -/* - * U+25XX codepoints data - * - * References: - * http://www.unicode.org/charts/PDF/U2500.pdf - * http://www.unicode.org/charts/PDF/U2580.pdf - * - * Test page: - * https://github.com/GNOME/vte/blob/master/doc/boxes.txt - */ - -/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ -/* Categories (mutually exclusive except BDB): */ -/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ -#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ -#define BDA (1<<9) /* Box Draw Arc (light) */ - -#define BBD (1<<10) /* Box Block Down (lower) X/8 */ -#define BBL (2<<10) /* Box Block Left X/8 */ -#define BBU (3<<10) /* Box Block Upper X/8 */ -#define BBR (4<<10) /* Box Block Right X/8 */ -#define BBQ (5<<10) /* Box Block Quadrants */ -#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ - -#define BBS (1<<14) /* Box Block Shades */ -#define BDB (1<<15) /* Box Draw is Bold */ - -/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ -/* Heavy is light+double (literally drawing light+double align to form heavy) */ -#define LL (1<<0) -#define LU (1<<1) -#define LR (1<<2) -#define LD (1<<3) -#define LH (LL+LR) -#define LV (LU+LD) - -#define DL (1<<4) -#define DU (1<<5) -#define DR (1<<6) -#define DD (1<<7) -#define DH (DL+DR) -#define DV (DU+DD) - -#define HL (LL+DL) -#define HU (LU+DU) -#define HR (LR+DR) -#define HD (LD+DD) -#define HH (HL+HR) -#define HV (HU+HD) - -/* (BBQ) Quadrants Top/Bottom x Left/Right */ -#define TL (1<<0) -#define TR (1<<1) -#define BL (1<<2) -#define BR (1<<3) - -/* Data for U+2500 - U+259F except dashes/diagonals */ -static const unsigned short boxdata[256] = { - /* light lines */ - [0x00] = BDL + LH, /* light horizontal */ - [0x02] = BDL + LV, /* light vertical */ - [0x0c] = BDL + LD + LR, /* light down and right */ - [0x10] = BDL + LD + LL, /* light down and left */ - [0x14] = BDL + LU + LR, /* light up and right */ - [0x18] = BDL + LU + LL, /* light up and left */ - [0x1c] = BDL + LV + LR, /* light vertical and right */ - [0x24] = BDL + LV + LL, /* light vertical and left */ - [0x2c] = BDL + LH + LD, /* light horizontal and down */ - [0x34] = BDL + LH + LU, /* light horizontal and up */ - [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ - [0x74] = BDL + LL, /* light left */ - [0x75] = BDL + LU, /* light up */ - [0x76] = BDL + LR, /* light right */ - [0x77] = BDL + LD, /* light down */ - - /* heavy [+light] lines */ - [0x01] = BDL + HH, - [0x03] = BDL + HV, - [0x0d] = BDL + HR + LD, - [0x0e] = BDL + HD + LR, - [0x0f] = BDL + HD + HR, - [0x11] = BDL + HL + LD, - [0x12] = BDL + HD + LL, - [0x13] = BDL + HD + HL, - [0x15] = BDL + HR + LU, - [0x16] = BDL + HU + LR, - [0x17] = BDL + HU + HR, - [0x19] = BDL + HL + LU, - [0x1a] = BDL + HU + LL, - [0x1b] = BDL + HU + HL, - [0x1d] = BDL + HR + LV, - [0x1e] = BDL + HU + LD + LR, - [0x1f] = BDL + HD + LR + LU, - [0x20] = BDL + HV + LR, - [0x21] = BDL + HU + HR + LD, - [0x22] = BDL + HD + HR + LU, - [0x23] = BDL + HV + HR, - [0x25] = BDL + HL + LV, - [0x26] = BDL + HU + LD + LL, - [0x27] = BDL + HD + LU + LL, - [0x28] = BDL + HV + LL, - [0x29] = BDL + HU + HL + LD, - [0x2a] = BDL + HD + HL + LU, - [0x2b] = BDL + HV + HL, - [0x2d] = BDL + HL + LD + LR, - [0x2e] = BDL + HR + LL + LD, - [0x2f] = BDL + HH + LD, - [0x30] = BDL + HD + LH, - [0x31] = BDL + HD + HL + LR, - [0x32] = BDL + HR + HD + LL, - [0x33] = BDL + HH + HD, - [0x35] = BDL + HL + LU + LR, - [0x36] = BDL + HR + LU + LL, - [0x37] = BDL + HH + LU, - [0x38] = BDL + HU + LH, - [0x39] = BDL + HU + HL + LR, - [0x3a] = BDL + HU + HR + LL, - [0x3b] = BDL + HH + HU, - [0x3d] = BDL + HL + LV + LR, - [0x3e] = BDL + HR + LV + LL, - [0x3f] = BDL + HH + LV, - [0x40] = BDL + HU + LH + LD, - [0x41] = BDL + HD + LH + LU, - [0x42] = BDL + HV + LH, - [0x43] = BDL + HU + HL + LD + LR, - [0x44] = BDL + HU + HR + LD + LL, - [0x45] = BDL + HD + HL + LU + LR, - [0x46] = BDL + HD + HR + LU + LL, - [0x47] = BDL + HH + HU + LD, - [0x48] = BDL + HH + HD + LU, - [0x49] = BDL + HV + HL + LR, - [0x4a] = BDL + HV + HR + LL, - [0x4b] = BDL + HV + HH, - [0x78] = BDL + HL, - [0x79] = BDL + HU, - [0x7a] = BDL + HR, - [0x7b] = BDL + HD, - [0x7c] = BDL + HR + LL, - [0x7d] = BDL + HD + LU, - [0x7e] = BDL + HL + LR, - [0x7f] = BDL + HU + LD, - - /* double [+light] lines */ - [0x50] = BDL + DH, - [0x51] = BDL + DV, - [0x52] = BDL + DR + LD, - [0x53] = BDL + DD + LR, - [0x54] = BDL + DR + DD, - [0x55] = BDL + DL + LD, - [0x56] = BDL + DD + LL, - [0x57] = BDL + DL + DD, - [0x58] = BDL + DR + LU, - [0x59] = BDL + DU + LR, - [0x5a] = BDL + DU + DR, - [0x5b] = BDL + DL + LU, - [0x5c] = BDL + DU + LL, - [0x5d] = BDL + DL + DU, - [0x5e] = BDL + DR + LV, - [0x5f] = BDL + DV + LR, - [0x60] = BDL + DV + DR, - [0x61] = BDL + DL + LV, - [0x62] = BDL + DV + LL, - [0x63] = BDL + DV + DL, - [0x64] = BDL + DH + LD, - [0x65] = BDL + DD + LH, - [0x66] = BDL + DD + DH, - [0x67] = BDL + DH + LU, - [0x68] = BDL + DU + LH, - [0x69] = BDL + DH + DU, - [0x6a] = BDL + DH + LV, - [0x6b] = BDL + DV + LH, - [0x6c] = BDL + DH + DV, - - /* (light) arcs */ - [0x6d] = BDA + LD + LR, - [0x6e] = BDA + LD + LL, - [0x6f] = BDA + LU + LL, - [0x70] = BDA + LU + LR, - - /* Lower (Down) X/8 block (data is 8 - X) */ - [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, - [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, - - /* Left X/8 block (data is X) */ - [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, - [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, - - /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ - [0x80] = BBU + 4, [0x94] = BBU + 1, - [0x90] = BBR + 4, [0x95] = BBR + 7, - - /* Quadrants */ - [0x96] = BBQ + BL, - [0x97] = BBQ + BR, - [0x98] = BBQ + TL, - [0x99] = BBQ + TL + BL + BR, - [0x9a] = BBQ + TL + BR, - [0x9b] = BBQ + TL + TR + BL, - [0x9c] = BBQ + TL + TR + BR, - [0x9d] = BBQ + TR, - [0x9e] = BBQ + BL + TR, - [0x9f] = BBQ + BL + TR + BR, - - /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ - [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, - - /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ - /* U+2571 - U+2573: unsupported (diagonals) */ -}; diff --git a/config.def.h b/config.def.h index bdfb540..2cd740a 100644 --- a/config.def.h +++ b/config.def.h @@ -1,37 +1,12 @@ /* See LICENSE file for copyright and license details. */ /* - * Override/adjust fontsize of choosen monitors: - */ -MonitorConfig monitors_config[] = { - // skip = fixed relative points size (monitor dpi) - // =0 : fixed absolute pixel size (default screen dpi) - // >0 : auto absolute pixel size (monitor dpi) - // <0 : auto relative points size (monitor dpi) - // {"DP-1", 0}, // BUG:(size=0): not restored to default after back'n'forth - {"HDMI-0~1", -20}, // BUG:(ignored DPI=220): = 20 is eqv to 10pt (DPI=110) - {"HDMI-0~2", -14}, -}; -float winmovethreshold = 0.6; - -/* * appearance * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - * borderperc: percentage of cell width to use as a border - * 0 = no border, 100 = border width is same as cell width */ -static char *font = "mononoki Nerd Font Mono:pixelsize=12:antialias=true:autohint=true"; -/* Spare fonts */ -static char *font2[] = { -/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ -/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ - "Symbola:pixelsize=12:antialias=true:autohint=true" -}; - -static int borderperc = 2; - -static int center_text = 1; +static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static int borderpx = 2; /* * What program is execed by st depends of these precedence rules: @@ -53,9 +28,6 @@ char *vtiden = "\033[?6c"; /* Kerning / character bounding-box multipliers */ static float cwscale = 1.0; static float chscale = 1.0; -/* Character rendering offsets in pixels */ -static short cxoffset = 0; -static short cyoffset = 0; /* * word delimiter string @@ -73,7 +45,7 @@ int allowaltscreen = 1; /* allow certain non-interactive (insecure) window operations such as: setting the clipboard text */ -int allowwindowops = 1; +int allowwindowops = 0; /* * draw latency range in ms - from new content/keypress/etc until drawing. @@ -81,16 +53,10 @@ int allowwindowops = 1; * near minlatency, but it waits longer for slow updates to avoid partial draw. * low minlatency will tear/flicker more, as it can "detect" idle too early. */ -static double minlatency = 8; +static double minlatency = 2; static double maxlatency = 33; /* - * Synchronized-Update timeout in ms - * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec - */ -static uint su_timeout = 200; - -/* * blinking timeout (set to 0 to disable blinking) for the terminal blinking * attribute. */ @@ -102,18 +68,6 @@ static unsigned int blinktimeout = 800; static unsigned int cursorthickness = 2; /* - * 1: render most of the lines/blocks characters without using the font for - * perfect alignment between cells (U2500 - U259F except dashes/diagonals). - * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. - * 0: disable (render all U25XX glyphs normally from the font). - */ -const int boxdraw = 1; -const int boxdraw_bold = 1; - -/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 1; - -/* * bell volume. It must be a value between -100 and 100. Use 0 for disabling * it */ @@ -137,10 +91,7 @@ char *termname = "st-256color"; * * stty tabs */ -unsigned int tabspaces = 2; - -/* bg opacity */ -float alpha = 0.8, alphaUnfocused = 0.7; +unsigned int tabspaces = 8; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { @@ -179,10 +130,9 @@ static const char *colorname[] = { * foreground, background, cursor, reverse cursor */ unsigned int defaultfg = 258; -unsigned int defaultbg = 0; //259 +unsigned int defaultbg = 259; unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; -unsigned int bg = 259, bgUnfocused = 259; /* * Default shape of cursor @@ -221,50 +171,11 @@ static unsigned int defaultattr = 11; static uint forcemousemod = ShiftMask; /* - * Xresources preferences to load at startup - */ -ResourcePref resources[] = { - { "font", STRING, &font }, - { "color0", STRING, &colorname[0] }, - { "color1", STRING, &colorname[1] }, - { "color2", STRING, &colorname[2] }, - { "color3", STRING, &colorname[3] }, - { "color4", STRING, &colorname[4] }, - { "color5", STRING, &colorname[5] }, - { "color6", STRING, &colorname[6] }, - { "color7", STRING, &colorname[7] }, - { "color8", STRING, &colorname[8] }, - { "color9", STRING, &colorname[9] }, - { "color10", STRING, &colorname[10] }, - { "color11", STRING, &colorname[11] }, - { "color12", STRING, &colorname[12] }, - { "color13", STRING, &colorname[13] }, - { "color14", STRING, &colorname[14] }, - { "color15", STRING, &colorname[15] }, - { "background", STRING, &colorname[259] }, - { "foreground", STRING, &colorname[257] }, - { "cursorColor", STRING, &colorname[258] }, - { "termname", STRING, &termname }, - { "shell", STRING, &shell }, - { "minlatency", INTEGER, &minlatency }, - { "maxlatency", INTEGER, &maxlatency }, - { "blinktimeout", INTEGER, &blinktimeout }, - { "bellvolume", INTEGER, &bellvolume }, - { "tabspaces", INTEGER, &tabspaces }, - { "borderpx", INTEGER, &borderpx }, - { "cwscale", FLOAT, &cwscale }, - { "chscale", FLOAT, &chscale }, -}; - -/* * Internal mouse shortcuts. * Beware that overloading Button1 will disable the selection. */ -const unsigned int mousescrollincrement = 1; static MouseShortcut mshortcuts[] = { /* mask button function argument release */ - { 0, Button4, kscrollup, {.i = mousescrollincrement }, 0, /* !alt */ -1 }, - { 0, Button5, kscrolldown, {.i = mousescrollincrement }, 0, /* !alt */ -1 }, { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, @@ -273,7 +184,7 @@ static MouseShortcut mshortcuts[] = { }; /* Internal keyboard shortcuts. */ -#define MODKEY Mod4Mask +#define MODKEY Mod1Mask #define TERMMOD (ControlMask|ShiftMask) static Shortcut shortcuts[] = { @@ -282,18 +193,14 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_plus, zoomreset, {.f = 0} }, - { TERMMOD, XK_underscore, refreshxrandr, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} }, { ShiftMask, XK_Insert, selpaste, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { MODKEY, XK_l, copyurl, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; /* @@ -371,7 +278,7 @@ static Key key[] = { { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, @@ -439,7 +346,7 @@ static Key key[] = { { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, { XK_Delete, ShiftMask, "\033[2K", -1, 0}, { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, @@ -565,27 +472,3 @@ static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~"; - -/** - * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. - * - * Curly: Dunno how to draw it *shrug* - * _ _ _ _ - * ( ) ( ) ( ) ( ) - * (_) (_) (_) (_) - * - * Spiky: - * /\ /\ /\ /\ - * \/ \/ \/ - * - * Capped: - * _ _ _ - * / \ / \ / \ - * \_/ \_/ - */ -// Available styles -#define UNDERCURL_CURLY 0 -#define UNDERCURL_SPIKY 1 -#define UNDERCURL_CAPPED 2 -// Active style -#define UNDERCURL_STYLE UNDERCURL_CURLY @@ -1,13 +1,11 @@ # st version -VERSION = 0.9 +VERSION = 0.9.2 # Customize below to fit your system # paths PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man -ICONPREFIX = $(PREFIX)/share/pixmaps -ICONNAME = st.png X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib @@ -18,14 +16,12 @@ PKG_CONFIG = pkg-config INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender -lgd\ +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` -LIBS += -lXrandr - # flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -DICON=\"$(ICONPREFIX)/$(ICONNAME)\" -D_XOPEN_SOURCE=600 +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) diff --git a/patches/st-alpha-20220206-0.8.5.diff b/patches/st-alpha-20220206-0.8.5.diff deleted file mode 100644 index ab029f6..0000000 --- a/patches/st-alpha-20220206-0.8.5.diff +++ /dev/null @@ -1,146 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 91ab8ca..6af616e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -93,6 +93,9 @@ char *termname = "st-256color"; - */ - unsigned int tabspaces = 8; - -+/* bg opacity */ -+float alpha = 0.8; -+ - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { - /* 8 normal colors */ -diff --git a/config.mk b/config.mk -index 4c4c5d5..0114bad 100644 ---- a/config.mk -+++ b/config.mk -@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config - INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` --LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ -+LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -diff --git a/st.h b/st.h -index 519b9bd..8bb533d 100644 ---- a/st.h -+++ b/st.h -@@ -126,3 +126,4 @@ extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; - extern unsigned int defaultcs; -+extern float alpha; -diff --git a/x.c b/x.c -index 8a16faa..ddf4178 100644 ---- a/x.c -+++ b/x.c -@@ -105,6 +105,7 @@ typedef struct { - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ -+ int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ - } XWindow; -@@ -243,6 +244,7 @@ static char *usedfont = NULL; - static double usedfontsize = 0; - static double defaultfontsize = 0; - -+static char *opt_alpha = NULL; - static char *opt_class = NULL; - static char **opt_cmd = NULL; - static char *opt_embed = NULL; -@@ -736,7 +738,7 @@ xresize(int col, int row) - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - -@@ -796,6 +798,13 @@ xloadcols(void) - else - die("could not allocate color %d\n", i); - } -+ -+ /* set alpha value of bg color */ -+ if (opt_alpha) -+ alpha = strtof(opt_alpha, NULL); -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; - } - -@@ -1118,11 +1127,23 @@ xinit(int cols, int rows) - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ XWindowAttributes attr; -+ XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); -- xw.vis = XDefaultVisual(xw.dpy, xw.scr); -+ -+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { -+ parent = XRootWindow(xw.dpy, xw.scr); -+ xw.depth = 32; -+ } else { -+ XGetWindowAttributes(xw.dpy, parent, &attr); -+ xw.depth = attr.depth; -+ } -+ -+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); -+ xw.vis = vis.visual; - - /* font */ - if (!FcInit()) -@@ -1132,7 +1153,7 @@ xinit(int cols, int rows) - xloadfonts(usedfont, 0); - - /* colors */ -- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ -@@ -1152,19 +1173,15 @@ xinit(int cols, int rows) - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - -- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) -- parent = XRootWindow(xw.dpy, xw.scr); - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, -- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, -+ win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; -- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, -- &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); -+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -2019,6 +2036,9 @@ main(int argc, char *argv[]) - case 'a': - allowaltscreen = 0; - break; -+ case 'A': -+ opt_alpha = EARGF(usage()); -+ break; - case 'c': - opt_class = EARGF(usage()); - break; diff --git a/patches/st-alpha-osc11-20220222-0.8.5.diff b/patches/st-alpha-osc11-20220222-0.8.5.diff deleted file mode 100644 index 09a5533..0000000 --- a/patches/st-alpha-osc11-20220222-0.8.5.diff +++ /dev/null @@ -1,142 +0,0 @@ -From f4c164a63fc34c9989af15db3c10e6b658586804 Mon Sep 17 00:00:00 2001 -From: Santtu Lakkala <inz@inz.fi> -Date: Wed, 16 Feb 2022 21:23:44 +0200 -Subject: [PATCH] Alpha background - -Building on previous patches, but also apply alpha to the OSC 11, set -background, sequence. ---- - config.def.h | 3 +++ - x.c | 43 +++++++++++++++++++++++++++++++++---------- - 2 files changed, 36 insertions(+), 10 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 91ab8ca..6af616e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -93,6 +93,9 @@ char *termname = "st-256color"; - */ - unsigned int tabspaces = 8; - -+/* bg opacity */ -+float alpha = 0.8; -+ - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { - /* 8 normal colors */ -diff --git a/x.c b/x.c -index 8a16faa..812af66 100644 ---- a/x.c -+++ b/x.c -@@ -105,6 +105,7 @@ typedef struct { - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ -+ int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ - } XWindow; -@@ -736,7 +737,7 @@ xresize(int col, int row) - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - -@@ -796,6 +797,10 @@ xloadcols(void) - else - die("could not allocate color %d\n", i); - } -+ -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; - } - -@@ -826,6 +831,12 @@ xsetcolorname(int x, const char *name) - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - -+ if (x == defaultbg) { -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; -+ } -+ - return 0; - } - -@@ -1118,11 +1129,23 @@ xinit(int cols, int rows) - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ XWindowAttributes attr; -+ XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); -- xw.vis = XDefaultVisual(xw.dpy, xw.scr); -+ -+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { -+ parent = XRootWindow(xw.dpy, xw.scr); -+ xw.depth = 32; -+ } else { -+ XGetWindowAttributes(xw.dpy, parent, &attr); -+ xw.depth = attr.depth; -+ } -+ -+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); -+ xw.vis = vis.visual; - - /* font */ - if (!FcInit()) -@@ -1132,7 +1155,7 @@ xinit(int cols, int rows) - xloadfonts(usedfont, 0); - - /* colors */ -- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ -@@ -1152,19 +1175,15 @@ xinit(int cols, int rows) - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - -- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) -- parent = XRootWindow(xw.dpy, xw.scr); - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, -- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, -+ win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; -- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, -- &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); -+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -2019,6 +2038,10 @@ main(int argc, char *argv[]) - case 'a': - allowaltscreen = 0; - break; -+ case 'A': -+ alpha = strtof(EARGF(usage()), NULL); -+ LIMIT(alpha, 0.0, 1.0); -+ break; - case 'c': - opt_class = EARGF(usage()); - break; --- -2.32.0 - diff --git a/patches/st-anysize-20220718-baa9357.diff b/patches/st-anysize-20220718-baa9357.diff deleted file mode 100644 index 675ffdf..0000000 --- a/patches/st-anysize-20220718-baa9357.diff +++ /dev/null @@ -1,164 +0,0 @@ -From 8dcdc4b21a73268e167d98aa30f24315c7f3b7ff Mon Sep 17 00:00:00 2001 -From: Bakkeby <bakkeby@gmail.com> -Date: Mon, 18 Jul 2022 16:52:03 +0200 -Subject: [PATCH] Adding anysize patch - ---- - x.c | 56 ++++++++++++++++++++++++++++++-------------------------- - 1 file changed, 30 insertions(+), 26 deletions(-) - -diff --git a/x.c b/x.c -index 2a3bd38..f534347 100644 ---- a/x.c -+++ b/x.c -@@ -81,6 +81,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; - typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ -+ int hborderpx, vborderpx; - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ -@@ -331,7 +332,7 @@ ttysend(const Arg *arg) - int - evcol(XEvent *e) - { -- int x = e->xbutton.x - borderpx; -+ int x = e->xbutton.x - win.hborderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; - } -@@ -339,7 +340,7 @@ evcol(XEvent *e) - int - evrow(XEvent *e) - { -- int y = e->xbutton.y - borderpx; -+ int y = e->xbutton.y - win.vborderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; - } -@@ -739,6 +740,9 @@ cresize(int width, int height) - col = MAX(1, col); - row = MAX(1, row); - -+ win.hborderpx = (win.w - col * win.cw) / 2; -+ win.vborderpx = (win.h - row * win.ch) / 2; -+ - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -@@ -869,8 +873,8 @@ xhints(void) - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; -- sizeh->height_inc = win.ch; -- sizeh->width_inc = win.cw; -+ sizeh->height_inc = 1; -+ sizeh->width_inc = 1; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; -@@ -1152,8 +1156,8 @@ xinit(int cols, int rows) - xloadcols(); - - /* adjust fixed window geometry */ -- win.w = 2 * borderpx + cols * win.cw; -- win.h = 2 * borderpx + rows * win.ch; -+ win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw; -+ win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) -@@ -1242,7 +1246,7 @@ xinit(int cols, int rows) - int - xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) - { -- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; -+ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; -@@ -1375,7 +1379,7 @@ void - xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) - { - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); -- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, -+ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; -@@ -1465,17 +1469,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { -- xclear(0, (y == 0)? 0 : winy, borderpx, -+ xclear(0, (y == 0)? 0 : winy, win.hborderpx, - winy + win.ch + -- ((winy + win.ch >= borderpx + win.th)? win.h : 0)); -+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); - } -- if (winx + width >= borderpx + win.tw) { -+ if (winx + width >= win.hborderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, -- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); -+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) -- xclear(winx, 0, winx + width, borderpx); -- if (winy + win.ch >= borderpx + win.th) -+ xclear(winx, 0, winx + width, win.vborderpx); -+ if (winy + win.ch >= win.vborderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ -@@ -1569,35 +1573,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, -- borderpx + cx * win.cw, -- borderpx + (cy + 1) * win.ch - \ -+ win.hborderpx + cx * win.cw, -+ win.vborderpx + (cy + 1) * win.ch - \ - cursorthickness, - win.cw, cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, -- borderpx + cx * win.cw, -- borderpx + cy * win.ch, -+ win.hborderpx + cx * win.cw, -+ win.vborderpx + cy * win.ch, - cursorthickness, win.ch); - break; - } - } else { - XftDrawRect(xw.draw, &drawcol, -- borderpx + cx * win.cw, -- borderpx + cy * win.ch, -+ win.hborderpx + cx * win.cw, -+ win.vborderpx + cy * win.ch, - win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, -- borderpx + cx * win.cw, -- borderpx + cy * win.ch, -+ win.hborderpx + cx * win.cw, -+ win.vborderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, -- borderpx + (cx + 1) * win.cw - 1, -- borderpx + cy * win.ch, -+ win.hborderpx + (cx + 1) * win.cw - 1, -+ win.vborderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, -- borderpx + cx * win.cw, -- borderpx + (cy + 1) * win.ch - 1, -+ win.hborderpx + cx * win.cw, -+ win.vborderpx + (cy + 1) * win.ch - 1, - win.cw, 1); - } - } --- -2.37.1 - diff --git a/patches/st-appsync-20200618-b27a383.diff b/patches/st-appsync-20200618-b27a383.diff deleted file mode 100644 index 4736325..0000000 --- a/patches/st-appsync-20200618-b27a383.diff +++ /dev/null @@ -1,259 +0,0 @@ -From 8c9c920325fa10440a96736ba58ec647a0365e22 Mon Sep 17 00:00:00 2001 -From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> -Date: Sat, 18 Apr 2020 13:56:11 +0300 -Subject: [PATCH] application-sync: support Synchronized-Updates - -See https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec - -In a nutshell: allow an application to suspend drawing until it has -completed some output - so that the terminal will not flicker/tear by -rendering partial content. If the end-of-suspension sequence doesn't -arrive, the terminal bails out after a timeout (default: 200 ms). - -The feature is supported and pioneered by iTerm2. There are probably -very few other terminals or applications which support this feature -currently. - -One notable application which does support it is tmux (master as of -2020-04-18) - where cursor flicker is completely avoided when a pane -has new content. E.g. run in one pane: `while :; do cat x.c; done' -while the cursor is at another pane. - -The terminfo string `Sync' added to `st.info' is also a tmux extension -which tmux detects automatically when `st.info` is installed. - -Notes: - -- Draw-suspension begins on BSU sequence (Begin-Synchronized-Update), - and ends on ESU sequence (End-Synchronized-Update). - -- BSU, ESU are "\033P=1s\033\\", "\033P=2s\033\\" respectively (DCS). - -- SU doesn't support nesting - BSU begins or extends, ESU always ends. - -- ESU without BSU is ignored. - -- BSU after BSU extends (resets the timeout), so an application could - send BSU in a loop and keep drawing suspended - exactly like it can - not-draw anything in a loop. But as soon as it exits/aborted then - drawing is resumed according to the timeout even without ESU. - -- This implementation focuses on ESU and doesn't really care about BSU - in the sense that it tries hard to draw exactly once ESU arrives (if - it's not too soon after the last draw - according to minlatency), - and doesn't try to draw the content just up-to BSU. These two sides - complement eachother - not-drawing on BSU increases the chance that - ESU is not too soon after the last draw. This approach was chosen - because the application's main focus is that ESU indicates to the - terminal that the content is now ready - and that's when we try to - draw. ---- - config.def.h | 6 ++++++ - st.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- - st.info | 1 + - x.c | 22 +++++++++++++++++++--- - 4 files changed, 72 insertions(+), 5 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 6f05dce..80d768e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -56,6 +56,12 @@ int allowwindowops = 0; - static double minlatency = 8; - static double maxlatency = 33; - -+/* -+ * Synchronized-Update timeout in ms -+ * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec -+ */ -+static uint su_timeout = 200; -+ - /* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. -diff --git a/st.c b/st.c -index 76b7e0d..0582e77 100644 ---- a/st.c -+++ b/st.c -@@ -231,6 +231,33 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; - static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; - static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -+#include <time.h> -+static int su = 0; -+struct timespec sutv; -+ -+static void -+tsync_begin() -+{ -+ clock_gettime(CLOCK_MONOTONIC, &sutv); -+ su = 1; -+} -+ -+static void -+tsync_end() -+{ -+ su = 0; -+} -+ -+int -+tinsync(uint timeout) -+{ -+ struct timespec now; -+ if (su && !clock_gettime(CLOCK_MONOTONIC, &now) -+ && TIMEDIFF(now, sutv) >= timeout) -+ su = 0; -+ return su; -+} -+ - ssize_t - xwrite(int fd, const char *s, size_t len) - { -@@ -818,6 +845,9 @@ ttynew(char *line, char *cmd, char *out, char **args) - return cmdfd; - } - -+static int twrite_aborted = 0; -+int ttyread_pending() { return twrite_aborted; } -+ - size_t - ttyread(void) - { -@@ -826,7 +856,7 @@ ttyread(void) - int ret, written; - - /* append read bytes to unprocessed bytes */ -- ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); -+ ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: -@@ -834,7 +864,7 @@ ttyread(void) - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: -- buflen += ret; -+ buflen += twrite_aborted ? 0 : ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ -@@ -994,6 +1024,7 @@ tsetdirtattr(int attr) - void - tfulldirt(void) - { -+ tsync_end(); - tsetdirt(0, term.row-1); - } - -@@ -1895,6 +1926,12 @@ strhandle(void) - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ -+ /* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */ -+ if (strstr(strescseq.buf, "=1s") == strescseq.buf) -+ tsync_begin(); /* BSU */ -+ else if (strstr(strescseq.buf, "=2s") == strescseq.buf) -+ tsync_end(); /* ESU */ -+ return; - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; -@@ -2436,6 +2473,9 @@ twrite(const char *buf, int buflen, int show_ctrl) - Rune u; - int n; - -+ int su0 = su; -+ twrite_aborted = 0; -+ - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ -@@ -2446,6 +2486,10 @@ twrite(const char *buf, int buflen, int show_ctrl) - u = buf[n] & 0xFF; - charsize = 1; - } -+ if (su0 && !su) { -+ twrite_aborted = 1; -+ break; // ESU - allow rendering before a new BSU -+ } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; -diff --git a/st.info b/st.info -index 8201ad6..b32b446 100644 ---- a/st.info -+++ b/st.info -@@ -191,6 +191,7 @@ st-mono| simpleterm monocolor, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, -+ Sync=\EP=%p1%ds\E\\, - - st| simpleterm, - use=st-mono, -diff --git a/x.c b/x.c -index 210f184..27ff4e2 100644 ---- a/x.c -+++ b/x.c -@@ -1861,6 +1861,9 @@ resize(XEvent *e) - cresize(e->xconfigure.width, e->xconfigure.height); - } - -+int tinsync(uint); -+int ttyread_pending(); -+ - void - run(void) - { -@@ -1895,7 +1898,7 @@ run(void) - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - -- if (XPending(xw.dpy)) -+ if (XPending(xw.dpy) || ttyread_pending()) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; -@@ -1909,7 +1912,8 @@ run(void) - } - clock_gettime(CLOCK_MONOTONIC, &now); - -- if (FD_ISSET(ttyfd, &rfd)) -+ int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending(); -+ if (ttyin) - ttyread(); - - xev = 0; -@@ -1933,7 +1937,7 @@ run(void) - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ -- if (FD_ISSET(ttyfd, &rfd) || xev) { -+ if (ttyin || xev) { - if (!drawing) { - trigger = now; - drawing = 1; -@@ -1944,6 +1948,18 @@ run(void) - continue; /* we have time, try to find idle */ - } - -+ if (tinsync(su_timeout)) { -+ /* -+ * on synchronized-update draw-suspension: don't reset -+ * drawing so that we draw ASAP once we can (just after -+ * ESU). it won't be too soon because we already can -+ * draw now but we skip. we set timeout > 0 to draw on -+ * SU-timeout even without new content. -+ */ -+ timeout = minlatency; -+ continue; -+ } -+ - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - -base-commit: b27a383a3acc7decf00e6e889fca265430b5d329 --- -2.17.1 - diff --git a/patches/st-bold-is-not-bright-20190127-3be4cf1.diff b/patches/st-bold-is-not-bright-20190127-3be4cf1.diff deleted file mode 100644 index dd3e5bf..0000000 --- a/patches/st-bold-is-not-bright-20190127-3be4cf1.diff +++ /dev/null @@ -1,27 +0,0 @@ -From e8f3c86d93613eef5af187dfd2dba9ae9919a2ee Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rapha=C3=ABl=20Proust?= <code@bnwr.net> -Date: Sun, 27 Jan 2019 13:31:28 +0800 -Subject: [PATCH] Show bold not as bright - ---- - x.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/x.c b/x.c -index 0422421..904e1dc 100644 ---- a/x.c -+++ b/x.c -@@ -1296,10 +1296,6 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i - bg = &dc.col[base.bg]; - } - -- /* Change basic system colors [0-7] to bright system colors [8-15] */ -- if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) -- fg = &dc.col[base.fg + 8]; -- - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; --- -2.20.1 - diff --git a/patches/st-boxdraw_v2-0.8.5.diff b/patches/st-boxdraw_v2-0.8.5.diff deleted file mode 100644 index 1ba0e46..0000000 --- a/patches/st-boxdraw_v2-0.8.5.diff +++ /dev/null @@ -1,583 +0,0 @@ -From 46a1124957b8de5e7f827656b64bfc3baeaa097f Mon Sep 17 00:00:00 2001 -From: wael <40663@protonmail.com> -Date: Mon, 11 Apr 2022 17:04:30 +0300 -Subject: [PATCH] [st][patch][boxdraw] update to 0.8.5 - ---- - Makefile | 3 +- - boxdraw.c | 194 ++++++++++++++++++++++++++++++++++++++++++++ - boxdraw_data.h | 214 +++++++++++++++++++++++++++++++++++++++++++++++++ - config.def.h | 12 +++ - st.c | 3 + - st.h | 10 +++ - x.c | 21 +++-- - 7 files changed, 451 insertions(+), 6 deletions(-) - create mode 100644 boxdraw.c - create mode 100644 boxdraw_data.h - -diff --git a/Makefile b/Makefile -index 470ac86..6dfa212 100644 ---- a/Makefile -+++ b/Makefile -@@ -4,7 +4,7 @@ - - include config.mk - --SRC = st.c x.c -+SRC = st.c x.c boxdraw.c - OBJ = $(SRC:.c=.o) - - all: options st -@@ -23,6 +23,7 @@ config.h: - - st.o: config.h st.h win.h - x.o: arg.h config.h st.h win.h -+boxdraw.o: config.h st.h boxdraw_data.h - - $(OBJ): config.h config.mk - -diff --git a/boxdraw.c b/boxdraw.c -new file mode 100644 -index 0000000..28a92d0 ---- /dev/null -+++ b/boxdraw.c -@@ -0,0 +1,194 @@ -+/* -+ * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih -+ * MIT/X Consortium License -+ */ -+ -+#include <X11/Xft/Xft.h> -+#include "st.h" -+#include "boxdraw_data.h" -+ -+/* Rounded non-negative integers division of n / d */ -+#define DIV(n, d) (((n) + (d) / 2) / (d)) -+ -+static Display *xdpy; -+static Colormap xcmap; -+static XftDraw *xd; -+static Visual *xvis; -+ -+static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); -+static void drawboxlines(int, int, int, int, XftColor *, ushort); -+ -+/* public API */ -+ -+void -+boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) -+{ -+ xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; -+} -+ -+int -+isboxdraw(Rune u) -+{ -+ Rune block = u & ~0xff; -+ return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || -+ (boxdraw_braille && block == 0x2800); -+} -+ -+/* the "index" is actually the entire shape data encoded as ushort */ -+ushort -+boxdrawindex(const Glyph *g) -+{ -+ if (boxdraw_braille && (g->u & ~0xff) == 0x2800) -+ return BRL | (uint8_t)g->u; -+ if (boxdraw_bold && (g->mode & ATTR_BOLD)) -+ return BDB | boxdata[(uint8_t)g->u]; -+ return boxdata[(uint8_t)g->u]; -+} -+ -+void -+drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, -+ const XftGlyphFontSpec *specs, int len) -+{ -+ for ( ; len-- > 0; x += cw, specs++) -+ drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); -+} -+ -+/* implementation */ -+ -+void -+drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) -+{ -+ ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ -+ if (bd & (BDL | BDA)) { -+ /* lines (light/double/heavy/arcs) */ -+ drawboxlines(x, y, w, h, fg, bd); -+ -+ } else if (cat == BBD) { -+ /* lower (8-X)/8 block */ -+ int d = DIV((uint8_t)bd * h, 8); -+ XftDrawRect(xd, fg, x, y + d, w, h - d); -+ -+ } else if (cat == BBU) { -+ /* upper X/8 block */ -+ XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); -+ -+ } else if (cat == BBL) { -+ /* left X/8 block */ -+ XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); -+ -+ } else if (cat == BBR) { -+ /* right (8-X)/8 block */ -+ int d = DIV((uint8_t)bd * w, 8); -+ XftDrawRect(xd, fg, x + d, y, w - d, h); -+ -+ } else if (cat == BBQ) { -+ /* Quadrants */ -+ int w2 = DIV(w, 2), h2 = DIV(h, 2); -+ if (bd & TL) -+ XftDrawRect(xd, fg, x, y, w2, h2); -+ if (bd & TR) -+ XftDrawRect(xd, fg, x + w2, y, w - w2, h2); -+ if (bd & BL) -+ XftDrawRect(xd, fg, x, y + h2, w2, h - h2); -+ if (bd & BR) -+ XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); -+ -+ } else if (bd & BBS) { -+ /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ -+ int d = (uint8_t)bd; -+ XftColor xfc; -+ XRenderColor xrc = { .alpha = 0xffff }; -+ -+ xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); -+ xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); -+ xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); -+ -+ XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); -+ XftDrawRect(xd, &xfc, x, y, w, h); -+ XftColorFree(xdpy, xvis, xcmap, &xfc); -+ -+ } else if (cat == BRL) { -+ /* braille, each data bit corresponds to one dot at 2x4 grid */ -+ int w1 = DIV(w, 2); -+ int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); -+ -+ if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); -+ if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); -+ if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); -+ if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); -+ if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); -+ if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); -+ if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); -+ if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); -+ -+ } -+} -+ -+void -+drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) -+{ -+ /* s: stem thickness. width/8 roughly matches underscore thickness. */ -+ /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ -+ /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ -+ int mwh = MIN(w, h); -+ int base_s = MAX(1, DIV(mwh, 8)); -+ int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ -+ int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; -+ int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); -+ /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ -+ /* The base length (per direction till edge) includes this square. */ -+ -+ int light = bd & (LL | LU | LR | LD); -+ int double_ = bd & (DL | DU | DR | DD); -+ -+ if (light) { -+ /* d: additional (negative) length to not-draw the center */ -+ /* texel - at arcs and avoid drawing inside (some) doubles */ -+ int arc = bd & BDA; -+ int multi_light = light & (light - 1); -+ int multi_double = double_ & (double_ - 1); -+ /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ -+ int d = arc || (multi_double && !multi_light) ? -s : 0; -+ -+ if (bd & LL) -+ XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); -+ if (bd & LU) -+ XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); -+ if (bd & LR) -+ XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); -+ if (bd & LD) -+ XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); -+ } -+ -+ /* double lines - also align with light to form heavy when combined */ -+ if (double_) { -+ /* -+ * going clockwise, for each double-ray: p is additional length -+ * to the single-ray nearer to the previous direction, and n to -+ * the next. p and n adjust from the base length to lengths -+ * which consider other doubles - shorter to avoid intersections -+ * (p, n), or longer to draw the far-corner texel (n). -+ */ -+ int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; -+ if (dl) { -+ int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; -+ XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); -+ XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); -+ } -+ if (du) { -+ int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; -+ XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); -+ XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); -+ } -+ if (dr) { -+ int p = du ? -s : 0, n = dd ? -s : du ? s : 0; -+ XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); -+ XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); -+ } -+ if (dd) { -+ int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; -+ XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); -+ XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); -+ } -+ } -+} -diff --git a/boxdraw_data.h b/boxdraw_data.h -new file mode 100644 -index 0000000..7890500 ---- /dev/null -+++ b/boxdraw_data.h -@@ -0,0 +1,214 @@ -+/* -+ * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih -+ * MIT/X Consortium License -+ */ -+ -+/* -+ * U+25XX codepoints data -+ * -+ * References: -+ * http://www.unicode.org/charts/PDF/U2500.pdf -+ * http://www.unicode.org/charts/PDF/U2580.pdf -+ * -+ * Test page: -+ * https://github.com/GNOME/vte/blob/master/doc/boxes.txt -+ */ -+ -+/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ -+/* Categories (mutually exclusive except BDB): */ -+/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ -+#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ -+#define BDA (1<<9) /* Box Draw Arc (light) */ -+ -+#define BBD (1<<10) /* Box Block Down (lower) X/8 */ -+#define BBL (2<<10) /* Box Block Left X/8 */ -+#define BBU (3<<10) /* Box Block Upper X/8 */ -+#define BBR (4<<10) /* Box Block Right X/8 */ -+#define BBQ (5<<10) /* Box Block Quadrants */ -+#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ -+ -+#define BBS (1<<14) /* Box Block Shades */ -+#define BDB (1<<15) /* Box Draw is Bold */ -+ -+/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ -+/* Heavy is light+double (literally drawing light+double align to form heavy) */ -+#define LL (1<<0) -+#define LU (1<<1) -+#define LR (1<<2) -+#define LD (1<<3) -+#define LH (LL+LR) -+#define LV (LU+LD) -+ -+#define DL (1<<4) -+#define DU (1<<5) -+#define DR (1<<6) -+#define DD (1<<7) -+#define DH (DL+DR) -+#define DV (DU+DD) -+ -+#define HL (LL+DL) -+#define HU (LU+DU) -+#define HR (LR+DR) -+#define HD (LD+DD) -+#define HH (HL+HR) -+#define HV (HU+HD) -+ -+/* (BBQ) Quadrants Top/Bottom x Left/Right */ -+#define TL (1<<0) -+#define TR (1<<1) -+#define BL (1<<2) -+#define BR (1<<3) -+ -+/* Data for U+2500 - U+259F except dashes/diagonals */ -+static const unsigned short boxdata[256] = { -+ /* light lines */ -+ [0x00] = BDL + LH, /* light horizontal */ -+ [0x02] = BDL + LV, /* light vertical */ -+ [0x0c] = BDL + LD + LR, /* light down and right */ -+ [0x10] = BDL + LD + LL, /* light down and left */ -+ [0x14] = BDL + LU + LR, /* light up and right */ -+ [0x18] = BDL + LU + LL, /* light up and left */ -+ [0x1c] = BDL + LV + LR, /* light vertical and right */ -+ [0x24] = BDL + LV + LL, /* light vertical and left */ -+ [0x2c] = BDL + LH + LD, /* light horizontal and down */ -+ [0x34] = BDL + LH + LU, /* light horizontal and up */ -+ [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ -+ [0x74] = BDL + LL, /* light left */ -+ [0x75] = BDL + LU, /* light up */ -+ [0x76] = BDL + LR, /* light right */ -+ [0x77] = BDL + LD, /* light down */ -+ -+ /* heavy [+light] lines */ -+ [0x01] = BDL + HH, -+ [0x03] = BDL + HV, -+ [0x0d] = BDL + HR + LD, -+ [0x0e] = BDL + HD + LR, -+ [0x0f] = BDL + HD + HR, -+ [0x11] = BDL + HL + LD, -+ [0x12] = BDL + HD + LL, -+ [0x13] = BDL + HD + HL, -+ [0x15] = BDL + HR + LU, -+ [0x16] = BDL + HU + LR, -+ [0x17] = BDL + HU + HR, -+ [0x19] = BDL + HL + LU, -+ [0x1a] = BDL + HU + LL, -+ [0x1b] = BDL + HU + HL, -+ [0x1d] = BDL + HR + LV, -+ [0x1e] = BDL + HU + LD + LR, -+ [0x1f] = BDL + HD + LR + LU, -+ [0x20] = BDL + HV + LR, -+ [0x21] = BDL + HU + HR + LD, -+ [0x22] = BDL + HD + HR + LU, -+ [0x23] = BDL + HV + HR, -+ [0x25] = BDL + HL + LV, -+ [0x26] = BDL + HU + LD + LL, -+ [0x27] = BDL + HD + LU + LL, -+ [0x28] = BDL + HV + LL, -+ [0x29] = BDL + HU + HL + LD, -+ [0x2a] = BDL + HD + HL + LU, -+ [0x2b] = BDL + HV + HL, -+ [0x2d] = BDL + HL + LD + LR, -+ [0x2e] = BDL + HR + LL + LD, -+ [0x2f] = BDL + HH + LD, -+ [0x30] = BDL + HD + LH, -+ [0x31] = BDL + HD + HL + LR, -+ [0x32] = BDL + HR + HD + LL, -+ [0x33] = BDL + HH + HD, -+ [0x35] = BDL + HL + LU + LR, -+ [0x36] = BDL + HR + LU + LL, -+ [0x37] = BDL + HH + LU, -+ [0x38] = BDL + HU + LH, -+ [0x39] = BDL + HU + HL + LR, -+ [0x3a] = BDL + HU + HR + LL, -+ [0x3b] = BDL + HH + HU, -+ [0x3d] = BDL + HL + LV + LR, -+ [0x3e] = BDL + HR + LV + LL, -+ [0x3f] = BDL + HH + LV, -+ [0x40] = BDL + HU + LH + LD, -+ [0x41] = BDL + HD + LH + LU, -+ [0x42] = BDL + HV + LH, -+ [0x43] = BDL + HU + HL + LD + LR, -+ [0x44] = BDL + HU + HR + LD + LL, -+ [0x45] = BDL + HD + HL + LU + LR, -+ [0x46] = BDL + HD + HR + LU + LL, -+ [0x47] = BDL + HH + HU + LD, -+ [0x48] = BDL + HH + HD + LU, -+ [0x49] = BDL + HV + HL + LR, -+ [0x4a] = BDL + HV + HR + LL, -+ [0x4b] = BDL + HV + HH, -+ [0x78] = BDL + HL, -+ [0x79] = BDL + HU, -+ [0x7a] = BDL + HR, -+ [0x7b] = BDL + HD, -+ [0x7c] = BDL + HR + LL, -+ [0x7d] = BDL + HD + LU, -+ [0x7e] = BDL + HL + LR, -+ [0x7f] = BDL + HU + LD, -+ -+ /* double [+light] lines */ -+ [0x50] = BDL + DH, -+ [0x51] = BDL + DV, -+ [0x52] = BDL + DR + LD, -+ [0x53] = BDL + DD + LR, -+ [0x54] = BDL + DR + DD, -+ [0x55] = BDL + DL + LD, -+ [0x56] = BDL + DD + LL, -+ [0x57] = BDL + DL + DD, -+ [0x58] = BDL + DR + LU, -+ [0x59] = BDL + DU + LR, -+ [0x5a] = BDL + DU + DR, -+ [0x5b] = BDL + DL + LU, -+ [0x5c] = BDL + DU + LL, -+ [0x5d] = BDL + DL + DU, -+ [0x5e] = BDL + DR + LV, -+ [0x5f] = BDL + DV + LR, -+ [0x60] = BDL + DV + DR, -+ [0x61] = BDL + DL + LV, -+ [0x62] = BDL + DV + LL, -+ [0x63] = BDL + DV + DL, -+ [0x64] = BDL + DH + LD, -+ [0x65] = BDL + DD + LH, -+ [0x66] = BDL + DD + DH, -+ [0x67] = BDL + DH + LU, -+ [0x68] = BDL + DU + LH, -+ [0x69] = BDL + DH + DU, -+ [0x6a] = BDL + DH + LV, -+ [0x6b] = BDL + DV + LH, -+ [0x6c] = BDL + DH + DV, -+ -+ /* (light) arcs */ -+ [0x6d] = BDA + LD + LR, -+ [0x6e] = BDA + LD + LL, -+ [0x6f] = BDA + LU + LL, -+ [0x70] = BDA + LU + LR, -+ -+ /* Lower (Down) X/8 block (data is 8 - X) */ -+ [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, -+ [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, -+ -+ /* Left X/8 block (data is X) */ -+ [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, -+ [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, -+ -+ /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ -+ [0x80] = BBU + 4, [0x94] = BBU + 1, -+ [0x90] = BBR + 4, [0x95] = BBR + 7, -+ -+ /* Quadrants */ -+ [0x96] = BBQ + BL, -+ [0x97] = BBQ + BR, -+ [0x98] = BBQ + TL, -+ [0x99] = BBQ + TL + BL + BR, -+ [0x9a] = BBQ + TL + BR, -+ [0x9b] = BBQ + TL + TR + BL, -+ [0x9c] = BBQ + TL + TR + BR, -+ [0x9d] = BBQ + TR, -+ [0x9e] = BBQ + BL + TR, -+ [0x9f] = BBQ + BL + TR + BR, -+ -+ /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ -+ [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, -+ -+ /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ -+ /* U+2571 - U+2573: unsupported (diagonals) */ -+}; -diff --git a/config.def.h b/config.def.h -index 91ab8ca..7bb3ff7 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -67,6 +67,18 @@ static unsigned int blinktimeout = 800; - */ - static unsigned int cursorthickness = 2; - -+/* -+ * 1: render most of the lines/blocks characters without using the font for -+ * perfect alignment between cells (U2500 - U259F except dashes/diagonals). -+ * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. -+ * 0: disable (render all U25XX glyphs normally from the font). -+ */ -+const int boxdraw = 0; -+const int boxdraw_bold = 0; -+ -+/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -+const int boxdraw_braille = 0; -+ - /* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it -diff --git a/st.c b/st.c -index f43cfd3..baa2bed 100644 ---- a/st.c -+++ b/st.c -@@ -1214,6 +1214,9 @@ tsetchar(Rune u, const Glyph *attr, int x, int y) - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; -+ -+ if (isboxdraw(u)) -+ term.line[y][x].mode |= ATTR_BOXDRAW; - } - - void -diff --git a/st.h b/st.h -index 519b9bd..07a7c66 100644 ---- a/st.h -+++ b/st.h -@@ -33,6 +33,7 @@ enum glyph_attribute { - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, -+ ATTR_BOXDRAW = 1 << 11, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, - }; - -@@ -113,6 +114,14 @@ char *xstrdup(const char *); - - int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); - -+int isboxdraw(Rune); -+ushort boxdrawindex(const Glyph *); -+#ifdef XFT_VERSION -+/* only exposed to x.c, otherwise we'll need Xft.h for the types */ -+void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *); -+void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int); -+#endif -+ - /* config.h globals */ - extern char *utmp; - extern char *scroll; -@@ -126,3 +135,4 @@ extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; - extern unsigned int defaultcs; -+extern const int boxdraw, boxdraw_bold, boxdraw_braille; -diff --git a/x.c b/x.c -index 2a3bd38..bf6bbf9 100644 ---- a/x.c -+++ b/x.c -@@ -1237,6 +1237,8 @@ xinit(int cols, int rows) - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -+ -+ boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); - } - - int -@@ -1283,8 +1285,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x - yp = winy + font->ascent; - } - -- /* Lookup character index with default font. */ -- glyphidx = XftCharIndex(xw.dpy, font->match, rune); -+ if (mode & ATTR_BOXDRAW) { -+ /* 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].glyph = glyphidx; -@@ -1488,8 +1495,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - -- /* Render the glyphs. */ -- XftDrawGlyphFontSpec(xw.draw, fg, specs, len); -+ if (base.mode & ATTR_BOXDRAW) { -+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); -+ } else { -+ /* Render the glyphs. */ -+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); -+ } - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { -@@ -1532,7 +1543,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - /* - * Select the right color for the right mode. - */ -- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; -+ g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; --- -2.35.1 - diff --git a/patches/st-charoffsets-20220311-0.8.5.diff b/patches/st-charoffsets-20220311-0.8.5.diff deleted file mode 100644 index 4034d3f..0000000 --- a/patches/st-charoffsets-20220311-0.8.5.diff +++ /dev/null @@ -1,43 +0,0 @@ -From 944b234710e2fc00ea6e9ce9d925dc85514ac9c3 Mon Sep 17 00:00:00 2001 -From: Zacchary Dempsey-Plante <zacc@ztdp.ca> -Date: Fri, 11 Mar 2022 01:33:05 -0500 -Subject: [PATCH] Added character rendering offsets for correcting different - font dimensions. - ---- - config.def.h | 3 +++ - x.c | 4 ++-- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 91ab8ca..8877e5c 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -28,6 +28,9 @@ char *vtiden = "\033[?6c"; - /* Kerning / character bounding-box multipliers */ - static float cwscale = 1.0; - static float chscale = 1.0; -+/* Character rendering offsets in pixels */ -+static short cxoffset = 0; -+static short cyoffset = 0; - - /* - * word delimiter string -diff --git a/x.c b/x.c -index cd96575..6983743 100644 ---- a/x.c -+++ b/x.c -@@ -1288,8 +1288,8 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; -- specs[numspecs].x = (short)xp; -- specs[numspecs].y = (short)yp; -+ specs[numspecs].x = (short)xp + cxoffset; -+ specs[numspecs].y = (short)yp + cyoffset; - xp += runewidth; - numspecs++; - continue; --- -2.35.1 - diff --git a/patches/st-clipboard-0.8.3.diff b/patches/st-clipboard-0.8.3.diff deleted file mode 100644 index c1e0e9e..0000000 --- a/patches/st-clipboard-0.8.3.diff +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/x.c b/x.c -index e5f1737..5cabd60 100644 ---- a/x.c -+++ b/x.c -@@ -673,6 +673,7 @@ setsel(char *str, Time t) - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -+ clipcopy(NULL); - } - - void diff --git a/patches/st-copyurl-multiline-20220221-0.8.5.diff b/patches/st-copyurl-multiline-20220221-0.8.5.diff deleted file mode 100644 index 7cd26e2..0000000 --- a/patches/st-copyurl-multiline-20220221-0.8.5.diff +++ /dev/null @@ -1,156 +0,0 @@ -From 30a04d9ecb3998953bdbe42e5617d00d6002869b Mon Sep 17 00:00:00 2001 -From: Santtu Lakkala <inz@inz.fi> -Date: Wed, 16 Feb 2022 20:34:20 +0200 -Subject: [PATCH] Loop through urls on screen and copy to clipboard - -Replace url detection heuristics with a DFA, enabling urls that span -multiple lines. Also fix the selection not to use snapping so that urls -are selected exactly. ---- - config.def.h | 1 + - st.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - st.h | 1 + - 3 files changed, 95 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 91ab8ca..3f365c7 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -201,6 +201,7 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { MODKEY, XK_l, copyurl, {.i = 0} }, - }; - - /* -diff --git a/st.c b/st.c -index 51049ba..5b6d919 100644 ---- a/st.c -+++ b/st.c -@@ -152,6 +152,11 @@ typedef struct { - int narg; /* nb of args */ - } STREscape; - -+typedef struct { -+ int state; -+ size_t length; -+} URLdfa; -+ - static void execsh(char *, char **); - static void stty(char **); - static void sigchld(int); -@@ -200,6 +205,7 @@ static void tdefutf8(char); - static int32_t tdefcolor(const int *, int *, int); - static void tdeftran(char); - static void tstrsequence(uchar); -+static int daddch(URLdfa *, char); - - static void drawregion(int, int, int, int); - -@@ -2688,3 +2694,90 @@ redraw(void) - tfulldirt(); - draw(); - } -+ -+int -+daddch(URLdfa *dfa, char c) -+{ -+ /* () and [] can appear in urls, but excluding them here will reduce false -+ * positives when figuring out where a given url ends. -+ */ -+ static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -+ "abcdefghijklmnopqrstuvwxyz" -+ "0123456789-._~:/?#@!$&'*+,;=%"; -+ static const char RPFX[] = "//:sptth"; -+ -+ if (!strchr(URLCHARS, c)) { -+ dfa->length = 0; -+ dfa->state = 0; -+ -+ return 0; -+ } -+ -+ dfa->length++; -+ -+ if (dfa->state == 2 && c == '/') { -+ dfa->state = 0; -+ } else if (dfa->state == 3 && c == 'p') { -+ dfa->state++; -+ } else if (c != RPFX[dfa->state]) { -+ dfa->state = 0; -+ return 0; -+ } -+ -+ if (dfa->state++ == 7) { -+ dfa->state = 0; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* -+** Select and copy the previous url on screen (do nothing if there's no url). -+*/ -+void -+copyurl(const Arg *arg) { -+ int row = 0, /* row of current URL */ -+ col = 0, /* column of current URL start */ -+ colend = 0, /* column of last occurrence */ -+ passes = 0; /* how many rows have been scanned */ -+ -+ const char *c = NULL, -+ *match = NULL; -+ URLdfa dfa = { 0 }; -+ -+ row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; -+ LIMIT(row, term.top, term.bot); -+ -+ colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; -+ LIMIT(colend, 0, term.col); -+ -+ /* -+ ** Scan from (term.row - 1,term.col - 1) to (0,0) and find -+ ** next occurrance of a URL -+ */ -+ for (passes = 0; passes < term.row; passes++) { -+ /* Read in each column of every row until -+ ** we hit previous occurrence of URL -+ */ -+ for (col = colend; col--;) -+ if (daddch(&dfa, term.line[row][col].u < 128 ? term.line[row][col].u : ' ')) -+ break; -+ -+ if (col >= 0) -+ break; -+ -+ if (--row < 0) -+ row = term.row - 1; -+ -+ colend = term.col; -+ } -+ -+ if (passes < term.row) { -+ selstart(col, row, 0); -+ selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 0); -+ selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 1); -+ xsetsel(getsel()); -+ xclipcopy(); -+ } -+} -diff --git a/st.h b/st.h -index 519b9bd..0458005 100644 ---- a/st.h -+++ b/st.h -@@ -85,6 +85,7 @@ void printscreen(const Arg *); - void printsel(const Arg *); - void sendbreak(const Arg *); - void toggleprinter(const Arg *); -+void copyurl(const Arg *); - - int tattrset(int); - void tnew(int, int); --- -2.32.0 - diff --git a/patches/st-csi_22_23-0.8.5.diff b/patches/st-csi_22_23-0.8.5.diff deleted file mode 100644 index c49aa30..0000000 --- a/patches/st-csi_22_23-0.8.5.diff +++ /dev/null @@ -1,208 +0,0 @@ -From c90af45228c1100377d64ad021fa3f0cff9a1df4 Mon Sep 17 00:00:00 2001 -From: wael <40663@protonmail.com> -Date: Mon, 11 Apr 2022 21:28:43 +0300 -Subject: [PATCH] [st][patch][csi 22 23] update to 0.8.5 - ---- - st.c | 36 ++++++++++++++++++++++++++++++++---- - st.info | 4 ++-- - win.h | 4 +++- - x.c | 41 ++++++++++++++++++++++++++++++++++++++--- - 4 files changed, 75 insertions(+), 10 deletions(-) - -diff --git a/st.c b/st.c -index f43cfd3..2802381 100644 ---- a/st.c -+++ b/st.c -@@ -1801,6 +1801,33 @@ csihandle(void) - goto unknown; - } - break; -+ case 't': /* title stack operations */ -+ switch (csiescseq.arg[0]) { -+ case 22: /* pust current title on stack */ -+ switch (csiescseq.arg[1]) { -+ case 0: -+ case 1: -+ case 2: -+ xpushtitle(); -+ break; -+ default: -+ goto unknown; -+ } -+ break; -+ case 23: /* pop last title from stack */ -+ switch (csiescseq.arg[1]) { -+ case 0: -+ case 1: -+ case 2: -+ xsettitle(NULL, 1); -+ break; -+ default: -+ goto unknown; -+ } -+ break; -+ default: -+ goto unknown; -+ } - } - } - -@@ -1885,7 +1912,7 @@ strhandle(void) - switch (par) { - case 0: - if (narg > 1) { -- xsettitle(strescseq.args[1]); -+ xsettitle(strescseq.args[1], 0); - xseticontitle(strescseq.args[1]); - } - return; -@@ -1895,7 +1922,7 @@ strhandle(void) - return; - case 2: - if (narg > 1) -- xsettitle(strescseq.args[1]); -+ xsettitle(strescseq.args[1], 0); - return; - case 52: - if (narg > 2 && allowwindowops) { -@@ -1973,7 +2000,7 @@ strhandle(void) - } - break; - case 'k': /* old title set compatibility */ -- xsettitle(strescseq.args[0]); -+ xsettitle(strescseq.args[0], 0); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ -@@ -2345,6 +2372,7 @@ eschandle(uchar ascii) - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); -+ xfreetitlestack(); - resettitle(); - xloadcols(); - break; -@@ -2631,7 +2659,7 @@ tresize(int col, int row) - void - resettitle(void) - { -- xsettitle(NULL); -+ xsettitle(NULL, 0); - } - - void -diff --git a/st.info b/st.info -index 8201ad6..aeef606 100644 ---- a/st.info -+++ b/st.info -@@ -161,7 +161,7 @@ st-mono| simpleterm monocolor, - rin=\E[%p1%dT, - ritm=\E[23m, - rmacs=\E(B, -- rmcup=\E[?1049l, -+ rmcup=\E[?1049l\E[23;0;0t, - rmir=\E[4l, - rmkx=\E[?1l\E>, - rmso=\E[27m, -@@ -172,7 +172,7 @@ st-mono| simpleterm monocolor, - sitm=\E[3m, - sgr0=\E[0m, - smacs=\E(0, -- smcup=\E[?1049h, -+ smcup=\E[?1049h\E[22;0;0t, - smir=\E[4h, - smkx=\E[?1h\E=, - smso=\E[7m, -diff --git a/win.h b/win.h -index e6e4369..ef67fd6 100644 ---- a/win.h -+++ b/win.h -@@ -31,7 +31,9 @@ void xfinishdraw(void); - void xloadcols(void); - int xsetcolorname(int, const char *); - void xseticontitle(char *); --void xsettitle(char *); -+void xfreetitlestack(void); -+void xsettitle(char *, int); -+void xpushtitle(void); - int xsetcursor(int); - void xsetmode(int, unsigned int); - void xsetpointermotion(int); -diff --git a/x.c b/x.c -index 2a3bd38..babb04c 100644 ---- a/x.c -+++ b/x.c -@@ -63,6 +63,9 @@ static void ttysend(const Arg *); - /* config.h for applying patches and the configuration. */ - #include "config.h" - -+/* size of title stack */ -+#define TITLESTACKSIZE 8 -+ - /* XEMBED messages */ - #define XEMBED_FOCUS_IN 4 - #define XEMBED_FOCUS_OUT 5 -@@ -220,6 +223,8 @@ static DC dc; - static XWindow xw; - static XSelection xsel; - static TermWindow win; -+static int tstki; /* title stack index */ -+static char *titlestack[TITLESTACKSIZE]; /* title stack */ - - /* Font Ring Cache */ - enum { -@@ -1626,10 +1631,30 @@ xseticontitle(char *p) - } - - void --xsettitle(char *p) -+xfreetitlestack(void) - { -- XTextProperty prop; -- DEFAULT(p, opt_title); -+ for (int i = 0; i < LEN(titlestack); i++) { -+ free(titlestack[i]); -+ titlestack[i] = NULL; -+ } -+} -+ -+void -+xsettitle(char *p, int pop) -+{ -+ XTextProperty prop; -+ -+ free(titlestack[tstki]); -+ if (pop) { -+ titlestack[tstki] = NULL; -+ tstki = (tstki - 1 + TITLESTACKSIZE) % TITLESTACKSIZE; -+ p = titlestack[tstki] ? titlestack[tstki] : opt_title; -+ } else if (p) { -+ titlestack[tstki] = xstrdup(p); -+ } else { -+ titlestack[tstki] = NULL; -+ p = opt_title; -+ } - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) -@@ -1639,6 +1664,16 @@ xsettitle(char *p) - XFree(prop.value); - } - -+void -+xpushtitle(void) -+{ -+ int tstkin = (tstki + 1) % TITLESTACKSIZE; -+ -+ free(titlestack[tstkin]); -+ titlestack[tstkin] = titlestack[tstki] ? xstrdup(titlestack[tstki]) : NULL; -+ tstki = tstkin; -+} -+ - int - xstartdraw(void) - { --- -2.35.1 - diff --git a/patches/st-defaultfontsize-20210225-4ef0cbd.diff b/patches/st-defaultfontsize-20210225-4ef0cbd.diff deleted file mode 100644 index ee6f46d..0000000 --- a/patches/st-defaultfontsize-20210225-4ef0cbd.diff +++ /dev/null @@ -1,79 +0,0 @@ -From e3c97b85f0e94011e77af9259d379c956f9d6d64 Mon Sep 17 00:00:00 2001 -From: Randy Palamar <palamar@ualberta.ca> -Date: Thu, 25 Feb 2021 23:53:47 -0700 -Subject: [PATCH] support setting the default font size on invocation - ---- - st.1 | 8 ++++++++ - x.c | 8 +++++++- - 2 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/st.1 b/st.1 -index 39120b4..57ddfb8 100644 ---- a/st.1 -+++ b/st.1 -@@ -22,6 +22,8 @@ st \- simple terminal - .IR line ] - .RB [ \-w - .IR windowid ] -+.RB [ \-z -+.IR fontsize ] - .RB [[ \-e ] - .IR command - .RI [ arguments ...]] -@@ -44,6 +46,8 @@ st \- simple terminal - .IR title ] - .RB [ \-w - .IR windowid ] -+.RB [ \-z -+.IR fontsize ] - .RB \-l - .IR line - .RI [ stty_args ...] -@@ -91,6 +95,10 @@ defines the window title (default 'st'). - embeds st within the window identified by - .I windowid - .TP -+.BI \-z " fontsize" -+sets the default fontsize to -+.I fontsize -+.TP - .BI \-l " line" - use a tty - .I line -diff --git a/x.c b/x.c -index 120e495..224f26e 100644 ---- a/x.c -+++ b/x.c -@@ -4,6 +4,7 @@ - #include <limits.h> - #include <locale.h> - #include <signal.h> -+#include <stdlib.h> - #include <sys/select.h> - #include <time.h> - #include <unistd.h> -@@ -1114,7 +1115,7 @@ xinit(int cols, int rows) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; -- xloadfonts(usedfont, 0); -+ xloadfonts(usedfont, defaultfontsize); - - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -@@ -2038,6 +2039,11 @@ main(int argc, char *argv[]) - case 'v': - die("%s " VERSION "\n", argv0); - break; -+ case 'z': -+ defaultfontsize = strtod(EARGF(usage()), NULL); -+ if (!(defaultfontsize > 0)) -+ usage(); -+ break; - default: - usage(); - } ARGEND; --- -2.26.2 - diff --git a/patches/st-delkey-20201112-4ef0cbd.diff b/patches/st-delkey-20201112-4ef0cbd.diff deleted file mode 100644 index c334b0d..0000000 --- a/patches/st-delkey-20201112-4ef0cbd.diff +++ /dev/null @@ -1,20 +0,0 @@ ---- config.def.h.orig 2020-11-12 20:23:48.867954750 +0100 -+++ config.def.h 2020-11-12 20:21:15.055922720 +0100 -@@ -276,7 +276,7 @@ - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, -- { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, -+ { XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, -@@ -344,7 +344,7 @@ - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, -- { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, -+ { XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, diff --git a/patches/st-dynamic-cursor-color-0.9.diff b/patches/st-dynamic-cursor-color-0.9.diff deleted file mode 100644 index 1034595..0000000 --- a/patches/st-dynamic-cursor-color-0.9.diff +++ /dev/null @@ -1,50 +0,0 @@ -From 215ec30d6b5fe3319f88f1c9d16a37b6e14e5a53 Mon Sep 17 00:00:00 2001 -From: Bakkeby <bakkeby@gmail.com> -Date: Mon, 19 Dec 2022 10:20:47 +0100 -Subject: [PATCH] dynamic cursor color: cursor color taken from current - character - ---- - x.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/x.c b/x.c -index 2a3bd38..21aadce 100644 ---- a/x.c -+++ b/x.c -@@ -1520,6 +1520,7 @@ void - xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - { - Color drawcol; -+ XRenderColor colbg; - - /* remove the old cursor */ - if (selected(ox, oy)) -@@ -1548,11 +1549,21 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; -+ } else if (!(og.mode & ATTR_REVERSE)) { -+ unsigned long col = g.bg; -+ g.bg = g.fg; -+ g.fg = col; -+ } -+ -+ if (IS_TRUECOL(g.bg)) { -+ colbg.alpha = 0xffff; -+ colbg.red = TRUERED(g.bg); -+ colbg.green = TRUEGREEN(g.bg); -+ colbg.blue = TRUEBLUE(g.bg); -+ XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); - } else { -- g.fg = defaultbg; -- g.bg = defaultcs; -+ drawcol = dc.col[g.bg]; - } -- drawcol = dc.col[g.bg]; - } - - /* draw the new one */ --- -2.38.1 - diff --git a/patches/st-focus-20200731-patch_alpha.diff b/patches/st-focus-20200731-patch_alpha.diff deleted file mode 100644 index 42166b7..0000000 --- a/patches/st-focus-20200731-patch_alpha.diff +++ /dev/null @@ -1,167 +0,0 @@ -From 3307b33b60adb4e1b5db4dd9849c78fce72b6ca4 Mon Sep 17 00:00:00 2001 -From: Julius Huelsmann <juliusHuelsmann@gmail.com> -Date: Fri, 31 Jul 2020 10:13:30 +0200 -Subject: [PATCH] patch: focus - ---- - config.def.h | 5 +++-- - st.c | 1 - - st.h | 3 ++- - x.c | 44 ++++++++++++++++++++++++++++++-------------- - 4 files changed, 35 insertions(+), 18 deletions(-) - -diff --git a/config.def.h b/config.def.h -index b94b23c..577d1f1 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -85,7 +85,7 @@ char *termname = "st-256color"; - unsigned int tabspaces = 8; - - /* bg opacity */ --float alpha = 0.8; -+float alpha = 0.8, alphaUnfocused = 0.6; - - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { -@@ -123,9 +123,10 @@ static const char *colorname[] = { - * foreground, background, cursor, reverse cursor - */ - unsigned int defaultfg = 7; --unsigned int defaultbg = 258; -+unsigned int defaultbg = 0; - static unsigned int defaultcs = 256; - static unsigned int defaultrcs = 257; -+unsigned int bg = 17, bgUnfocused = 16; - - /* - * Default shape of cursor -diff --git a/st.c b/st.c -index 0ce6ac2..c7f40c8 100644 ---- a/st.c -+++ b/st.c -@@ -194,7 +194,6 @@ static void tsetscroll(int, int); - static void tswapscreen(void); - static void tsetmode(int, int, int *, int); - static int twrite(const char *, int, int); --static void tfulldirt(void); - static void tcontrolcode(uchar ); - static void tdectest(char ); - static void tdefutf8(char); -diff --git a/st.h b/st.h -index 2c656af..44cb3fd 100644 ---- a/st.h -+++ b/st.h -@@ -79,6 +79,7 @@ typedef union { - - void die(const char *, ...); - void redraw(void); -+void tfulldirt(void); - void draw(void); - - void printscreen(const Arg *); -@@ -122,4 +123,4 @@ extern char *termname; - extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; --extern float alpha; -+extern float alpha, alphaUnfocused; -diff --git a/x.c b/x.c -index 50da23c..a2e820f 100644 ---- a/x.c -+++ b/x.c -@@ -254,6 +254,8 @@ static char *opt_line = NULL; - static char *opt_name = NULL; - static char *opt_title = NULL; - -+static int focused = 0; -+ - static int oldbutton = 3; /* button event on startup: 3 = release */ - - void -@@ -774,35 +776,38 @@ xloadcolor(int i, const char *name, Color *ncolor) - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); - } - -+void -+xloadalpha(void) -+{ -+ float const usedAlpha = focused ? alpha : alphaUnfocused; -+ if (opt_alpha) alpha = strtof(opt_alpha, NULL); -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * usedAlpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24; -+} -+ - void - xloadcols(void) - { -- int i; - static int loaded; - Color *cp; - -- if (loaded) { -- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) -- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); -- } else { -- dc.collen = MAX(LEN(colorname), 256); -- dc.col = xmalloc(dc.collen * sizeof(Color)); -+ if (!loaded) { -+ dc.collen = 1 + (defaultbg = MAX(LEN(colorname), 256)); -+ dc.col = xmalloc((dc.collen) * sizeof(Color)); - } - -- for (i = 0; i < dc.collen; i++) -+ for (int i = 0; i+1 < dc.collen; ++i) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } -+ if (dc.collen) // cannot die, as the color is already loaded. -+ xloadcolor(focused ?bg :bgUnfocused, NULL, &dc.col[defaultbg]); - -- /* set alpha value of bg color */ -- if (opt_alpha) -- alpha = strtof(opt_alpha, NULL); -- dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -- dc.col[defaultbg].pixel &= 0x00FFFFFF; -- dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; -+ xloadalpha(); - loaded = 1; - } - -@@ -1747,12 +1752,22 @@ focus(XEvent *ev) - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); -+ if (!focused) { -+ focused = 1; -+ xloadcols(); -+ tfulldirt(); -+ } - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); -+ if (focused) { -+ focused = 0; -+ xloadcols(); -+ tfulldirt(); -+ } - } - } - -@@ -2065,6 +2080,7 @@ run: - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); -+ defaultbg = MAX(LEN(colorname), 256); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); --- -2.28.0 - diff --git a/patches/st-font2-0.8.5.diff b/patches/st-font2-0.8.5.diff deleted file mode 100644 index 9b22b8a..0000000 --- a/patches/st-font2-0.8.5.diff +++ /dev/null @@ -1,163 +0,0 @@ -From 1635e04d3643dd4caa0c7c2043b585c6d7e4705f Mon Sep 17 00:00:00 2001 -From: Rizqi Nur Assyaufi <bandithijo@gmail.com> -Date: Mon, 18 Jul 2022 01:15:45 +0800 -Subject: [PATCH] [st][patch][font2] Add patch for st-0.8.5 - ---- - config.def.h | 6 +++ - x.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 107 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 91ab8ca..717b2f0 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -6,6 +6,12 @@ - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ - static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -+/* Spare fonts */ -+static char *font2[] = { -+/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ -+/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ -+}; -+ - static int borderpx = 2; - - /* -diff --git a/x.c b/x.c -index 8a16faa..220fc4f 100644 ---- a/x.c -+++ b/x.c -@@ -157,6 +157,8 @@ static void xhints(void); - static int xloadcolor(int, const char *, Color *); - static int xloadfont(Font *, FcPattern *); - static void xloadfonts(const char *, double); -+static int xloadsparefont(FcPattern *, int); -+static void xloadsparefonts(void); - static void xunloadfont(Font *); - static void xunloadfonts(void); - static void xsetenv(void); -@@ -306,6 +308,7 @@ zoomabs(const Arg *arg) - { - xunloadfonts(); - xloadfonts(usedfont, arg->f); -+ xloadsparefonts(); - cresize(0, 0); - redraw(); - xhints(); -@@ -1034,6 +1037,101 @@ xloadfonts(const char *fontstr, double fontsize) - FcPatternDestroy(pattern); - } - -+int -+xloadsparefont(FcPattern *pattern, int flags) -+{ -+ FcPattern *match; -+ FcResult result; -+ -+ match = FcFontMatch(NULL, pattern, &result); -+ if (!match) { -+ return 1; -+ } -+ -+ if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { -+ FcPatternDestroy(match); -+ return 1; -+ } -+ -+ frc[frclen].flags = flags; -+ /* Believe U+0000 glyph will present in each default font */ -+ frc[frclen].unicodep = 0; -+ frclen++; -+ -+ return 0; -+} -+ -+void -+xloadsparefonts(void) -+{ -+ FcPattern *pattern; -+ double sizeshift, fontval; -+ int fc; -+ char **fp; -+ -+ if (frclen != 0) -+ die("can't embed spare fonts. cache isn't empty"); -+ -+ /* Calculate count of spare fonts */ -+ fc = sizeof(font2) / sizeof(*font2); -+ if (fc == 0) -+ return; -+ -+ /* Allocate memory for cache entries. */ -+ if (frccap < 4 * fc) { -+ frccap += 4 * fc - frccap; -+ frc = xrealloc(frc, frccap * sizeof(Fontcache)); -+ } -+ -+ for (fp = font2; fp - font2 < fc; ++fp) { -+ -+ if (**fp == '-') -+ pattern = XftXlfdParse(*fp, False, False); -+ else -+ pattern = FcNameParse((FcChar8 *)*fp); -+ -+ if (!pattern) -+ die("can't open spare font %s\n", *fp); -+ -+ if (defaultfontsize > 0) { -+ sizeshift = usedfontsize - defaultfontsize; -+ if (sizeshift != 0 && -+ FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == -+ FcResultMatch) { -+ fontval += sizeshift; -+ FcPatternDel(pattern, FC_PIXEL_SIZE); -+ FcPatternDel(pattern, FC_SIZE); -+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); -+ } -+ } -+ -+ FcPatternAddBool(pattern, FC_SCALABLE, 1); -+ -+ FcConfigSubstitute(NULL, pattern, FcMatchPattern); -+ XftDefaultSubstitute(xw.dpy, xw.scr, pattern); -+ -+ if (xloadsparefont(pattern, FRC_NORMAL)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_SLANT); -+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); -+ if (xloadsparefont(pattern, FRC_ITALIC)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_WEIGHT); -+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); -+ if (xloadsparefont(pattern, FRC_ITALICBOLD)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_SLANT); -+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); -+ if (xloadsparefont(pattern, FRC_BOLD)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDestroy(pattern); -+ } -+} -+ - void - xunloadfont(Font *f) - { -@@ -1131,6 +1229,9 @@ xinit(int cols, int rows) - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - -+ /* spare fonts */ -+ xloadsparefonts(); -+ - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - xloadcols(); --- -2.37.1 - diff --git a/patches/st-hidecursor-0.8.3.diff b/patches/st-hidecursor-0.8.3.diff deleted file mode 100644 index 4895a66..0000000 --- a/patches/st-hidecursor-0.8.3.diff +++ /dev/null @@ -1,88 +0,0 @@ -diff --git a/x.c b/x.c -index e5f1737..7e759b0 100644 ---- a/x.c -+++ b/x.c -@@ -103,6 +103,11 @@ typedef struct { - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; -+ /* Here, we use the term *pointer* to differentiate the cursor -+ * one sees when hovering the mouse over the terminal from, e.g., -+ * a green rectangle where text would be entered. */ -+ Cursor vpointer, bpointer; /* visible and hidden pointers */ -+ int pointerisvisible; - int scr; - int isfixed; /* is fixed geometry? */ - int l, t; /* left and top offset */ -@@ -698,6 +703,13 @@ brelease(XEvent *e) - void - bmotion(XEvent *e) - { -+ if (!xw.pointerisvisible) { -+ XDefineCursor(xw.dpy, xw.win, xw.vpointer); -+ xw.pointerisvisible = 1; -+ if (!IS_SET(MODE_MOUSEMANY)) -+ xsetpointermotion(0); -+ } -+ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; -@@ -1099,10 +1111,10 @@ void - xinit(int cols, int rows) - { - XGCValues gcvalues; -- Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ Pixmap blankpm; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); -@@ -1166,8 +1178,9 @@ xinit(int cols, int rows) - } - - /* white cursor, black outline */ -- cursor = XCreateFontCursor(xw.dpy, mouseshape); -- XDefineCursor(xw.dpy, xw.win, cursor); -+ xw.pointerisvisible = 1; -+ xw.vpointer = XCreateFontCursor(xw.dpy, mouseshape); -+ XDefineCursor(xw.dpy, xw.win, xw.vpointer); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; -@@ -1181,7 +1194,10 @@ xinit(int cols, int rows) - xmousebg.blue = 0x0000; - } - -- XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); -+ XRecolorCursor(xw.dpy, xw.vpointer, &xmousefg, &xmousebg); -+ blankpm = XCreateBitmapFromData(xw.dpy, xw.win, &(char){0}, 1, 1); -+ xw.bpointer = XCreatePixmapCursor(xw.dpy, blankpm, blankpm, -+ &xmousefg, &xmousebg, 0, 0); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); -@@ -1673,6 +1689,8 @@ unmap(XEvent *ev) - void - xsetpointermotion(int set) - { -+ if (!set && !xw.pointerisvisible) -+ return; - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); - } -@@ -1793,6 +1811,12 @@ kpress(XEvent *ev) - Status status; - Shortcut *bp; - -+ if (xw.pointerisvisible) { -+ XDefineCursor(xw.dpy, xw.win, xw.bpointer); -+ xsetpointermotion(1); -+ xw.pointerisvisible = 0; -+ } -+ - if (IS_SET(MODE_KBDLOCK)) - return; - diff --git a/patches/st-netwmicon-0.8.5-v2.diff b/patches/st-netwmicon-0.8.5-v2.diff deleted file mode 100644 index b02d9df..0000000 --- a/patches/st-netwmicon-0.8.5-v2.diff +++ /dev/null @@ -1,128 +0,0 @@ -From 8b0128e8b295fc97bfa3bc5fb4b5e64856d4e3cb Mon Sep 17 00:00:00 2001 -From: Aleksandrs Stier <aleks.stier@icloud.com> -Date: Sat, 4 Jun 2022 01:24:07 +0200 -Subject: [PATCH] Set _NET_WM_ICON with a png-image - ---- - Makefile | 3 +++ - config.mk | 6 ++++-- - st.h | 2 ++ - x.c | 37 ++++++++++++++++++++++++++++++++++++- - 4 files changed, 45 insertions(+), 3 deletions(-) - -diff --git a/Makefile b/Makefile -index 470ac86..96e27e3 100644 ---- a/Makefile -+++ b/Makefile -@@ -49,9 +49,12 @@ install: st - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 - tic -sx st.info - @echo Please see the README file regarding the terminfo entry of st. -+ mkdir -p $(DESTDIR)$(ICONPREFIX) -+ [ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || : - - uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/st - rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 -+ rm -f $(DESTDIR)$(ICONPREFIX)/$(ICONNAME) - - .PHONY: all options clean dist install uninstall -diff --git a/config.mk b/config.mk -index 4c4c5d5..f8fc780 100644 ---- a/config.mk -+++ b/config.mk -@@ -6,6 +6,8 @@ VERSION = 0.8.5 - # paths - PREFIX = /usr/local - MANPREFIX = $(PREFIX)/share/man -+ICONPREFIX = $(PREFIX)/share/pixmaps -+ICONNAME = st.png - - X11INC = /usr/X11R6/include - X11LIB = /usr/X11R6/lib -@@ -16,12 +18,12 @@ PKG_CONFIG = pkg-config - INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` --LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ -+LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lgd \ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - - # flags --STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -+STCPPFLAGS = -DVERSION=\"$(VERSION)\" -DICON=\"$(ICONPREFIX)/$(ICONNAME)\" -D_XOPEN_SOURCE=600 - STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) - STLDFLAGS = $(LIBS) $(LDFLAGS) - -diff --git a/st.h b/st.h -index 519b9bd..c10af86 100644 ---- a/st.h -+++ b/st.h -@@ -3,6 +3,8 @@ - #include <stdint.h> - #include <sys/types.h> - -+#include <gd.h> -+ - /* macros */ - #define MIN(a, b) ((a) < (b) ? (a) : (b)) - #define MAX(a, b) ((a) < (b) ? (b) : (a)) -diff --git a/x.c b/x.c -index 8a16faa..169e833 100644 ---- a/x.c -+++ b/x.c -@@ -93,7 +93,7 @@ typedef struct { - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ -- Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; -+ Atom xembed, wmdeletewin, netwmname, netwmicon, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; -@@ -1204,6 +1204,41 @@ xinit(int cols, int rows) - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - -+ /* use a png-image to set _NET_WM_ICON */ -+ FILE* file = fopen(ICON, "r"); -+ if (file) { -+ /* load image in rgba-format */ -+ const gdImagePtr icon_rgba = gdImageCreateFromPng(file); -+ fclose(file); -+ /* declare icon-variable which will store the image in argb-format */ -+ const int width = gdImageSX(icon_rgba); -+ const int height = gdImageSY(icon_rgba); -+ const int icon_n = width * height + 2; -+ long icon_argb[icon_n]; -+ /* set width and height of the icon */ -+ int i = 0; -+ icon_argb[i++] = width; -+ icon_argb[i++] = height; -+ /* rgba -> argb */ -+ for (int y = 0; y < height; y++) { -+ for (int x = 0; x < width; x++) { -+ const int pixel_rgba = gdImageGetPixel(icon_rgba, x, y); -+ unsigned char *pixel_argb = (unsigned char *) &icon_argb[i++]; -+ pixel_argb[0] = gdImageBlue(icon_rgba, pixel_rgba); -+ pixel_argb[1] = gdImageGreen(icon_rgba, pixel_rgba); -+ pixel_argb[2] = gdImageRed(icon_rgba, pixel_rgba); -+ /* scale alpha from 0-127 to 0-255 */ -+ const unsigned char alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba); -+ pixel_argb[3] = alpha == 127 ? 255 : alpha * 2; -+ } -+ } -+ gdImageDestroy(icon_rgba); -+ /* set _NET_WM_ICON */ -+ xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); -+ XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, -+ PropModeReplace, (uchar *) icon_argb, icon_n); -+ } -+ - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); --- -2.36.1 - diff --git a/patches/st-relativeborder-0.8.3.diff b/patches/st-relativeborder-0.8.3.diff deleted file mode 100644 index 55839d2..0000000 --- a/patches/st-relativeborder-0.8.3.diff +++ /dev/null @@ -1,39 +0,0 @@ -diff -up ../st-0.8.3/config.def.h ./config.def.h ---- ../st-0.8.3/config.def.h 2020-04-27 13:58:27.000000000 +0200 -+++ ./config.def.h 2020-05-24 18:27:19.179361165 +0200 -@@ -4,9 +4,11 @@ - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html -+ * borderperc: percentage of cell width to use as a border -+ * 0 = no border, 100 = border width is same as cell width - */ - static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; --static int borderpx = 2; -+static int borderperc = 20; - - /* - * What program is execed by st depends of these precedence rules: -diff -up ../st-0.8.3/st.h ./st.h ---- ../st-0.8.3/st.h 2020-04-27 13:58:27.000000000 +0200 -+++ ./st.h 2020-05-24 18:27:20.255369735 +0200 -@@ -52,6 +52,7 @@ enum selection_snap { - SNAP_LINE = 2 - }; - -+int borderpx; - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; -diff -up ../st-0.8.3/x.c ./x.c ---- ../st-0.8.3/x.c 2020-04-27 13:58:27.000000000 +0200 -+++ ./x.c 2020-05-24 18:27:17.551348200 +0200 -@@ -1001,6 +1001,8 @@ xloadfonts(char *fontstr, double fontsiz - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - -+ borderpx = ceilf(((float)borderperc / 100) * win.cw); -+ - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) diff --git a/patches/st-scrollback-0.8.5.diff b/patches/st-scrollback-0.8.5.diff deleted file mode 100644 index 750111d..0000000 --- a/patches/st-scrollback-0.8.5.diff +++ /dev/null @@ -1,350 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 91ab8ca..e3b469b 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, -+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, - }; - - /* -diff --git a/st.c b/st.c -index 51049ba..cd750f2 100644 ---- a/st.c -+++ b/st.c -@@ -35,6 +35,7 @@ - #define ESC_ARG_SIZ 16 - #define STR_BUF_SIZ ESC_BUF_SIZ - #define STR_ARG_SIZ ESC_ARG_SIZ -+#define HISTSIZE 2000 - - /* macros */ - #define IS_SET(flag) ((term.mode & (flag)) != 0) -@@ -42,6 +43,9 @@ - #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) - #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) - #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ -+ term.scr + HISTSIZE + 1) % HISTSIZE] : \ -+ term.line[(y) - term.scr]) - - enum term_mode { - MODE_WRAP = 1 << 0, -@@ -115,6 +119,9 @@ typedef struct { - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ -+ Line hist[HISTSIZE]; /* history buffer */ -+ int histi; /* history index */ -+ int scr; /* scroll back */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ -@@ -184,8 +191,8 @@ static void tnewline(int); - static void tputtab(int); - static void tputc(Rune); - static void treset(void); --static void tscrollup(int, int); --static void tscrolldown(int, int); -+static void tscrollup(int, int, int); -+static void tscrolldown(int, int, int); - static void tsetattr(const int *, int); - static void tsetchar(Rune, const Glyph *, int, int); - static void tsetdirt(int, int); -@@ -416,10 +423,10 @@ tlinelen(int y) - { - int i = term.col; - -- if (term.line[y][i - 1].mode & ATTR_WRAP) -+ if (TLINE(y)[i - 1].mode & ATTR_WRAP) - return i; - -- while (i > 0 && term.line[y][i - 1].u == ' ') -+ while (i > 0 && TLINE(y)[i - 1].u == ' ') - --i; - - return i; -@@ -528,7 +535,7 @@ selsnap(int *x, int *y, int direction) - * Snap around if the word wraps around at the end or - * beginning of a line. - */ -- prevgp = &term.line[*y][*x]; -+ prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; -@@ -543,14 +550,14 @@ selsnap(int *x, int *y, int direction) - yt = *y, xt = *x; - else - yt = newy, xt = newx; -- if (!(term.line[yt][xt].mode & ATTR_WRAP)) -+ if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - -- gp = &term.line[newy][newx]; -+ gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) -@@ -571,14 +578,14 @@ selsnap(int *x, int *y, int direction) - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { -- if (!(term.line[*y-1][term.col-1].mode -+ if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { -- if (!(term.line[*y][term.col-1].mode -+ if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } -@@ -609,13 +616,13 @@ getsel(void) - } - - if (sel.type == SEL_RECTANGULAR) { -- gp = &term.line[y][sel.nb.x]; -+ gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { -- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; -+ gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } -- last = &term.line[y][MIN(lastx, linelen-1)]; -+ last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - -@@ -851,6 +858,9 @@ void - ttywrite(const char *s, size_t n, int may_echo) - { - const char *next; -+ Arg arg = (Arg) { .i = term.scr }; -+ -+ kscrolldown(&arg); - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); -@@ -1062,12 +1072,52 @@ tswapscreen(void) - } - - void --tscrolldown(int orig, int n) -+kscrolldown(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (n > term.scr) -+ n = term.scr; -+ -+ if (term.scr > 0) { -+ term.scr -= n; -+ selscroll(0, -n); -+ tfulldirt(); -+ } -+} -+ -+void -+kscrollup(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (term.scr <= HISTSIZE-n) { -+ term.scr += n; -+ selscroll(0, n); -+ tfulldirt(); -+ } -+} -+ -+void -+tscrolldown(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); -+ if (copyhist) { -+ term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[term.bot]; -+ term.line[term.bot] = temp; -+ } -+ - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); -@@ -1078,17 +1128,28 @@ tscrolldown(int orig, int n) - term.line[i-n] = temp; - } - -- selscroll(orig, n); -+ if (term.scr == 0) -+ selscroll(orig, n); - } - - void --tscrollup(int orig, int n) -+tscrollup(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - -+ if (copyhist) { -+ term.histi = (term.histi + 1) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[orig]; -+ term.line[orig] = temp; -+ } -+ -+ if (term.scr > 0 && term.scr < HISTSIZE) -+ term.scr = MIN(term.scr + n, HISTSIZE-1); -+ - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - -@@ -1098,7 +1159,8 @@ tscrollup(int orig, int n) - term.line[i+n] = temp; - } - -- selscroll(orig, -n); -+ if (term.scr == 0) -+ selscroll(orig, -n); - } - - void -@@ -1127,7 +1189,7 @@ tnewline(int first_col) - int y = term.c.y; - - if (y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - y++; - } -@@ -1292,14 +1354,14 @@ void - tinsertblankline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrolldown(term.c.y, n); -+ tscrolldown(term.c.y, n, 0); - } - - void - tdeleteline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrollup(term.c.y, n); -+ tscrollup(term.c.y, n, 0); - } - - int32_t -@@ -1736,11 +1798,11 @@ csihandle(void) - break; - case 'S': /* SU -- Scroll <n> line up */ - DEFAULT(csiescseq.arg[0], 1); -- tscrollup(term.top, csiescseq.arg[0]); -+ tscrollup(term.top, csiescseq.arg[0], 0); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); -- tscrolldown(term.top, csiescseq.arg[0]); -+ tscrolldown(term.top, csiescseq.arg[0], 0); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); -@@ -2330,7 +2392,7 @@ eschandle(uchar ascii) - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } -@@ -2343,7 +2405,7 @@ eschandle(uchar ascii) - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { -- tscrolldown(term.top, 1); -+ tscrolldown(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } -@@ -2557,7 +2619,7 @@ twrite(const char *buf, int buflen, int show_ctrl) - void - tresize(int col, int row) - { -- int i; -+ int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; -@@ -2594,6 +2656,14 @@ tresize(int col, int row) - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - -+ for (i = 0; i < HISTSIZE; i++) { -+ term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); -+ for (j = mincol; j < col; j++) { -+ term.hist[i][j] = term.c.attr; -+ term.hist[i][j].u = ' '; -+ } -+ } -+ - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -@@ -2652,7 +2722,7 @@ drawregion(int x1, int y1, int x2, int y2) - continue; - - term.dirty[y] = 0; -- xdrawline(term.line[y], x1, y, x2); -+ xdrawline(TLINE(y), x1, y, x2); - } - } - -@@ -2673,8 +2743,9 @@ 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]); -+ if (term.scr == 0) -+ xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], -+ term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); -diff --git a/st.h b/st.h -index 519b9bd..da36b34 100644 ---- a/st.h -+++ b/st.h -@@ -81,6 +81,8 @@ void die(const char *, ...); - void redraw(void); - void draw(void); - -+void kscrolldown(const Arg *); -+void kscrollup(const Arg *); - void printscreen(const Arg *); - void printsel(const Arg *); - void sendbreak(const Arg *); diff --git a/patches/st-scrollback-mouse-20220127-2c5edf2.diff b/patches/st-scrollback-mouse-20220127-2c5edf2.diff deleted file mode 100644 index 5c47abc..0000000 --- a/patches/st-scrollback-mouse-20220127-2c5edf2.diff +++ /dev/null @@ -1,25 +0,0 @@ -From b5d3351a21442a842e01e8c0317603b6890b379c Mon Sep 17 00:00:00 2001 -From: asparagii <michele.lambertucci1@gmail.com> -Date: Thu, 27 Jan 2022 15:44:02 +0100 -Subject: [PATCH] st-scrollback-mouse - ---- - config.def.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/config.def.h b/config.def.h -index e3b469b..c217315 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -176,6 +176,8 @@ static uint forcemousemod = ShiftMask; - */ - static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ -+ { ShiftMask, Button4, kscrollup, {.i = 1} }, -+ { ShiftMask, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, --- -2.34.1 - diff --git a/patches/st-scrollback-mouse-altscreen-20220127-2c5edf2.diff b/patches/st-scrollback-mouse-altscreen-20220127-2c5edf2.diff deleted file mode 100644 index 6a8722b..0000000 --- a/patches/st-scrollback-mouse-altscreen-20220127-2c5edf2.diff +++ /dev/null @@ -1,78 +0,0 @@ -From 580e3f386e9215707100e9ba44797701943fd927 Mon Sep 17 00:00:00 2001 -From: asparagii <michele.lambertucci1@gmail.com> -Date: Thu, 27 Jan 2022 15:49:27 +0100 -Subject: [PATCH] st-scrollback-mouse-altscreen - ---- - config.def.h | 4 ++-- - st.c | 5 +++++ - st.h | 1 + - x.c | 2 ++ - 4 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/config.def.h b/config.def.h -index c217315..c223706 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -176,8 +176,8 @@ static uint forcemousemod = ShiftMask; - */ - static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ -- { ShiftMask, Button4, kscrollup, {.i = 1} }, -- { ShiftMask, Button5, kscrolldown, {.i = 1} }, -+ { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, /* !alt */ -1 }, -+ { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, /* !alt */ -1 }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, -diff --git a/st.c b/st.c -index f3af82b..876a6bf 100644 ---- a/st.c -+++ b/st.c -@@ -1060,6 +1060,11 @@ tnew(int col, int row) - treset(); - } - -+int tisaltscr(void) -+{ -+ return IS_SET(MODE_ALTSCREEN); -+} -+ - void - tswapscreen(void) - { -diff --git a/st.h b/st.h -index da36b34..e95c6f8 100644 ---- a/st.h -+++ b/st.h -@@ -89,6 +89,7 @@ void sendbreak(const Arg *); - void toggleprinter(const Arg *); - - int tattrset(int); -+int tisaltscr(void); - void tnew(int, int); - void tresize(int, int); - void tsetdirtattr(int); -diff --git a/x.c b/x.c -index cd96575..9274556 100644 ---- a/x.c -+++ b/x.c -@@ -34,6 +34,7 @@ typedef struct { - void (*func)(const Arg *); - const Arg arg; - uint release; -+ int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */ - } MouseShortcut; - - typedef struct { -@@ -455,6 +456,7 @@ mouseaction(XEvent *e, uint release) - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && -+ (!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); --- -2.34.1 - diff --git a/patches/st-scrollback-mouse-increment-0.8.2.diff b/patches/st-scrollback-mouse-increment-0.8.2.diff deleted file mode 100644 index 9556a9d..0000000 --- a/patches/st-scrollback-mouse-increment-0.8.2.diff +++ /dev/null @@ -1,34 +0,0 @@ -From 63e717e51dcd2f59c7a3aa75b659926aa92e08f3 Mon Sep 17 00:00:00 2001 -From: Jacob Louis Prosser <geriatricjacob@cumallover.me> -Date: Mon, 5 Aug 2019 18:20:25 +1000 -Subject: [st] [patch] Exposed variable to easily change mouse scroll increment. - ---- - config.def.h | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/config.def.h b/config.def.h -index ad20c4c..47e4b66 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -154,6 +154,7 @@ static unsigned int defaultattr = 11; - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -+const unsigned int mousescrollincrement = 1; - static MouseShortcut mshortcuts[] = { - /* button mask string */ - { Button4, XK_NO_MOD, "\031" }, -@@ -162,8 +163,8 @@ static MouseShortcut mshortcuts[] = { - - MouseKey mkeys[] = { - /* button mask function argument */ -- { Button4, ShiftMask, kscrollup, {.i = 1} }, -- { Button5, ShiftMask, kscrolldown, {.i = 1} }, -+ { Button4, ShiftMask, kscrollup, {.i = mousescrollincrement} }, -+ { Button5, ShiftMask, kscrolldown, {.i = mousescrollincrement} }, - }; - - /* Internal keyboard shortcuts. */ --- -2.22.0 diff --git a/patches/st-scrollback-reflow-0.8.5.diff b/patches/st-scrollback-reflow-0.8.5.diff deleted file mode 100644 index 085c828..0000000 --- a/patches/st-scrollback-reflow-0.8.5.diff +++ /dev/null @@ -1,1478 +0,0 @@ -diff --git a/st.c b/st.c -index 91e7077..a76d983 100644 ---- a/st.c -+++ b/st.c -@@ -36,6 +36,7 @@ - #define STR_BUF_SIZ ESC_BUF_SIZ - #define STR_ARG_SIZ ESC_ARG_SIZ - #define HISTSIZE 2000 -+#define RESIZEBUFFER 1000 - - /* macros */ - #define IS_SET(flag) ((term.mode & (flag)) != 0) -@@ -43,9 +44,22 @@ - #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) - #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) - #define ISDELIM(u) (u && wcschr(worddelimiters, u)) --#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ -- term.scr + HISTSIZE + 1) % HISTSIZE] : \ -- term.line[(y) - term.scr]) -+ -+#define TLINE(y) ( \ -+ (y) < term.scr ? term.hist[(term.histi + (y) - term.scr + 1 + HISTSIZE) % HISTSIZE] \ -+ : term.line[(y) - term.scr] \ -+) -+ -+#define TLINEABS(y) ( \ -+ (y) < 0 ? term.hist[(term.histi + (y) + 1 + HISTSIZE) % HISTSIZE] : term.line[(y)] \ -+) -+ -+#define UPDATEWRAPNEXT(alt, col) do { \ -+ if ((term.c.state & CURSOR_WRAPNEXT) && term.c.x + term.wrapcwidth[alt] < col) { \ -+ term.c.x += term.wrapcwidth[alt]; \ -+ term.c.state &= ~CURSOR_WRAPNEXT; \ -+ } \ -+} while (0); - - enum term_mode { - MODE_WRAP = 1 << 0, -@@ -57,6 +71,12 @@ enum term_mode { - MODE_UTF8 = 1 << 6, - }; - -+enum scroll_mode { -+ SCROLL_RESIZE = -1, -+ SCROLL_NOSAVEHIST = 0, -+ SCROLL_SAVEHIST = 1 -+}; -+ - enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -@@ -118,10 +138,11 @@ typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ -- Line *alt; /* alternate screen */ - Line hist[HISTSIZE]; /* history buffer */ -- int histi; /* history index */ -- int scr; /* scroll back */ -+ int histi; /* history index */ -+ int histf; /* nb history available */ -+ int scr; /* scroll back */ -+ int wrapcwidth[2]; /* used in updating WRAPNEXT when resizing */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ -@@ -179,26 +200,37 @@ static void tprinter(char *, size_t); - static void tdumpsel(void); - static void tdumpline(int); - static void tdump(void); --static void tclearregion(int, int, int, int); -+static void tclearregion(int, int, int, int, int); - static void tcursor(int); -+static void tclearglyph(Glyph *, int); -+static void tresetcursor(void); - static void tdeletechar(int); - static void tdeleteline(int); - static void tinsertblank(int); - static void tinsertblankline(int); --static int tlinelen(int); -+static int tlinelen(Line len); -+static int tiswrapped(Line line); -+static char *tgetglyphs(char *, const Glyph *, const Glyph *); -+static size_t tgetline(char *, const Glyph *); - static void tmoveto(int, int); - static void tmoveato(int, int); - static void tnewline(int); - static void tputtab(int); - static void tputc(Rune); - static void treset(void); --static void tscrollup(int, int, int); --static void tscrolldown(int, int, int); -+static void tscrollup(int, int, int, int); -+static void tscrolldown(int, int); -+static void treflow(int, int); -+static void rscrolldown(int); -+static void tresizedef(int, int); -+static void tresizealt(int, int); - static void tsetattr(const int *, int); - static void tsetchar(Rune, const Glyph *, int, int); - static void tsetdirt(int, int); - static void tsetscroll(int, int); - static void tswapscreen(void); -+static void tloaddefscreen(int, int); -+static void tloadaltscreen(int, int); - static void tsetmode(int, int, const int *, int); - static int twrite(const char *, int, int); - static void tfulldirt(void); -@@ -212,7 +244,10 @@ static void tstrsequence(uchar); - static void drawregion(int, int, int, int); - - static void selnormalize(void); --static void selscroll(int, int); -+static void selscroll(int, int, int); -+static void selmove(int); -+static void selremove(void); -+static int regionselected(int, int, int, int); - static void selsnap(int *, int *, int); - - static size_t utf8decode(const char *, Rune *, size_t); -@@ -412,17 +447,46 @@ selinit(void) - } - - int --tlinelen(int y) -+tlinelen(Line line) - { -- int i = term.col; -+ int i = term.col - 1; -+ -+ for (; i >= 0 && !(line[i].mode & (ATTR_SET | ATTR_WRAP)); i--); -+ return i + 1; -+} - -- if (TLINE(y)[i - 1].mode & ATTR_WRAP) -- return i; -+int -+tiswrapped(Line line) -+{ -+ int len = tlinelen(line); - -- while (i > 0 && TLINE(y)[i - 1].u == ' ') -- --i; -+ return len > 0 && (line[len - 1].mode & ATTR_WRAP); -+} - -- return i; -+char * -+tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp) -+{ -+ while (gp <= lgp) -+ if (gp->mode & ATTR_WDUMMY) { -+ gp++; -+ } else { -+ buf += utf8encode((gp++)->u, buf); -+ } -+ return buf; -+} -+ -+size_t -+tgetline(char *buf, const Glyph *fgp) -+{ -+ char *ptr; -+ const Glyph *lgp = &fgp[term.col - 1]; -+ -+ while (lgp > fgp && !(lgp->mode & (ATTR_SET | ATTR_WRAP))) -+ lgp--; -+ ptr = tgetglyphs(buf, fgp, lgp); -+ if (!(lgp->mode & ATTR_WRAP)) -+ *(ptr++) = '\n'; -+ return ptr - buf; - } - - void -@@ -462,10 +526,11 @@ selextend(int col, int row, int type, int done) - - sel.oe.x = col; - sel.oe.y = row; -- selnormalize(); - sel.type = type; -+ selnormalize(); - -- if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) -+ if (oldey != sel.oe.y || oldex != sel.oe.x || -+ oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -@@ -492,36 +557,43 @@ selnormalize(void) - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; -- i = tlinelen(sel.nb.y); -- if (i < sel.nb.x) -+ -+ i = tlinelen(TLINE(sel.nb.y)); -+ if (sel.nb.x > i) - sel.nb.x = i; -- if (tlinelen(sel.ne.y) <= sel.ne.x) -- sel.ne.x = term.col - 1; -+ if (sel.ne.x >= tlinelen(TLINE(sel.ne.y))) -+ sel.ne.x = term.col - 1; - } - - int --selected(int x, int y) -+regionselected(int x1, int y1, int x2, int y2) - { -- if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || -- sel.alt != IS_SET(MODE_ALTSCREEN)) -+ if (sel.ob.x == -1 || sel.mode == SEL_EMPTY || -+ sel.alt != IS_SET(MODE_ALTSCREEN) || sel.nb.y > y2 || sel.ne.y < y1) - return 0; - -- if (sel.type == SEL_RECTANGULAR) -- return BETWEEN(y, sel.nb.y, sel.ne.y) -- && BETWEEN(x, sel.nb.x, sel.ne.x); -+ return (sel.type == SEL_RECTANGULAR) ? sel.nb.x <= x2 && sel.ne.x >= x1 -+ : (sel.nb.y != y2 || sel.nb.x <= x2) && -+ (sel.ne.y != y1 || sel.ne.x >= x1); -+} - -- return BETWEEN(y, sel.nb.y, sel.ne.y) -- && (y != sel.nb.y || x >= sel.nb.x) -- && (y != sel.ne.y || x <= sel.ne.x); -+int -+selected(int x, int y) -+{ -+ return regionselected(x, y, x, y); - } - - void - selsnap(int *x, int *y, int direction) - { - int newx, newy, xt, yt; -+ int rtop = 0, rbot = term.row - 1; - int delim, prevdelim; - const Glyph *gp, *prevgp; - -+ if (!IS_SET(MODE_ALTSCREEN)) -+ rtop += -term.histf + term.scr, rbot += term.scr; -+ - switch (sel.snap) { - case SNAP_WORD: - /* -@@ -536,7 +608,7 @@ selsnap(int *x, int *y, int direction) - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; -- if (!BETWEEN(newy, 0, term.row - 1)) -+ if (!BETWEEN(newy, rtop, rbot)) - break; - - if (direction > 0) -@@ -547,13 +619,13 @@ selsnap(int *x, int *y, int direction) - break; - } - -- if (newx >= tlinelen(newy)) -+ if (newx >= tlinelen(TLINE(newy))) - break; - - gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); -- if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim -- || (delim && gp->u != prevgp->u))) -+ if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || -+ (delim && !(gp->u == ' ' && prevgp->u == ' ')))) - break; - - *x = newx; -@@ -570,18 +642,14 @@ selsnap(int *x, int *y, int direction) - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { -- for (; *y > 0; *y += direction) { -- if (!(TLINE(*y-1)[term.col-1].mode -- & ATTR_WRAP)) { -+ for (; *y > rtop; *y -= 1) { -+ if (!tiswrapped(TLINE(*y-1))) - break; -- } - } - } else if (direction > 0) { -- for (; *y < term.row-1; *y += direction) { -- if (!(TLINE(*y)[term.col-1].mode -- & ATTR_WRAP)) { -+ for (; *y < rbot; *y += 1) { -+ if (!tiswrapped(TLINE(*y))) - break; -- } - } - } - break; -@@ -592,40 +660,34 @@ char * - getsel(void) - { - char *str, *ptr; -- int y, bufsize, lastx, linelen; -- const Glyph *gp, *last; -+ int y, lastx, linelen; -+ const Glyph *gp, *lgp; - -- if (sel.ob.x == -1) -+ if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) - return NULL; - -- bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; -- ptr = str = xmalloc(bufsize); -+ str = xmalloc((term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ); -+ ptr = str; - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { -- if ((linelen = tlinelen(y)) == 0) { -+ Line line = TLINE(y); -+ -+ if ((linelen = tlinelen(line)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { -- gp = &TLINE(y)[sel.nb.x]; -+ gp = &line[sel.nb.x]; - lastx = sel.ne.x; - } else { -- gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; -+ gp = &line[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } -- last = &TLINE(y)[MIN(lastx, linelen-1)]; -- while (last >= gp && last->u == ' ') -- --last; -- -- for ( ; gp <= last; ++gp) { -- if (gp->mode & ATTR_WDUMMY) -- continue; -- -- ptr += utf8encode(gp->u, ptr); -- } -+ lgp = &line[MIN(lastx, linelen-1)]; - -+ ptr = tgetglyphs(ptr, gp, lgp); - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. -@@ -636,10 +698,10 @@ getsel(void) - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && -- (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) -+ (!(lgp->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } -- *ptr = 0; -+ *ptr = '\0'; - return str; - } - -@@ -648,9 +710,15 @@ selclear(void) - { - if (sel.ob.x == -1) - return; -+ selremove(); -+ tsetdirt(sel.nb.y, sel.ne.y); -+} -+ -+void -+selremove(void) -+{ - sel.mode = SEL_IDLE; - sel.ob.x = -1; -- tsetdirt(sel.nb.y, sel.ne.y); - } - - void -@@ -851,10 +919,8 @@ void - ttywrite(const char *s, size_t n, int may_echo) - { - const char *next; -- Arg arg = (Arg) { .i = term.scr }; -- -- kscrolldown(&arg); - -+ kscrolldown(&((Arg){ .i = term.scr })); - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - -@@ -990,7 +1056,7 @@ tsetdirtattr(int attr) - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) { -- tsetdirt(i, i); -+ term.dirty[i] = 1; - break; - } - } -@@ -1000,7 +1066,8 @@ tsetdirtattr(int attr) - void - tfulldirt(void) - { -- tsetdirt(0, term.row-1); -+ for (int i = 0; i < term.row; i++) -+ term.dirty[i] = 1; - } - - void -@@ -1017,51 +1084,116 @@ tcursor(int mode) - } - } - -+void -+tresetcursor(void) -+{ -+ term.c = (TCursor){ { .mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg }, -+ .x = 0, .y = 0, .state = CURSOR_DEFAULT }; -+} -+ - void - treset(void) - { - uint i; -+ int x, y; - -- term.c = (TCursor){{ -- .mode = ATTR_NULL, -- .fg = defaultfg, -- .bg = defaultbg -- }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; -+ tresetcursor(); - - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; -+ term.histf = 0; -+ term.scr = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - -+ selremove(); - for (i = 0; i < 2; i++) { -- tmoveto(0, 0); -- tcursor(CURSOR_SAVE); -- tclearregion(0, 0, term.col-1, term.row-1); -+ tcursor(CURSOR_SAVE); /* reset saved cursor */ -+ for (y = 0; y < term.row; y++) -+ for (x = 0; x < term.col; x++) -+ tclearglyph(&term.line[y][x], 0); - tswapscreen(); - } -+ tfulldirt(); - } - - void - tnew(int col, int row) - { -- term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; -- tresize(col, row); -- treset(); -+ int i, j; -+ -+ for (i = 0; i < 2; i++) { -+ term.line = xmalloc(row * sizeof(Line)); -+ for (j = 0; j < row; j++) -+ term.line[j] = xmalloc(col * sizeof(Glyph)); -+ term.col = col, term.row = row; -+ tswapscreen(); -+ } -+ term.dirty = xmalloc(row * sizeof(*term.dirty)); -+ term.tabs = xmalloc(col * sizeof(*term.tabs)); -+ for (i = 0; i < HISTSIZE; i++) -+ term.hist[i] = xmalloc(col * sizeof(Glyph)); -+ treset(); - } - -+/* handle it with care */ - void - tswapscreen(void) - { -- Line *tmp = term.line; -+ static Line *altline; -+ static int altcol, altrow; -+ Line *tmpline = term.line; -+ int tmpcol = term.col, tmprow = term.row; - -- term.line = term.alt; -- term.alt = tmp; -+ term.line = altline; -+ term.col = altcol, term.row = altrow; -+ altline = tmpline; -+ altcol = tmpcol, altrow = tmprow; - term.mode ^= MODE_ALTSCREEN; -- tfulldirt(); -+} -+ -+void -+tloaddefscreen(int clear, int loadcursor) -+{ -+ int col, row, alt = IS_SET(MODE_ALTSCREEN); -+ -+ if (alt) { -+ if (clear) -+ tclearregion(0, 0, term.col-1, term.row-1, 1); -+ col = term.col, row = term.row; -+ tswapscreen(); -+ } -+ if (loadcursor) -+ tcursor(CURSOR_LOAD); -+ if (alt) -+ tresizedef(col, row); -+} -+ -+void -+tloadaltscreen(int clear, int savecursor) -+{ -+ int col, row, def = !IS_SET(MODE_ALTSCREEN); -+ -+ if (savecursor) -+ tcursor(CURSOR_SAVE); -+ if (def) { -+ col = term.col, row = term.row; -+ tswapscreen(); -+ term.scr = 0; -+ tresizealt(col, row); -+ } -+ if (clear) -+ tclearregion(0, 0, term.col-1, term.row-1, 1); -+} -+ -+int -+tisaltscreen(void) -+{ -+ return IS_SET(MODE_ALTSCREEN); - } - - void -@@ -1069,17 +1201,22 @@ kscrolldown(const Arg* a) - { - int n = a->i; - -- if (n < 0) -- n = term.row + n; -+ if (!term.scr || IS_SET(MODE_ALTSCREEN)) -+ return; - -- if (n > term.scr) -- n = term.scr; -+ if (n < 0) -+ n = MAX(term.row / -n, 1); - -- if (term.scr > 0) { -+ if (n <= term.scr) { - term.scr -= n; -- selscroll(0, -n); -- tfulldirt(); -+ } else { -+ n = term.scr; -+ term.scr = 0; - } -+ -+ if (sel.ob.x != -1 && !sel.alt) -+ selmove(-n); /* negate change in term.scr */ -+ tfulldirt(); - } - - void -@@ -1087,92 +1224,118 @@ kscrollup(const Arg* a) - { - int n = a->i; - -+ if (!term.histf || IS_SET(MODE_ALTSCREEN)) -+ return; -+ - if (n < 0) -- n = term.row + n; -+ n = MAX(term.row / -n, 1); - -- if (term.scr <= HISTSIZE-n) { -+ if (term.scr + n <= term.histf) { - term.scr += n; -- selscroll(0, n); -- tfulldirt(); -+ } else { -+ n = term.histf - term.scr; -+ term.scr = term.histf; - } -+ -+ if (sel.ob.x != -1 && !sel.alt) -+ selmove(n); /* negate change in term.scr */ -+ tfulldirt(); - } - - void --tscrolldown(int orig, int n, int copyhist) -+tscrolldown(int top, int n) - { -- int i; -+ int i, bot = term.bot; - Line temp; - -- LIMIT(n, 0, term.bot-orig+1); -- if (copyhist) { -- term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; -- temp = term.hist[term.histi]; -- term.hist[term.histi] = term.line[term.bot]; -- term.line[term.bot] = temp; -- } -- -+ if (n <= 0) -+ return; -+ n = MIN(n, bot-top+1); - -- tsetdirt(orig, term.bot-n); -- tclearregion(0, term.bot-n+1, term.col-1, term.bot); -+ tsetdirt(top, bot-n); -+ tclearregion(0, bot-n+1, term.col-1, bot, 1); - -- for (i = term.bot; i >= orig+n; i--) { -+ for (i = bot; i >= top+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - -- if (term.scr == 0) -- selscroll(orig, n); -+ if (sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN)) -+ selscroll(top, bot, n); - } - - void --tscrollup(int orig, int n, int copyhist) -+tscrollup(int top, int bot, int n, int mode) - { -- int i; -+ int i, j, s; -+ int alt = IS_SET(MODE_ALTSCREEN); -+ int savehist = !alt && top == 0 && mode != SCROLL_NOSAVEHIST; - Line temp; - -- LIMIT(n, 0, term.bot-orig+1); -- -- if (copyhist) { -- term.histi = (term.histi + 1) % HISTSIZE; -- temp = term.hist[term.histi]; -- term.hist[term.histi] = term.line[orig]; -- term.line[orig] = temp; -+ if (n <= 0) -+ return; -+ n = MIN(n, bot-top+1); -+ -+ if (savehist) { -+ for (i = 0; i < n; i++) { -+ term.histi = (term.histi + 1) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ for (j = 0; j < term.col; j++) -+ tclearglyph(&temp[j], 1); -+ term.hist[term.histi] = term.line[i]; -+ term.line[i] = temp; -+ } -+ term.histf = MIN(term.histf + n, HISTSIZE); -+ s = n; -+ if (term.scr) { -+ j = term.scr; -+ term.scr = MIN(j + n, HISTSIZE); -+ s = j + n - term.scr; -+ } -+ if (mode != SCROLL_RESIZE) -+ tfulldirt(); -+ } else { -+ tclearregion(0, top, term.col-1, top+n-1, 1); -+ tsetdirt(top+n, bot); - } - -- if (term.scr > 0 && term.scr < HISTSIZE) -- term.scr = MIN(term.scr + n, HISTSIZE-1); -- -- tclearregion(0, orig, term.col-1, orig+n-1); -- tsetdirt(orig+n, term.bot); -- -- for (i = orig; i <= term.bot-n; i++) { -+ for (i = top; i <= bot-n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i+n]; - term.line[i+n] = temp; - } - -- if (term.scr == 0) -- selscroll(orig, -n); -+ if (sel.ob.x != -1 && sel.alt == alt) { -+ if (!savehist) { -+ selscroll(top, bot, -n); -+ } else if (s > 0) { -+ selmove(-s); -+ if (-term.scr + sel.nb.y < -term.histf) -+ selremove(); -+ } -+ } - } - - void --selscroll(int orig, int n) -+selmove(int n) - { -- if (sel.ob.x == -1) -- return; -+ sel.ob.y += n, sel.nb.y += n; -+ sel.oe.y += n, sel.ne.y += n; -+} -+ -+void -+selscroll(int top, int bot, int n) -+{ -+ /* turn absolute coordinates into relative */ -+ top += term.scr, bot += term.scr; - -- if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { -+ if (BETWEEN(sel.nb.y, top, bot) != BETWEEN(sel.ne.y, top, bot)) { - selclear(); -- } else if (BETWEEN(sel.nb.y, orig, term.bot)) { -- sel.ob.y += n; -- sel.oe.y += n; -- if (sel.ob.y < term.top || sel.ob.y > term.bot || -- sel.oe.y < term.top || sel.oe.y > term.bot) { -+ } else if (BETWEEN(sel.nb.y, top, bot)) { -+ selmove(n); -+ if (sel.nb.y < top || sel.ne.y > bot) - selclear(); -- } else { -- selnormalize(); -- } - } - } - -@@ -1182,7 +1345,7 @@ tnewline(int first_col) - int y = term.c.y; - - if (y == term.bot) { -- tscrollup(term.top, 1, 1); -+ tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); - } else { - y++; - } -@@ -1272,89 +1435,93 @@ tsetchar(Rune u, const Glyph *attr, int x, int y) - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x-1].u = ' '; - term.line[y][x-1].mode &= ~ATTR_WIDE; -- } -+ } - - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; -+ term.line[y][x].mode |= ATTR_SET; - } - - void --tclearregion(int x1, int y1, int x2, int y2) -+tclearglyph(Glyph *gp, int usecurattr) - { -- int x, y, temp; -- Glyph *gp; -+ if (usecurattr) { -+ gp->fg = term.c.attr.fg; -+ gp->bg = term.c.attr.bg; -+ } else { -+ gp->fg = defaultfg; -+ gp->bg = defaultbg; -+ } -+ gp->mode = ATTR_NULL; -+ gp->u = ' '; -+} - -- if (x1 > x2) -- temp = x1, x1 = x2, x2 = temp; -- if (y1 > y2) -- temp = y1, y1 = y2, y2 = temp; -+void -+tclearregion(int x1, int y1, int x2, int y2, int usecurattr) -+{ -+ int x, y; - -- LIMIT(x1, 0, term.col-1); -- LIMIT(x2, 0, term.col-1); -- LIMIT(y1, 0, term.row-1); -- LIMIT(y2, 0, term.row-1); -+ /* regionselected() takes relative coordinates */ -+ if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) -+ selremove(); - - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; -- for (x = x1; x <= x2; x++) { -- gp = &term.line[y][x]; -- if (selected(x, y)) -- selclear(); -- gp->fg = term.c.attr.fg; -- gp->bg = term.c.attr.bg; -- gp->mode = 0; -- gp->u = ' '; -- } -+ for (x = x1; x <= x2; x++) -+ tclearglyph(&term.line[y][x], usecurattr); - } - } - - void - tdeletechar(int n) - { -- int dst, src, size; -- Glyph *line; -- -- LIMIT(n, 0, term.col - term.c.x); -+ int src, dst, size; -+ Line line; - -+ if (n <= 0) -+ return; - dst = term.c.x; -- src = term.c.x + n; -+ src = MIN(term.c.x + n, term.col); - size = term.col - src; -- line = term.line[term.c.y]; -- -- memmove(&line[dst], &line[src], size * sizeof(Glyph)); -- tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); -+ if (size > 0) { /* otherwise src would point beyond the array -+ https://stackoverflow.com/questions/29844298 */ -+ line = term.line[term.c.y]; -+ memmove(&line[dst], &line[src], size * sizeof(Glyph)); -+ } -+ tclearregion(dst + size, term.c.y, term.col - 1, term.c.y, 1); - } - - void - tinsertblank(int n) - { -- int dst, src, size; -- Glyph *line; -+ int src, dst, size; -+ Line line; - -- LIMIT(n, 0, term.col - term.c.x); -- -- dst = term.c.x + n; -+ if (n <= 0) -+ return; -+ dst = MIN(term.c.x + n, term.col); - src = term.c.x; - size = term.col - dst; -- line = term.line[term.c.y]; -- -- memmove(&line[dst], &line[src], size * sizeof(Glyph)); -- tclearregion(src, term.c.y, dst - 1, term.c.y); -+ if (size > 0) { /* otherwise dst would point beyond the array */ -+ line = term.line[term.c.y]; -+ memmove(&line[dst], &line[src], size * sizeof(Glyph)); -+ } -+ tclearregion(src, term.c.y, dst - 1, term.c.y, 1); - } - - void - tinsertblankline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrolldown(term.c.y, n, 0); -+ tscrolldown(term.c.y, n); - } - - void - tdeleteline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrollup(term.c.y, n, 0); -+ tscrollup(term.c.y, term.bot, n, SCROLL_NOSAVEHIST); - } - - int32_t -@@ -1528,7 +1695,7 @@ tsetscroll(int t, int b) - void - tsetmode(int priv, int set, const int *args, int narg) - { -- int alt; const int *lim; -+ const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { -@@ -1589,25 +1756,18 @@ tsetmode(int priv, int set, const int *args, int narg) - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ -- if (!allowaltscreen) -- break; -- tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); -- /* FALLTHROUGH */ - case 47: /* swap screen */ -- case 1047: -+ case 1047: /* swap screen, clearing alternate screen */ - if (!allowaltscreen) - break; -- alt = IS_SET(MODE_ALTSCREEN); -- if (alt) { -- tclearregion(0, 0, term.col-1, -- term.row-1); -- } -- if (set ^ alt) /* set is always 1 or 0 */ -- tswapscreen(); -- if (*args != 1049) -- break; -- /* FALLTHROUGH */ -+ if (set) -+ tloadaltscreen(*args == 1049, *args == 1049); -+ else -+ tloaddefscreen(*args == 1047, *args == 1049); -+ break; - case 1048: -+ if (!allowaltscreen) -+ break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ -@@ -1659,7 +1819,7 @@ void - csihandle(void) - { - char buf[40]; -- int len; -+ int n, x; - - switch (csiescseq.mode[0]) { - default: -@@ -1757,20 +1917,30 @@ csihandle(void) - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ -- tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); -+ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); - if (term.c.y < term.row-1) { -- tclearregion(0, term.c.y+1, term.col-1, -- term.row-1); -+ tclearregion(0, term.c.y+1, term.col-1, term.row-1, 1); - } - break; - case 1: /* above */ -- if (term.c.y > 1) -- tclearregion(0, 0, term.col-1, term.c.y-1); -- tclearregion(0, term.c.y, term.c.x, term.c.y); -+ if (term.c.y >= 1) -+ tclearregion(0, 0, term.col-1, term.c.y-1, 1); -+ tclearregion(0, term.c.y, term.c.x, term.c.y, 1); - break; - case 2: /* all */ -- tclearregion(0, 0, term.col-1, term.row-1); -- break; -+ if (IS_SET(MODE_ALTSCREEN)) { -+ tclearregion(0, 0, term.col-1, term.row-1, 1); -+ break; -+ } -+ /* vte does this: -+ tscrollup(0, term.row-1, term.row, SCROLL_SAVEHIST); */ -+ -+ /* alacritty does this: */ -+ for (n = term.row-1; n >= 0 && tlinelen(term.line[n]) == 0; n--); -+ if (n >= 0) -+ tscrollup(0, term.row-1, n+1, SCROLL_SAVEHIST); -+ tscrollup(0, term.row-1, term.row-n-1, SCROLL_NOSAVEHIST); -+ break; - default: - goto unknown; - } -@@ -1778,24 +1948,24 @@ csihandle(void) - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ -- tclearregion(term.c.x, term.c.y, term.col-1, -- term.c.y); -+ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); - break; - case 1: /* left */ -- tclearregion(0, term.c.y, term.c.x, term.c.y); -+ tclearregion(0, term.c.y, term.c.x, term.c.y, 1); - break; - case 2: /* all */ -- tclearregion(0, term.c.y, term.col-1, term.c.y); -+ tclearregion(0, term.c.y, term.col-1, term.c.y, 1); - break; - } - break; - case 'S': /* SU -- Scroll <n> line up */ - DEFAULT(csiescseq.arg[0], 1); -- tscrollup(term.top, csiescseq.arg[0], 0); -+ /* xterm, urxvt, alacritty save this in history */ -+ tscrollup(term.top, term.bot, csiescseq.arg[0], SCROLL_SAVEHIST); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); -- tscrolldown(term.top, csiescseq.arg[0], 0); -+ tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); -@@ -1809,9 +1979,11 @@ csihandle(void) - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase <n> char */ -+ if (csiescseq.arg[0] < 0) -+ return; - DEFAULT(csiescseq.arg[0], 1); -- tclearregion(term.c.x, term.c.y, -- term.c.x + csiescseq.arg[0] - 1, term.c.y); -+ x = MIN(term.c.x + csiescseq.arg[0], term.col) - 1; -+ tclearregion(term.c.x, term.c.y, x, term.c.y, 1); - break; - case 'P': /* DCH -- Delete <n> char */ - DEFAULT(csiescseq.arg[0], 1); -@@ -1833,9 +2005,9 @@ csihandle(void) - break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { -- len = snprintf(buf, sizeof(buf), "\033[%i;%iR", -+ n = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); -- ttywrite(buf, len, 0); -+ ttywrite(buf, n, 0); - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ -@@ -2128,16 +2300,8 @@ tdumpsel(void) - void - tdumpline(int n) - { -- char buf[UTF_SIZ]; -- const Glyph *bp, *end; -- -- bp = &term.line[n][0]; -- end = &bp[MIN(tlinelen(n), term.col) - 1]; -- if (bp != end || bp->u != ' ') { -- for ( ; bp <= end; ++bp) -- tprinter(buf, utf8encode(bp->u, buf)); -- } -- tprinter("\n", 1); -+ char str[(term.col + 1) * UTF_SIZ]; -+ tprinter(str, tgetline(str, &term.line[n][0])); - } - - void -@@ -2358,7 +2522,7 @@ eschandle(uchar ascii) - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { -- tscrollup(term.top, 1, 1); -+ tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); - } else { - tmoveto(term.c.x, term.c.y+1); - } -@@ -2371,7 +2535,7 @@ eschandle(uchar ascii) - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { -- tscrolldown(term.top, 1, 1); -+ tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } -@@ -2511,7 +2675,8 @@ check_control_code: - */ - return; - } -- if (selected(term.c.x, term.c.y)) -+ /* selected() takes relative coordinates */ -+ if (selected(term.c.x + term.scr, term.c.y + term.scr)) - selclear(); - - gp = &term.line[term.c.y][term.c.x]; -@@ -2546,6 +2711,7 @@ check_control_code: - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { -+ term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = width; - term.c.state |= CURSOR_WRAPNEXT; - } - } -@@ -2583,93 +2749,275 @@ twrite(const char *buf, int buflen, int show_ctrl) - } - - void --tresize(int col, int row) -+treflow(int col, int row) - { - int i, j; -- int minrow = MIN(row, term.row); -- int mincol = MIN(col, term.col); -- int *bp; -- TCursor c; -- -- if (col < 1 || row < 1) { -- fprintf(stderr, -- "tresize: error resizing to %dx%d\n", col, row); -- return; -+ int oce, nce, bot, scr; -+ int ox = 0, oy = -term.histf, nx = 0, ny = -1, len; -+ int cy = -1; /* proxy for new y coordinate of cursor */ -+ int nlines; -+ Line *buf, line; -+ -+ /* y coordinate of cursor line end */ -+ for (oce = term.c.y; oce < term.row - 1 && -+ tiswrapped(term.line[oce]); oce++); -+ -+ nlines = term.histf + oce + 1; -+ if (col < term.col) { -+ /* each line can take this many lines after reflow */ -+ j = (term.col + col - 1) / col; -+ nlines = j * nlines; -+ if (nlines > HISTSIZE + RESIZEBUFFER + row) { -+ nlines = HISTSIZE + RESIZEBUFFER + row; -+ oy = -(nlines / j - oce - 1); -+ } - } -+ buf = xmalloc(nlines * sizeof(Line)); -+ do { -+ if (!nx) -+ buf[++ny] = xmalloc(col * sizeof(Glyph)); -+ if (!ox) { -+ line = TLINEABS(oy); -+ len = tlinelen(line); -+ } -+ if (oy == term.c.y) { -+ if (!ox) -+ len = MAX(len, term.c.x + 1); -+ /* update cursor */ -+ if (cy < 0 && term.c.x - ox < col - nx) { -+ term.c.x = nx + term.c.x - ox, cy = ny; -+ UPDATEWRAPNEXT(0, col); -+ } -+ } -+ /* get reflowed lines in buf */ -+ if (col - nx > len - ox) { -+ memcpy(&buf[ny][nx], &line[ox], (len-ox) * sizeof(Glyph)); -+ nx += len - ox; -+ if (len == 0 || !(line[len - 1].mode & ATTR_WRAP)) { -+ for (j = nx; j < col; j++) -+ tclearglyph(&buf[ny][j], 0); -+ nx = 0; -+ } else if (nx > 0) { -+ buf[ny][nx - 1].mode &= ~ATTR_WRAP; -+ } -+ ox = 0, oy++; -+ } else if (col - nx == len - ox) { -+ memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); -+ ox = 0, oy++, nx = 0; -+ } else/* if (col - nx < len - ox) */ { -+ memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); -+ ox += col - nx; -+ buf[ny][col - 1].mode |= ATTR_WRAP; -+ nx = 0; -+ } -+ } while (oy <= oce); -+ if (nx) -+ for (j = nx; j < col; j++) -+ tclearglyph(&buf[ny][j], 0); - -- /* -- * slide screen to keep cursor where we expect it - -- * tscrollup would work here, but we can optimize to -- * memmove because we're freeing the earlier lines -- */ -- for (i = 0; i <= term.c.y - row; i++) { -+ /* free extra lines */ -+ for (i = row; i < term.row; i++) - free(term.line[i]); -- free(term.alt[i]); -+ /* resize to new height */ -+ term.line = xrealloc(term.line, row * sizeof(Line)); -+ -+ bot = MIN(ny, row - 1); -+ scr = MAX(row - term.row, 0); -+ /* update y coordinate of cursor line end */ -+ nce = MIN(oce + scr, bot); -+ /* update cursor y coordinate */ -+ term.c.y = nce - (ny - cy); -+ if (term.c.y < 0) { -+ j = nce, nce = MIN(nce + -term.c.y, bot); -+ term.c.y += nce - j; -+ while (term.c.y < 0) { -+ free(buf[ny--]); -+ term.c.y++; -+ } - } -- /* ensure that both src and dst are not NULL */ -- if (i > 0) { -- memmove(term.line, term.line + i, row * sizeof(Line)); -- memmove(term.alt, term.alt + i, row * sizeof(Line)); -+ /* allocate new rows */ -+ for (i = row - 1; i > nce; i--) { -+ term.line[i] = xmalloc(col * sizeof(Glyph)); -+ for (j = 0; j < col; j++) -+ tclearglyph(&term.line[i][j], 0); - } -- for (i += row; i < term.row; i++) { -+ /* fill visible area */ -+ for (/*i = nce */; i >= term.row; i--, ny--) -+ term.line[i] = buf[ny]; -+ for (/*i = term.row - 1 */; i >= 0; i--, ny--) { - free(term.line[i]); -- free(term.alt[i]); -+ term.line[i] = buf[ny]; -+ } -+ /* fill lines in history buffer and update term.histf */ -+ for (/*i = -1 */; ny >= 0 && i >= -HISTSIZE; i--, ny--) { -+ j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; -+ free(term.hist[j]); -+ term.hist[j] = buf[ny]; - } -+ term.histf = -i - 1; -+ term.scr = MIN(term.scr, term.histf); -+ /* resize rest of the history lines */ -+ for (/*i = -term.histf - 1 */; i >= -HISTSIZE; i--) { -+ j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; -+ term.hist[j] = xrealloc(term.hist[j], col * sizeof(Glyph)); -+ } -+ free(buf); -+} - -- /* resize to new height */ -- term.line = xrealloc(term.line, row * sizeof(Line)); -- term.alt = xrealloc(term.alt, row * sizeof(Line)); -- term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); -- term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); -+void -+rscrolldown(int n) -+{ -+ int i; -+ Line temp; - -- for (i = 0; i < HISTSIZE; i++) { -- term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); -- for (j = mincol; j < col; j++) { -- term.hist[i][j] = term.c.attr; -- term.hist[i][j].u = ' '; -- } -- } -+ /* can never be true as of now -+ if (IS_SET(MODE_ALTSCREEN)) -+ return; */ - -- /* resize each row to new width, zero-pad if needed */ -- for (i = 0; i < minrow; i++) { -- term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -- term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); -- } -+ if ((n = MIN(n, term.histf)) <= 0) -+ return; - -- /* allocate any new rows */ -- for (/* i = minrow */; i < row; i++) { -- term.line[i] = xmalloc(col * sizeof(Glyph)); -- term.alt[i] = xmalloc(col * sizeof(Glyph)); -+ for (i = term.c.y + n; i >= n; i--) { -+ temp = term.line[i]; -+ term.line[i] = term.line[i-n]; -+ term.line[i-n] = temp; - } -+ for (/*i = n - 1 */; i >= 0; i--) { -+ temp = term.line[i]; -+ term.line[i] = term.hist[term.histi]; -+ term.hist[term.histi] = temp; -+ term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; -+ } -+ term.c.y += n; -+ term.histf -= n; -+ if ((i = term.scr - n) >= 0) { -+ term.scr = i; -+ } else { -+ term.scr = 0; -+ if (sel.ob.x != -1 && !sel.alt) -+ selmove(-i); -+ } -+} -+ -+void -+tresize(int col, int row) -+{ -+ int *bp; -+ -+ /* col and row are always MAX(_, 1) -+ if (col < 1 || row < 1) { -+ fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); -+ return; -+ } */ -+ -+ term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); -+ term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - if (col > term.col) { - bp = term.tabs + term.col; -- - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } -- /* update terminal size */ -- term.col = col; -- term.row = row; -- /* reset scrolling region */ -- tsetscroll(0, row-1); -- /* make use of the LIMIT in tmoveto */ -- tmoveto(term.c.x, term.c.y); -- /* Clearing both screens (it makes dirty all lines) */ -- c = term.c; -- for (i = 0; i < 2; i++) { -- if (mincol < col && 0 < minrow) { -- tclearregion(mincol, 0, col - 1, minrow - 1); -+ -+ if (IS_SET(MODE_ALTSCREEN)) -+ tresizealt(col, row); -+ else -+ tresizedef(col, row); -+} -+ -+void -+tresizedef(int col, int row) -+{ -+ int i, j; -+ -+ /* return if dimensions haven't changed */ -+ if (term.col == col && term.row == row) { -+ tfulldirt(); -+ return; -+ } -+ if (col != term.col) { -+ if (!sel.alt) -+ selremove(); -+ treflow(col, row); -+ } else { -+ /* slide screen up if otherwise cursor would get out of the screen */ -+ if (term.c.y >= row) { -+ tscrollup(0, term.row - 1, term.c.y - row + 1, SCROLL_RESIZE); -+ term.c.y = row - 1; - } -- if (0 < col && minrow < row) { -- tclearregion(0, minrow, col - 1, row - 1); -+ for (i = row; i < term.row; i++) -+ free(term.line[i]); -+ -+ /* resize to new height */ -+ term.line = xrealloc(term.line, row * sizeof(Line)); -+ /* allocate any new rows */ -+ for (i = term.row; i < row; i++) { -+ term.line[i] = xmalloc(col * sizeof(Glyph)); -+ for (j = 0; j < col; j++) -+ tclearglyph(&term.line[i][j], 0); - } -- tswapscreen(); -- tcursor(CURSOR_LOAD); -+ /* scroll down as much as height has increased */ -+ rscrolldown(row - term.row); -+ } -+ /* update terminal size */ -+ term.col = col, term.row = row; -+ /* reset scrolling region */ -+ term.top = 0, term.bot = row - 1; -+ /* dirty all lines */ -+ tfulldirt(); -+} -+ -+void -+tresizealt(int col, int row) -+{ -+ int i, j; -+ -+ /* return if dimensions haven't changed */ -+ if (term.col == col && term.row == row) { -+ tfulldirt(); -+ return; - } -- term.c = c; -+ if (sel.alt) -+ selremove(); -+ /* slide screen up if otherwise cursor would get out of the screen */ -+ for (i = 0; i <= term.c.y - row; i++) -+ free(term.line[i]); -+ if (i > 0) { -+ /* ensure that both src and dst are not NULL */ -+ memmove(term.line, term.line + i, row * sizeof(Line)); -+ term.c.y = row - 1; -+ } -+ for (i += row; i < term.row; i++) -+ free(term.line[i]); -+ /* resize to new height */ -+ term.line = xrealloc(term.line, row * sizeof(Line)); -+ /* resize to new width */ -+ for (i = 0; i < MIN(row, term.row); i++) { -+ term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -+ for (j = term.col; j < col; j++) -+ tclearglyph(&term.line[i][j], 0); -+ } -+ /* allocate any new rows */ -+ for (/*i = MIN(row, term.row) */; i < row; i++) { -+ term.line[i] = xmalloc(col * sizeof(Glyph)); -+ for (j = 0; j < col; j++) -+ tclearglyph(&term.line[i][j], 0); -+ } -+ /* update cursor */ -+ if (term.c.x >= col) { -+ term.c.state &= ~CURSOR_WRAPNEXT; -+ term.c.x = col - 1; -+ } else { -+ UPDATEWRAPNEXT(1, col); -+ } -+ /* update terminal size */ -+ term.col = col, term.row = row; -+ /* reset scrolling region */ -+ term.top = 0, term.bot = row - 1; -+ /* dirty all lines */ -+ tfulldirt(); - } - - void -@@ -2709,9 +3057,8 @@ draw(void) - cx--; - - drawregion(0, 0, term.col, term.row); -- if (term.scr == 0) -- 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.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); -diff --git a/st.h b/st.h -index 818a6f8..514ec08 100644 ---- a/st.h -+++ b/st.h -@@ -22,17 +22,19 @@ - - enum glyph_attribute { - ATTR_NULL = 0, -- ATTR_BOLD = 1 << 0, -- ATTR_FAINT = 1 << 1, -- ATTR_ITALIC = 1 << 2, -- ATTR_UNDERLINE = 1 << 3, -- ATTR_BLINK = 1 << 4, -- ATTR_REVERSE = 1 << 5, -- ATTR_INVISIBLE = 1 << 6, -- ATTR_STRUCK = 1 << 7, -- ATTR_WRAP = 1 << 8, -- ATTR_WIDE = 1 << 9, -- ATTR_WDUMMY = 1 << 10, -+ ATTR_SET = 1 << 0, -+ ATTR_BOLD = 1 << 1, -+ ATTR_FAINT = 1 << 2, -+ ATTR_ITALIC = 1 << 3, -+ ATTR_UNDERLINE = 1 << 4, -+ ATTR_BLINK = 1 << 5, -+ ATTR_REVERSE = 1 << 6, -+ ATTR_INVISIBLE = 1 << 7, -+ ATTR_STRUCK = 1 << 8, -+ ATTR_WRAP = 1 << 9, -+ ATTR_WIDE = 1 << 10, -+ ATTR_WDUMMY = 1 << 11, -+ ATTR_SELECTED = 1 << 12, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, - }; - -@@ -90,6 +92,7 @@ void toggleprinter(const Arg *); - - int tattrset(int); - void tnew(int, int); -+int tisaltscreen(void); - void tresize(int, int); - void tsetdirtattr(int); - void ttyhangup(void); diff --git a/patches/st-title_parsing_fix-0.8.5.diff b/patches/st-title_parsing_fix-0.8.5.diff deleted file mode 100644 index a5cee40..0000000 --- a/patches/st-title_parsing_fix-0.8.5.diff +++ /dev/null @@ -1,145 +0,0 @@ -From 8446609384429bfc4342ede4b52ff42214ad2b77 Mon Sep 17 00:00:00 2001 -From: Rizqi Nur Assyaufi <bandithijo@gmail.com> -Date: Mon, 18 Jul 2022 00:35:26 +0800 -Subject: [PATCH] Fixes title parsing for st-0.8.5 - -In st, titles get truncated after the first ';' character, this patch -fixes that. ---- - st.c | 38 ++++++++++++++++++++------------------ - 1 file changed, 20 insertions(+), 18 deletions(-) - -diff --git a/st.c b/st.c -index 51049ba..a2e595c 100644 ---- a/st.c -+++ b/st.c -@@ -42,6 +42,8 @@ - #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) - #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) - #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -+#define STRESCARGREST(n) ((n) == 0 ? strescseq.buf : strescseq.argp[(n)-1] + 1) -+#define STRESCARGJUST(n) (*(strescseq.argp[n]) = '\0', STRESCARGREST(n)) - - enum term_mode { - MODE_WRAP = 1 << 0, -@@ -148,7 +150,7 @@ typedef struct { - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ -- char *args[STR_ARG_SIZ]; -+ char *argp[STR_ARG_SIZ]; /* pointers to the end of nth argument */ - int narg; /* nb of args */ - } STREscape; - -@@ -1885,29 +1887,30 @@ strhandle(void) - int j, narg, par; - - term.esc &= ~(ESC_STR_END|ESC_STR); -- strparse(); -- par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; -+ strescseq.buf[strescseq.len] = '\0'; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ -+ strparse(); -+ par = (narg = strescseq.narg) ? atoi(STRESCARGJUST(0)) : 0; - switch (par) { - case 0: - if (narg > 1) { -- xsettitle(strescseq.args[1]); -- xseticontitle(strescseq.args[1]); -+ xsettitle(STRESCARGREST(1)); -+ xseticontitle(STRESCARGREST(1)); - } - return; - case 1: - if (narg > 1) -- xseticontitle(strescseq.args[1]); -+ xseticontitle(STRESCARGREST(1)); - return; - case 2: - if (narg > 1) -- xsettitle(strescseq.args[1]); -+ xsettitle(STRESCARGREST(1)); - return; - case 52: - if (narg > 2 && allowwindowops) { -- dec = base64dec(strescseq.args[2]); -+ dec = base64dec(STRESCARGJUST(2)); - if (dec) { - xsetsel(dec); - xclipcopy(); -@@ -1920,7 +1923,7 @@ strhandle(void) - if (narg < 2) - break; - -- p = strescseq.args[1]; -+ p = STRESCARGREST(1); - - if (!strcmp(p, "?")) - osc_color_response(defaultfg, 10); -@@ -1933,7 +1936,7 @@ strhandle(void) - if (narg < 2) - break; - -- p = strescseq.args[1]; -+ p = STRESCARGREST(1); - - if (!strcmp(p, "?")) - osc_color_response(defaultbg, 11); -@@ -1946,7 +1949,7 @@ strhandle(void) - if (narg < 2) - break; - -- p = strescseq.args[1]; -+ p = STRESCARGREST(1); - - if (!strcmp(p, "?")) - osc_color_response(defaultcs, 12); -@@ -1958,10 +1961,10 @@ strhandle(void) - case 4: /* color set */ - if (narg < 3) - break; -- p = strescseq.args[2]; -+ p = STRESCARGJUST(2); - /* FALLTHROUGH */ - case 104: /* color reset */ -- j = (narg > 1) ? atoi(strescseq.args[1]) : -1; -+ j = (narg > 1) ? atoi(STRESCARGJUST(1)) : -1; - - if (p && !strcmp(p, "?")) - osc4_color_response(j); -@@ -1981,7 +1984,7 @@ strhandle(void) - } - break; - case 'k': /* old title set compatibility */ -- xsettitle(strescseq.args[0]); -+ xsettitle(strescseq.buf); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ -@@ -2000,18 +2003,17 @@ strparse(void) - char *p = strescseq.buf; - - strescseq.narg = 0; -- strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { -- strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') -- ++p; -+ p++; -+ strescseq.argp[strescseq.narg++] = p; - if (c == '\0') - return; -- *p++ = '\0'; -+ p++; - } - } - --- -2.37.1 - diff --git a/patches/st-undercurl-0.8.4-20210822.diff b/patches/st-undercurl-0.8.4-20210822.diff deleted file mode 100644 index fab2ddc..0000000 --- a/patches/st-undercurl-0.8.4-20210822.diff +++ /dev/null @@ -1,605 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 6f05dce..7ae1b92 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -470,3 +470,27 @@ static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; -+ -+/** -+ * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. -+ * -+ * Curly: Dunno how to draw it *shrug* -+ * _ _ _ _ -+ * ( ) ( ) ( ) ( ) -+ * (_) (_) (_) (_) -+ * -+ * Spiky: -+ * /\ /\ /\ /\ -+ * \/ \/ \/ -+ * -+ * Capped: -+ * _ _ _ -+ * / \ / \ / \ -+ * \_/ \_/ -+ */ -+// Available styles -+#define UNDERCURL_CURLY 0 -+#define UNDERCURL_SPIKY 1 -+#define UNDERCURL_CAPPED 2 -+// Active style -+#define UNDERCURL_STYLE UNDERCURL_SPIKY -diff --git a/st.c b/st.c -index 76b7e0d..542ab3a 100644 ---- a/st.c -+++ b/st.c -@@ -33,6 +33,7 @@ - #define UTF_SIZ 4 - #define ESC_BUF_SIZ (128*UTF_SIZ) - #define ESC_ARG_SIZ 16 -+#define CAR_PER_ARG 4 - #define STR_BUF_SIZ ESC_BUF_SIZ - #define STR_ARG_SIZ ESC_ARG_SIZ - -@@ -139,6 +140,7 @@ typedef struct { - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; -+ int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ - } CSIEscape; - - /* STR Escape sequence structs */ -@@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t); - - static void csidump(void); - static void csihandle(void); -+static void readcolonargs(char **, int, int[][CAR_PER_ARG]); - static void csiparse(void); - static void csireset(void); - static int eschandle(uchar); -@@ -1131,6 +1134,28 @@ tnewline(int first_col) - tmoveto(first_col ? 0 : term.c.x, y); - } - -+void -+readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) -+{ -+ int i = 0; -+ for (; i < CAR_PER_ARG; i++) -+ params[cursor][i] = -1; -+ -+ if (**p != ':') -+ return; -+ -+ char *np = NULL; -+ i = 0; -+ -+ while (**p == ':' && i < CAR_PER_ARG) { -+ while (**p == ':') -+ (*p)++; -+ params[cursor][i] = strtol(*p, &np, 10); -+ *p = np; -+ i++; -+ } -+} -+ - void - csiparse(void) - { -@@ -1153,6 +1178,7 @@ csiparse(void) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; -+ readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); - if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; -@@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l) - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; -+ term.c.attr.ustyle = -1; -+ term.c.attr.ucolor[0] = -1; -+ term.c.attr.ucolor[1] = -1; -+ term.c.attr.ucolor[2] = -1; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; -@@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l) - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: -- term.c.attr.mode |= ATTR_UNDERLINE; -+ term.c.attr.ustyle = csiescseq.carg[i][0]; -+ -+ if (term.c.attr.ustyle != 0) -+ term.c.attr.mode |= ATTR_UNDERLINE; -+ else -+ term.c.attr.mode &= ~ATTR_UNDERLINE; -+ -+ term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ -@@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l) - case 49: - term.c.attr.bg = defaultbg; - break; -+ case 58: -+ term.c.attr.ucolor[0] = csiescseq.carg[i][1]; -+ term.c.attr.ucolor[1] = csiescseq.carg[i][2]; -+ term.c.attr.ucolor[2] = csiescseq.carg[i][3]; -+ term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; -+ break; -+ case 59: -+ term.c.attr.ucolor[0] = -1; -+ term.c.attr.ucolor[1] = -1; -+ term.c.attr.ucolor[2] = -1; -+ term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; -+ break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; -diff --git a/st.h b/st.h -index 3d351b6..95bdcbd 100644 ---- a/st.h -+++ b/st.h -@@ -34,6 +34,7 @@ enum glyph_attribute { - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, -+ ATTR_DIRTYUNDERLINE = 1 << 15, - }; - - enum selection_mode { -@@ -65,6 +66,8 @@ typedef struct { - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ -+ int ustyle; /* underline style */ -+ int ucolor[3]; /* underline color */ - } Glyph; - - typedef Glyph *Line; -diff --git a/st.info b/st.info -index 8201ad6..659878c 100644 ---- a/st.info -+++ b/st.info -@@ -1,4 +1,5 @@ - st-mono| simpleterm monocolor, -+ Su, - acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, - am, - bce, -diff --git a/x.c b/x.c -index 210f184..3a0e79e 100644 ---- a/x.c -+++ b/x.c -@@ -45,6 +45,14 @@ typedef struct { - signed char appcursor; /* application cursor */ - } Key; - -+/* Undercurl slope types */ -+enum undercurl_slope_type { -+ UNDERCURL_SLOPE_ASCENDING = 0, -+ UNDERCURL_SLOPE_TOP_CAP = 1, -+ UNDERCURL_SLOPE_DESCENDING = 2, -+ UNDERCURL_SLOPE_BOTTOM_CAP = 3 -+}; -+ - /* X modifiers */ - #define XK_ANY_MOD UINT_MAX - #define XK_NO_MOD 0 -@@ -1339,6 +1347,51 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x - return numspecs; - } - -+static int isSlopeRising (int x, int iPoint, int waveWidth) -+{ -+ // . . . . -+ // / \ / \ / \ / \ -+ // / \ / \ / \ / \ -+ // . . . . . -+ -+ // Find absolute `x` of point -+ x += iPoint * (waveWidth/2); -+ -+ // Find index of absolute wave -+ int absSlope = x / ((float)waveWidth/2); -+ -+ return (absSlope % 2); -+} -+ -+static int getSlope (int x, int iPoint, int waveWidth) -+{ -+ // Sizes: Caps are half width of slopes -+ // 1_2 1_2 1_2 1_2 -+ // / \ / \ / \ / \ -+ // / \ / \ / \ / \ -+ // 0 3_0 3_0 3_0 3_ -+ // <2-> <1> <---6----> -+ -+ // Find type of first point -+ int firstType; -+ x -= (x / waveWidth) * waveWidth; -+ if (x < (waveWidth * (2.f/6.f))) -+ firstType = UNDERCURL_SLOPE_ASCENDING; -+ else if (x < (waveWidth * (3.f/6.f))) -+ firstType = UNDERCURL_SLOPE_TOP_CAP; -+ else if (x < (waveWidth * (5.f/6.f))) -+ firstType = UNDERCURL_SLOPE_DESCENDING; -+ else -+ firstType = UNDERCURL_SLOPE_BOTTOM_CAP; -+ -+ // Find type of given point -+ int pointType = (iPoint % 4); -+ pointType += firstType; -+ pointType %= 4; -+ -+ return pointType; -+} -+ - void - xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) - { -@@ -1461,8 +1514,357 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { -- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, -- width, 1); -+ // Underline Color -+ const int widthThreshold = 28; // +1 width every widthThreshold px of font -+ int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width -+ int linecolor; -+ if ((base.ucolor[0] >= 0) && -+ !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) && -+ !(base.mode & ATTR_INVISIBLE) -+ ) { -+ // Special color for underline -+ // Index -+ if (base.ucolor[1] < 0) { -+ linecolor = dc.col[base.ucolor[0]].pixel; -+ } -+ // RGB -+ else { -+ XColor lcolor; -+ lcolor.red = base.ucolor[0] * 257; -+ lcolor.green = base.ucolor[1] * 257; -+ lcolor.blue = base.ucolor[2] * 257; -+ lcolor.flags = DoRed | DoGreen | DoBlue; -+ XAllocColor(xw.dpy, xw.cmap, &lcolor); -+ linecolor = lcolor.pixel; -+ } -+ } else { -+ // Foreground color for underline -+ linecolor = fg->pixel; -+ } -+ -+ XGCValues ugcv = { -+ .foreground = linecolor, -+ .line_width = wlw, -+ .line_style = LineSolid, -+ .cap_style = CapNotLast -+ }; -+ -+ GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), -+ GCForeground | GCLineWidth | GCLineStyle | GCCapStyle, -+ &ugcv); -+ -+ // Underline Style -+ if (base.ustyle != 3) { -+ //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); -+ XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx, -+ winy + dc.font.ascent + 1, width, wlw); -+ } else if (base.ustyle == 3) { -+ int ww = win.cw;//width; -+ int wh = dc.font.descent - wlw/2 - 1;//r.height/7; -+ int wx = winx; -+ int wy = winy + win.ch - dc.font.descent; -+ -+#if UNDERCURL_STYLE == UNDERCURL_CURLY -+ // Draw waves -+ int narcs = charlen * 2 + 1; -+ XArc *arcs = xmalloc(sizeof(XArc) * narcs); -+ -+ int i = 0; -+ for (i = 0; i < charlen-1; i++) { -+ arcs[i*2] = (XArc) { -+ .x = wx + win.cw * i + ww / 4, -+ .y = wy, -+ .width = win.cw / 2, -+ .height = wh, -+ .angle1 = 0, -+ .angle2 = 180 * 64 -+ }; -+ arcs[i*2+1] = (XArc) { -+ .x = wx + win.cw * i + ww * 0.75, -+ .y = wy, -+ .width = win.cw/2, -+ .height = wh, -+ .angle1 = 180 * 64, -+ .angle2 = 180 * 64 -+ }; -+ } -+ // Last wave -+ arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh, -+ 0, 180 * 64 }; -+ // Last wave tail -+ arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.), -+ wh, 180 * 64, 90 * 64}; -+ // First wave tail -+ i++; -+ arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64, -+ 90 * 64 }; -+ -+ XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs); -+ -+ free(arcs); -+#elif UNDERCURL_STYLE == UNDERCURL_SPIKY -+ // Make the underline corridor larger -+ /* -+ wy -= wh; -+ */ -+ wh *= 2; -+ -+ // Set the angle of the slope to 45° -+ ww = wh; -+ -+ // Position of wave is independent of word, it's absolute -+ wx = (wx / (ww/2)) * (ww/2); -+ -+ int marginStart = winx - wx; -+ -+ // Calculate number of points with floating precision -+ float n = width; // Width of word in pixels -+ n = (n / ww) * 2; // Number of slopes (/ or \) -+ n += 2; // Add two last points -+ int npoints = n; // Convert to int -+ -+ // Total length of underline -+ float waveLength = 0; -+ -+ if (npoints >= 3) { -+ // We add an aditional slot in case we use a bonus point -+ XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); -+ -+ // First point (Starts with the word bounds) -+ points[0] = (XPoint) { -+ .x = wx + marginStart, -+ .y = (isSlopeRising(wx, 0, ww)) -+ ? (wy - marginStart + ww/2.f) -+ : (wy + marginStart) -+ }; -+ -+ // Second point (Goes back to the absolute point coordinates) -+ points[1] = (XPoint) { -+ .x = (ww/2.f) - marginStart, -+ .y = (isSlopeRising(wx, 1, ww)) -+ ? (ww/2.f - marginStart) -+ : (-ww/2.f + marginStart) -+ }; -+ waveLength += (ww/2.f) - marginStart; -+ -+ // The rest of the points -+ for (int i = 2; i < npoints-1; i++) { -+ points[i] = (XPoint) { -+ .x = ww/2, -+ .y = (isSlopeRising(wx, i, ww)) -+ ? wh/2 -+ : -wh/2 -+ }; -+ waveLength += ww/2; -+ } -+ -+ // Last point -+ points[npoints-1] = (XPoint) { -+ .x = ww/2, -+ .y = (isSlopeRising(wx, npoints-1, ww)) -+ ? wh/2 -+ : -wh/2 -+ }; -+ waveLength += ww/2; -+ -+ // End -+ if (waveLength < width) { // Add a bonus point? -+ int marginEnd = width - waveLength; -+ points[npoints] = (XPoint) { -+ .x = marginEnd, -+ .y = (isSlopeRising(wx, npoints, ww)) -+ ? (marginEnd) -+ : (-marginEnd) -+ }; -+ -+ npoints++; -+ } else if (waveLength > width) { // Is last point too far? -+ int marginEnd = waveLength - width; -+ points[npoints-1].x -= marginEnd; -+ if (isSlopeRising(wx, npoints-1, ww)) -+ points[npoints-1].y -= (marginEnd); -+ else -+ points[npoints-1].y += (marginEnd); -+ } -+ -+ // Draw the lines -+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, -+ CoordModePrevious); -+ -+ // Draw a second underline with an offset of 1 pixel -+ if ( ((win.ch / (widthThreshold/2)) % 2)) { -+ points[0].x++; -+ -+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, -+ npoints, CoordModePrevious); -+ } -+ -+ // Free resources -+ free(points); -+ } -+#else // UNDERCURL_CAPPED -+ // Cap is half of wave width -+ float capRatio = 0.5f; -+ -+ // Make the underline corridor larger -+ wh *= 2; -+ -+ // Set the angle of the slope to 45° -+ ww = wh; -+ ww *= 1 + capRatio; // Add a bit of width for the cap -+ -+ // Position of wave is independent of word, it's absolute -+ wx = (wx / ww) * ww; -+ -+ float marginStart; -+ switch(getSlope(winx, 0, ww)) { -+ case UNDERCURL_SLOPE_ASCENDING: -+ marginStart = winx - wx; -+ break; -+ case UNDERCURL_SLOPE_TOP_CAP: -+ marginStart = winx - (wx + (ww * (2.f/6.f))); -+ break; -+ case UNDERCURL_SLOPE_DESCENDING: -+ marginStart = winx - (wx + (ww * (3.f/6.f))); -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ marginStart = winx - (wx + (ww * (5.f/6.f))); -+ break; -+ } -+ -+ // Calculate number of points with floating precision -+ float n = width; // Width of word in pixels -+ // ._. -+ n = (n / ww) * 4; // Number of points (./ \.) -+ n += 2; // Add two last points -+ int npoints = n; // Convert to int -+ -+ // Position of the pen to draw the lines -+ float penX = 0; -+ float penY = 0; -+ -+ if (npoints >= 3) { -+ XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); -+ -+ // First point (Starts with the word bounds) -+ penX = winx; -+ switch (getSlope(winx, 0, ww)) { -+ case UNDERCURL_SLOPE_ASCENDING: -+ penY = wy + wh/2.f - marginStart; -+ break; -+ case UNDERCURL_SLOPE_TOP_CAP: -+ penY = wy; -+ break; -+ case UNDERCURL_SLOPE_DESCENDING: -+ penY = wy + marginStart; -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ penY = wy + wh/2.f; -+ break; -+ } -+ points[0].x = penX; -+ points[0].y = penY; -+ -+ // Second point (Goes back to the absolute point coordinates) -+ switch (getSlope(winx, 1, ww)) { -+ case UNDERCURL_SLOPE_ASCENDING: -+ penX += ww * (1.f/6.f) - marginStart; -+ penY += 0; -+ break; -+ case UNDERCURL_SLOPE_TOP_CAP: -+ penX += ww * (2.f/6.f) - marginStart; -+ penY += -wh/2.f + marginStart; -+ break; -+ case UNDERCURL_SLOPE_DESCENDING: -+ penX += ww * (1.f/6.f) - marginStart; -+ penY += 0; -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ penX += ww * (2.f/6.f) - marginStart; -+ penY += -marginStart + wh/2.f; -+ break; -+ } -+ points[1].x = penX; -+ points[1].y = penY; -+ -+ // The rest of the points -+ for (int i = 2; i < npoints; i++) { -+ switch (getSlope(winx, i, ww)) { -+ case UNDERCURL_SLOPE_ASCENDING: -+ case UNDERCURL_SLOPE_DESCENDING: -+ penX += ww * (1.f/6.f); -+ penY += 0; -+ break; -+ case UNDERCURL_SLOPE_TOP_CAP: -+ penX += ww * (2.f/6.f); -+ penY += -wh / 2.f; -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ penX += ww * (2.f/6.f); -+ penY += wh / 2.f; -+ break; -+ } -+ points[i].x = penX; -+ points[i].y = penY; -+ } -+ -+ // End -+ float waveLength = penX - winx; -+ if (waveLength < width) { // Add a bonus point? -+ int marginEnd = width - waveLength; -+ penX += marginEnd; -+ switch(getSlope(winx, npoints, ww)) { -+ case UNDERCURL_SLOPE_ASCENDING: -+ case UNDERCURL_SLOPE_DESCENDING: -+ //penY += 0; -+ break; -+ case UNDERCURL_SLOPE_TOP_CAP: -+ penY += -marginEnd; -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ penY += marginEnd; -+ break; -+ } -+ -+ points[npoints].x = penX; -+ points[npoints].y = penY; -+ -+ npoints++; -+ } else if (waveLength > width) { // Is last point too far? -+ int marginEnd = waveLength - width; -+ points[npoints-1].x -= marginEnd; -+ switch(getSlope(winx, npoints-1, ww)) { -+ case UNDERCURL_SLOPE_TOP_CAP: -+ points[npoints-1].y += marginEnd; -+ break; -+ case UNDERCURL_SLOPE_BOTTOM_CAP: -+ points[npoints-1].y -= marginEnd; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ // Draw the lines -+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, -+ CoordModeOrigin); -+ -+ // Draw a second underline with an offset of 1 pixel -+ if ( ((win.ch / (widthThreshold/2)) % 2)) { -+ for (int i = 0; i < npoints; i++) -+ points[i].x++; -+ -+ XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, -+ npoints, CoordModeOrigin); -+ } -+ -+ // Free resources -+ free(points); -+ } -+#endif -+ } -+ -+ XFreeGC(xw.dpy, ugc); - } - - if (base.mode & ATTR_STRUCK) { diff --git a/patches/st-xresources-20200604-9ba7ecf.diff b/patches/st-xresources-20200604-9ba7ecf.diff deleted file mode 100644 index 78ba00a..0000000 --- a/patches/st-xresources-20200604-9ba7ecf.diff +++ /dev/null @@ -1,184 +0,0 @@ -From 2752a599ee01305a435729bfacf43b1dde7cf0ef Mon Sep 17 00:00:00 2001 -From: Benji Encalada Mora <benji@encalada.dev> -Date: Thu, 4 Jun 2020 00:41:10 -0500 -Subject: [PATCH] fix: replace xfps and actionfps variables - ---- - config.def.h | 36 ++++++++++++++++++++++++ - x.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 110 insertions(+), 4 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 6f05dce..9b99782 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -168,6 +168,42 @@ static unsigned int defaultattr = 11; - */ - static uint forcemousemod = ShiftMask; - -+/* -+ * Xresources preferences to load at startup -+ */ -+ResourcePref resources[] = { -+ { "font", STRING, &font }, -+ { "color0", STRING, &colorname[0] }, -+ { "color1", STRING, &colorname[1] }, -+ { "color2", STRING, &colorname[2] }, -+ { "color3", STRING, &colorname[3] }, -+ { "color4", STRING, &colorname[4] }, -+ { "color5", STRING, &colorname[5] }, -+ { "color6", STRING, &colorname[6] }, -+ { "color7", STRING, &colorname[7] }, -+ { "color8", STRING, &colorname[8] }, -+ { "color9", STRING, &colorname[9] }, -+ { "color10", STRING, &colorname[10] }, -+ { "color11", STRING, &colorname[11] }, -+ { "color12", STRING, &colorname[12] }, -+ { "color13", STRING, &colorname[13] }, -+ { "color14", STRING, &colorname[14] }, -+ { "color15", STRING, &colorname[15] }, -+ { "background", STRING, &colorname[256] }, -+ { "foreground", STRING, &colorname[257] }, -+ { "cursorColor", STRING, &colorname[258] }, -+ { "termname", STRING, &termname }, -+ { "shell", STRING, &shell }, -+ { "minlatency", INTEGER, &minlatency }, -+ { "maxlatency", INTEGER, &maxlatency }, -+ { "blinktimeout", INTEGER, &blinktimeout }, -+ { "bellvolume", INTEGER, &bellvolume }, -+ { "tabspaces", INTEGER, &tabspaces }, -+ { "borderpx", INTEGER, &borderpx }, -+ { "cwscale", FLOAT, &cwscale }, -+ { "chscale", FLOAT, &chscale }, -+}; -+ - /* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. -diff --git a/x.c b/x.c -index 210f184..76f167f 100644 ---- a/x.c -+++ b/x.c -@@ -14,6 +14,7 @@ - #include <X11/keysym.h> - #include <X11/Xft/Xft.h> - #include <X11/XKBlib.h> -+#include <X11/Xresource.h> - - char *argv0; - #include "arg.h" -@@ -45,6 +46,19 @@ typedef struct { - signed char appcursor; /* application cursor */ - } Key; - -+/* Xresources preferences */ -+enum resource_type { -+ STRING = 0, -+ INTEGER = 1, -+ FLOAT = 2 -+}; -+ -+typedef struct { -+ char *name; -+ enum resource_type type; -+ void *dst; -+} ResourcePref; -+ - /* X modifiers */ - #define XK_ANY_MOD UINT_MAX - #define XK_NO_MOD 0 -@@ -828,8 +842,8 @@ xclear(int x1, int y1, int x2, int y2) - void - xhints(void) - { -- XClassHint class = {opt_name ? opt_name : termname, -- opt_class ? opt_class : termname}; -+ XClassHint class = {opt_name ? opt_name : "st", -+ opt_class ? opt_class : "St"}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - -@@ -1104,8 +1118,6 @@ xinit(int cols, int rows) - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - -- if (!(xw.dpy = XOpenDisplay(NULL))) -- die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.scr); - -@@ -1964,6 +1976,59 @@ run(void) - } - } - -+int -+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) -+{ -+ char **sdst = dst; -+ int *idst = dst; -+ float *fdst = dst; -+ -+ char fullname[256]; -+ char fullclass[256]; -+ char *type; -+ XrmValue ret; -+ -+ snprintf(fullname, sizeof(fullname), "%s.%s", -+ opt_name ? opt_name : "st", name); -+ snprintf(fullclass, sizeof(fullclass), "%s.%s", -+ opt_class ? opt_class : "St", name); -+ fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; -+ -+ XrmGetResource(db, fullname, fullclass, &type, &ret); -+ if (ret.addr == NULL || strncmp("String", type, 64)) -+ return 1; -+ -+ switch (rtype) { -+ case STRING: -+ *sdst = ret.addr; -+ break; -+ case INTEGER: -+ *idst = strtoul(ret.addr, NULL, 10); -+ break; -+ case FLOAT: -+ *fdst = strtof(ret.addr, NULL); -+ break; -+ } -+ return 0; -+} -+ -+void -+config_init(void) -+{ -+ char *resm; -+ XrmDatabase db; -+ ResourcePref *p; -+ -+ XrmInitialize(); -+ resm = XResourceManagerString(xw.dpy); -+ if (!resm) -+ return; -+ -+ db = XrmGetStringDatabase(resm); -+ for (p = resources; p < resources + LEN(resources); p++) -+ resource_load(db, p->name, p->type, p->dst); -+} -+ - void - usage(void) - { -@@ -2037,6 +2102,11 @@ run: - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); -+ -+ if(!(xw.dpy = XOpenDisplay(NULL))) -+ die("Can't open display\n"); -+ -+ config_init(); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); --- -2.26.2 - diff --git a/patches/xrandrfontsize-0.8.4-20211224-2f6e597.diff b/patches/xrandrfontsize-0.8.4-20211224-2f6e597.diff deleted file mode 100644 index d7817a0..0000000 --- a/patches/xrandrfontsize-0.8.4-20211224-2f6e597.diff +++ /dev/null @@ -1,288 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index f92798a..517abbb 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -9,5 +9,19 @@ - static int borderpx = 2; - -+/* -+ * Override/adjust fontsize of choosen monitors: -+ */ -+MonitorConfig monitors_config[] = { -+ // skip = fixed relative points size (monitor dpi) -+ // =0 : fixed absolute pixel size (default screen dpi) -+ // >0 : auto absolute pixel size (monitor dpi) -+ // <0 : auto relative points size (monitor dpi) -+ // {"DP-1", 0}, // BUG:(size=0): not restored to default after back'n'forth -+ {"HDMI-0~1", -20}, // BUG:(ignored DPI=220): = 20 is eqv to 10pt (DPI=110) -+ {"HDMI-0~2", -14}, -+}; -+float winmovethreshold = 0.6; -+ - /* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e -@@ -272,6 +272,7 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, -+ { TERMMOD, XK_End, refreshxrandr, {.i = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, -diff --git a/config.mk b/config.mk -index aaa54ff..2d28597 100644 ---- a/config.mk -+++ b/config.mk -@@ -24,5 +24,7 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - -+LIBS += -lXrandr -+ - # flags - STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 - STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) - STLDFLAGS = $(LIBS) $(LDFLAGS) -diff --git a/x.c b/x.c -index 684311c..ce1c418 100644 ---- a/x.c -+++ b/x.c -@@ -14,6 +14,7 @@ - #include <X11/keysym.h> - #include <X11/Xft/Xft.h> - #include <X11/XKBlib.h> -+#include <X11/extensions/Xrandr.h> - - char *argv0; - #include "arg.h" -@@ -45,5 +46,18 @@ typedef struct { - signed char appcursor; /* application cursor */ - } Key; - -+typedef struct { -+ const char *name; -+ float defaultfontsize; -+} MonitorConfig; -+ -+typedef struct { -+ Atom name; -+ int x, y, w, h; -+ float defaultfontsize, usedfontsize; -+} MonitorInfo; -+ -+static void refreshxrandr(const Arg *dummy); -+ - /* X modifiers */ - #define XK_ANY_MOD UINT_MAX -@@ -233,7 +233,12 @@ static XWindow xw; - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, - }; - -+static double defaultrelfontsize = 0; -+static MonitorInfo *monitors_info = NULL; -+static int monitors_num = 0; -+static int prev_mindex = -1; -+ - /* Globals */ - static DC dc; - static XWindow xw; -@@ -2280,6 +2280,144 @@ xseturgency(int add) - XFree(h); - } - -+static void -+cachemonitorinfo() -+{ -+ int prev_num = monitors_num; -+ MonitorInfo *prev_info = monitors_info; -+ XRRMonitorInfo *xmonitors = XRRGetMonitors(xw.dpy, XRootWindow(xw.dpy, xw.scr), 1, &monitors_num); -+ if (!monitors_num) -+ die("xrandr found no monitors"); -+ -+ monitors_info = xmalloc(monitors_num * sizeof(MonitorInfo)); -+ -+ for (int i = 0; i < monitors_num; ++i) { -+ XRRMonitorInfo *xm = &xmonitors[i]; -+ MonitorInfo *m = &monitors_info[i]; -+ -+ m->name = xm->name; -+ m->x = xm->x; -+ m->y = xm->y; -+ m->w = xm->width; -+ m->h = xm->height; -+ -+ float px_mm = ((float)m->w / xm->mwidth + (float)m->h / xm->mheight) / 2; -+ float px_pt = 25.4 * px_mm / 72; -+ m->defaultfontsize = defaultrelfontsize * px_pt; -+ -+ // Override defaultfontsize (dpi) by user config -+ char *name = XGetAtomName(xw.dpy, xm->name); -+ for (int j = 0; j < LEN(monitors_config); ++j) -+ if (!strcmp(name, monitors_config[j].name)) { -+ m->defaultfontsize = monitors_config[j].defaultfontsize; -+ if (m->defaultfontsize < 0) -+ m->defaultfontsize *= -px_pt; -+ break; -+ } -+ // fprintf(stderr, "%s: %fpx, %f\n", name, m->defaultfontsize, m->usedfontsize); -+ XFree(name); -+ -+ // Restore usedfontsize (zoom) after re-cache for monitors with the same name -+ m->usedfontsize = m->defaultfontsize; -+ for (int j = 0; j < prev_num; ++j) -+ if (prev_info[j].name == m->name) { -+ m->usedfontsize = prev_info[j].usedfontsize; -+ break; -+ } -+ } -+ -+ XRRFreeMonitors(xmonitors); -+ free(prev_info); -+} -+ -+static int -+getmonitorindex_threshold(int w, int h, int x, int y) -+{ -+ int mindex = -1; -+ float fontsize = 0; -+ int thresholdarea = winmovethreshold * w * h; -+ -+ for (int i = 0; i < monitors_num; ++i) { -+ MonitorInfo *m = &monitors_info[i]; -+ int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); -+ int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); -+ int area = overlap_w * overlap_h; -+ // Choose monitor with largest dpi (defaultfontsize) -+ // from all "mirrored"/overlapped (e.g. projector) -+ if (area >= thresholdarea && fontsize < m->defaultfontsize) { -+ fontsize = m->defaultfontsize; -+ mindex = i; -+ } -+ } -+ return mindex; -+} -+ -+static int -+getmonitorindex_nearest(int w, int h, int x, int y) -+{ -+ int mindex = -1; -+ float fontsize = 0; -+ int overlaparea = 0; -+ -+ for (int i = 0; i < monitors_num; ++i) { -+ MonitorInfo *m = &monitors_info[i]; -+ int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); -+ int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); -+ int area = overlap_w * overlap_h; -+ // Choose monitor with largest overlapping area -+ // e.g. when "st" is initially spawned in-between monitors -+ if (area > overlaparea) { -+ overlaparea = area; -+ mindex = i; -+ } -+ } -+ return mindex; -+} -+ -+static void -+adjustmonitorfontsize(int mindex) -+{ -+ if (mindex < 0 || prev_mindex == mindex) -+ return; -+ // Save zoom of current monitor before switching -+ if (prev_mindex >= 0) -+ monitors_info[prev_mindex].usedfontsize = usedfontsize; -+ -+ defaultfontsize = monitors_info[mindex].defaultfontsize; -+ // fprintf(stderr, "Crossing: %fpx\n", defaultfontsize); -+ -+ // NOTE: do nothing if font size differs by less than 1% -+ double fontsize = monitors_info[mindex].usedfontsize; -+ double delta = 0.01 * usedfontsize; -+ if (!BETWEEN(fontsize - usedfontsize, -delta, delta)) { -+ // fprintf(stderr, "Adjusted: %fpx\n", fontsize); -+ xunloadfonts(); -+ xloadfonts(usedfont, fontsize); -+ } -+ prev_mindex = mindex; -+} -+ -+void -+refreshxrandr(const Arg *dummy) -+{ -+ // Reset index to detect change of window association on "xrandr ... --primary" -+ // otherwise: zoom won't be saved on switching and new font size won't be loaded -+ // CRIT!!! event from xrandr may place another monitor into same index -+ if (prev_mindex >= 0) -+ monitors_info[prev_mindex].usedfontsize = usedfontsize; -+ prev_mindex = -1; -+ -+ XWindowAttributes xattr = {0}; -+ cachemonitorinfo(); -+ XGetWindowAttributes(xw.dpy, xw.win, &xattr); -+ -+ int mindex = getmonitorindex_threshold(xattr.width, xattr.height, xattr.x, xattr.y); -+ if (mindex < 0) -+ mindex = getmonitorindex_nearest(xattr.width, xattr.height, xattr.x, xattr.y); -+ adjustmonitorfontsize(mindex); -+} -+ -+ - void - xbell(void) - { -@@ -2437,6 +2437,14 @@ cmessage(XEvent *e) - void - resize(XEvent *e) - { -+ // BAD: no resize on monitor plug/unplug/reconfigure -- until window itself is kept in the same place -+ // NOTE: no resize event on zoomabs() -+ // fprintf(stderr, "Resize: %dx%d+%d+%d\n", -+ // e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y); -+ -+ adjustmonitorfontsize(getmonitorindex_threshold( -+ e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y)); -+ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - -@@ -2469,6 +2469,22 @@ run(void) - } - } while (ev.type != MapNotify); - -+ int rr_event_base, rr_error_base, rr_major, rr_minor; -+ if (!XRRQueryExtension (xw.dpy, &rr_event_base, &rr_error_base) || -+ !XRRQueryVersion (xw.dpy, &rr_major, &rr_minor) || -+ rr_major < 1 || (rr_major == 1 && rr_minor < 5)) -+ { -+ die("RandR 1.5 extension isn't available\n"); -+ } -+ XRRSelectInput(xw.dpy, xw.win, RRCrtcChangeNotifyMask); -+ -+ // WARN: can query actual window size/pos only after window is mapped and its width/height are adjusted by WM -+ // * x/y are WM-dependent and can't be determined beforehand anyway -+ // * defaultfontsize isn't available until font is loaded and actual Fc*() size queried -+ // BAD: fonts on startup are always reloaded -- how to specify their size beforehand ? -+ FcPatternGetDouble(dc.font.match->pattern, FC_SIZE, 0, &defaultrelfontsize); -+ refreshxrandr(0); -+ - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - -@@ -2500,6 +2500,16 @@ run(void) - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; -+ if (LASTEvent <= ev.type) { -+ if (rr_event_base + RRNotify == ev.type && -+ RRNotify_CrtcChange == ((XRRNotifyEvent *)&ev)->subtype) -+ { -+ XRRUpdateConfiguration(&ev); -+ // fprintf(stderr, "Monitor change: %d > %d\n", rr_event_base, LASTEvent); -+ refreshxrandr(0); -+ } -+ continue; -+ } - if (handler[ev.type]) - (handler[ev.type])(&ev); - } @@ -22,8 +22,6 @@ st \- simple terminal .IR line ] .RB [ \-w .IR windowid ] -.RB [ \-z -.IR fontsize ] .RB [[ \-e ] .IR command .RI [ arguments ...]] @@ -46,8 +44,6 @@ st \- simple terminal .IR title ] .RB [ \-w .IR windowid ] -.RB [ \-z -.IR fontsize ] .RB \-l .IR line .RI [ stty_args ...] @@ -95,10 +91,6 @@ defines the window title (default 'st'). embeds st within the window identified by .I windowid .TP -.BI \-z " fontsize" -sets the default fontsize to -.I fontsize -.TP .BI \-l " line" use a tty .I line @@ -33,11 +33,8 @@ #define UTF_SIZ 4 #define ESC_BUF_SIZ (128*UTF_SIZ) #define ESC_ARG_SIZ 16 -#define CAR_PER_ARG 4 #define STR_BUF_SIZ ESC_BUF_SIZ #define STR_ARG_SIZ ESC_ARG_SIZ -#define HISTSIZE 2000 -#define RESIZEBUFFER 2000 /* macros */ #define IS_SET(flag) ((term.mode & (flag)) != 0) @@ -45,24 +42,6 @@ #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -#define STRESCARGREST(n) ((n) == 0 ? strescseq.buf : strescseq.argp[(n)-1] + 1) -#define STRESCARGJUST(n) (*(strescseq.argp[n]) = '\0', STRESCARGREST(n)) - -#define TLINE(y) ( \ - (y) < term.scr ? term.hist[(term.histi + (y) - term.scr + 1 + HISTSIZE) % HISTSIZE] \ - : term.line[(y) - term.scr] \ -) - -#define TLINEABS(y) ( \ - (y) < 0 ? term.hist[(term.histi + (y) + 1 + HISTSIZE) % HISTSIZE] : term.line[(y)] \ -) - -#define UPDATEWRAPNEXT(alt, col) do { \ - if ((term.c.state & CURSOR_WRAPNEXT) && term.c.x + term.wrapcwidth[alt] < col) { \ - term.c.x += term.wrapcwidth[alt]; \ - term.c.state &= ~CURSOR_WRAPNEXT; \ - } \ -} while (0); enum term_mode { MODE_WRAP = 1 << 0, @@ -74,12 +53,6 @@ enum term_mode { MODE_UTF8 = 1 << 6, }; -enum scroll_mode { - SCROLL_RESIZE = -1, - SCROLL_NOSAVEHIST = 0, - SCROLL_SAVEHIST = 1 -}; - enum cursor_movement { CURSOR_SAVE, CURSOR_LOAD @@ -141,11 +114,7 @@ typedef struct { int row; /* nb row */ int col; /* nb col */ Line *line; /* screen */ - Line hist[HISTSIZE]; /* history buffer */ - int histi; /* history index */ - int histf; /* nb history available */ - int scr; /* scroll back */ - int wrapcwidth[2]; /* used in updating WRAPNEXT when resizing */ + Line *alt; /* alternate screen */ int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ @@ -170,7 +139,6 @@ typedef struct { int arg[ESC_ARG_SIZ]; int narg; /* nb of args */ char mode[2]; - int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ } CSIEscape; /* STR Escape sequence structs */ @@ -180,24 +148,17 @@ typedef struct { char *buf; /* allocated raw string */ size_t siz; /* allocation size */ size_t len; /* raw string length */ - char *argp[STR_ARG_SIZ]; /* pointers to the end of nth argument */ + char *args[STR_ARG_SIZ]; int narg; /* nb of args */ } STREscape; -typedef struct { - int state; - size_t length; -} URLdfa; - static void execsh(char *, char **); static void stty(char **); static void sigchld(int); static void ttywriteraw(const char *, size_t); -static void histclean(void); static void csidump(void); static void csihandle(void); -static void readcolonargs(char **, int, int[][CAR_PER_ARG]); static void csiparse(void); static void csireset(void); static void osc_color_response(int, int, int); @@ -211,54 +172,40 @@ static void tprinter(char *, size_t); static void tdumpsel(void); static void tdumpline(int); static void tdump(void); -static void tclearregion(int, int, int, int, int); +static void tclearregion(int, int, int, int); static void tcursor(int); -static void tclearglyph(Glyph *, int); -static void tresetcursor(void); static void tdeletechar(int); static void tdeleteline(int); static void tinsertblank(int); static void tinsertblankline(int); -static int tlinelen(Line len); -static int tiswrapped(Line line); -static char *tgetglyphs(char *, const Glyph *, const Glyph *); -static size_t tgetline(char *, const Glyph *); +static int tlinelen(int); static void tmoveto(int, int); static void tmoveato(int, int); static void tnewline(int); static void tputtab(int); static void tputc(Rune); static void treset(void); -static void tscrollup(int, int, int, int); +static void tscrollup(int, int); static void tscrolldown(int, int); -static void treflow(int, int); -static void rscrolldown(int); -static void tresizedef(int, int); -static void tresizealt(int, int); static void tsetattr(const int *, int); static void tsetchar(Rune, const Glyph *, int, int); static void tsetdirt(int, int); static void tsetscroll(int, int); static void tswapscreen(void); -static void tloaddefscreen(int, int); -static void tloadaltscreen(int, int); static void tsetmode(int, int, const int *, int); static int twrite(const char *, int, int); +static void tfulldirt(void); static void tcontrolcode(uchar ); static void tdectest(char ); static void tdefutf8(char); static int32_t tdefcolor(const int *, int *, int); static void tdeftran(char); static void tstrsequence(uchar); -static int daddch(URLdfa *, char); static void drawregion(int, int, int, int); static void selnormalize(void); -static void selscroll(int, int, int); -static void selmove(int); -static void selremove(void); -static int regionselected(int, int, int, int); +static void selscroll(int, int); static void selsnap(int *, int *, int); static size_t utf8decode(const char *, Rune *, size_t); @@ -285,33 +232,6 @@ static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; -#include <time.h> -static int su = 0; -struct timespec sutv; - -static void -tsync_begin() -{ - clock_gettime(CLOCK_MONOTONIC, &sutv); - su = 1; -} - -static void -tsync_end() -{ - su = 0; -} - -int -tinsync(uint timeout) -{ - struct timespec now; - if (su && !clock_gettime(CLOCK_MONOTONIC, &now) - && TIMEDIFF(now, sutv) >= timeout) - su = 0; - return su; -} - ssize_t xwrite(int fd, const char *s, size_t len) { @@ -485,46 +405,17 @@ selinit(void) } int -tlinelen(Line line) +tlinelen(int y) { - int i = term.col - 1; + int i = term.col; - for (; i >= 0 && !(line[i].mode & (ATTR_SET | ATTR_WRAP)); i--); - return i + 1; -} + if (term.line[y][i - 1].mode & ATTR_WRAP) + return i; -int -tiswrapped(Line line) -{ - int len = tlinelen(line); + while (i > 0 && term.line[y][i - 1].u == ' ') + --i; - return len > 0 && (line[len - 1].mode & ATTR_WRAP); -} - -char * -tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp) -{ - while (gp <= lgp) - if (gp->mode & ATTR_WDUMMY) { - gp++; - } else { - buf += utf8encode((gp++)->u, buf); - } - return buf; -} - -size_t -tgetline(char *buf, const Glyph *fgp) -{ - char *ptr; - const Glyph *lgp = &fgp[term.col - 1]; - - while (lgp > fgp && !(lgp->mode & (ATTR_SET | ATTR_WRAP))) - lgp--; - ptr = tgetglyphs(buf, fgp, lgp); - if (!(lgp->mode & ATTR_WRAP)) - *(ptr++) = '\n'; - return ptr - buf; + return i; } void @@ -564,11 +455,10 @@ selextend(int col, int row, int type, int done) sel.oe.x = col; sel.oe.y = row; - sel.type = type; selnormalize(); + sel.type = type; - if (oldey != sel.oe.y || oldex != sel.oe.x || - oldtype != sel.type || sel.mode == SEL_EMPTY) + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); sel.mode = done ? SEL_IDLE : SEL_READY; @@ -595,50 +485,43 @@ selnormalize(void) /* expand selection over line breaks */ if (sel.type == SEL_RECTANGULAR) return; - - i = tlinelen(TLINE(sel.nb.y)); - if (sel.nb.x > i) + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) sel.nb.x = i; - if (sel.ne.x >= tlinelen(TLINE(sel.ne.y))) - sel.ne.x = term.col - 1; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; } int -regionselected(int x1, int y1, int x2, int y2) +selected(int x, int y) { - if (sel.ob.x == -1 || sel.mode == SEL_EMPTY || - sel.alt != IS_SET(MODE_ALTSCREEN) || sel.nb.y > y2 || sel.ne.y < y1) + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) return 0; - return (sel.type == SEL_RECTANGULAR) ? sel.nb.x <= x2 && sel.ne.x >= x1 - : (sel.nb.y != y2 || sel.nb.x <= x2) && - (sel.ne.y != y1 || sel.ne.x >= x1); -} + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); -int -selected(int x, int y) -{ - return regionselected(x, y, x, y); + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); } void selsnap(int *x, int *y, int direction) { int newx, newy, xt, yt; - int rtop = 0, rbot = term.row - 1; int delim, prevdelim; const Glyph *gp, *prevgp; - if (!IS_SET(MODE_ALTSCREEN)) - rtop += -term.histf + term.scr, rbot += term.scr; - switch (sel.snap) { case SNAP_WORD: /* * Snap around if the word wraps around at the end or * beginning of a line. */ - prevgp = &TLINE(*y)[*x]; + prevgp = &term.line[*y][*x]; prevdelim = ISDELIM(prevgp->u); for (;;) { newx = *x + direction; @@ -646,24 +529,24 @@ selsnap(int *x, int *y, int direction) if (!BETWEEN(newx, 0, term.col - 1)) { newy += direction; newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, rtop, rbot)) + if (!BETWEEN(newy, 0, term.row - 1)) break; if (direction > 0) yt = *y, xt = *x; else yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + if (!(term.line[yt][xt].mode & ATTR_WRAP)) break; } - if (newx >= tlinelen(TLINE(newy))) + if (newx >= tlinelen(newy)) break; - gp = &TLINE(newy)[newx]; + gp = &term.line[newy][newx]; delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || - (delim && !(gp->u == ' ' && prevgp->u == ' ')))) + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) break; *x = newx; @@ -680,14 +563,18 @@ selsnap(int *x, int *y, int direction) */ *x = (direction < 0) ? 0 : term.col - 1; if (direction < 0) { - for (; *y > rtop; *y -= 1) { - if (!tiswrapped(TLINE(*y-1))) + for (; *y > 0; *y += direction) { + if (!(term.line[*y-1][term.col-1].mode + & ATTR_WRAP)) { break; + } } } else if (direction > 0) { - for (; *y < rbot; *y += 1) { - if (!tiswrapped(TLINE(*y))) + for (; *y < term.row-1; *y += direction) { + if (!(term.line[*y][term.col-1].mode + & ATTR_WRAP)) { break; + } } } break; @@ -698,34 +585,40 @@ char * getsel(void) { char *str, *ptr; - int y, lastx, linelen; - const Glyph *gp, *lgp; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; - if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + if (sel.ob.x == -1) return NULL; - str = xmalloc((term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ); - ptr = str; + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); /* append every set & selected glyph to the selection */ for (y = sel.nb.y; y <= sel.ne.y; y++) { - Line line = TLINE(y); - - if ((linelen = tlinelen(line)) == 0) { + if ((linelen = tlinelen(y)) == 0) { *ptr++ = '\n'; continue; } if (sel.type == SEL_RECTANGULAR) { - gp = &line[sel.nb.x]; + gp = &term.line[y][sel.nb.x]; lastx = sel.ne.x; } else { - gp = &line[sel.nb.y == y ? sel.nb.x : 0]; + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } - lgp = &line[MIN(lastx, linelen-1)]; + last = &term.line[y][MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } - ptr = tgetglyphs(ptr, gp, lgp); /* * Copy and pasting of line endings is inconsistent * in the inconsistent terminal and GUI world. @@ -736,10 +629,10 @@ getsel(void) * FIXME: Fix the computer world. */ if ((y < sel.ne.y || lastx >= linelen) && - (!(lgp->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) *ptr++ = '\n'; } - *ptr = '\0'; + *ptr = 0; return str; } @@ -748,15 +641,9 @@ selclear(void) { if (sel.ob.x == -1) return; - selremove(); - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selremove(void) -{ sel.mode = SEL_IDLE; sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); } void @@ -927,9 +814,6 @@ ttynew(const char *line, char *cmd, const char *out, char **args) return cmdfd; } -static int twrite_aborted = 0; -int ttyread_pending() { return twrite_aborted; } - size_t ttyread(void) { @@ -938,7 +822,7 @@ ttyread(void) int ret, written; /* append read bytes to unprocessed bytes */ - ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen); + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); switch (ret) { case 0: @@ -946,7 +830,7 @@ ttyread(void) case -1: die("couldn't read from shell: %s\n", strerror(errno)); default: - buflen += twrite_aborted ? 0 : ret; + buflen += ret; written = twrite(buf, buflen, 0); buflen -= written; /* keep any incomplete UTF-8 byte sequence for the next call */ @@ -961,7 +845,6 @@ ttywrite(const char *s, size_t n, int may_echo) { const char *next; - kscrolldown(&((Arg){ .i = term.scr })); if (may_echo && IS_SET(MODE_ECHO)) twrite(s, n, 1); @@ -986,14 +869,6 @@ ttywrite(const char *s, size_t n, int may_echo) } void -histclean() -{ - for (int i = 0; i < HISTSIZE; i++) - term.hist[i] = xmalloc(term.col * sizeof(Glyph)); - term.histf = 0; -} - -void ttywriteraw(const char *s, size_t n) { fd_set wfd, rfd; @@ -1097,11 +972,6 @@ tsetdirt(int top, int bot) term.dirty[i] = 1; } -int tisaltscr(void) -{ - return IS_SET(MODE_ALTSCREEN); -} - void tsetdirtattr(int attr) { @@ -1110,7 +980,7 @@ tsetdirtattr(int attr) for (i = 0; i < term.row-1; i++) { for (j = 0; j < term.col-1; j++) { if (term.line[i][j].mode & attr) { - term.dirty[i] = 1; + tsetdirt(i, i); break; } } @@ -1120,9 +990,7 @@ tsetdirtattr(int attr) void tfulldirt(void) { - tsync_end(); - for (int i = 0; i < term.row; i++) - term.dirty[i] = 1; + tsetdirt(0, term.row-1); } void @@ -1140,257 +1008,109 @@ tcursor(int mode) } void -tresetcursor(void) -{ - term.c = (TCursor){ { .mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg }, - .x = 0, .y = 0, .state = CURSOR_DEFAULT }; -} - -void treset(void) { uint i; - int x, y; - tresetcursor(); + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; memset(term.tabs, 0, term.col * sizeof(*term.tabs)); for (i = tabspaces; i < term.col; i += tabspaces) term.tabs[i] = 1; term.top = 0; - term.histf = 0; - term.scr = 0; term.bot = term.row - 1; term.mode = MODE_WRAP|MODE_UTF8; memset(term.trantbl, CS_USA, sizeof(term.trantbl)); term.charset = 0; - selremove(); for (i = 0; i < 2; i++) { - tcursor(CURSOR_SAVE); /* reset saved cursor */ - for (y = 0; y < term.row; y++) - for (x = 0; x < term.col; x++) - tclearglyph(&term.line[y][x], 0); + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); tswapscreen(); } - tfulldirt(); } void tnew(int col, int row) { - int i, j; - - for (i = 0; i < 2; i++) { - term.line = xmalloc(row * sizeof(Line)); - for (j = 0; j < row; j++) - term.line[j] = xmalloc(col * sizeof(Glyph)); - term.col = col, term.row = row; - tswapscreen(); - } - term.dirty = xmalloc(row * sizeof(*term.dirty)); - term.tabs = xmalloc(col * sizeof(*term.tabs)); - for (i = 0; i < HISTSIZE; i++) - term.hist[i] = xmalloc(col * sizeof(Glyph)); - treset(); + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); } -/* handle it with care */ void tswapscreen(void) { - static Line *altline; - static int altcol, altrow; - Line *tmpline = term.line; - int tmpcol = term.col, tmprow = term.row; + Line *tmp = term.line; - term.line = altline; - term.col = altcol, term.row = altrow; - altline = tmpline; - altcol = tmpcol, altrow = tmprow; + term.line = term.alt; + term.alt = tmp; term.mode ^= MODE_ALTSCREEN; -} - -void -tloaddefscreen(int clear, int loadcursor) -{ - int col, row, alt = IS_SET(MODE_ALTSCREEN); - - if (alt) { - if (clear) - tclearregion(0, 0, term.col-1, term.row-1, 1); - col = term.col, row = term.row; - tswapscreen(); - } - if (loadcursor) - tcursor(CURSOR_LOAD); - if (alt) - tresizedef(col, row); -} - -void -tloadaltscreen(int clear, int savecursor) -{ - int col, row, def = !IS_SET(MODE_ALTSCREEN); - - if (savecursor) - tcursor(CURSOR_SAVE); - if (def) { - col = term.col, row = term.row; - tswapscreen(); - term.scr = 0; - tresizealt(col, row); - } - if (clear) - tclearregion(0, 0, term.col-1, term.row-1, 1); -} - -int -tisaltscreen(void) -{ - return IS_SET(MODE_ALTSCREEN); -} - -void -kscrolldown(const Arg* a) -{ - int n = a->i; - - if (!term.scr || IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) - n = MAX(term.row / -n, 1); - - if (n <= term.scr) { - term.scr -= n; - } else { - n = term.scr; - term.scr = 0; - } - - if (sel.ob.x != -1 && !sel.alt) - selmove(-n); /* negate change in term.scr */ tfulldirt(); } void -kscrollup(const Arg* a) +tscrolldown(int orig, int n) { - int n = a->i; - - if (!term.histf || IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) - n = MAX(term.row / -n, 1); - - if (term.scr + n <= term.histf) { - term.scr += n; - } else { - n = term.histf - term.scr; - term.scr = term.histf; - } - - if (sel.ob.x != -1 && !sel.alt) - selmove(n); /* negate change in term.scr */ - tfulldirt(); -} - -void -tscrolldown(int top, int n) -{ - int i, bot = term.bot; + int i; Line temp; - if (n <= 0) - return; - n = MIN(n, bot-top+1); + LIMIT(n, 0, term.bot-orig+1); - tsetdirt(top, bot-n); - tclearregion(0, bot-n+1, term.col-1, bot, 1); + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); - for (i = bot; i >= top+n; i--) { + for (i = term.bot; i >= orig+n; i--) { temp = term.line[i]; term.line[i] = term.line[i-n]; term.line[i-n] = temp; } - if (sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN)) - selscroll(top, bot, n); + selscroll(orig, n); } void -tscrollup(int top, int bot, int n, int mode) +tscrollup(int orig, int n) { - int i, j, s; - int alt = IS_SET(MODE_ALTSCREEN); - int savehist = !alt && top == 0 && mode != SCROLL_NOSAVEHIST; + int i; Line temp; - if (n <= 0) - return; - n = MIN(n, bot-top+1); - - if (savehist) { - for (i = 0; i < n; i++) { - term.histi = (term.histi + 1) % HISTSIZE; - temp = term.hist[term.histi]; - for (j = 0; j < term.col; j++) - tclearglyph(&temp[j], 1); - term.hist[term.histi] = term.line[i]; - term.line[i] = temp; - } - term.histf = MIN(term.histf + n, HISTSIZE); - s = n; - if (term.scr) { - j = term.scr; - term.scr = MIN(j + n, HISTSIZE); - s = j + n - term.scr; - } - if (mode != SCROLL_RESIZE) - tfulldirt(); - } else { - tclearregion(0, top, term.col-1, top+n-1, 1); - tsetdirt(top+n, bot); - } + LIMIT(n, 0, term.bot-orig+1); + + tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig+n, term.bot); - for (i = top; i <= bot-n; i++) { + for (i = orig; i <= term.bot-n; i++) { temp = term.line[i]; term.line[i] = term.line[i+n]; term.line[i+n] = temp; } - if (sel.ob.x != -1 && sel.alt == alt) { - if (!savehist) { - selscroll(top, bot, -n); - } else if (s > 0) { - selmove(-s); - if (-term.scr + sel.nb.y < -term.histf) - selremove(); - } - } + selscroll(orig, -n); } void -selmove(int n) +selscroll(int orig, int n) { - sel.ob.y += n, sel.nb.y += n; - sel.oe.y += n, sel.ne.y += n; -} - -void -selscroll(int top, int bot, int n) -{ - /* turn absolute coordinates into relative */ - top += term.scr, bot += term.scr; + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return; - if (BETWEEN(sel.nb.y, top, bot) != BETWEEN(sel.ne.y, top, bot)) { + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { selclear(); - } else if (BETWEEN(sel.nb.y, top, bot)) { - selmove(n); - if (sel.nb.y < top || sel.ne.y > bot) + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { selclear(); + } else { + selnormalize(); + } } } @@ -1400,7 +1120,7 @@ tnewline(int first_col) int y = term.c.y; if (y == term.bot) { - tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); + tscrollup(term.top, 1); } else { y++; } @@ -1408,28 +1128,6 @@ tnewline(int first_col) } void -readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) -{ - int i = 0; - for (; i < CAR_PER_ARG; i++) - params[cursor][i] = -1; - - if (**p != ':') - return; - - char *np = NULL; - i = 0; - - while (**p == ':' && i < CAR_PER_ARG) { - while (**p == ':') - (*p)++; - params[cursor][i] = strtol(*p, &np, 10); - *p = np; - i++; - } -} - -void csiparse(void) { char *p = csiescseq.buf, *np; @@ -1451,7 +1149,6 @@ csiparse(void) v = -1; csiescseq.arg[csiescseq.narg++] = v; p = np; - readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) break; p++; @@ -1518,80 +1215,70 @@ tsetchar(Rune u, const Glyph *attr, int x, int y) term.dirty[y] = 1; term.line[y][x] = *attr; term.line[y][x].u = u; - term.line[y][x].mode |= ATTR_SET; - - if (isboxdraw(u)) - term.line[y][x].mode |= ATTR_BOXDRAW; } void -tclearglyph(Glyph *gp, int usecurattr) -{ - if (usecurattr) { - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - } else { - gp->fg = defaultfg; - gp->bg = defaultbg; - } - gp->mode =ATTR_NULL; - gp->u = ' '; -} - -void -tclearregion(int x1, int y1, int x2, int y2, int usecurattr) +tclearregion(int x1, int y1, int x2, int y2) { int x, y, temp; Glyph *gp; - /* regionselected() takes relative coordinates */ - if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) - selremove(); + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.col-1); + LIMIT(x2, 0, term.col-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); for (y = y1; y <= y2; y++) { term.dirty[y] = 1; - for (x = x1; x <= x2; x++) - tclearglyph(&term.line[y][x], usecurattr); + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } } } void tdeletechar(int n) { - int src, dst, size; - Line line; + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); - if (n <= 0) - return; dst = term.c.x; - src = MIN(term.c.x + n,term.col); + src = term.c.x + n; size = term.col - src; + line = term.line[term.c.y]; - if (size > 0) { /* otherwise src would point beyond the array - https://stackoverflow.com/questions/29844298 */ - line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - } - tclearregion(dst + size, term.c.y, term.col - 1, term.c.y, 1); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); } void tinsertblank(int n) { - int src, dst, size; - Line line; + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); - if (n <= 0) - return; - dst= MIN(term.c.x + n, term.col); + dst = term.c.x + n; src = term.c.x; size = term.col - dst; + line = term.line[term.c.y]; - if (size > 0) { /* otherwise dst would point beyond the array */ - line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - } - tclearregion(src, term.c.y, dst - 1, term.c.y, 1); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); } void @@ -1605,7 +1292,7 @@ void tdeleteline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, term.bot, n, SCROLL_NOSAVEHIST); + tscrollup(term.c.y, n); } int32_t @@ -1678,10 +1365,6 @@ tsetattr(const int *attr, int l) ATTR_STRUCK ); term.c.attr.fg = defaultfg; term.c.attr.bg = defaultbg; - term.c.attr.ustyle = -1; - term.c.attr.ucolor[0] = -1; - term.c.attr.ucolor[1] = -1; - term.c.attr.ucolor[2] = -1; break; case 1: term.c.attr.mode |= ATTR_BOLD; @@ -1693,14 +1376,7 @@ tsetattr(const int *attr, int l) term.c.attr.mode |= ATTR_ITALIC; break; case 4: - term.c.attr.ustyle = csiescseq.carg[i][0]; - - if (term.c.attr.ustyle != 0) - term.c.attr.mode |= ATTR_UNDERLINE; - else - term.c.attr.mode &= ~ATTR_UNDERLINE; - - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; + term.c.attr.mode |= ATTR_UNDERLINE; break; case 5: /* slow blink */ /* FALLTHROUGH */ @@ -1751,18 +1427,6 @@ tsetattr(const int *attr, int l) case 49: term.c.attr.bg = defaultbg; break; - case 58: - term.c.attr.ucolor[0] = csiescseq.carg[i][1]; - term.c.attr.ucolor[1] = csiescseq.carg[i][2]; - term.c.attr.ucolor[2] = csiescseq.carg[i][3]; - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; - case 59: - term.c.attr.ucolor[0] = -1; - term.c.attr.ucolor[1] = -1; - term.c.attr.ucolor[2] = -1; - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; default: if (BETWEEN(attr[i], 30, 37)) { term.c.attr.fg = attr[i] - 30; @@ -1802,7 +1466,7 @@ tsetscroll(int t, int b) void tsetmode(int priv, int set, const int *args, int narg) { - const int *lim; + int alt; const int *lim; for (lim = args + narg; args < lim; ++args) { if (priv) { @@ -1863,18 +1527,25 @@ tsetmode(int priv, int set, const int *args, int narg) xsetmode(set, MODE_8BIT); break; case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ case 47: /* swap screen */ - case 1047: /* swap screen, clearing alternate screen */ + case 1047: if (!allowaltscreen) break; - if (set) - tloadaltscreen(*args == 1049, *args == 1049); - else - tloaddefscreen(*args == 1047, *args == 1049); - break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col-1, + term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ case 1048: - if (!allowaltscreen) - break; tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); break; case 2004: /* 2004: bracketed paste mode */ @@ -1926,7 +1597,7 @@ void csihandle(void) { char buf[40]; - int n, x; + int len; switch (csiescseq.mode[0]) { default: @@ -1972,7 +1643,7 @@ csihandle(void) ttywrite(vtiden, strlen(vtiden), 0); break; case 'b': /* REP -- if last char is printable print it <n> more times */ - DEFAULT(csiescseq.arg[0], 1); + LIMIT(csiescseq.arg[0], 1, 65535); if (term.lastc) while (csiescseq.arg[0]-- > 0) tputc(term.lastc); @@ -2024,31 +1695,20 @@ csihandle(void) case 'J': /* ED -- Clear screen */ switch (csiescseq.arg[0]) { case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, term.row-1, 1); + tclearregion(0, term.c.y+1, term.col-1, + term.row-1); } break; case 1: /* above */ - if (term.c.y >= 1) - tclearregion(0, 0, term.col-1, term.c.y-1, 1); - tclearregion(0, term.c.y, term.c.x, term.c.y, 1); + if (term.c.y > 1) + tclearregion(0, 0, term.col-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); break; case 2: /* all */ - if (IS_SET(MODE_ALTSCREEN)) { - tclearregion(0, 0, term.col-1, term.row-1, 1); - break; - } - /* vte does this: - tscrollup(0, term.row-1, term.row, SCROLL_SAVEHIST); */ - - /* alacritty does this: */ - for (n = term.row-1; n >= 0 && tlinelen(term.line[n]) == 0; n--); - if (n >= 0) - tscrollup(0, term.row-1, n+1, SCROLL_SAVEHIST); - tscrollup(0, term.row-1, term.row-n-1, SCROLL_NOSAVEHIST); - histclean(); - break; + tclearregion(0, 0, term.col-1, term.row-1); + break; default: goto unknown; } @@ -2056,20 +1716,21 @@ csihandle(void) case 'K': /* EL -- Clear line */ switch (csiescseq.arg[0]) { case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); + tclearregion(term.c.x, term.c.y, term.col-1, + term.c.y); break; case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y, 1); + tclearregion(0, term.c.y, term.c.x, term.c.y); break; case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y, 1); + tclearregion(0, term.c.y, term.col-1, term.c.y); break; } break; case 'S': /* SU -- Scroll <n> line up */ + if (csiescseq.priv) break; DEFAULT(csiescseq.arg[0], 1); - /* xterm, urxvt, alacritty save this in history */ - tscrollup(term.top, term.bot, csiescseq.arg[0], SCROLL_SAVEHIST); + tscrollup(term.top, csiescseq.arg[0]); break; case 'T': /* SD -- Scroll <n> line down */ DEFAULT(csiescseq.arg[0], 1); @@ -2087,11 +1748,9 @@ csihandle(void) tdeleteline(csiescseq.arg[0]); break; case 'X': /* ECH -- Erase <n> char */ - if (csiescseq.arg[0] < 0) - return; DEFAULT(csiescseq.arg[0], 1); - x = MIN(term.c.x + csiescseq.arg[0], term.col) - 1; - tclearregion(term.c.x, term.c.y, x, term.c.y, 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); break; case 'P': /* DCH -- Delete <n> char */ DEFAULT(csiescseq.arg[0], 1); @@ -2111,11 +1770,18 @@ csihandle(void) case 'm': /* SGR -- Terminal attribute (color) */ tsetattr(csiescseq.arg, csiescseq.narg); break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { - n = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, n, 0); + case 'n': /* DSR -- Device Status Report */ + 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(buf, sizeof(buf), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buf, len, 0); + break; + default: + goto unknown; } break; case 'r': /* DECSTBM -- Set Scrolling Region */ @@ -2144,33 +1810,6 @@ csihandle(void) goto unknown; } break; - case 't': /* title stack operations */ - switch (csiescseq.arg[0]) { - case 22: /* pust current title on stack */ - switch (csiescseq.arg[1]) { - case 0: - case 1: - case 2: - xpushtitle(); - break; - default: - goto unknown; - } - break; - case 23: /* pop last title from stack */ - switch (csiescseq.arg[1]) { - case 0: - case 1: - case 2: - xsettitle(NULL, 1); - break; - default: - goto unknown; - } - break; - default: - goto unknown; - } } } @@ -2241,30 +1880,29 @@ strhandle(void) }; term.esc &= ~(ESC_STR_END|ESC_STR); - strescseq.buf[strescseq.len] = '\0'; + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; switch (strescseq.type) { case ']': /* OSC -- Operating System Command */ - strparse(); - par = (narg = strescseq.narg) ? atoi(STRESCARGJUST(0)) : 0; switch (par) { case 0: if (narg > 1) { - xsettitle(STRESCARGREST(1), 0); - xseticontitle(STRESCARGREST(1)); + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); } return; case 1: if (narg > 1) - xseticontitle(STRESCARGREST(1)); + xseticontitle(strescseq.args[1]); return; case 2: if (narg > 1) - xsettitle(STRESCARGREST(1), 0); + xsettitle(strescseq.args[1]); return; case 52: if (narg > 2 && allowwindowops) { - dec = base64dec(STRESCARGREST(2)); + dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); xclipcopy(); @@ -2278,7 +1916,7 @@ strhandle(void) case 12: if (narg < 2) break; - p = STRESCARGREST(1); + p = strescseq.args[1]; if ((j = par - 10) < 0 || j >= LEN(osc_table)) break; /* shouldn't be possible */ @@ -2294,16 +1932,18 @@ strhandle(void) case 4: /* color set */ if (narg < 3) break; - p = STRESCARGJUST(2); + p = strescseq.args[2]; /* FALLTHROUGH */ case 104: /* color reset */ - j = (narg > 1) ? atoi(STRESCARGJUST(1)) : -1; + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; if (p && !strcmp(p, "?")) { osc_color_response(j, 0, 1); } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) + if (par == 104 && narg <= 1) { + xloadcols(); return; /* color reset without parameter */ + } fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, p ? p : "(null)"); } else { @@ -2317,15 +1957,9 @@ strhandle(void) } break; case 'k': /* old title set compatibility */ - xsettitle(strescseq.buf, 0); + xsettitle(strescseq.args[0]); return; case 'P': /* DCS -- Device Control String */ - /* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */ - if (strstr(strescseq.buf, "=1s") == strescseq.buf) - tsync_begin(); /* BSU */ - else if (strstr(strescseq.buf, "=2s") == strescseq.buf) - tsync_end(); /* ESU */ - return; case '_': /* APC -- Application Program Command */ case '^': /* PM -- Privacy Message */ return; @@ -2342,17 +1976,18 @@ strparse(void) char *p = strescseq.buf; strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; if (*p == '\0') return; while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; while ((c = *p) != ';' && c != '\0') - p++; - strescseq.argp[strescseq.narg++] = p; + ++p; if (c == '\0') return; - p++; + *p++ = '\0'; } } @@ -2441,8 +2076,16 @@ tdumpsel(void) void tdumpline(int n) { - char str[(term.col + 1) * UTF_SIZ]; - tprinter(str, tgetline(str, &term.line[n][0])); + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); } void @@ -2663,7 +2306,7 @@ eschandle(uchar ascii) return 0; case 'D': /* IND -- Linefeed */ if (term.c.y == term.bot) { - tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); + tscrollup(term.top, 1); } else { tmoveto(term.c.x, term.c.y+1); } @@ -2686,9 +2329,9 @@ eschandle(uchar ascii) break; case 'c': /* RIS -- Reset to initial state */ treset(); - xfreetitlestack(); resettitle(); xloadcols(); + xsetmode(0, MODE_HIDE); break; case '=': /* DECPAM -- Application keypad */ xsetmode(1, MODE_APPKEYPAD); @@ -2781,6 +2424,9 @@ check_control_code: * they must not cause conflicts with sequences. */ if (control) { + /* in UTF-8 mode ignore handling C1 control characters */ + if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) + return; tcontrolcode(u); /* * control codes are not shown ever @@ -2817,8 +2463,7 @@ check_control_code: */ return; } - /* selected() takes relative coordinates */ - if (selected(term.c.x + term.scr, term.c.y + term.scr)) + if (selected(term.c.x, term.c.y)) selclear(); gp = &term.line[term.c.y][term.c.x]; @@ -2828,11 +2473,16 @@ check_control_code: gp = &term.line[term.c.y][term.c.x]; } - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + gp->mode &= ~ATTR_WIDE; + } if (term.c.x+width > term.col) { - tnewline(1); + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); gp = &term.line[term.c.y][term.c.x]; } @@ -2853,7 +2503,6 @@ check_control_code: if (term.c.x+width < term.col) { tmoveto(term.c.x+width, term.c.y); } else { - term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = width; term.c.state |= CURSOR_WRAPNEXT; } } @@ -2865,9 +2514,6 @@ twrite(const char *buf, int buflen, int show_ctrl) Rune u; int n; - int su0 = su; - twrite_aborted = 0; - for (n = 0; n < buflen; n += charsize) { if (IS_SET(MODE_UTF8)) { /* process a complete utf8 char */ @@ -2878,10 +2524,6 @@ twrite(const char *buf, int buflen, int show_ctrl) u = buf[n] & 0xFF; charsize = 1; } - if (su0 && !su) { - twrite_aborted = 1; - break; // ESU - allow rendering before a new BSU - } if (show_ctrl && ISCONTROL(u)) { if (u & 0x80) { u &= 0x7f; @@ -2898,281 +2540,91 @@ twrite(const char *buf, int buflen, int show_ctrl) } void -treflow(int col, int row) -{ - int i, j; - int oce, nce, bot, scr; - int ox = 0, oy = -term.histf, nx = 0, ny = -1, len; - int cy = -1; /* proxy for new y coordinate of cursor */ - int nlines; - Line *buf, line; - - /* y coordinate of cursor line end */ - for (oce = term.c.y; oce < term.row - 1 && - tiswrapped(term.line[oce]); oce++); - - nlines = term.histf + oce + 1; - if (col < term.col) { - /* each line can take this many lines after reflow */ - j = (term.col + col - 1) / col; - nlines = j * nlines; - if (nlines > HISTSIZE + RESIZEBUFFER + row) { - nlines = HISTSIZE + RESIZEBUFFER + row; - oy = -(nlines / j - oce - 1); - } - } - buf = xmalloc(nlines * sizeof(Line)); - do { - if (!nx) - buf[++ny] = xmalloc(col * sizeof(Glyph)); - if (!ox) { - line = TLINEABS(oy); - len = tlinelen(line); - } - if (oy == term.c.y) { - if (!ox) - len = MAX(len, term.c.x + 1); - /* update cursor */ - if (cy < 0 && term.c.x - ox < col - nx) { - term.c.x = nx + term.c.x - ox, cy = ny; - UPDATEWRAPNEXT(0, col); - } - } - /* get reflowed lines in buf */ - if (col - nx > len - ox) { - memcpy(&buf[ny][nx], &line[ox], (len-ox) * sizeof(Glyph)); - nx += len - ox; - if (len == 0 || !(line[len - 1].mode & ATTR_WRAP)) { - for (j = nx; j < col; j++) - tclearglyph(&buf[ny][j], 0); - nx = 0; - } else if (nx > 0) { - buf[ny][nx - 1].mode &= ~ATTR_WRAP; - } - ox = 0, oy++; - } else if (col - nx == len - ox) { - memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); - ox = 0, oy++, nx = 0; - } else/* if (col - nx < len - ox) */ { - memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); - ox += col - nx; - buf[ny][col - 1].mode |= ATTR_WRAP; - nx = 0; - } - } while (oy <= oce); - if (nx) - for (j = nx; j < col; j++) - tclearglyph(&buf[ny][j], 0); - - /* free extra lines */ - for (i = row; i < term.row; i++) - free(term.line[i]); - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - - bot = MIN(ny, row - 1); - scr = MAX(row - term.row, 0); - /* update y coordinate of cursor line end */ - nce = MIN(oce + scr, bot); - /* update cursor y coordinate */ - term.c.y = nce - (ny - cy); - if (term.c.y < 0) { - j = nce, nce = MIN(nce + -term.c.y, bot); - term.c.y += nce - j; - while (term.c.y < 0) { - free(buf[ny--]); - term.c.y++; - } - } - /* allocate new rows */ - for (i = row - 1; i > nce; i--) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* fill visible area */ - for (/*i = nce */; i >= term.row; i--, ny--) - term.line[i] = buf[ny]; - for (/*i = term.row - 1 */; i >= 0; i--, ny--) { - free(term.line[i]); - term.line[i] = buf[ny]; - } - /* fill lines in history buffer and update term.histf */ - for (/*i = -1 */; ny >= 0 && i >= -HISTSIZE; i--, ny--) { - j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; - free(term.hist[j]); - term.hist[j] = buf[ny]; - } - term.histf = -i - 1; - term.scr = MIN(term.scr, term.histf); - /* resize rest of the history lines */ - for (/*i = -term.histf - 1 */; i >= -HISTSIZE; i--) { - j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; - term.hist[j] = xrealloc(term.hist[j], col * sizeof(Glyph)); - } - free(buf); -} - -void -rscrolldown(int n) -{ - int i; - Line temp; - - /* can never be true as of now - if (IS_SET(MODE_ALTSCREEN)) - return; */ - - if ((n = MIN(n, term.histf)) <= 0) - return; - - for (i = term.c.y + n; i >= n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - for (/*i = n - 1 */; i >= 0; i--) { - temp = term.line[i]; - term.line[i] = term.hist[term.histi]; - term.hist[term.histi] = temp; - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; - } - term.c.y += n; - term.histf -= n; - if ((i = term.scr - n) >= 0) { - term.scr = i; - } else { - term.scr = 0; - if (sel.ob.x != -1 && !sel.alt) - selmove(-i); - } -} - -void tresize(int col, int row) { + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); int *bp; + TCursor c; - /* col and row are always MAX(_, 1) if (col < 1 || row < 1) { - fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); - return; - } */ - - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - if (col > term.col) { - bp = term.tabs + term.col; - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - - if (IS_SET(MODE_ALTSCREEN)) - tresizealt(col, row); - else - tresizedef(col, row); -} - -void -tresizedef(int col, int row) -{ - int i, j; - - /* return if dimensions haven't changed */ - if (term.col == col && term.row == row) { - tfulldirt(); + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); return; } - if (col != term.col) { - if (!sel.alt) - selremove(); - treflow(col, row); - } else { - /* slide screen up if otherwise cursor would get out of the screen */ - if (term.c.y >= row) { - tscrollup(0, term.row - 1, term.c.y - row + 1, SCROLL_RESIZE); - term.c.y = row - 1; - } - for (i = row; i < term.row; i++) - free(term.line[i]); - - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - /* allocate any new rows */ - for (i = term.row; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* scroll down as much as height has increased */ - rscrolldown(row - term.row); - } - /* update terminal size */ - term.col = col, term.row = row; - /* reset scrolling region */ - term.top = 0, term.bot = row - 1; - /* dirty all lines */ - tfulldirt(); -} -void -tresizealt(int col, int row) -{ - int i, j; - - /* return if dimensions haven't changed */ - if (term.col == col && term.row == row) { - tfulldirt(); - return; - } - if (sel.alt) - selremove(); - /* slide screen up if otherwise cursor would get out of the screen */ - for (i = 0; i <= term.c.y - row; i++) + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ if (i > 0) { - /* ensure that both src and dst are not NULL */ memmove(term.line, term.line + i, row * sizeof(Line)); - term.c.y = row - 1; + memmove(term.alt, term.alt + i, row * sizeof(Line)); } - for (i += row; i < term.row; i++) + for (i += row; i < term.row; i++) { free(term.line[i]); + free(term.alt[i]); + } + /* resize to new height */ term.line = xrealloc(term.line, row * sizeof(Line)); - /* resize to new width */ - for (i = 0; i < MIN(row, term.row); i++) { + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - for (j = term.col; j < col; j++) - tclearglyph(&term.line[i][j], 0); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); } + /* allocate any new rows */ - for (/*i = MIN(row, term.row) */; i < row; i++) { + for (/* i = minrow */; i < row; i++) { term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); + term.alt[i] = xmalloc(col * sizeof(Glyph)); } - /* update cursor */ - if (term.c.x >= col) { - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = col - 1; - } else { - UPDATEWRAPNEXT(1, col); + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; } /* update terminal size */ - term.col = col, term.row = row; + term.col = col; + term.row = row; /* reset scrolling region */ - term.top = 0, term.bot = row - 1; - /* dirty all lines */ - tfulldirt(); + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; } void resettitle(void) { - xsettitle(NULL, 0); + xsettitle(NULL); } void @@ -3185,7 +2637,7 @@ drawregion(int x1, int y1, int x2, int y2) continue; term.dirty[y] = 0; - xdrawline(TLINE(y), x1, y, x2); + xdrawline(term.line[y], x1, y, x2); } } @@ -3221,90 +2673,3 @@ redraw(void) tfulldirt(); draw(); } - -int -daddch(URLdfa *dfa, char c) -{ - /* () and [] can appear in urls, but excluding them here will reduce false - * positives when figuring out where a given url ends. - */ - static const char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789-._~:/?#@!$&'*+,;=%"; - static const char RPFX[] = "//:sptth"; - - if (!strchr(URLCHARS, c)) { - dfa->length = 0; - dfa->state = 0; - - return 0; - } - - dfa->length++; - - if (dfa->state == 2 && c == '/') { - dfa->state = 0; - } else if (dfa->state == 3 && c == 'p') { - dfa->state++; - } else if (c != RPFX[dfa->state]) { - dfa->state = 0; - return 0; - } - - if (dfa->state++ == 7) { - dfa->state = 0; - return 1; - } - - return 0; -} - -/* -** Select and copy the previous url on screen (do nothing if there's no url). -*/ -void -copyurl(const Arg *arg) { - int row = 0, /* row of current URL */ - col = 0, /* column of current URL start */ - colend = 0, /* column of last occurrence */ - passes = 0; /* how many rows have been scanned */ - - const char *c = NULL, - *match = NULL; - URLdfa dfa = { 0 }; - - row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; - LIMIT(row, term.top, term.bot); - - colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; - LIMIT(colend, 0, term.col); - - /* - ** Scan from (term.row - 1,term.col - 1) to (0,0) and find - ** next occurrance of a URL - */ - for (passes = 0; passes < term.row; passes++) { - /* Read in each column of every row until - ** we hit previous occurrence of URL - */ - for (col = colend; col--;) - if (daddch(&dfa, term.line[row][col].u < 128 ? term.line[row][col].u : ' ')) - break; - - if (col >= 0) - break; - - if (--row < 0) - row = term.row - 1; - - colend = term.col; - } - - if (passes < term.row) { - selstart(col, row, 0); - selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 0); - selextend((col + dfa.length - 1) % term.col, row + (col + dfa.length - 1) / term.col, SEL_REGULAR, 1); - xsetsel(getsel()); - xclipcopy(); - } -} @@ -3,8 +3,6 @@ #include <stdint.h> #include <sys/types.h> -#include <gd.h> - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -24,22 +22,18 @@ enum glyph_attribute { ATTR_NULL = 0, - ATTR_SET = 1 << 0, - ATTR_BOLD = 1 << 1, - ATTR_FAINT = 1 << 2, - ATTR_ITALIC = 1 << 3, - ATTR_UNDERLINE = 1 << 4, - ATTR_BLINK = 1 << 5, - ATTR_REVERSE = 1 << 6, - ATTR_INVISIBLE = 1 << 7, - ATTR_STRUCK = 1 << 8, - ATTR_WRAP = 1 << 9, - ATTR_WIDE = 1 << 10, - ATTR_WDUMMY = 1 << 11, - ATTR_SELECTED = 1 << 12, - ATTR_BOXDRAW = 1 << 13, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, - ATTR_DIRTYUNDERLINE = 1 << 15, }; enum selection_mode { @@ -71,8 +65,6 @@ typedef struct { ushort mode; /* attribute flags */ uint32_t fg; /* foreground */ uint32_t bg; /* background */ - int ustyle; /* underline style */ - int ucolor[3]; /* underline color */ } Glyph; typedef Glyph *Line; @@ -87,22 +79,15 @@ typedef union { void die(const char *, ...); void redraw(void); -void tfulldirt(void); void draw(void); -void kscrolldown(const Arg *); -void kscrollup(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *); void toggleprinter(const Arg *); -void copyurl(const Arg *); -static int borderpx; int tattrset(int); -int tisaltscr(void); void tnew(int, int); -int tisaltscreen(void); void tresize(int, int); void tsetdirtattr(int); void ttyhangup(void); @@ -126,14 +111,6 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); -int isboxdraw(Rune); -ushort boxdrawindex(const Glyph *); -#ifdef XFT_VERSION -/* only exposed to x.c, otherwise we'll need Xft.h for the types */ -void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *); -void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int); -#endif - /* config.h globals */ extern char *utmp; extern char *scroll; @@ -147,5 +124,3 @@ extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; extern unsigned int defaultcs; -extern const int boxdraw, boxdraw_bold, boxdraw_braille; -extern float alpha, alphaUnfocused; @@ -1,5 +1,4 @@ st-mono| simpleterm monocolor, - Su, acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, am, bce, @@ -162,7 +161,7 @@ st-mono| simpleterm monocolor, rin=\E[%p1%dT, ritm=\E[23m, rmacs=\E(B, - rmcup=\E[?1049l\E[23;0;0t, + rmcup=\E[?1049l, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[27m, @@ -173,7 +172,7 @@ st-mono| simpleterm monocolor, sitm=\E[3m, sgr0=\E[0m, smacs=\E(0, - smcup=\E[?1049h\E[22;0;0t, + smcup=\E[?1049h, smir=\E[4h, smkx=\E[?1h\E=, smso=\E[7m, @@ -185,6 +184,10 @@ st-mono| simpleterm monocolor, # XTerm extensions rmxx=\E[29m, smxx=\E[9m, + BE=\E[?2004h, + BD=\E[?2004l, + PS=\E[200~, + PE=\E[201~, # disabled rep for now: causes some issues with older ncurses versions. # rep=%p1%c\E[%p2%{1}%-%db, # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) @@ -192,7 +195,6 @@ st-mono| simpleterm monocolor, Ms=\E]52;%p1%s;%p2%s\007, Se=\E[2 q, Ss=\E[%p1%d q, - Sync=\EP=%p1%ds\E\\, st| simpleterm, use=st-mono, Binary files differ@@ -32,9 +32,7 @@ void xloadcols(void); int xsetcolorname(int, const char *); int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); void xseticontitle(char *); -void xfreetitlestack(void); -void xsettitle(char *, int); -void xpushtitle(void); +void xsettitle(char *); int xsetcursor(int); void xsetmode(int, unsigned int); void xsetpointermotion(int); @@ -4,7 +4,6 @@ #include <limits.h> #include <locale.h> #include <signal.h> -#include <stdlib.h> #include <sys/select.h> #include <time.h> #include <unistd.h> @@ -15,8 +14,6 @@ #include <X11/keysym.h> #include <X11/Xft/Xft.h> #include <X11/XKBlib.h> -#include <X11/Xresource.h> -#include <X11/extensions/Xrandr.h> char *argv0; #include "arg.h" @@ -37,7 +34,6 @@ typedef struct { void (*func)(const Arg *); const Arg arg; uint release; - int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */ } MouseShortcut; typedef struct { @@ -49,40 +45,6 @@ typedef struct { signed char appcursor; /* application cursor */ } Key; -/* Undercurl slope types */ -enum undercurl_slope_type { - UNDERCURL_SLOPE_ASCENDING = 0, - UNDERCURL_SLOPE_TOP_CAP = 1, - UNDERCURL_SLOPE_DESCENDING = 2, - UNDERCURL_SLOPE_BOTTOM_CAP = 3 -}; - -typedef struct { - const char *name; - float defaultfontsize; -} MonitorConfig; - -typedef struct { - Atom name; - int x, y, w, h; - float defaultfontsize, usedfontsize; -} MonitorInfo; - -static void refreshxrandr(const Arg *dummy); - -/* Xresources preferences */ -enum resource_type { - STRING = 0, - INTEGER = 1, - FLOAT = 2 -}; - -typedef struct { - char *name; - enum resource_type type; - void *dst; -} ResourcePref; - /* X modifiers */ #define XK_ANY_MOD UINT_MAX #define XK_NO_MOD 0 @@ -101,9 +63,6 @@ static void ttysend(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" -/* size of title stack */ -#define TITLESTACKSIZE 8 - /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 #define XEMBED_FOCUS_OUT 5 @@ -122,7 +81,6 @@ typedef XftGlyphFontSpec GlyphFontSpec; typedef struct { int tw, th; /* tty width and height */ int w, h; /* window width and height */ - int hborderpx, vborderpx; int ch; /* char height */ int cw; /* char width */ int mode; /* window state/mode flags */ @@ -135,7 +93,7 @@ typedef struct { Window win; Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmicon, netwmiconname, netwmpid; + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; struct { XIM xim; XIC xic; @@ -145,14 +103,8 @@ typedef struct { Draw draw; Visual *vis; XSetWindowAttributes attrs; - /* Here, we use the term *pointer* to differentiate the cursor - * one sees when hovering the mouse over the terminal from, e.g., - * a green rectangle where text would be entered. */ - Cursor vpointer, bpointer; /* visible and hidden pointers */ - int pointerisvisible; int scr; int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ int l, t; /* left and top offset */ int gm; /* geometry mask */ } XWindow; @@ -205,8 +157,6 @@ static void xhints(void); static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); static void xloadfonts(const char *, double); -static int xloadsparefont(FcPattern *, int); -static void xloadsparefonts(void); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); @@ -265,18 +215,11 @@ static void (*handler[LASTEvent])(XEvent *) = { [SelectionRequest] = selrequest, }; -static double defaultrelfontsize = 0; -static MonitorInfo *monitors_info = NULL; -static int monitors_num = 0; -static int prev_mindex = -1; - /* Globals */ static DC dc; static XWindow xw; static XSelection xsel; static TermWindow win; -static int tstki; /* title stack index */ -static char *titlestack[TITLESTACKSIZE]; /* title stack */ /* Font Ring Cache */ enum { @@ -300,7 +243,6 @@ static char *usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; -static char *opt_alpha = NULL; static char *opt_class = NULL; static char **opt_cmd = NULL; static char *opt_embed = NULL; @@ -310,8 +252,6 @@ static char *opt_line = NULL; static char *opt_name = NULL; static char *opt_title = NULL; -static int focused = 0; - static uint buttons; /* bit field of pressed buttons */ void @@ -366,7 +306,6 @@ zoomabs(const Arg *arg) { xunloadfonts(); xloadfonts(usedfont, arg->f); - xloadsparefonts(); cresize(0, 0); redraw(); xhints(); @@ -392,7 +331,7 @@ ttysend(const Arg *arg) int evcol(XEvent *e) { - int x = e->xbutton.x - win.hborderpx; + int x = e->xbutton.x - borderpx; LIMIT(x, 0, win.tw - 1); return x / win.cw; } @@ -400,7 +339,7 @@ evcol(XEvent *e) int evrow(XEvent *e) { - int y = e->xbutton.y - win.vborderpx; + int y = e->xbutton.y - borderpx; LIMIT(y, 0, win.th - 1); return y / win.ch; } @@ -516,7 +455,6 @@ mouseaction(XEvent *e, uint release) for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { if (ms->release == release && ms->button == e->xbutton.button && - (!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) && (match(ms->mod, state) || /* exact or forced */ match(ms->mod, state & ~forcemousemod))) { ms->func(&(ms->arg)); @@ -748,7 +686,6 @@ setsel(char *str, Time t) XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) selclear(); - clipcopy(NULL); } void @@ -779,13 +716,6 @@ brelease(XEvent *e) void bmotion(XEvent *e) { - if (!xw.pointerisvisible) { - XDefineCursor(xw.dpy, xw.win, xw.vpointer); - xw.pointerisvisible = 1; - if (!IS_SET(MODE_MOUSEMANY)) - xsetpointermotion(0); - } - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -809,9 +739,6 @@ cresize(int width, int height) col = MAX(1, col); row = MAX(1, row); - win.hborderpx = center_text ? (win.w - col * win.cw) / 2 : 0; // (win.w - col * win.cw) / 2 - win.vborderpx = center_text ? (win.h - row * win.ch) / 2 : 0; // (win.h - row * win.ch) / 2 - tresize(col, row); xresize(col, row); ttyresize(win.tw, win.th); @@ -825,7 +752,7 @@ xresize(int col, int row) XFreePixmap(xw.dpy, xw.buf); xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); + DefaultDepth(xw.dpy, xw.scr)); XftDrawChange(xw.draw, xw.buf); xclear(0, 0, win.w, win.h); @@ -864,44 +791,34 @@ xloadcolor(int i, const char *name, Color *ncolor) } void -xloadalpha(void) -{ - float const usedAlpha = focused ? alpha : alphaUnfocused; - if (opt_alpha) alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * usedAlpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24; -} - -void xloadcols(void) { + int i; static int loaded; Color *cp; - if (!loaded) { - dc.collen = 1 + (defaultbg = MAX(LEN(colorname), 256)); - dc.col = xmalloc((dc.collen) * sizeof(Color)); + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); } - for (int i = 0; i+1 < dc.collen; ++i) + for (i = 0; i < dc.collen; i++) if (!xloadcolor(i, NULL, &dc.col[i])) { if (colorname[i]) die("could not allocate color '%s'\n", colorname[i]); else die("could not allocate color %d\n", i); } - if (dc.collen) // cannot die, as the color is already loaded. - xloadcolor(focused ?bg :bgUnfocused, NULL, &dc.col[defaultbg]); - - xloadalpha(); loaded = 1; } int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) { - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; *r = dc.col[x].color.red >> 8; @@ -916,7 +833,7 @@ xsetcolorname(int x, const char *name) { Color ncolor; - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; if (!xloadcolor(x, name, &ncolor)) @@ -942,8 +859,8 @@ xclear(int x1, int y1, int x2, int y2) void xhints(void) { - XClassHint class = {opt_name ? opt_name : "st", - opt_class ? opt_class : "St"}; + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; XWMHints wm = {.flags = InputHint, .input = 1}; XSizeHints *sizeh; @@ -952,8 +869,8 @@ xhints(void) sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; sizeh->height = win.h; sizeh->width = win.w; - sizeh->height_inc = 1; - sizeh->width_inc = 1; + sizeh->height_inc = win.ch; + sizeh->width_inc = win.cw; sizeh->base_height = 2 * borderpx; sizeh->base_width = 2 * borderpx; sizeh->min_height = win.ch + 2 * borderpx; @@ -1115,8 +1032,6 @@ xloadfonts(const char *fontstr, double fontsize) win.cw = ceilf(dc.font.width * cwscale); win.ch = ceilf(dc.font.height * chscale); - borderpx = ceilf(((float)borderperc / 100) * win.cw); - FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); if (xloadfont(&dc.ifont, pattern)) @@ -1135,101 +1050,6 @@ xloadfonts(const char *fontstr, double fontsize) FcPatternDestroy(pattern); } -int -xloadsparefont(FcPattern *pattern, int flags) -{ - FcPattern *match; - FcResult result; - - match = FcFontMatch(NULL, pattern, &result); - if (!match) { - return 1; - } - - if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(match); - return 1; - } - - frc[frclen].flags = flags; - /* Believe U+0000 glyph will present in each default font */ - frc[frclen].unicodep = 0; - frclen++; - - return 0; -} - -void -xloadsparefonts(void) -{ - FcPattern *pattern; - double sizeshift, fontval; - int fc; - char **fp; - - if (frclen != 0) - die("can't embed spare fonts. cache isn't empty"); - - /* Calculate count of spare fonts */ - fc = sizeof(font2) / sizeof(*font2); - if (fc == 0) - return; - - /* Allocate memory for cache entries. */ - if (frccap < 4 * fc) { - frccap += 4 * fc - frccap; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - for (fp = font2; fp - font2 < fc; ++fp) { - - if (**fp == '-') - pattern = XftXlfdParse(*fp, False, False); - else - pattern = FcNameParse((FcChar8 *)*fp); - - if (!pattern) - die("can't open spare font %s\n", *fp); - - if (defaultfontsize > 0) { - sizeshift = usedfontsize - defaultfontsize; - if (sizeshift != 0 && - FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - fontval += sizeshift; - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); - } - } - - FcPatternAddBool(pattern, FC_SCALABLE, 1); - - FcConfigSubstitute(NULL, pattern, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, pattern); - - if (xloadsparefont(pattern, FRC_NORMAL)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadsparefont(pattern, FRC_ITALIC)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadsparefont(pattern, FRC_ITALICBOLD)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadsparefont(pattern, FRC_BOLD)) - die("can't open spare font %s\n", *fp); - - FcPatternDestroy(pattern); - } -} - void xunloadfont(Font *f) { @@ -1314,40 +1134,26 @@ xinit(int cols, int rows) Window parent; pid_t thispid = getpid(); XColor xmousefg, xmousebg; - Pixmap blankpm; - XWindowAttributes attr; - XVisualInfo vis; + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; + xw.vis = XDefaultVisual(xw.dpy, xw.scr); /* font */ if (!FcInit()) die("could not init fontconfig.\n"); usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, defaultfontsize); - - /* spare fonts */ - xloadsparefonts(); + xloadfonts(usedfont, 0); /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xw.cmap = XDefaultColormap(xw.dpy, xw.scr); xloadcols(); /* adjust fixed window geometry */ - win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw; - win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch; + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1362,15 +1168,19 @@ xinit(int cols, int rows) | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; xw.attrs.colormap = xw.cmap; + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, - win.w, win.h, 0, xw.depth, InputOutput, + win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask | CWColormap, &xw.attrs); memset(&gcvalues, 0, sizeof(gcvalues)); gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, + &gcvalues); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); @@ -1387,9 +1197,8 @@ xinit(int cols, int rows) } /* white cursor, black outline */ - xw.pointerisvisible = 1; - xw.vpointer = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, xw.vpointer); + cursor = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, cursor); if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { xmousefg.red = 0xffff; @@ -1403,10 +1212,7 @@ xinit(int cols, int rows) xmousebg.blue = 0x0000; } - XRecolorCursor(xw.dpy, xw.vpointer, &xmousefg, &xmousebg); - blankpm = XCreateBitmapFromData(xw.dpy, xw.win, &(char){0}, 1, 1); - xw.bpointer = XCreatePixmapCursor(xw.dpy, blankpm, blankpm, - &xmousefg, &xmousebg, 0, 0); + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); @@ -1414,41 +1220,6 @@ xinit(int cols, int rows) xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - /* use a png-image to set _NET_WM_ICON */ - FILE* file = fopen(ICON, "r"); - if (file) { - /* load image in rgba-format */ - const gdImagePtr icon_rgba = gdImageCreateFromPng(file); - fclose(file); - /* declare icon-variable which will store the image in argb-format */ - const int width = gdImageSX(icon_rgba); - const int height = gdImageSY(icon_rgba); - const int icon_n = width * height + 2; - long icon_argb[icon_n]; - /* set width and height of the icon */ - int i = 0; - icon_argb[i++] = width; - icon_argb[i++] = height; - /* rgba -> argb */ - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - const int pixel_rgba = gdImageGetPixel(icon_rgba, x, y); - unsigned char *pixel_argb = (unsigned char *) &icon_argb[i++]; - pixel_argb[0] = gdImageBlue(icon_rgba, pixel_rgba); - pixel_argb[1] = gdImageGreen(icon_rgba, pixel_rgba); - pixel_argb[2] = gdImageRed(icon_rgba, pixel_rgba); - /* scale alpha from 0-127 to 0-255 */ - const unsigned char alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba); - pixel_argb[3] = alpha == 127 ? 255 : alpha * 2; - } - } - gdImageDestroy(icon_rgba); - /* set _NET_WM_ICON */ - xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, - PropModeReplace, (uchar *) icon_argb, icon_n); - } - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace, (uchar *)&thispid, 1); @@ -1466,14 +1237,12 @@ xinit(int cols, int rows) xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); if (xsel.xtarget == None) xsel.xtarget = XA_STRING; - - boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); } int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { - float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; ushort mode, prevmode = USHRT_MAX; Font *font = &dc.font; int frcflags = FRC_NORMAL; @@ -1514,18 +1283,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x yp = winy + font->ascent; } - if (mode & ATTR_BOXDRAW) { - /* 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); - } + /* Lookup character index with default font. */ + glyphidx = XftCharIndex(xw.dpy, font->match, rune); if (glyphidx) { specs[numspecs].font = font->match; specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp + cxoffset; - specs[numspecs].y = (short)yp + cyoffset; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; xp += runewidth; numspecs++; continue; @@ -1607,56 +1371,11 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x return numspecs; } -static int isSlopeRising (int x, int iPoint, int waveWidth) -{ - // . . . . - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // . . . . . - - // Find absolute `x` of point - x += iPoint * (waveWidth/2); - - // Find index of absolute wave - int absSlope = x / ((float)waveWidth/2); - - return (absSlope % 2); -} - -static int getSlope (int x, int iPoint, int waveWidth) -{ - // Sizes: Caps are half width of slopes - // 1_2 1_2 1_2 1_2 - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // 0 3_0 3_0 3_0 3_ - // <2-> <1> <---6----> - - // Find type of first point - int firstType; - x -= (x / waveWidth) * waveWidth; - if (x < (waveWidth * (2.f/6.f))) - firstType = UNDERCURL_SLOPE_ASCENDING; - else if (x < (waveWidth * (3.f/6.f))) - firstType = UNDERCURL_SLOPE_TOP_CAP; - else if (x < (waveWidth * (5.f/6.f))) - firstType = UNDERCURL_SLOPE_DESCENDING; - else - firstType = UNDERCURL_SLOPE_BOTTOM_CAP; - - // Find type of given point - int pointType = (iPoint % 4); - pointType += firstType; - pointType %= 4; - - return pointType; -} - void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) { int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, width = charlen * win.cw; Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; @@ -1693,6 +1412,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i bg = &dc.col[base.bg]; } + /* Change basic system colors [0-7] to bright system colors [8-15] */ + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) + fg = &dc.col[base.fg + 8]; + if (IS_SET(MODE_REVERSE)) { if (fg == &dc.col[defaultfg]) { fg = &dc.col[defaultbg]; @@ -1742,17 +1465,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Intelligent cleaning up of the borders. */ if (x == 0) { - xclear(0, (y == 0)? 0 : winy, win.hborderpx, + xclear(0, (y == 0)? 0 : winy, borderpx, winy + win.ch + - ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); } - if (winx + width >= win.hborderpx + win.tw) { + if (winx + width >= borderpx + win.tw) { xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); } if (y == 0) - xclear(winx, 0, winx + width, win.vborderpx); - if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) xclear(winx, winy + win.ch, winx + width, win.h); /* Clean up the region we want to draw to. */ @@ -1765,367 +1488,13 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i r.width = width; XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - if (base.mode & ATTR_BOXDRAW) { - drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); - } else { - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - } + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { - // Underline Color - const int widthThreshold = 28; // +1 width every widthThreshold px of font - int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width - int linecolor; - if ((base.ucolor[0] >= 0) && - !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) && - !(base.mode & ATTR_INVISIBLE) - ) { - // Special color for underline - // Index - if (base.ucolor[1] < 0) { - linecolor = dc.col[base.ucolor[0]].pixel; - } - // RGB - else { - XColor lcolor; - lcolor.red = base.ucolor[0] * 257; - lcolor.green = base.ucolor[1] * 257; - lcolor.blue = base.ucolor[2] * 257; - lcolor.flags = DoRed | DoGreen | DoBlue; - XAllocColor(xw.dpy, xw.cmap, &lcolor); - linecolor = lcolor.pixel; - } - } else { - // Foreground color for underline - linecolor = fg->pixel; - } - - XGCValues ugcv = { - .foreground = linecolor, - .line_width = wlw, - .line_style = LineSolid, - .cap_style = CapNotLast - }; - - GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), - GCForeground | GCLineWidth | GCLineStyle | GCCapStyle, - &ugcv); - - // Underline Style - if (base.ustyle != 3) { - //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); - XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx, - winy + dc.font.ascent + 1, width, wlw); - } else if (base.ustyle == 3) { - int ww = win.cw;//width; - int wh = dc.font.descent - wlw/2 - 1;//r.height/7; - int wx = winx; - int wy = winy + win.ch - dc.font.descent; - -#if UNDERCURL_STYLE == UNDERCURL_CURLY - // Draw waves - int narcs = charlen * 2 + 1; - XArc *arcs = xmalloc(sizeof(XArc) * narcs); - - int i = 0; - for (i = 0; i < charlen-1; i++) { - arcs[i*2] = (XArc) { - .x = wx + win.cw * i + ww / 4, - .y = wy, - .width = win.cw / 2, - .height = wh, - .angle1 = 0, - .angle2 = 180 * 64 - }; - arcs[i*2+1] = (XArc) { - .x = wx + win.cw * i + ww * 0.75, - .y = wy, - .width = win.cw/2, - .height = wh, - .angle1 = 180 * 64, - .angle2 = 180 * 64 - }; - } - // Last wave - arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh, - 0, 180 * 64 }; - // Last wave tail - arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.), - wh, 180 * 64, 90 * 64}; - // First wave tail - i++; - arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64, - 90 * 64 }; - - XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs); - - free(arcs); -#elif UNDERCURL_STYLE == UNDERCURL_SPIKY - // Make the underline corridor larger - /* - wy -= wh; - */ - wh *= 2; - - // Set the angle of the slope to 45° - ww = wh; - - // Position of wave is independent of word, it's absolute - wx = (wx / (ww/2)) * (ww/2); - - int marginStart = winx - wx; - - // Calculate number of points with floating precision - float n = width; // Width of word in pixels - n = (n / ww) * 2; // Number of slopes (/ or \) - n += 2; // Add two last points - int npoints = n; // Convert to int - - // Total length of underline - float waveLength = 0; - - if (npoints >= 3) { - // We add an aditional slot in case we use a bonus point - XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); - - // First point (Starts with the word bounds) - points[0] = (XPoint) { - .x = wx + marginStart, - .y = (isSlopeRising(wx, 0, ww)) - ? (wy - marginStart + ww/2.f) - : (wy + marginStart) - }; - - // Second point (Goes back to the absolute point coordinates) - points[1] = (XPoint) { - .x = (ww/2.f) - marginStart, - .y = (isSlopeRising(wx, 1, ww)) - ? (ww/2.f - marginStart) - : (-ww/2.f + marginStart) - }; - waveLength += (ww/2.f) - marginStart; - - // The rest of the points - for (int i = 2; i < npoints-1; i++) { - points[i] = (XPoint) { - .x = ww/2, - .y = (isSlopeRising(wx, i, ww)) - ? wh/2 - : -wh/2 - }; - waveLength += ww/2; - } - - // Last point - points[npoints-1] = (XPoint) { - .x = ww/2, - .y = (isSlopeRising(wx, npoints-1, ww)) - ? wh/2 - : -wh/2 - }; - waveLength += ww/2; - - // End - if (waveLength < width) { // Add a bonus point? - int marginEnd = width - waveLength; - points[npoints] = (XPoint) { - .x = marginEnd, - .y = (isSlopeRising(wx, npoints, ww)) - ? (marginEnd) - : (-marginEnd) - }; - - npoints++; - } else if (waveLength > width) { // Is last point too far? - int marginEnd = waveLength - width; - points[npoints-1].x -= marginEnd; - if (isSlopeRising(wx, npoints-1, ww)) - points[npoints-1].y -= (marginEnd); - else - points[npoints-1].y += (marginEnd); - } - - // Draw the lines - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, - CoordModePrevious); - - // Draw a second underline with an offset of 1 pixel - if ( ((win.ch / (widthThreshold/2)) % 2)) { - points[0].x++; - - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, - npoints, CoordModePrevious); - } - - // Free resources - free(points); - } -#else // UNDERCURL_CAPPED - // Cap is half of wave width - float capRatio = 0.5f; - - // Make the underline corridor larger - wh *= 2; - - // Set the angle of the slope to 45° - ww = wh; - ww *= 1 + capRatio; // Add a bit of width for the cap - - // Position of wave is independent of word, it's absolute - wx = (wx / ww) * ww; - - float marginStart; - switch(getSlope(winx, 0, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - marginStart = winx - wx; - break; - case UNDERCURL_SLOPE_TOP_CAP: - marginStart = winx - (wx + (ww * (2.f/6.f))); - break; - case UNDERCURL_SLOPE_DESCENDING: - marginStart = winx - (wx + (ww * (3.f/6.f))); - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - marginStart = winx - (wx + (ww * (5.f/6.f))); - break; - } - - // Calculate number of points with floating precision - float n = width; // Width of word in pixels - // ._. - n = (n / ww) * 4; // Number of points (./ \.) - n += 2; // Add two last points - int npoints = n; // Convert to int - - // Position of the pen to draw the lines - float penX = 0; - float penY = 0; - - if (npoints >= 3) { - XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); - - // First point (Starts with the word bounds) - penX = winx; - switch (getSlope(winx, 0, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - penY = wy + wh/2.f - marginStart; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penY = wy; - break; - case UNDERCURL_SLOPE_DESCENDING: - penY = wy + marginStart; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penY = wy + wh/2.f; - break; - } - points[0].x = penX; - points[0].y = penY; - - // Second point (Goes back to the absolute point coordinates) - switch (getSlope(winx, 1, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - penX += ww * (1.f/6.f) - marginStart; - penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penX += ww * (2.f/6.f) - marginStart; - penY += -wh/2.f + marginStart; - break; - case UNDERCURL_SLOPE_DESCENDING: - penX += ww * (1.f/6.f) - marginStart; - penY += 0; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penX += ww * (2.f/6.f) - marginStart; - penY += -marginStart + wh/2.f; - break; - } - points[1].x = penX; - points[1].y = penY; - - // The rest of the points - for (int i = 2; i < npoints; i++) { - switch (getSlope(winx, i, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - case UNDERCURL_SLOPE_DESCENDING: - penX += ww * (1.f/6.f); - penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penX += ww * (2.f/6.f); - penY += -wh / 2.f; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penX += ww * (2.f/6.f); - penY += wh / 2.f; - break; - } - points[i].x = penX; - points[i].y = penY; - } - - // End - float waveLength = penX - winx; - if (waveLength < width) { // Add a bonus point? - int marginEnd = width - waveLength; - penX += marginEnd; - switch(getSlope(winx, npoints, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - case UNDERCURL_SLOPE_DESCENDING: - //penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penY += -marginEnd; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penY += marginEnd; - break; - } - - points[npoints].x = penX; - points[npoints].y = penY; - - npoints++; - } else if (waveLength > width) { // Is last point too far? - int marginEnd = waveLength - width; - points[npoints-1].x -= marginEnd; - switch(getSlope(winx, npoints-1, ww)) { - case UNDERCURL_SLOPE_TOP_CAP: - points[npoints-1].y += marginEnd; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - points[npoints-1].y -= marginEnd; - break; - default: - break; - } - } - - // Draw the lines - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, - CoordModeOrigin); - - // Draw a second underline with an offset of 1 pixel - if ( ((win.ch / (widthThreshold/2)) % 2)) { - for (int i = 0; i < npoints; i++) - points[i].x++; - - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, - npoints, CoordModeOrigin); - } - - // Free resources - free(points); - } -#endif - } - - XFreeGC(xw.dpy, ugc); - + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, + width, 1); } if (base.mode & ATTR_STRUCK) { @@ -2151,7 +1520,6 @@ void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) { Color drawcol; - XRenderColor colbg; /* remove the old cursor */ if (selected(ox, oy)) @@ -2164,7 +1532,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) /* * Select the right color for the right mode. */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW; + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; if (IS_SET(MODE_REVERSE)) { g.mode |= ATTR_REVERSE; @@ -2180,21 +1548,11 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) if (selected(cx, cy)) { g.fg = defaultfg; g.bg = defaultrcs; - } else if (!(og.mode & ATTR_REVERSE)) { - unsigned long col = g.bg; - g.bg = g.fg; - g.fg = col; - } - - if (IS_TRUECOL(g.bg)) { - colbg.alpha = 0xffff; - colbg.red = TRUERED(g.bg); - colbg.green = TRUEGREEN(g.bg); - colbg.blue = TRUEBLUE(g.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); } else { - drawcol = dc.col[g.bg]; + g.fg = defaultbg; + g.bg = defaultcs; } + drawcol = dc.col[g.bg]; } /* draw the new one */ @@ -2211,35 +1569,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) case 3: /* Blinking Underline */ case 4: /* Steady Underline */ XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + (cy + 1) * win.ch - \ + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ cursorthickness, win.cw, cursorthickness); break; case 5: /* Blinking bar */ case 6: /* Steady bar */ XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, cursorthickness, win.ch); break; } } else { XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, win.cw - 1, 1); XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - win.hborderpx + (cx + 1) * win.cw - 1, - win.vborderpx + cy * win.ch, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + (cy + 1) * win.ch - 1, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, win.cw, 1); } } @@ -2259,6 +1617,9 @@ xseticontitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); + if (p[0] == '\0') + p = opt_title; + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) return; @@ -2268,30 +1629,13 @@ xseticontitle(char *p) } void -xfreetitlestack(void) +xsettitle(char *p) { - for (int i = 0; i < LEN(titlestack); i++) { - free(titlestack[i]); - titlestack[i] = NULL; - } -} + XTextProperty prop; + DEFAULT(p, opt_title); -void -xsettitle(char *p, int pop) -{ - XTextProperty prop; - - free(titlestack[tstki]); - if (pop) { - titlestack[tstki] = NULL; - tstki = (tstki - 1 + TITLESTACKSIZE) % TITLESTACKSIZE; - p = titlestack[tstki] ? titlestack[tstki] : opt_title; - } else if (p) { - titlestack[tstki] = xstrdup(p); - } else { - titlestack[tstki] = NULL; + if (p[0] == '\0') p = opt_title; - } if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) @@ -2301,16 +1645,6 @@ xsettitle(char *p, int pop) XFree(prop.value); } -void -xpushtitle(void) -{ - int tstkin = (tstki + 1) % TITLESTACKSIZE; - - free(titlestack[tstkin]); - titlestack[tstkin] = titlestack[tstki] ? xstrdup(titlestack[tstki]) : NULL; - tstki = tstkin; -} - int xstartdraw(void) { @@ -2393,8 +1727,6 @@ unmap(XEvent *ev) void xsetpointermotion(int set) { - if (!set && !xw.pointerisvisible) - return; MODBIT(xw.attrs.event_mask, set, PointerMotionMask); XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } @@ -2427,144 +1759,6 @@ xseturgency(int add) XFree(h); } -static void -cachemonitorinfo() -{ - int prev_num = monitors_num; - MonitorInfo *prev_info = monitors_info; - XRRMonitorInfo *xmonitors = XRRGetMonitors(xw.dpy, XRootWindow(xw.dpy, xw.scr), 1, &monitors_num); - if (!monitors_num) - die("xrandr found no monitors"); - - monitors_info = xmalloc(monitors_num * sizeof(MonitorInfo)); - - for (int i = 0; i < monitors_num; ++i) { - XRRMonitorInfo *xm = &xmonitors[i]; - MonitorInfo *m = &monitors_info[i]; - - m->name = xm->name; - m->x = xm->x; - m->y = xm->y; - m->w = xm->width; - m->h = xm->height; - - float px_mm = ((float)m->w / xm->mwidth + (float)m->h / xm->mheight) / 2; - float px_pt = 25.4 * px_mm / 72; - m->defaultfontsize = defaultrelfontsize * px_pt; - - // Override defaultfontsize (dpi) by user config - char *name = XGetAtomName(xw.dpy, xm->name); - for (int j = 0; j < LEN(monitors_config); ++j) - if (!strcmp(name, monitors_config[j].name)) { - m->defaultfontsize = monitors_config[j].defaultfontsize; - if (m->defaultfontsize < 0) - m->defaultfontsize *= -px_pt; - break; - } - // fprintf(stderr, "%s: %fpx, %f\n", name, m->defaultfontsize, m->usedfontsize); - XFree(name); - - // Restore usedfontsize (zoom) after re-cache for monitors with the same name - m->usedfontsize = m->defaultfontsize; - for (int j = 0; j < prev_num; ++j) - if (prev_info[j].name == m->name) { - m->usedfontsize = prev_info[j].usedfontsize; - break; - } - } - - XRRFreeMonitors(xmonitors); - free(prev_info); -} - -static int -getmonitorindex_threshold(int w, int h, int x, int y) -{ - int mindex = -1; - float fontsize = 0; - int thresholdarea = winmovethreshold * w * h; - - for (int i = 0; i < monitors_num; ++i) { - MonitorInfo *m = &monitors_info[i]; - int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); - int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); - int area = overlap_w * overlap_h; - // Choose monitor with largest dpi (defaultfontsize) - // from all "mirrored"/overlapped (e.g. projector) - if (area >= thresholdarea && fontsize < m->defaultfontsize) { - fontsize = m->defaultfontsize; - mindex = i; - } - } - return mindex; -} - -static int -getmonitorindex_nearest(int w, int h, int x, int y) -{ - int mindex = -1; - float fontsize = 0; - int overlaparea = 0; - - for (int i = 0; i < monitors_num; ++i) { - MonitorInfo *m = &monitors_info[i]; - int overlap_w = MAX(0, MIN(x + w, m->x + m->w) - MAX(x, m->x)); - int overlap_h = MAX(0, MIN(y + h, m->y + m->h) - MAX(y, m->y)); - int area = overlap_w * overlap_h; - // Choose monitor with largest overlapping area - // e.g. when "st" is initially spawned in-between monitors - if (area > overlaparea) { - overlaparea = area; - mindex = i; - } - } - return mindex; -} - -static void -adjustmonitorfontsize(int mindex) -{ - if (mindex < 0 || prev_mindex == mindex) - return; - // Save zoom of current monitor before switching - if (prev_mindex >= 0) - monitors_info[prev_mindex].usedfontsize = usedfontsize; - - defaultfontsize = monitors_info[mindex].defaultfontsize; - // fprintf(stderr, "Crossing: %fpx\n", defaultfontsize); - - // NOTE: do nothing if font size differs by less than 1% - double fontsize = monitors_info[mindex].usedfontsize; - double delta = 0.01 * usedfontsize; - if (!BETWEEN(fontsize - usedfontsize, -delta, delta)) { - // fprintf(stderr, "Adjusted: %fpx\n", fontsize); - xunloadfonts(); - xloadfonts(usedfont, fontsize); - } - prev_mindex = mindex; -} - -void -refreshxrandr(const Arg *dummy) -{ - // Reset index to detect change of window association on "xrandr ... --primary" - // otherwise: zoom won't be saved on switching and new font size won't be loaded - // CRIT!!! event from xrandr may place another monitor into same index - if (prev_mindex >= 0) - monitors_info[prev_mindex].usedfontsize = usedfontsize; - prev_mindex = -1; - - XWindowAttributes xattr = {0}; - cachemonitorinfo(); - XGetWindowAttributes(xw.dpy, xw.win, &xattr); - - int mindex = getmonitorindex_threshold(xattr.width, xattr.height, xattr.x, xattr.y); - if (mindex < 0) - mindex = getmonitorindex_nearest(xattr.width, xattr.height, xattr.x, xattr.y); - adjustmonitorfontsize(mindex); -} - - void xbell(void) { @@ -2589,22 +1783,12 @@ focus(XEvent *ev) xseturgency(0); if (IS_SET(MODE_FOCUS)) ttywrite("\033[I", 3, 0); - if (!focused) { - focused = 1; - xloadcols(); - tfulldirt(); - } } else { if (xw.ime.xic) XUnsetICFocus(xw.ime.xic); win.mode &= ~MODE_FOCUSED; if (IS_SET(MODE_FOCUS)) ttywrite("\033[O", 3, 0); - if (focused) { - focused = 0; - xloadcols(); - tfulldirt(); - } } } @@ -2655,26 +1839,23 @@ void kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; - KeySym ksym; + KeySym ksym = NoSymbol; char buf[64], *customkey; int len; Rune c; Status status; Shortcut *bp; - if (xw.pointerisvisible) { - XDefineCursor(xw.dpy, xw.win, xw.bpointer); - xsetpointermotion(1); - xw.pointerisvisible = 0; - } - if (IS_SET(MODE_KBDLOCK)) return; - if (xw.ime.xic) + if (xw.ime.xic) { 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); + } /* 1. shortcuts */ for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if (ksym == bp->keysym && match(bp->mod, e->state)) { @@ -2730,23 +1911,12 @@ cmessage(XEvent *e) void resize(XEvent *e) { - // BAD: no resize on monitor plug/unplug/reconfigure -- until window itself is kept in the same place - // NOTE: no resize event on zoomabs() - // fprintf(stderr, "Resize: %dx%d+%d+%d\n", - // e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y); - - adjustmonitorfontsize(getmonitorindex_threshold( - e->xconfigure.width, e->xconfigure.height, e->xconfigure.x, e->xconfigure.y)); - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) return; cresize(e->xconfigure.width, e->xconfigure.height); } -int tinsync(uint); -int ttyread_pending(); - void run(void) { @@ -2773,22 +1943,6 @@ run(void) } } while (ev.type != MapNotify); - int rr_event_base, rr_error_base, rr_major, rr_minor; - if (!XRRQueryExtension (xw.dpy, &rr_event_base, &rr_error_base) || - !XRRQueryVersion (xw.dpy, &rr_major, &rr_minor) || - rr_major < 1 || (rr_major == 1 && rr_minor < 5)) - { - die("RandR 1.5 extension isn't available\n"); - } - XRRSelectInput(xw.dpy, xw.win, RRCrtcChangeNotifyMask); - - // WARN: can query actual window size/pos only after window is mapped and its width/height are adjusted by WM - // * x/y are WM-dependent and can't be determined beforehand anyway - // * defaultfontsize isn't available until font is loaded and actual Fc*() size queried - // BAD: fonts on startup are always reloaded -- how to specify their size beforehand ? - FcPatternGetDouble(dc.font.match->pattern, FC_SIZE, 0, &defaultrelfontsize); - refreshxrandr(0); - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); cresize(w, h); @@ -2797,7 +1951,7 @@ run(void) FD_SET(ttyfd, &rfd); FD_SET(xfd, &rfd); - if (XPending(xw.dpy) || ttyread_pending()) + if (XPending(xw.dpy)) timeout = 0; /* existing events might not set xfd */ seltv.tv_sec = timeout / 1E3; @@ -2811,8 +1965,7 @@ run(void) } clock_gettime(CLOCK_MONOTONIC, &now); - int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending(); - if (ttyin) + if (FD_ISSET(ttyfd, &rfd)) ttyread(); xev = 0; @@ -2821,16 +1974,6 @@ run(void) XNextEvent(xw.dpy, &ev); if (XFilterEvent(&ev, None)) continue; - if (LASTEvent <= ev.type) { - if (rr_event_base + RRNotify == ev.type && - RRNotify_CrtcChange == ((XRRNotifyEvent *)&ev)->subtype) - { - XRRUpdateConfiguration(&ev); - // fprintf(stderr, "Monitor change: %d > %d\n", rr_event_base, LASTEvent); - refreshxrandr(0); - } - continue; - } if (handler[ev.type]) (handler[ev.type])(&ev); } @@ -2846,7 +1989,7 @@ run(void) * maximum latency intervals during `cat huge.txt`, and perfect * sync with periodic updates from animations/key-repeats/etc. */ - if (ttyin || xev) { + if (FD_ISSET(ttyfd, &rfd) || xev) { if (!drawing) { trigger = now; drawing = 1; @@ -2857,18 +2000,6 @@ run(void) continue; /* we have time, try to find idle */ } - if (tinsync(su_timeout)) { - /* - * on synchronized-update draw-suspension: don't reset - * drawing so that we draw ASAP once we can (just after - * ESU). it won't be too soon because we already can - * draw now but we skip. we set timeout > 0 to draw on - * SU-timeout even without new content. - */ - timeout = minlatency; - continue; - } - /* idle detected or maxlatency exhausted -> draw */ timeout = -1; if (blinktimeout && tattrset(ATTR_BLINK)) { @@ -2889,59 +2020,6 @@ run(void) } } -int -resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) -{ - char **sdst = dst; - int *idst = dst; - float *fdst = dst; - - char fullname[256]; - char fullclass[256]; - char *type; - XrmValue ret; - - snprintf(fullname, sizeof(fullname), "%s.%s", - opt_name ? opt_name : "st", name); - snprintf(fullclass, sizeof(fullclass), "%s.%s", - opt_class ? opt_class : "St", name); - fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; - - XrmGetResource(db, fullname, fullclass, &type, &ret); - if (ret.addr == NULL || strncmp("String", type, 64)) - return 1; - - switch (rtype) { - case STRING: - *sdst = ret.addr; - break; - case INTEGER: - *idst = strtoul(ret.addr, NULL, 10); - break; - case FLOAT: - *fdst = strtof(ret.addr, NULL); - break; - } - return 0; -} - -void -config_init(void) -{ - char *resm; - XrmDatabase db; - ResourcePref *p; - - XrmInitialize(); - resm = XResourceManagerString(xw.dpy); - if (!resm) - return; - - db = XrmGetStringDatabase(resm); - for (p = resources; p < resources + LEN(resources); p++) - resource_load(db, p->name, p->type, p->dst); -} - void usage(void) { @@ -2966,9 +2044,6 @@ main(int argc, char *argv[]) case 'a': allowaltscreen = 0; break; - case 'A': - opt_alpha = EARGF(usage()); - break; case 'c': opt_class = EARGF(usage()); break; @@ -3005,11 +2080,6 @@ main(int argc, char *argv[]) case 'v': die("%s " VERSION "\n", argv0); break; - case 'z': - defaultfontsize = strtod(EARGF(usage()), NULL); - if (!(defaultfontsize > 0)) - usage(); - break; default: usage(); } ARGEND; @@ -3023,14 +2093,8 @@ run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - - if(!(xw.dpy = XOpenDisplay(NULL))) - die("Can't open display\n"); - - config_init(); cols = MAX(cols, 1); rows = MAX(rows, 1); - defaultbg = MAX(LEN(colorname), 256); tnew(cols, rows); xinit(cols, rows); xsetenv(); |