From 3285ec77ca47ab6c6c9cdf49339a4835c16639ed Mon Sep 17 00:00:00 2001 From: doryan Date: Sat, 14 Sep 2024 22:44:52 +0400 Subject: [PATCH] first commit: new st config --- Makefile | 5 +- config.def.h | 90 +++++----- config.h | 474 +++++++++++++++++++++++++++++++++++++++++++++++++++ config.mk | 9 +- hb.c | 125 ++++++++++++++ hb.h | 14 ++ hb.o | Bin 0 -> 4208 bytes st | Bin 0 -> 115544 bytes st.c | 128 +++++++++++--- st.h | 5 +- st.o | Bin 0 -> 81456 bytes win.h | 2 +- x.c | 335 ++++++++++++++++++++++-------------- x.o | Bin 0 -> 77152 bytes 14 files changed, 979 insertions(+), 208 deletions(-) create mode 100644 config.h create mode 100644 hb.c create mode 100644 hb.h create mode 100644 hb.o create mode 100755 st create mode 100644 st.o create mode 100644 x.o diff --git a/Makefile b/Makefile index 15db421..dfcea0f 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ include config.mk -SRC = st.c x.c +SRC = st.c x.c hb.c OBJ = $(SRC:.c=.o) all: st @@ -16,7 +16,8 @@ config.h: $(CC) $(STCFLAGS) -c $< st.o: config.h st.h win.h -x.o: arg.h config.h st.h win.h +x.o: arg.h config.h st.h win.h hb.h +hb.o: st.h $(OBJ): config.h config.mk diff --git a/config.def.h b/config.def.h index 2cd740a..ec8321f 100644 --- a/config.def.h +++ b/config.def.h @@ -5,8 +5,8 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -static int borderpx = 2; +static char *font = "FiraCode Nerd Font Propo:pixelsize=13"; +static int borderpx = 5; /* * What program is execed by st depends of these precedence rules: @@ -96,52 +96,52 @@ unsigned int tabspaces = 8; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - + "#323437", + "#ff5454", + "#8cc85f", + "#e3c78a", + "#80a0ff", + "#d183e8", + "#79dac8", + "#a1aab8", + "#7c8f8f", + "#ff5189", + "#36c692", + "#bfbf97", + "#74b2ff", + "#ae81ff", + "#85dc85", + "#e2637f", [255] = 0, /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "gray90", /* default foreground colour */ - "black", /* default background colour */ + "#272727", + "#f8f8f2", + "#080808", + "#eeeeee", }; - - /* * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 258; -unsigned int defaultbg = 259; -unsigned int defaultcs = 256; +unsigned int defaultfg = 259; +unsigned int defaultbg = 256; +unsigned int defaultcs = 257; static unsigned int defaultrcs = 257; -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") +/* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 + * Default style of cursor + * 0: blinking block + * 1: blinking block (default) + * 2: steady block ("█") + * 3: blinking underline + * 4: steady underline ("_") + * 5: blinking bar + * 6: steady bar ("|") + * 7: blinking st cursor + * 8: steady st cursor */ -static unsigned int cursorshape = 2; +static unsigned int cursorshape = 0; /* * Default columns and rows numbers @@ -175,12 +175,9 @@ static uint forcemousemod = ShiftMask; * Beware that overloading Button1 will disable the selection. */ static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, + /* mask button function argument release alt */ + { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, -1 }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, -1 }, }; /* Internal keyboard shortcuts. */ @@ -193,16 +190,19 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, + { ControlMask, XK_KP_Add, zoom, {.f = +1} }, + { ControlMask, XK_minus, 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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; + /* * Special keys (change & recompile st.info accordingly) * diff --git a/config.h b/config.h new file mode 100644 index 0000000..ec8321f --- /dev/null +++ b/config.h @@ -0,0 +1,474 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "FiraCode Nerd Font Propo:pixelsize=13"; +static int borderpx = 5; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: scroll and/or utmp + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +/* scroll program: to enable use a string like "scroll" */ +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* allow certain non-interactive (insecure) window operations such as: + setting the clipboard text */ +int allowwindowops = 0; + +/* + * draw latency range in ms - from new content/keypress/etc until drawing. + * within this range, st draws when content stops arriving (idle). mostly it's + * 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 = 2; +static double maxlatency = 33; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "#323437", + "#ff5454", + "#8cc85f", + "#e3c78a", + "#80a0ff", + "#d183e8", + "#79dac8", + "#a1aab8", + "#7c8f8f", + "#ff5189", + "#36c692", + "#bfbf97", + "#74b2ff", + "#ae81ff", + "#85dc85", + "#e2637f", + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#272727", + "#f8f8f2", + "#080808", + "#eeeeee", +}; +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 259; +unsigned int defaultbg = 256; +unsigned int defaultcs = 257; +static unsigned int defaultrcs = 257; + +/* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 + * Default style of cursor + * 0: blinking block + * 1: blinking block (default) + * 2: steady block ("█") + * 3: blinking underline + * 4: steady underline ("_") + * 5: blinking bar + * 6: steady bar ("|") + * 7: blinking st cursor + * 8: steady st cursor + */ +static unsigned int cursorshape = 0; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release alt */ + { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, -1 }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, -1 }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { ControlMask, XK_KP_Add, zoom, {.f = +1} }, + { ControlMask, XK_minus, 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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { 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_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { 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_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/config.mk b/config.mk index fdc29a7..07fedba 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # st version -VERSION = 0.9.2 +VERSION = 0.9 # Customize below to fit your system @@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config # includes and libs INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` + `$(PKG_CONFIG) --cflags freetype2` \ + `$(PKG_CONFIG) --cflags harfbuzz` LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` + `$(PKG_CONFIG) --libs freetype2` \ + `$(PKG_CONFIG) --libs harfbuzz` # flags STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 @@ -34,3 +36,4 @@ STLDFLAGS = $(LIBS) $(LDFLAGS) # compiler and linker # CC = c99 + diff --git a/hb.c b/hb.c new file mode 100644 index 0000000..99412c8 --- /dev/null +++ b/hb.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "hb.h" + +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } +#define BUFFER_STEP 256 + +hb_font_t *hbfindfont(XftFont *match); + +typedef struct { + XftFont *match; + hb_font_t *font; +} HbFontMatch; + +typedef struct { + size_t capacity; + HbFontMatch *fonts; +} HbFontCache; + +static HbFontCache hbfontcache = { 0, NULL }; + +typedef struct { + size_t capacity; + Rune *runes; +} RuneBuffer; + +static RuneBuffer hbrunebuffer = { 0, NULL }; + +/* + * Poplulate the array with a list of font features, wrapped in FEATURE macro, + * e. g. + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') + */ +hb_feature_t features[] = { }; + +void +hbunloadfonts() +{ + for (int i = 0; i < hbfontcache.capacity; i++) { + hb_font_destroy(hbfontcache.fonts[i].font); + XftUnlockFace(hbfontcache.fonts[i].match); + } + + if (hbfontcache.fonts != NULL) { + free(hbfontcache.fonts); + hbfontcache.fonts = NULL; + } + hbfontcache.capacity = 0; +} + +hb_font_t * +hbfindfont(XftFont *match) +{ + for (int i = 0; i < hbfontcache.capacity; i++) { + if (hbfontcache.fonts[i].match == match) + return hbfontcache.fonts[i].font; + } + + /* Font not found in cache, caching it now. */ + hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1)); + FT_Face face = XftLockFace(match); + hb_font_t *font = hb_ft_font_create(face, NULL); + if (font == NULL) + die("Failed to load Harfbuzz font."); + + hbfontcache.fonts[hbfontcache.capacity].match = match; + hbfontcache.fonts[hbfontcache.capacity].font = font; + hbfontcache.capacity += 1; + + return font; +} + +void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) { + ushort mode = USHRT_MAX; + unsigned int glyph_count; + int rune_idx, glyph_idx, end = start + length; + + hb_font_t *font = hbfindfont(xfont); + if (font == NULL) + return; + + hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); + + /* Resize the buffer if required length is larger. */ + if (hbrunebuffer.capacity < length) { + hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP; + hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune)); + } + + /* Fill buffer with codepoints. */ + for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) { + hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u; + mode = glyphs[glyph_idx].mode; + if (mode & ATTR_WDUMMY) + hbrunebuffer.runes[rune_idx] = 0x0020; + } + hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); + + /* Shape the segment. */ + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + + /* Get new glyph info. */ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count); + + /* Fill the output. */ + data->buffer = buffer; + data->glyphs = info; + data->positions = pos; + data->count = glyph_count; +} + +void hbcleanup(HbTransformData *data) { + hb_buffer_destroy(data->buffer); + memset(data, 0, sizeof(HbTransformData)); +} diff --git a/hb.h b/hb.h new file mode 100644 index 0000000..3b0ef44 --- /dev/null +++ b/hb.h @@ -0,0 +1,14 @@ +#include +#include +#include + +typedef struct { + hb_buffer_t *buffer; + hb_glyph_info_t *glyphs; + hb_glyph_position_t *positions; + unsigned int count; +} HbTransformData; + +void hbunloadfonts(); +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); +void hbcleanup(HbTransformData *); diff --git a/hb.o b/hb.o new file mode 100644 index 0000000000000000000000000000000000000000..8fc18d87427deee59f7b2a75fdfee78535e36fbc GIT binary patch literal 4208 zcmbuBUu;uV9LLXX%c%Uh?NGFeU`?iuC}qPK87l1V51b`Mi8ztWQM&e))^%;Uy+wu? z63a*~wL(I|GY=-d_`r+Azq4b^1$^*(HJl&%-`?abGEZf?~^CFJ?DJR z_xI=gxu^F)cXXpiQHUrCSx;trf)a9l(QLb&HQR|w7L(qswEU}|mS14ZT=yB))cS#r z{p6#Sd8}92-|W9^w>Wsd+3uIe75dzA95TM973PDEOq)S_bdsr=q0}s&@%QzQ^SIVO zw6d5fM$Vcmc)(8?XbYKpX!*24%e5eFJ6F0!tGg9CHU(+1Kz0nv&d9pRyOX16%sUfw zq-H)VreU3?V?X++cPVpkJw&ZHVB$4}3LlrLog1yB{a3HkDhu=RjK8a=v~Aj}TCesB zOFq1y(6R(FU(!=I#2+AC0^u#%y^e(iOwU)!O@#;YUK5Ow6Y zK+nWUQay<$lqPOaizNel>Z!A*zudVqJ zAxaIIcy|=uzXuqW`|OG+`(7r>-k`E<(R}|=5H|sTn2+tnT2q6EJenFRd%M)IC$EM8 zXsW*%hPt@!qq}v-76_rXkWd&eaP6CzP=^{k;^|OB?|D1aaMjnLHorShQ(F!-XzJSX z{4RBiH>@mB*8e zFI&~QtO2?T@G!?gUN7NX^hNy$8=tv2xY}OlB~o0r)-bvT9$`BphDL`A-{Qi1fun!n zm+cX-oi6&c3pZW(As2oaIL2Lt3l4?tH`K@BsW-0=T=`X$v-9=B*1Ca#$;QO42C(=5!jZ#h@D5X-mK_b!479gb@ zzWt~vLNA7mSW+*VMt+#QmNI)`I5D^}p3q6k(9uOIlVfsX=Q??Glx^6#`=S~z#= z+ax{45_)kr3ca{fH@o=RCiz()`Pt#nhj~Ba;33{W=-?vmQ3n_EJ>|mLcN2{H;K5HV zF|X4u`g5G49zTGD{yT}Q5})GSxjy(FV-Z~BiSMh-#k`hF9Pefk_X*B1pMb>sB)(AM zS&27Fe80r;ju-wdiQg;nW1Nfp#b@d%2N(apf4cBnl7G~SxDDtS3RX+u5xkLeobUY- ze^lZRNPM-#@$3jc2RO$H-xrbpVFwraACdgX=j6DH{)D8*yHdpcP~!NG3Lb_w798dh z*2ixOEP{*wIn%~7T>KB!99-PjBvKq6GUEeKn}%JdMa$5$@rbGKHAy5HH{&ESP%M&& zk;e|oTO+L`lE@DY={b<(@}?evPp?(%isJoUxl*KHSJ0MYBJP{VIp;Fy+2yt) zuHer2Pr(5CblM9b?p+u&xMB{RoxjMV9mcWkjI)B<vVJGSy z7!++;*Lv54>`|w7JK*{7IG1ZJw|C|x)?dWh4Gr|^v`=&U3qr_ir+pT9z5NgJ7k?+W z!~MtqH(@XKzg}!KX-B6}PVmIg9nRBfk3Q=y)g^wQ2OSIM=)yN&eft8>|1B7oi_`u; Dk#2~~ literal 0 HcmV?d00001 diff --git a/st b/st new file mode 100755 index 0000000000000000000000000000000000000000..1a7cf8104f8289df691189cf7db45592393df31f GIT binary patch literal 115544 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 DEBc(% literal 0 HcmV?d00001 diff --git a/st.c b/st.c index 57c6e96..c9e6b59 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 */ @@ -185,8 +192,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); @@ -409,10 +416,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; @@ -521,7 +528,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; @@ -536,14 +543,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))) @@ -564,14 +571,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; } @@ -602,13 +609,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; @@ -844,6 +851,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); @@ -1043,6 +1053,11 @@ tnew(int col, int row) treset(); } +int tisaltscr(void) +{ + return IS_SET(MODE_ALTSCREEN); +} + void tswapscreen(void) { @@ -1055,13 +1070,53 @@ 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); @@ -1071,17 +1126,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); @@ -1091,7 +1157,8 @@ tscrollup(int orig, int n) term.line[i+n] = temp; } - selscroll(orig, -n); + if (term.scr == 0) + selscroll(orig, -n); } void @@ -1120,7 +1187,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++; } @@ -1288,14 +1355,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 @@ -1733,11 +1800,11 @@ csihandle(void) case 'S': /* SU -- Scroll line up */ if (csiescseq.priv) break; DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); + tscrollup(term.top, csiescseq.arg[0], 0); break; case 'T': /* SD -- Scroll 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 blank lines */ DEFAULT(csiescseq.arg[0], 1); @@ -2309,7 +2376,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); } @@ -2322,7 +2389,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); } @@ -2545,7 +2612,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; @@ -2582,6 +2649,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)); @@ -2640,7 +2715,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); } } @@ -2662,7 +2737,8 @@ draw(void) 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]); + term.ocx, term.ocy, term.line[term.ocy][term.ocx], + term.line[term.ocy], term.col); term.ocx = cx; term.ocy = term.c.y; xfinishdraw(); diff --git a/st.h b/st.h index fd3b0d8..4e584b6 100644 --- a/st.h +++ b/st.h @@ -11,7 +11,8 @@ #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) #define DEFAULT(a, b) (a) = (a) ? (a) : (b) #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b).mode & (~ATTR_WRAP)) || \ + (a).fg != (b).fg || \ (a).bg != (b).bg) #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ (t1.tv_nsec-t2.tv_nsec)/1E6) @@ -81,6 +82,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/st.o b/st.o new file mode 100644 index 0000000000000000000000000000000000000000..6ec53d2d761680c97c44280c5bc6afaa40af821b GIT binary patch literal 81456 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 Is5Z<04^H*Qy8r+H literal 0 HcmV?d00001 diff --git a/win.h b/win.h index 6de960d..94679e4 100644 --- a/win.h +++ b/win.h @@ -25,7 +25,7 @@ enum win_mode { void xbell(void); void xclipcopy(void); -void xdrawcursor(int, int, Glyph, int, int, Glyph); +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int); void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); diff --git a/x.c b/x.c index d73152b..0b2bcf1 100644 --- a/x.c +++ b/x.c @@ -19,6 +19,7 @@ char *argv0; #include "arg.h" #include "st.h" #include "win.h" +#include "hb.h" /* types used in config.h */ typedef struct { @@ -141,8 +142,9 @@ typedef struct { } DC; static inline ushort sixd_to_16bit(int); +static void xresetfontsettings(ushort mode, Font **font, int *frcflags); static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); @@ -253,6 +255,7 @@ static char *opt_name = NULL; static char *opt_title = NULL; static uint buttons; /* bit field of pressed buttons */ +static int cursorblinks = 0; void clipcopy(const Arg *dummy) @@ -757,7 +760,7 @@ xresize(int col, int row) xclear(0, 0, win.w, win.h); /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4); } ushort @@ -1062,6 +1065,9 @@ xunloadfont(Font *f) void xunloadfonts(void) { + /* Clear Harfbuzz font cache. */ + hbunloadfonts(); + /* Free the loaded fonts in the font cache. */ while (frclen > 0) XftFontClose(xw.dpy, frc[--frclen].font); @@ -1188,7 +1194,7 @@ xinit(int cols, int rows) XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4); /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); @@ -1242,6 +1248,22 @@ xinit(int cols, int rows) xsel.xtarget = XA_STRING; } +void +xresetfontsettings(ushort mode, Font **font, int *frcflags) +{ + *font = &dc.font; + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { + *font = &dc.ibfont; + *frcflags = FRC_ITALICBOLD; + } else if (mode & ATTR_ITALIC) { + *font = &dc.ifont; + *frcflags = FRC_ITALIC; + } else if (mode & ATTR_BOLD) { + *font = &dc.bfont; + *frcflags = FRC_BOLD; + } +} + int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { @@ -1256,128 +1278,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x FcPattern *fcpattern, *fontpattern; FcFontSet *fcsets[] = { NULL }; FcCharSet *fccharset; - int i, f, numspecs = 0; + int i, f, length = 0, start = 0, numspecs = 0; + float cluster_xp = xp, cluster_yp = yp; + HbTransformData shaped = { 0 }; + + /* Initial values. */ + mode = prevmode = glyphs[0].mode & ~ATTR_WRAP; + xresetfontsettings(mode, &font, &frcflags); for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; + mode = glyphs[i].mode & ~ATTR_WRAP; /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) + if (mode & ATTR_WDUMMY && i < (len - 1)) continue; - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* 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; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); + if ( + prevmode != mode + || ATTRCMP(glyphs[start], glyphs[i]) + || selected(x + i, y) != selected(x + start, y) + || i == (len - 1) + ) { + /* Handle 1-character wide segments and end of line */ + length = i - start; + if (i == start) { + length = 1; + } else if (i == (len - 1)) { + length = (i - start + 1); } - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; + /* Shape the segment. */ + hbtransform(&shaped, font->match, glyphs, start, length); + runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f); + cluster_xp = xp; cluster_yp = yp; + for (int code_idx = 0; code_idx < shaped.count; code_idx++) { + int idx = shaped.glyphs[code_idx].cluster; - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); + if (glyphs[start + idx].mode & ATTR_WDUMMY) + continue; - f = frclen; - frclen++; + /* Advance the drawing cursor if we've moved to a new cluster */ + if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) { + xp += runewidth; + cluster_xp = xp; + cluster_yp = yp; + runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f); + } - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); + if (shaped.glyphs[code_idx].codepoint != 0) { + /* If symbol is found, put it into the specs. */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; + specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.); + specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.); + cluster_xp += shaped.positions[code_idx].x_advance / 64.; + cluster_yp += shaped.positions[code_idx].y_advance / 64.; + numspecs++; + } else { + /* If it's not found, try to fetch it through the font cache. */ + rune = glyphs[start + idx].u; + for (f = 0; f < frclen; f++) { + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); + /* Everything correct. */ + if (glyphidx && frc[f].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if (!glyphidx && frc[f].flags == frcflags + && frc[f].unicodep == rune) { + break; + } + } + + /* Nothing was found. Use fontconfig to find matching font. */ + if (f >= frclen) { + if (!font->set) + font->set = FcFontSort(0, font->pattern, + 1, 0, &fcres); + fcsets[0] = font->set; + + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + * + * Xft and fontconfig are design failures. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, rune); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); + + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); + + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + frc[frclen].font = XftFontOpenPattern(xw.dpy, + fontpattern); + if (!frc[frclen].font) + die("XftFontOpenPattern failed seeking fallback font: %s\n", + strerror(errno)); + frc[frclen].flags = frcflags; + frc[frclen].unicodep = rune; + + glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); + + f = frclen; + frclen++; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + } + + specs[numspecs].font = frc[f].font; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + numspecs++; + } + } + + /* Cleanup and get ready for next segment. */ + hbcleanup(&shaped); + start = i; + + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + xresetfontsettings(mode, &font, &frcflags); + yp = winy + font->ascent; + } } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; } return numspecs; } void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int charlen) { - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, width = charlen * win.cw; Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; @@ -1513,21 +1563,24 @@ void xdrawglyph(Glyph g, int x, int y) { int numspecs; - XftGlyphFontSpec spec; + XftGlyphFontSpec *specs = xw.specbuf; - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); + numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y); + xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 : 1); } void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) { Color drawcol; /* remove the old cursor */ if (selected(ox, oy)) og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); + + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); if (IS_SET(MODE_HIDE)) return; @@ -1561,29 +1614,44 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) /* draw the new one */ if (IS_SET(MODE_FOCUSED)) { switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ + default: + case 0: /* blinking block */ + case 1: /* blinking block (default) */ + if (IS_SET(MODE_BLINK)) + break; /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ + case 2: /* steady block */ xdrawglyph(g, cx, cy); break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ + case 3: /* blinking underline */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 4: /* steady underline */ XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, borderpx + (cy + 1) * win.ch - \ cursorthickness, win.cw, cursorthickness); break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ + case 5: /* blinking bar */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 6: /* steady bar */ XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, borderpx + cy * win.ch, cursorthickness, win.ch); break; + case 7: /* blinking st cursor */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 8: /* steady st cursor */ + g.u = xsetcursor; + xdrawglyph(g, cx, cy); + break; } } else { XftDrawRect(xw.draw, &drawcol, @@ -1661,18 +1729,16 @@ xdrawline(Line line, int x1, int y1, int x2) Glyph base, new; XftGlyphFontSpec *specs = xw.specbuf; - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { + for (x = x1; x < x2; x++) { new = line[x]; if (new.mode == ATTR_WDUMMY) continue; if (selected(x, y1)) new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; + if ((i > 0) && ATTRCMP(base, new)) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - ox); i = 0; } if (i == 0) { @@ -1681,8 +1747,10 @@ xdrawline(Line line, int x1, int y1, int x2) } i++; } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); + if (i > 0) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox); + } } void @@ -1746,9 +1814,12 @@ xsetmode(int set, unsigned int flags) int xsetcursor(int cursor) { - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ + if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */ return 1; win.cursor = cursor; + cursorblinks = win.cursor == 0 || win.cursor == 1 || + win.cursor == 3 || win.cursor == 5 || + win.cursor == 7; return 0; } @@ -1995,6 +2066,10 @@ run(void) if (FD_ISSET(ttyfd, &rfd) || xev) { if (!drawing) { trigger = now; + if (IS_SET(MODE_BLINK)) { + win.mode ^= MODE_BLINK; + } + lastblink = now; drawing = 1; } timeout = (maxlatency - TIMEDIFF(now, trigger)) \ @@ -2005,7 +2080,7 @@ run(void) /* idle detected or maxlatency exhausted -> draw */ timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { + if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) { timeout = blinktimeout - TIMEDIFF(now, lastblink); if (timeout <= 0) { if (-timeout > blinktimeout) /* start visible */ diff --git a/x.o b/x.o new file mode 100644 index 0000000000000000000000000000000000000000..f4ffab56277e07a521097e93bb6fddbac4a22fc1 GIT binary patch literal 77152 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