From 4397a1814fd1ecc998c0dcd542ae2fcc8da6827f Mon Sep 17 00:00:00 2001 From: ant Date: Sat, 4 Jan 2025 21:59:53 +0100 Subject: [PATCH 01/67] fontfeature patch --- hb.c | 13 +++++-------- hb.h | 4 ++++ patches.def.h | 6 +++++- x.c | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/hb.c b/hb.c index ae3dcc3..d2edd98 100644 --- a/hb.c +++ b/hb.c @@ -35,13 +35,6 @@ typedef struct { static RuneBuffer hbrunebuffer = { 0, NULL }; static hb_buffer_t *hbbuffer; -/* - * 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 hbcreatebuffer(void) { @@ -125,7 +118,11 @@ hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int star hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); /* Shape the segment. */ - hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + #if FONTFEATURES_PATCH + hb_shape(font, buffer, data->features, data->features_count); + #else + hb_shape(font, buffer, NULL, 0); + #endif /* Get new glyph info. */ hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); diff --git a/hb.h b/hb.h index cb7ea48..3517855 100644 --- a/hb.h +++ b/hb.h @@ -7,6 +7,10 @@ typedef struct { hb_glyph_info_t *glyphs; hb_glyph_position_t *positions; unsigned int count; +#if FONTFEATURES_PATCH + hb_feature_t *features; + int features_count; +#endif // FONTFEATURES_PATCH } HbTransformData; void hbcreatebuffer(void); diff --git a/patches.def.h b/patches.def.h index ae5d37b..dbfb2a0 100644 --- a/patches.def.h +++ b/patches.def.h @@ -233,7 +233,11 @@ * https://github.com/cog1to/st-ligatures * https://st.suckless.org/patches/ligatures/ */ -#define LIGATURES_PATCH 0 +#define LIGATURES_PATCH 1 + +/* This patch add support for custom font features. It depends on the LIGATURES_PATCH patch + */ +#define FONTFEATURES_PATCH 1 /* This patch makes st ignore terminal color attributes by forcing display of the default * foreground and background colors only - making for a monochrome look. Idea ref. diff --git a/x.c b/x.c index be1a6ba..a54304f 100644 --- a/x.c +++ b/x.c @@ -1724,6 +1724,26 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x xp = winx, yp = winy + font->ascent; #endif // VERTCENTER_PATCH cluster_xp = xp; cluster_yp = yp; + #if FONTFEATURES_PATCH + { // Get font features + shaped.features = (hb_feature_t *) malloc(sizeof(hb_feature_t) * 128); + FcChar8 *s; + int feature_idx = 0; + while (FcPatternGetString(font->pattern, FC_FONT_FEATURES, feature_idx, &s) == FcResultMatch) { + if (strlen(s) != 4) + die("Invalid font feature tag"); + if (feature_idx >= 128) + die("Too many font features"); + shaped.features[feature_idx].tag = HB_TAG(s[0], s[1], s[2], s[3]); + shaped.features[feature_idx].value = 1; + shaped.features[feature_idx].start = HB_FEATURE_GLOBAL_START; + shaped.features[feature_idx].end = HB_FEATURE_GLOBAL_END; + feature_idx++; + } + shaped.features_count = feature_idx; + } + #endif // FONTFEATURES_PATCH + /* Shape the segment. */ hbtransform(&shaped, font->match, glyphs, 0, len); #endif // LIGATURES_PATCH From c87ded477c1af67af1fc1bf7320bdccc92f4d5ac Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Wed, 8 Jan 2025 14:05:15 +0100 Subject: [PATCH 02/67] config: increase scroll speed --- config.def.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 952efed..e3be44a 100644 --- a/config.def.h +++ b/config.def.h @@ -368,8 +368,8 @@ static MouseShortcut mshortcuts[] = { { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, #endif // CLIPBOARD_PATCH #if SCROLLBACK_MOUSE_PATCH - { ShiftMask, Button4, kscrollup, {.i = 1}, 0, S_PRI}, - { ShiftMask, Button5, kscrolldown, {.i = 1}, 0, S_PRI}, + { ShiftMask, Button4, kscrollup, {.i = 4}, 0, S_PRI}, + { ShiftMask, Button5, kscrolldown, {.i = 4}, 0, S_PRI}, #elif UNIVERSCROLL_PATCH { XK_ANY_MOD, Button4, ttysend, {.s = "\033[5;2~"}, 0, S_PRI }, { XK_ANY_MOD, Button5, ttysend, {.s = "\033[6;2~"}, 0, S_PRI }, @@ -378,8 +378,8 @@ static MouseShortcut mshortcuts[] = { { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, #endif // SCROLLBACK_MOUSE_PATCH #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH || REFLOW_PATCH - { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI }, - { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI }, + { XK_ANY_MOD, Button4, kscrollup, {.i = 4}, 0, S_PRI }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 4}, 0, S_PRI }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT }, { XK_ANY_MOD, Button5, ttysend, {.s = "\005"}, 0, S_ALT }, #else From 292f3ae44da870b0394ebdf7fe699729798ac493 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:02:31 +0100 Subject: [PATCH 03/67] font default to caskadia --- config.def.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/config.def.h b/config.def.h index e3be44a..bb41a98 100644 --- a/config.def.h +++ b/config.def.h @@ -5,13 +5,10 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = "Cascadia Code NF:regular:pixelsize=16:fontfeatures=calt,ss01:antialias=true:autohint=true"; #if FONT2_PATCH /* 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 char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=16:antialias=true:autohint=true" }; #endif // FONT2_PATCH #if BACKGROUND_IMAGE_PATCH From 816061be4785f9e5b32c1263d011c7c24c146ddc Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:05:02 +0100 Subject: [PATCH 04/67] Add darkman patch a patch to choose between two color themes by executing a command --- config.def.h | 38 ++++++++++++++++++++++++++++++++++++++ patches.def.h | 3 +++ x.c | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index bb41a98..d74ec00 100644 --- a/config.def.h +++ b/config.def.h @@ -203,6 +203,44 @@ static const char *colorname[] = { "#e5e5e5", /* 259 -> fg */ }; +#if DARKMAN_PATCH +#define colorname_len (sizeof(colorname) / sizeof(char *)) + +enum theme { + THEME_LIGHT, + THEME_DARK, + THEME_NUM, +}; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colornames[THEME_NUM][colorname_len] = { + { }, { + "#1a1a1a", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#f4005f", + "#98e024", + "#fa8419", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#c4c5b5", + "#625e4c", + "#f4005f", + "#98e024", + "#e0d561", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#f6f6ef", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#aaaaaa", /* 256 -> cursor */ + "#555555", /* 257 -> rev cursor*/ + "#000000", /* 258 -> bg */ + "#ffffff", /* 259 -> fg */ +}}; + +#endif // DARKMAN_PATCH + /* * Default colors (colorname index) diff --git a/patches.def.h b/patches.def.h index dbfb2a0..73c7d73 100644 --- a/patches.def.h +++ b/patches.def.h @@ -239,6 +239,9 @@ */ #define FONTFEATURES_PATCH 1 +#define DARKMAN_PATCH 1 + + /* This patch makes st ignore terminal color attributes by forcing display of the default * foreground and background colors only - making for a monochrome look. Idea ref. * https://www.reddit.com/r/suckless/comments/ixbx6z/how_to_use_black_and_white_only_for_st/ diff --git a/x.c b/x.c index a54304f..7bf72e9 100644 --- a/x.c +++ b/x.c @@ -795,10 +795,13 @@ setsel(char *str, Time t) #endif // CLIPBOARD_PATCH } -#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH +#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH void sigusr1_reload(int sig) { + #if DARKMAN_PATCH + xloadcols(); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH reload_config(sig); #endif // XRESOURCES_RELOAD_PATCH @@ -976,6 +979,28 @@ xloadalpha(void) } #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH +#if DARKMAN_PATCH +void +darkmanThemeChoose() { + FILE *fp; + char path[128]; + + fp = popen("darkman get", "r"); + if (fp == NULL) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else { + /* match the stdout with the theme */ + while (fgets(path, sizeof(path)-1, fp) != NULL) { + if (strcmp(path, "light\n") == 0) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else if (strcmp(path, "dark\n") == 0) { + memcpy(colorname, colornames[1], sizeof(colorname)); + } + } + } +} +#endif // DARKMAN_PATCH + #if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH void xloadcols(void) @@ -1009,6 +1034,8 @@ xloadcols(void) static int loaded; Color *cp; + darkmanThemeChoose(); + if (loaded) { for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); @@ -3978,9 +4005,12 @@ run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH + #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH signal(SIGUSR1, sigusr1_reload); - #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH + #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH | DARKMAN_PATCH + #if DARKMAN_PATCH + memcpy(colornames[0], colorname, sizeof(colorname)); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH if (!(xw.dpy = XOpenDisplay(NULL))) die("Can't open display\n"); From 0b4c1084f0228e99167bdc4c619a0cfc2a27bfc0 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:07:50 +0100 Subject: [PATCH 05/67] change default colors --- config.def.h | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/config.def.h b/config.def.h index d74ec00..9d38bbd 100644 --- a/config.def.h +++ b/config.def.h @@ -173,34 +173,29 @@ float alphaUnfocused = 0.6; #endif // ALPHA_PATCH /* 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", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#add8e6", /* 256 -> cursor */ - "#555555", /* 257 -> rev cursor*/ - "#000000", /* 258 -> bg */ - "#e5e5e5", /* 259 -> fg */ +static char *colorname[] = { + "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#d3423e", + "#2aa298", + "#daaa01", + "#4876d6", + "#403f53", + "#08916a", + "#7a8181", + "#7a8181", + "#f76e6e", + "#49d0c5", + "#dac26b", + "#5ca7e4", + "#697098", + "#00c990", + "#989fb1", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#403f53", /* 256 -> cursor */ + "#f2f2f2", /* 257 -> rev cursor*/ + "#ffffff", /* 258 -> bg */ + "#403f53", /* 259 -> fg */ }; #if DARKMAN_PATCH From f2c7f8073854bb71bb0527a1dfcf0133c03132ac Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:09:02 +0100 Subject: [PATCH 06/67] change keys to keyboard select and zoom --- config.def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 9d38bbd..625c5f2 100644 --- a/config.def.h +++ b/config.def.h @@ -440,8 +440,8 @@ 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} }, + { MODKEY | ControlMask, XK_comma, zoom, {.f = +1} }, + { MODKEY | ControlMask, XK_semicolon, zoom, {.f = -1} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, @@ -485,7 +485,7 @@ static Shortcut shortcuts[] = { #endif // EXTERNALPIPEIN_PATCH #endif // EXTERNALPIPE_PATCH #if KEYBOARDSELECT_PATCH - { TERMMOD, XK_Escape, keyboard_select, { 0 } }, + { TERMMOD, XK_space, keyboard_select, { 0 } }, #endif // KEYBOARDSELECT_PATCH #if KEYBOARDSELECT_PATCH && REFLOW_PATCH { TERMMOD, XK_F, searchforward, { 0 } }, From 2a20129a48c568c100fcf16adf5a72d9d6f06c3c Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:11:37 +0100 Subject: [PATCH 07/67] enable patches I want --- config.mk | 12 ++++++------ patches.def.h | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/config.mk b/config.mk index ffcd3cb..832bcff 100644 --- a/config.mk +++ b/config.mk @@ -21,14 +21,14 @@ PKG_CONFIG = pkg-config #XCURSOR = `$(PKG_CONFIG) --libs xcursor` # Uncomment the lines below for the ligatures patch / LIGATURES_PATCH -#LIGATURES_C = hb.c -#LIGATURES_H = hb.h -#LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` -#LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` +LIGATURES_C = hb.c +LIGATURES_H = hb.h +LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` +LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` # Uncomment this for the SIXEL patch / SIXEL_PATCH -#SIXEL_C = sixel.c sixel_hls.c -#SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` +SIXEL_C = sixel.c sixel_hls.c +SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` # Uncomment for the netwmicon patch / NETWMICON_PATCH #NETWMICON_LIBS = `$(PKG_CONFIG) --libs gdlib` diff --git a/patches.def.h b/patches.def.h index 73c7d73..6c22fd2 100644 --- a/patches.def.h +++ b/patches.def.h @@ -70,12 +70,12 @@ * This patch makes bold text rendered simply as bold, leaving the color unaffected. * https://st.suckless.org/patches/bold-is-not-bright/ */ -#define BOLD_IS_NOT_BRIGHT_PATCH 0 +#define BOLD_IS_NOT_BRIGHT_PATCH 1 /* This patch adds custom rendering of lines/blocks/braille characters for gapless alignment. * https://st.suckless.org/patches/boxdraw/ */ -#define BOXDRAW_PATCH 0 +#define BOXDRAW_PATCH 1 /* By default st only sets PRIMARY on selection. * This patch makes st set CLIPBOARD on selection. @@ -176,7 +176,7 @@ * that are available to GUI applications. * https://st.suckless.org/patches/fix_keyboard_input/ */ -#define FIXKEYBOARDINPUT_PATCH 0 +#define FIXKEYBOARDINPUT_PATCH 1 /* This patch allows you to add spare font besides the default. Some glyphs can be not present in * the default font. For this glyphs st uses font-config and try to find them in font cache first. @@ -184,7 +184,7 @@ * So they will be used first for glyphs that are absent in the default font. * https://st.suckless.org/patches/font2/ */ -#define FONT2_PATCH 0 +#define FONT2_PATCH 1 /* This patch adds the ability to toggle st into fullscreen mode. * Two key bindings are defined: F11 which is typical with other applications and Alt+Enter @@ -223,7 +223,7 @@ * * https://st.suckless.org/patches/keyboard_select/ */ -#define KEYBOARDSELECT_PATCH 0 +#define KEYBOARDSELECT_PATCH 1 /* This patch adds support for drawing ligatures using the Harfbuzz library to transform * original text of a single line to a list of glyphs with ligatures included. @@ -286,7 +286,7 @@ * same CWD (current working directory) as the original st instance. * https://st.suckless.org/patches/newterm/ */ -#define NEWTERM_PATCH 0 +#define NEWTERM_PATCH 1 /* This patch will set the _MOTIF_WM_HINTS property for the st window which, if the window manager * respects it, will show the st window without window decorations. @@ -306,7 +306,7 @@ * * https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/ */ -#define OPENURLONCLICK_PATCH 0 +#define OPENURLONCLICK_PATCH 1 /* This patch allows st to fetch the current working directory through the OSC 7 escape * sequence emitted by shells. Must be used with newterm patch. @@ -328,7 +328,7 @@ * Text wraps when the terminal window is made smaller. * Comes with scrollback. */ -#define REFLOW_PATCH 0 +#define REFLOW_PATCH 1 /* This patch allows you to specify a border that is relative in size to the width of a cell * in the terminal. @@ -345,19 +345,19 @@ /* Scroll back through terminal output using Shift+{PageUp, PageDown}. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_PATCH 0 +#define SCROLLBACK_PATCH 1 /* Scroll back through terminal output using Shift+MouseWheel. * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_PATCH 0 +#define SCROLLBACK_MOUSE_PATCH 1 /* Scroll back through terminal output using mouse wheel (when not in MODE_ALTSCREEN). * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 0 +#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 1 /* This patch adds the two color-settings selectionfg and selectionbg to config.def.h. * Those define the fore- and background colors which are used when text on the screen is selected @@ -385,7 +385,7 @@ * * https://gist.github.com/saitoha/70e0fdf22e3e8f63ce937c7f7da71809 */ -#define SIXEL_PATCH 0 +#define SIXEL_PATCH 1 /* This patch allows clients to embed into the st window and is useful if you tend to * start X applications from the terminal. For example: @@ -445,7 +445,7 @@ * * https://st.suckless.org/patches/undercurl/ */ -#define UNDERCURL_PATCH 0 +#define UNDERCURL_PATCH 1 /* Allows mouse scroll without modifier keys for regardless of alt screen using the external * scroll program. From 0f0f929022f0426bcf349f49c82224d5ba116874 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:15:49 +0100 Subject: [PATCH 08/67] Add a nix flake --- default.nix | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ flake.lock | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..0450b6c --- /dev/null +++ b/default.nix @@ -0,0 +1,56 @@ +{ lib +, stdenv +, pkg-config +, fontconfig +, freetype +, libX11 +, libXft +, harfbuzz +, gd +, glib +, ncurses +, writeText +, conf ? null +, patches ? [] +, extraLibs ? [] +, nixosTests +, imlib2 +}: + +stdenv.mkDerivation rec { + pname = "st"; + version = "0.8.5"; + + src = ./.; + inherit patches; + + configFile = + lib.optionalString (conf != null) (writeText "config.def.h" conf); + + postPatch = lib.optionalString (conf != null) "cp ${configFile} config.def.h" + + lib.optionalString stdenv.isDarwin '' + substituteInPlace config.mk --replace "-lrt" "" + ''; + + strictDeps = true; + + makeFlags = [ "PKG_CONFIG=${stdenv.cc.targetPrefix}pkg-config" ]; + + nativeBuildInputs = [ pkg-config ncurses fontconfig freetype ]; + buildInputs = [ libX11 libXft harfbuzz gd glib imlib2 ] ++ extraLibs; + + preInstall = '' + export TERMINFO=$out/share/terminfo + ''; + + installFlags = [ "PREFIX=$(out)" ]; + + passthru.tests.test = nixosTests.terminal-emulators.st; + + meta = with lib; { + description = "st terminal"; + license = licenses.mit; + maintainers = with maintainers; [ sioodmy ]; + platforms = platforms.unix; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..586a00c --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1736549401, + "narHash": "sha256-ibkQrMHxF/7TqAYcQE+tOnIsSEzXmMegzyBWza6uHKM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1dab772dd4a68a7bba5d9460685547ff8e17d899", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a30e80d --- /dev/null +++ b/flake.nix @@ -0,0 +1,41 @@ +{ + description = "st terminal"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; + in rec { + packages = flake-utils.lib.flattenTree { + st = pkgs.callPackage ./default.nix { }; + }; + defaultPackage = packages.st; + apps.st = flake-utils.lib.mkApp { + drv = packages.st; + exePath = "/bin/st"; + }; + apps.default = apps.st; + defaultApp = apps.st; + devShell = pkgs.mkShell rec { + name = "st"; + packages = with pkgs; [ + pkg-config + xorg.libX11 + xorg.libXft + fontconfig + harfbuzz.dev + imlib2 + gd + glib + # ccls + # bear + # lldb + # gdb + # valgrind + ]; + }; + + }); +} From 08b53c4960186ca64978a8463a2648336a42bd3e Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 20 Feb 2025 10:18:17 +0100 Subject: [PATCH 09/67] Adding drag-n-drop patch --- README.md | 5 ++ config.def.h | 9 ++ patch/drag-n-drop.c | 204 ++++++++++++++++++++++++++++++++++++++++++++ patch/drag-n-drop.h | 5 ++ patch/x_include.c | 3 + patch/x_include.h | 3 + patches.def.h | 5 ++ st.h | 14 +++ x.c | 44 ++++++++++ 9 files changed, 292 insertions(+) create mode 100644 patch/drag-n-drop.c create mode 100644 patch/drag-n-drop.h diff --git a/README.md b/README.md index 3710d13..fcf54db 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: +2025-02-20 - Added the drag-n-drop patch + 2024-05-31 - Added the anygeometry patch 2024-03-13 - Added the reflow patch and upgraded the netwmicon patch @@ -162,6 +164,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [disable-fonts](https://st.suckless.org/patches/disable_bold_italic_fonts/) - this patch adds the option of disabling bold/italic/roman fonts globally + - [drag-n-drop](https://st.suckless.org/patches/drag-n-drop) + - allows dragging a file into the terminal and have the path printed + - [dynamic-cursor-color](https://st.suckless.org/patches/dynamic-cursor-color/) - this patch makes the cursor color the inverse of the current cell color diff --git a/config.def.h b/config.def.h index 952efed..56971f2 100644 --- a/config.def.h +++ b/config.def.h @@ -175,6 +175,15 @@ float alphaUnfocused = 0.6; #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH #endif // ALPHA_PATCH +#if DRAG_AND_DROP_PATCH +/* + * drag and drop escape characters + * + * this will add a '\' before any characters specified in the string. + */ +char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; +#endif // DRAG_AND_DROP_PATCH + /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ diff --git a/patch/drag-n-drop.c b/patch/drag-n-drop.c new file mode 100644 index 0000000..917a9aa --- /dev/null +++ b/patch/drag-n-drop.c @@ -0,0 +1,204 @@ +const char XdndVersion = 5; + +void +xdndsel(XEvent *e) +{ + char* data; + unsigned long result; + + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor, + e->xselection.property, 0, LONG_MAX, False, + e->xselection.target, &actualType, &actualFormat, &result, + &bytesAfter, (unsigned char**) &data); + + if (result == 0) + return; + + if (data) { + xdndpastedata(data); + XFree(data); + } + + if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = xw.XdndActionCopy; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); + } +} + +int +xdndurldecode(char *src, char *dest) +{ + char c; + int i = 0; + + while (*src) { + if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_INT(src[2]) != -1) { + /* handle %xx escape sequences in url e.g. %20 == ' ' */ + c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_INT(src[2])); + src += 3; + } else { + c = *src++; + } + if (strchr(xdndescchar, c) != NULL) { + *dest++ = '\\'; + i++; + } + *dest++ = c; + i++; + } + *dest++ = ' '; + *dest = '\0'; + return i + 1; +} + +void +xdndpastedata(char *data) +{ + char *pastedata, *t; + int i = 0; + + pastedata = (char *)malloc(strlen(data) * 2 + 1); + *pastedata = '\0'; + + t = strtok(data, "\n\r"); + while(t != NULL) { + /* Remove 'file://' prefix if it exists */ + if (strncmp(data, "file://", 7) == 0) { + t += 7; + } + i += xdndurldecode(t, pastedata + i); + t = strtok(NULL, "\n\r"); + } + + xsetsel(pastedata); + selpaste(0); +} + +void +xdndenter(XEvent *e) +{ + unsigned long count; + Atom* formats; + Atom real_formats[6]; + Bool list; + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + unsigned long i; + + list = e->xclient.data.l[1] & 1; + + if (list) { + XGetWindowProperty((Display*) xw.dpy, + xw.XdndSourceWin, + xw.XdndTypeList, + 0, + LONG_MAX, + False, + 4, + &actualType, + &actualFormat, + &count, + &bytesAfter, + (unsigned char**) &formats); + } else { + count = 0; + + if (e->xclient.data.l[2] != None) + real_formats[count++] = e->xclient.data.l[2]; + if (e->xclient.data.l[3] != None) + real_formats[count++] = e->xclient.data.l[3]; + if (e->xclient.data.l[4] != None) + real_formats[count++] = e->xclient.data.l[4]; + + formats = real_formats; + } + + for (i = 0; i < count; i++) { + if (formats[i] == xw.XtextUriList || formats[i] == xw.XtextPlain) { + xw.XdndSourceFormat = formats[i]; + break; + } + } + + if (list) + XFree(formats); +} + +void +xdndpos(XEvent *e) +{ + const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff; + const int32_t yabs = (e->xclient.data.l[2]) & 0xffff; + Window dummy; + int32_t xpos, ypos; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XTranslateCoordinates((Display*) xw.dpy, + XDefaultRootWindow((Display*) xw.dpy), + (Window) xw.win, + xabs, yabs, + &xpos, &ypos, + &dummy); + + reply.xclient.message_type = xw.XdndStatus; + + if (xw.XdndSourceFormat) { + reply.xclient.data.l[1] = 1; + if (xw.XdndSourceVersion >= 2) + reply.xclient.data.l[4] = xw.XdndActionCopy; + } + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); +} + +void +xdnddrop(XEvent *e) +{ + Time time = CurrentTime; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + if (xw.XdndSourceFormat) { + if (xw.XdndSourceVersion >= 1) + time = e->xclient.data.l[2]; + + XConvertSelection((Display*) xw.dpy, xw.XdndSelection, + xw.XdndSourceFormat, xw.XdndSelection, (Window) xw.win, time); + } else if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, + False, NoEventMask, &reply); + XFlush((Display*) xw.dpy); + } +} diff --git a/patch/drag-n-drop.h b/patch/drag-n-drop.h new file mode 100644 index 0000000..ee8e82b --- /dev/null +++ b/patch/drag-n-drop.h @@ -0,0 +1,5 @@ +static void xdndenter(XEvent *); +static void xdndpos(XEvent *); +static void xdnddrop(XEvent *); +static void xdndsel(XEvent *); +static void xdndpastedata(char *); diff --git a/patch/x_include.c b/patch/x_include.c index 30b77da..20f083b 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.c" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.c" +#endif #if OPENCOPIED_PATCH #include "opencopied.c" #endif diff --git a/patch/x_include.h b/patch/x_include.h index 78290e1..fef502d 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.h" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.h" +#endif #if OPENCOPIED_PATCH #include "opencopied.h" #endif diff --git a/patches.def.h b/patches.def.h index ae5d37b..cd792f6 100644 --- a/patches.def.h +++ b/patches.def.h @@ -144,6 +144,11 @@ */ #define DISABLE_ROMAN_FONTS_PATCH 0 +/* Allows dragging a file into the terminal and have the path printed. + * https://st.suckless.org/patches/drag-n-drop + */ +#define DRAG_AND_DROP_PATCH 0 + /* This patch makes the cursor color the inverse of the current cell color. * https://st.suckless.org/patches/dynamic-cursor-color/ */ diff --git a/st.h b/st.h index 0682a0e..0464f24 100644 --- a/st.h +++ b/st.h @@ -37,6 +37,12 @@ #define HISTSIZE 2000 #endif // SCROLLBACK_PATCH | REFLOW_PATCH +#if DRAG_AND_DROP_PATCH +#define HEX_TO_INT(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \ + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \ + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : -1) +#endif // DRAG_AND_DROP_PATCH + enum glyph_attribute { ATTR_NULL = 0, ATTR_SET = 1 << 0, @@ -247,6 +253,14 @@ typedef struct { GlyphFontSeq *specseq; #endif // LIGATURES_PATCH Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + #if DRAG_AND_DROP_PATCH + Atom XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, + XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, + XdndActionLink, XdndActionAsk, XdndActionPrivate, XtextUriList, + XtextPlain, XdndAware; + int64_t XdndSourceWin, XdndSourceVersion; + int32_t XdndSourceFormat; + #endif // DRAG_AND_DROP_PATCH #if FULLSCREEN_PATCH Atom netwmstate, netwmfullscreen; #endif // FULLSCREEN_PATCH diff --git a/x.c b/x.c index be1a6ba..b4303e4 100644 --- a/x.c +++ b/x.c @@ -603,6 +603,13 @@ selnotify(XEvent *e) if (property == None) return; + #if DRAG_AND_DROP_PATCH + if (property == xw.XdndSelection) { + xdndsel(e); + return; + } + #endif // DRAG_AND_DROP_PATCH + do { if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ/4, False, AnyPropertyType, @@ -1656,6 +1663,28 @@ xinit(int cols, int rows) xw.netwmfullscreen = XInternAtom(xw.dpy, "_NET_WM_STATE_FULLSCREEN", False); #endif // FULLSCREEN_PATCH + #if DRAG_AND_DROP_PATCH + /* Xdnd setup */ + xw.XdndTypeList = XInternAtom(xw.dpy, "XdndTypeList", 0); + xw.XdndSelection = XInternAtom(xw.dpy, "XdndSelection", 0); + xw.XdndEnter = XInternAtom(xw.dpy, "XdndEnter", 0); + xw.XdndPosition = XInternAtom(xw.dpy, "XdndPosition", 0); + xw.XdndStatus = XInternAtom(xw.dpy, "XdndStatus", 0); + xw.XdndLeave = XInternAtom(xw.dpy, "XdndLeave", 0); + xw.XdndDrop = XInternAtom(xw.dpy, "XdndDrop", 0); + xw.XdndFinished = XInternAtom(xw.dpy, "XdndFinished", 0); + xw.XdndActionCopy = XInternAtom(xw.dpy, "XdndActionCopy", 0); + xw.XdndActionMove = XInternAtom(xw.dpy, "XdndActionMove", 0); + xw.XdndActionLink = XInternAtom(xw.dpy, "XdndActionLink", 0); + xw.XdndActionAsk = XInternAtom(xw.dpy, "XdndActionAsk", 0); + xw.XdndActionPrivate = XInternAtom(xw.dpy, "XdndActionPrivate", 0); + xw.XtextUriList = XInternAtom((Display*) xw.dpy, "text/uri-list", 0); + xw.XtextPlain = XInternAtom((Display*) xw.dpy, "text/plain", 0); + xw.XdndAware = XInternAtom(xw.dpy, "XdndAware", 0); + XChangeProperty(xw.dpy, xw.win, xw.XdndAware, 4, 32, PropModeReplace, + &XdndVersion, 1); + #endif // DRAG_AND_DROP_PATCH + win.mode = MODE_NUMLOCK; resettitle(); xhints(); @@ -3666,6 +3695,21 @@ cmessage(XEvent *e) } else if (e->xclient.data.l[0] == xw.wmdeletewin) { ttyhangup(); exit(0); + #if DRAG_AND_DROP_PATCH + } else if (e->xclient.message_type == xw.XdndEnter) { + xw.XdndSourceWin = e->xclient.data.l[0]; + xw.XdndSourceVersion = e->xclient.data.l[1] >> 24; + xw.XdndSourceFormat = None; + if (xw.XdndSourceVersion > 5) + return; + xdndenter(e); + } else if (e->xclient.message_type == xw.XdndPosition + && xw.XdndSourceVersion <= 5) { + xdndpos(e); + } else if (e->xclient.message_type == xw.XdndDrop + && xw.XdndSourceVersion <= 5) { + xdnddrop(e); + #endif // DRAG_AND_DROP_PATCH } } From 978e25f23b990db1e30c76ae0868e7df30c9a7c5 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 20 Feb 2025 22:36:51 +0100 Subject: [PATCH 10/67] Adding open selected text patch --- README.md | 5 ++++- config.def.h | 3 +++ patch/openselectedtext.c | 13 +++++++++++++ patch/openselectedtext.h | 3 +++ patch/x_include.c | 3 +++ patch/x_include.h | 3 +++ patches.def.h | 5 +++++ 7 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 patch/openselectedtext.c create mode 100644 patch/openselectedtext.h diff --git a/README.md b/README.md index fcf54db..44d7b6e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: -2025-02-20 - Added the drag-n-drop patch +2025-02-20 - Added the drag-n-drop and open-selected-text patches 2024-05-31 - Added the anygeometry patch @@ -235,6 +235,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [open-copied-url](https://st.suckless.org/patches/open_copied_url/) - open contents of the clipboard in a user-defined browser + - [open-selected-text](https://st.suckless.org/patches/open_selected_text) + - open the selected text using `xdg-open` + - [openurlonclick](https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/) - allows for URLs to be opened directly when you click on them diff --git a/config.def.h b/config.def.h index 56971f2..8e133a6 100644 --- a/config.def.h +++ b/config.def.h @@ -371,6 +371,9 @@ static uint forcemousemod = ShiftMask; */ static MouseShortcut mshortcuts[] = { /* mask button function argument release screen */ + #if OPEN_SELECTED_TEXT_PATCH + { ControlMask, Button2, selopen, {.i = 0}, 1 }, + #endif // OPEN_SELECTED_TEXT_PATCH #if CLIPBOARD_PATCH { XK_ANY_MOD, Button2, clippaste, {.i = 0}, 1 }, #else diff --git a/patch/openselectedtext.c b/patch/openselectedtext.c new file mode 100644 index 0000000..42d40e2 --- /dev/null +++ b/patch/openselectedtext.c @@ -0,0 +1,13 @@ +void +selopen(const Arg *dummy) +{ + pid_t chpid; + + if ((chpid = fork()) == 0) { + if (fork() == 0) + execlp("xdg-open", "xdg-open", getsel(), NULL); + exit(1); + } + if (chpid > 0) + waitpid(chpid, NULL, 0); +} diff --git a/patch/openselectedtext.h b/patch/openselectedtext.h new file mode 100644 index 0000000..3dccbc6 --- /dev/null +++ b/patch/openselectedtext.h @@ -0,0 +1,3 @@ +#include + +static void selopen(const Arg *); diff --git a/patch/x_include.c b/patch/x_include.c index 20f083b..5a0ba58 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -38,6 +38,9 @@ #elif NETWMICON_LEGACY_PATCH #include "netwmicon_legacy.c" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.c" +#endif #if OPENURLONCLICK_PATCH #include "openurlonclick.c" #endif diff --git a/patch/x_include.h b/patch/x_include.h index fef502d..ed10e8c 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -35,6 +35,9 @@ #if NETWMICON_PATCH || NETWMICON_FF_PATCH || NETWMICON_LEGACY_PATCH #include "netwmicon.h" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.h" +#endif #if RIGHTCLICKTOPLUMB_PATCH #include "rightclicktoplumb_x.h" #endif diff --git a/patches.def.h b/patches.def.h index cd792f6..3cc7375 100644 --- a/patches.def.h +++ b/patches.def.h @@ -299,6 +299,11 @@ */ #define OPENCOPIED_PATCH 0 +/* Open the selected text using xdg-open. + * https://st.suckless.org/patches/open_selected_text/ + */ +#define OPEN_SELECTED_TEXT_PATCH 0 + /* This patch allows for URLs to be opened directly when you click on them. This may not work with * all terminal applications. * From c4af76a9cc16a1fc3fcd7566fbca613b531ce40b Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 21:23:09 +0100 Subject: [PATCH 11/67] reflow: addressing selection clearing bug when selection includes the prompt ref. #166 --- patch/reflow.c | 4 ++-- st.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patch/reflow.c b/patch/reflow.c index bf145a6..dac7b9d 100644 --- a/patch/reflow.c +++ b/patch/reflow.c @@ -619,8 +619,8 @@ tclearregion(int x1, int y1, int x2, int y2, int usecurattr) int x, y; /* regionselected() takes relative coordinates */ - if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) - selremove(); + if (regionselected(x1, y1+term.scr, x2, y2+term.scr)) + selclear(); for (y = y1; y <= y2; y++) { term.dirty[y] = 1; diff --git a/st.c b/st.c index 5efe122..6a7a614 100644 --- a/st.c +++ b/st.c @@ -3434,7 +3434,7 @@ check_control_code: #if REFLOW_PATCH /* selected() takes relative coordinates */ - if (selected(term.c.x + term.scr, term.c.y + term.scr)) + if (selected(term.c.x, term.c.y + term.scr)) selclear(); #else if (selected(term.c.x, term.c.y)) From 75da349fb30222348f7d56d7cd4c42c50097da1f Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 21:58:05 +0100 Subject: [PATCH 12/67] selection colors vs dynamic cursor color patch compatibility issue ref. #167 --- x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x.c b/x.c index b4303e4..3ef6db7 100644 --- a/x.c +++ b/x.c @@ -2700,7 +2700,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if !DYNAMIC_CURSOR_COLOR_PATCH + #if !DYNAMIC_CURSOR_COLOR_PATCH || SELECTION_COLORS_PATCH /* remove the old cursor */ if (selected(ox, oy)) #if SELECTION_COLORS_PATCH @@ -2757,7 +2757,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) } #endif // SELECTION_COLORS_PATCH } else { - #if SELECTION_COLORS_PATCH + #if SELECTION_COLORS_PATCH && !DYNAMIC_CURSOR_COLOR_PATCH g.fg = defaultbg; g.bg = defaultcs; drawcol = dc.col[defaultcs]; From d60f1b355f8ec7e3254e5bf41bac578b04a25d10 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 22:36:19 +0100 Subject: [PATCH 13/67] Adding dynamic padding patch - a variant of anysize that do not alter size hints ref. #168 --- patches.def.h | 9 +++++++++ st.h | 5 +++++ x.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/patches.def.h b/patches.def.h index 3cc7375..63e5f21 100644 --- a/patches.def.h +++ b/patches.def.h @@ -154,6 +154,15 @@ */ #define DYNAMIC_CURSOR_COLOR_PATCH 0 +/* This is a variant of the anysize patch that explicitly do not change the size increment hints, + * i.e. only keeping the dynamic padding which is the main thing the anysize patch introduces. + * In practice this means that the dynamic padding / anysize functionality only ever comes into + * effect when the size hints are intentionally ignored. + * An example of this would be dwm respecting the size hints of floating windows, but disrespecting + * the size hints when the window is tiled (provided that resizehints config is set to 0). + */ +#define DYNAMIC_PADDING_PATCH 0 + /* Reading and writing st's screen through a pipe, e.g. pass info to dmenu. * https://st.suckless.org/patches/externalpipe/ */ diff --git a/st.h b/st.h index 0464f24..4af046c 100644 --- a/st.h +++ b/st.h @@ -11,6 +11,11 @@ #include #include "patches.h" +#if DYNAMIC_PADDING_PATCH +#undef ANYSIZE_PATCH +#define ANYSIZE_PATCH 1 +#endif // DYNAMIC_PADDING_PATCH + /* 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 3ef6db7..72862d9 100644 --- a/x.c +++ b/x.c @@ -1137,7 +1137,7 @@ xhints(void) sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; sizeh->height = win.h; sizeh->width = win.w; - #if ANYSIZE_PATCH || ANYSIZE_SIMPLE_PATCH + #if ANYSIZE_PATCH && !DYNAMIC_PADDING_PATCH || ANYSIZE_SIMPLE_PATCH sizeh->height_inc = 1; sizeh->width_inc = 1; #else From dc64384989a854b2eed8fb29f066aed710c63537 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 27 Feb 2025 21:57:48 +0100 Subject: [PATCH 14/67] dynamic cursor color: visual bug on selection ref. #169 --- x.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/x.c b/x.c index 72862d9..6ac13b0 100644 --- a/x.c +++ b/x.c @@ -2700,21 +2700,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if !DYNAMIC_CURSOR_COLOR_PATCH || SELECTION_COLORS_PATCH - /* remove the old cursor */ + #if LIGATURES_PATCH + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); + #else + /* Remove the old cursor */ if (selected(ox, oy)) #if SELECTION_COLORS_PATCH og.mode |= ATTR_SELECTED; #else og.mode ^= ATTR_REVERSE; #endif // SELECTION_COLORS_PATCH - #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if LIGATURES_PATCH - /* Redraw the line where cursor was previously. - * It will restore the ligatures broken by the cursor. */ - xdrawline(line, 0, oy, len); - #else xdrawglyph(og, ox, oy); #endif // LIGATURES_PATCH From da81ae1704464a58c1efd9eb394ac350b6e8865c Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 4 Mar 2025 10:12:43 +0100 Subject: [PATCH 15/67] dynamic padding - add explicit dependency on the ANYSIZE_PATCH ref. #168 --- patches.def.h | 2 ++ st.h | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/patches.def.h b/patches.def.h index 63e5f21..466b057 100644 --- a/patches.def.h +++ b/patches.def.h @@ -160,6 +160,8 @@ * effect when the size hints are intentionally ignored. * An example of this would be dwm respecting the size hints of floating windows, but disrespecting * the size hints when the window is tiled (provided that resizehints config is set to 0). + * + * Note that this patch depends on ANYSIZE_PATCH being enabled to have an effect. */ #define DYNAMIC_PADDING_PATCH 0 diff --git a/st.h b/st.h index 4af046c..0464f24 100644 --- a/st.h +++ b/st.h @@ -11,11 +11,6 @@ #include #include "patches.h" -#if DYNAMIC_PADDING_PATCH -#undef ANYSIZE_PATCH -#define ANYSIZE_PATCH 1 -#endif // DYNAMIC_PADDING_PATCH - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) From cb91e175baf446c1da7a7b5caffb29cbe190587c Mon Sep 17 00:00:00 2001 From: veltza <106755522+veltza@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:53:53 +0300 Subject: [PATCH 16/67] Prevent SelectionRequests from interfering with blinking cursor (#173) Some old clipboard managers, such as greenclip and parcellite, constantly poll applications with SelectionRequest events, which breaks the internal timer and blinking cursor. This fix prevents these events from causing any disruption. Fixes #172 --- x.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/x.c b/x.c index 6ac13b0..a011ccd 100644 --- a/x.c +++ b/x.c @@ -3804,8 +3804,12 @@ run(void) xev = 0; while (XPending(xw.dpy)) { - xev = 1; XNextEvent(xw.dpy, &ev); + #if BLINKING_CURSOR_PATCH + xev = (!xev || xev == SelectionRequest) ? ev.type : xev; + #else + xev = 1; + #endif // BLINKING_CURSOR_PATCH if (XFilterEvent(&ev, None)) continue; if (handler[ev.type]) @@ -3832,10 +3836,10 @@ run(void) if (!drawing) { trigger = now; #if BLINKING_CURSOR_PATCH - if (IS_SET(MODE_BLINK)) { - win.mode ^= MODE_BLINK; + if (xev != SelectionRequest) { + win.mode &= ~MODE_BLINK; + lastblink = now; } - lastblink = now; #endif // BLINKING_CURSOR_PATCH drawing = 1; } From f8e451e26c5fdafa6f60cda1e249fc20e7dd450c Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 6 May 2025 14:41:20 +0200 Subject: [PATCH 17/67] Refactoring Xft clipping ref. #175 --- x.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/x.c b/x.c index a011ccd..cf82659 100644 --- a/x.c +++ b/x.c @@ -2234,20 +2234,9 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i else #endif // BACKGROUND_IMAGE_PATCH - #if !WIDE_GLYPHS_PATCH - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - #endif // WIDE_GLYPHS_PATCH - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - #if WIDE_GLYPHS_PATCH /* Fill the background */ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + #if WIDE_GLYPHS_PATCH } #endif // WIDE_GLYPHS_PATCH @@ -2258,13 +2247,27 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i 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); - } + #endif // BOXDRAW_PATCH + /* Set the clip region because Xft is sometimes dirty. */ + #if WIDE_GLYPHS_PATCH + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = win.w; + XftDrawSetClipRectangles(xw.draw, 0, winy, &r, 1); #else + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + #endif // WIDE_GLYPHS_PATCH + #if BOXDRAW_PATCH + } + #endif // BOXDRAW_PATCH + /* Render the glyphs. */ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - #endif // BOXDRAW_PATCH /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { From 5a65d4a51220553ec18102cecc2035fed7d4362c Mon Sep 17 00:00:00 2001 From: ant Date: Wed, 21 May 2025 20:49:42 +0200 Subject: [PATCH 18/67] enable boxdraw --- config.def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 625c5f2..de4fd25 100644 --- a/config.def.h +++ b/config.def.h @@ -127,11 +127,11 @@ int hidecursor = 1; * 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; +const int boxdraw = 1; +const int boxdraw_bold = 1; /* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 0; +const int boxdraw_braille = 1; #endif // BOXDRAW_PATCH /* From 304293d4e14571da1032d88d6f56610cdfb3cf58 Mon Sep 17 00:00:00 2001 From: ant Date: Wed, 21 May 2025 20:41:36 +0200 Subject: [PATCH 19/67] Enable alpha patch --- patches.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches.def.h b/patches.def.h index 6c22fd2..46834e8 100644 --- a/patches.def.h +++ b/patches.def.h @@ -14,7 +14,7 @@ * when including this patch. * https://st.suckless.org/patches/alpha/ */ -#define ALPHA_PATCH 0 +#define ALPHA_PATCH 1 /* The alpha focus highlight patch allows the user to specify two distinct opacity values or * background colors in order to easily differentiate between focused and unfocused terminal From cae36041b4ce3057f79c019f74da9e5280a0d049 Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Mon, 2 Jun 2025 09:17:07 +0200 Subject: [PATCH 20/67] decrease default font size --- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index de4fd25..35beb92 100644 --- a/config.def.h +++ b/config.def.h @@ -5,10 +5,10 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Cascadia Code NF:regular:pixelsize=16:fontfeatures=calt,ss01:antialias=true:autohint=true"; +static char *font = "Cascadia Code NF:regular:pixelsize=13.5:fontfeatures=calt,ss01:antialias=true:autohint=true"; #if FONT2_PATCH /* Spare fonts */ -static char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=16:antialias=true:autohint=true" }; +static char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=13.5:antialias=true:autohint=true" }; #endif // FONT2_PATCH #if BACKGROUND_IMAGE_PATCH From 43d9be991b63ab2fc36704263473eb2442ebf9c2 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Mon, 16 Jun 2025 22:53:48 +0200 Subject: [PATCH 21/67] OpenBSD compatibility changes --- config.mk | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/config.mk b/config.mk index ffcd3cb..7becffc 100644 --- a/config.mk +++ b/config.mk @@ -38,7 +38,7 @@ INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` \ $(LIGATURES_INC) -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ +LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` \ $(LIGATURES_LIBS) \ @@ -50,10 +50,7 @@ STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) # OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `pkg-config --libs fontconfig` \ -# `pkg-config --libs freetype2` +#CPPFLAGS = $(STCPPFLAGS) -D_XOPEN_SOURCE=600 #MANPREFIX = ${PREFIX}/man # compiler and linker From dd9784883f60c1a3be3cf71c5bfef1c0311b555f Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 10:27:50 +0200 Subject: [PATCH 22/67] boxdraw: fix for rendering errors following commit f8e451e ref. #180 --- x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x.c b/x.c index cf82659..627e352 100644 --- a/x.c +++ b/x.c @@ -2262,13 +2262,14 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i r.width = width; XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); #endif // WIDE_GLYPHS_PATCH - #if BOXDRAW_PATCH - } - #endif // BOXDRAW_PATCH /* Render the glyphs. */ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + #if BOXDRAW_PATCH + } + #endif // BOXDRAW_PATCH + /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { #if UNDERCURL_PATCH From 4000b47a107f6b42ef073be7130d7615095aa72d Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 10:42:24 +0200 Subject: [PATCH 23/67] sync: adding mode 2026 for the sync patch to allow syncing to be controlled by programs ref. #179 --- st.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/st.c b/st.c index 6a7a614..d5d6eca 100644 --- a/st.c +++ b/st.c @@ -2039,6 +2039,15 @@ tsetmode(int priv, int set, const int *args, int narg) MODBIT(term.mode, set, MODE_SIXEL_CUR_RT); break; #endif // SIXEL_PATCH + #if SYNC_PATCH + case 2026: + if (set == 1) { + tsync_begin(); + } else if (set == 2) { + tsync_end(); + } + break; + #endif // SYNC_PATCH default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", From 9edaa4c1496ed9b53f5bb144367e897d9ff852b3 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 15:11:17 +0200 Subject: [PATCH 24/67] sync: mode 2026 correction ref. #179 --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index d5d6eca..794fdcb 100644 --- a/st.c +++ b/st.c @@ -2041,9 +2041,9 @@ tsetmode(int priv, int set, const int *args, int narg) #endif // SIXEL_PATCH #if SYNC_PATCH case 2026: - if (set == 1) { + if (set) { tsync_begin(); - } else if (set == 2) { + } else { tsync_end(); } break; From 7c28c7868aa4fcedaef9574ba814da1986fc479b Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 19:16:24 +0200 Subject: [PATCH 25/67] sync: add support for DECRQM queries for synchronization ref. #179 --- st.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/st.c b/st.c index 794fdcb..fadacf2 100644 --- a/st.c +++ b/st.c @@ -2444,6 +2444,23 @@ csihandle(void) goto unknown; } break; + #if SYNC_PATCH + case '$': /* DECRQM -- DEC Request Mode (private) */ + if (csiescseq.mode[1] == 'p' && csiescseq.priv) { + switch (csiescseq.arg[0]) { + #if SYNC_PATCH + case 2026: + /* https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 */ + ttywrite(su ? "\033[?2026;1$y" : "\033[?2026;2$y", 11, 0); + break; + #endif // SYNC_PATCH + default: + goto unknown; + } + break; + } + goto unknown; + #endif // SYNC_PATCH case 'r': /* DECSTBM -- Set Scrolling Region */ if (csiescseq.priv) { goto unknown; From f17e1dcf31aaf8f2bb8f3ed995549cbb2aae5d2f Mon Sep 17 00:00:00 2001 From: Laurent Cheylus Date: Wed, 9 Jul 2025 09:45:24 +0200 Subject: [PATCH 26/67] Do not interpret CSI ? u as DECRC (#181) The kitty keyboard protocol docs recommend CSI ? u to query support for that protocol, see https://sw.kovidgoyal.net/kitty/keyboard-protocol/ For better or worse, fish shell uses this query to work around bugs in other terminals triggered by requesting that protocol via CSI = 5 u. Unfortunately, st interprets CSI ? u as DECRC (restore cursor position). reproduce with 'printf "\x1b[?u"; cat'. fish could work around this by switching to the alternate screen before running this query; but that might cause tearing on terminals that don't support Synchronized Output. I'm not sure. In the meantime, let's correct our parser. This adds a redundant else-after-return, for consistency with the surrounding code. ref. https://git.suckless.org/st/commit/98610fcd37f655d44586323dc86c1d013c2798ce.html Signed-off-by: Laurent Cheylus --- st.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index fadacf2..1be93f2 100644 --- a/st.c +++ b/st.c @@ -2524,7 +2524,11 @@ csihandle(void) break; #endif // CSI_22_23_PATCH | SIXEL_PATCH case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); + if (csiescseq.priv) { + goto unknown; + } else { + tcursor(CURSOR_LOAD); + } break; case ' ': switch (csiescseq.mode[1]) { From fba8d104172d988f1fd67874c4e4231d7b9fe914 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 9 Jul 2025 09:47:04 +0200 Subject: [PATCH 27/67] Bump to 98610fc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44d7b6e..ec590cb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (6009e6e, 2024-11-25) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (98610fc, 2025-01-26) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c From 48f696499db3c6adfe6e0813afc49c582be20a3b Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Fri, 18 Jul 2025 00:22:52 +0200 Subject: [PATCH 28/67] add keybinnds to scroll --- config.def.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.def.h b/config.def.h index 35beb92..163e042 100644 --- a/config.def.h +++ b/config.def.h @@ -460,6 +460,10 @@ static Shortcut shortcuts[] = { #if SCROLLBACK_PATCH { ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_U, kscrollup, {.i = -1}, S_PRI }, + { TERMMOD, XK_D, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_K, kscrollup, {.i = 4}, S_PRI }, + { TERMMOD, XK_J, kscrolldown, {.i = 4}, S_PRI }, #endif // SCROLLBACK_PATCH #if CLIPBOARD_PATCH { TERMMOD, XK_Y, clippaste, {.i = 0} }, From 92e6c003f7097cd8471a505f79a92a28e1817f18 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sun, 27 Jul 2025 20:46:31 +0200 Subject: [PATCH 29/67] Eat up "CSI 58" sequences This is used in the wild by systemd systemctl for example and st misinterpreted it as "blink", because it didn't know "58", then saw "5" as "blink", and then didn't know "245". This should print "foo" as normal text: printf '\e[58:5:245mfoo\n' printf '\e[58:2:50:100:200mfoo\n' Ref. https://git.suckless.org/st/commit/f114bcedd113017d907aad32031db92c050f4bf3.html --- README.md | 2 +- st.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ec590cb..0b46f59 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (98610fc, 2025-01-26) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (f114bce, 2025-07-27) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c diff --git a/st.c b/st.c index 1be93f2..74dac7d 100644 --- a/st.c +++ b/st.c @@ -1864,6 +1864,13 @@ tsetattr(const int *attr, int l) term.c.attr.ucolor[2] = -1; term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; break; + #else + case 58: + /* This starts a sequence to change the color of + * "underline" pixels. We don't support that and + * instead eat up a following "5;n" or "2;r;g;b". */ + tdefcolor(attr, &i, l); + break; #endif // UNDERCURL_PATCH default: if (BETWEEN(attr[i], 30, 37)) { From 9328548866e94ac9df043651a25dd1704fa9b454 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sun, 3 Aug 2025 22:19:37 +0200 Subject: [PATCH 30/67] xresources: removing focus change ttywrite ref. #182 --- patch/xresources.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/patch/xresources.c b/patch/xresources.c index ba3d985..5617b1a 100644 --- a/patch/xresources.c +++ b/patch/xresources.c @@ -74,9 +74,5 @@ reload_config(int sig) xhints(); XCloseDisplay(dpy); - - /* from https://st.suckless.org/patches/xresources-with-reload-signal */ - /* triggers re-render if we're visible */ - ttywrite("\033[O", 3, 1); } #endif // XRESOURCES_RELOAD_PATCH From bdb21ddb8bdffa372b2870407a2869d5c5a822f3 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sun, 10 Aug 2025 15:44:48 +0200 Subject: [PATCH 31/67] bump version to 0.9.3 https://git.suckless.org/st/commit/5a4666c19e3956069147aee43a06b326d998366e.html add a few comments https://git.suckless.org/st/commit/5a4666c19e3956069147aee43a06b326d998366e.html Support OSC 110, 111, and 112 for resetting colors This adds support for OSC 110, 111, and 112 escape sequences to reset the foreground, background, and cursor colors in the terminal. The changes include handling these sequences in the `strhandle` function of `st.c`, allowing applications to reset colors to their default values. The OSC sequences originated from Xterm control sequences and are now widely used in terminal applications and supported by many terminal emulators. For applications, this allows them to reset colors to default values without needing to know the colors beforehand. https://git.suckless.org/st/commit/d6c431859c6c0201e0668ed24a9f17cebf0a68f5.html --- README.md | 2 +- config.mk | 2 +- st.c | 33 +++++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0b46f59..92f9889 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (f114bce, 2025-07-27) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.3 (6e97047, 2025-08-09) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c diff --git a/config.mk b/config.mk index 7becffc..a3b94cd 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # st version -VERSION = 0.9.2 +VERSION = 0.9.3 # Customize below to fit your system diff --git a/st.c b/st.c index 74dac7d..0d56e00 100644 --- a/st.c +++ b/st.c @@ -1837,7 +1837,7 @@ tsetattr(const int *attr, int l) term.c.attr.fg = idx; #endif // MONOCHROME_PATCH break; - case 39: + case 39: /* set foreground color to default */ term.c.attr.fg = defaultfg; break; case 48: @@ -1848,7 +1848,7 @@ tsetattr(const int *attr, int l) term.c.attr.bg = idx; #endif // MONOCHROME_PATCH break; - case 49: + case 49: /* set background color to default */ term.c.attr.bg = defaultbg; break; #if UNDERCURL_PATCH @@ -1985,7 +1985,7 @@ tsetmode(int priv, int set, const int *args, int narg) case 1006: /* 1006: extended reporting mode */ xsetmode(set, MODE_MOUSESGR); break; - case 1034: + case 1034: /* 1034: enable 8-bit mode for keyboard input */ xsetmode(set, MODE_8BIT); break; case 1049: /* swap screen & set/restore cursor as xterm */ @@ -1993,8 +1993,8 @@ tsetmode(int priv, int set, const int *args, int narg) break; tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: + case 47: /* swap screen buffer */ + case 1047: /* swap screen buffer */ if (!allowaltscreen) break; #if REFLOW_PATCH @@ -2018,7 +2018,7 @@ tsetmode(int priv, int set, const int *args, int narg) break; /* FALLTHROUGH */ #endif // REFLOW_PATCH - case 1048: + case 1048: /* save/restore cursor (like DECSC/DECRC) */ #if REFLOW_PATCH if (!allowaltscreen) break; @@ -2656,7 +2656,7 @@ strhandle(void) xsettitle(strescseq.args[1]); #endif // CSI_22_23_PATCH return; - case 52: + case 52: /* manipulate selection data */ if (narg > 2 && allowwindowops) { dec = base64dec(strescseq.args[2]); if (dec) { @@ -2674,9 +2674,9 @@ strhandle(void) #endif // OSC7_PATCH case 8: /* Clear Hyperlinks */ return; - case 10: - case 11: - case 12: + case 10: /* set dynamic VT100 text foreground color */ + case 11: /* set dynamic VT100 text background color */ + case 12: /* set dynamic text cursor color */ if (narg < 2) break; p = strescseq.args[1]; @@ -2717,6 +2717,19 @@ strhandle(void) tfulldirt(); } return; + case 110: /* reset dynamic VT100 text foreground color */ + case 111: /* reset dynamic VT100 text background color */ + case 112: /* reset dynamic text cursor color */ + if (narg != 1) + break; + if ((j = par - 110) < 0 || j >= LEN(osc_table)) + break; /* shouldn't be possible */ + if (xsetcolorname(osc_table[j].idx, NULL)) { + fprintf(stderr, "erresc: %s color not found\n", osc_table[j].str); + } else { + tfulldirt(); + } + return; #if OSC133_PATCH case 133: if (narg < 2) From 137bb152b301a0ad7f952e3e9ceb5ee0d5f6719c Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 20 Feb 2025 10:18:17 +0100 Subject: [PATCH 32/67] Adding drag-n-drop patch --- README.md | 5 ++ config.def.h | 9 ++ patch/drag-n-drop.c | 204 ++++++++++++++++++++++++++++++++++++++++++++ patch/drag-n-drop.h | 5 ++ patch/x_include.c | 3 + patch/x_include.h | 3 + patches.def.h | 5 ++ st.h | 14 +++ x.c | 44 ++++++++++ 9 files changed, 292 insertions(+) create mode 100644 patch/drag-n-drop.c create mode 100644 patch/drag-n-drop.h diff --git a/README.md b/README.md index 3710d13..fcf54db 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: +2025-02-20 - Added the drag-n-drop patch + 2024-05-31 - Added the anygeometry patch 2024-03-13 - Added the reflow patch and upgraded the netwmicon patch @@ -162,6 +164,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [disable-fonts](https://st.suckless.org/patches/disable_bold_italic_fonts/) - this patch adds the option of disabling bold/italic/roman fonts globally + - [drag-n-drop](https://st.suckless.org/patches/drag-n-drop) + - allows dragging a file into the terminal and have the path printed + - [dynamic-cursor-color](https://st.suckless.org/patches/dynamic-cursor-color/) - this patch makes the cursor color the inverse of the current cell color diff --git a/config.def.h b/config.def.h index 163e042..fb5d57b 100644 --- a/config.def.h +++ b/config.def.h @@ -172,6 +172,15 @@ float alphaUnfocused = 0.6; #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH #endif // ALPHA_PATCH +#if DRAG_AND_DROP_PATCH +/* + * drag and drop escape characters + * + * this will add a '\' before any characters specified in the string. + */ +char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; +#endif // DRAG_AND_DROP_PATCH + /* Terminal colors (16 first used in escape sequence) */ static char *colorname[] = { "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ diff --git a/patch/drag-n-drop.c b/patch/drag-n-drop.c new file mode 100644 index 0000000..917a9aa --- /dev/null +++ b/patch/drag-n-drop.c @@ -0,0 +1,204 @@ +const char XdndVersion = 5; + +void +xdndsel(XEvent *e) +{ + char* data; + unsigned long result; + + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor, + e->xselection.property, 0, LONG_MAX, False, + e->xselection.target, &actualType, &actualFormat, &result, + &bytesAfter, (unsigned char**) &data); + + if (result == 0) + return; + + if (data) { + xdndpastedata(data); + XFree(data); + } + + if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = xw.XdndActionCopy; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); + } +} + +int +xdndurldecode(char *src, char *dest) +{ + char c; + int i = 0; + + while (*src) { + if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_INT(src[2]) != -1) { + /* handle %xx escape sequences in url e.g. %20 == ' ' */ + c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_INT(src[2])); + src += 3; + } else { + c = *src++; + } + if (strchr(xdndescchar, c) != NULL) { + *dest++ = '\\'; + i++; + } + *dest++ = c; + i++; + } + *dest++ = ' '; + *dest = '\0'; + return i + 1; +} + +void +xdndpastedata(char *data) +{ + char *pastedata, *t; + int i = 0; + + pastedata = (char *)malloc(strlen(data) * 2 + 1); + *pastedata = '\0'; + + t = strtok(data, "\n\r"); + while(t != NULL) { + /* Remove 'file://' prefix if it exists */ + if (strncmp(data, "file://", 7) == 0) { + t += 7; + } + i += xdndurldecode(t, pastedata + i); + t = strtok(NULL, "\n\r"); + } + + xsetsel(pastedata); + selpaste(0); +} + +void +xdndenter(XEvent *e) +{ + unsigned long count; + Atom* formats; + Atom real_formats[6]; + Bool list; + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + unsigned long i; + + list = e->xclient.data.l[1] & 1; + + if (list) { + XGetWindowProperty((Display*) xw.dpy, + xw.XdndSourceWin, + xw.XdndTypeList, + 0, + LONG_MAX, + False, + 4, + &actualType, + &actualFormat, + &count, + &bytesAfter, + (unsigned char**) &formats); + } else { + count = 0; + + if (e->xclient.data.l[2] != None) + real_formats[count++] = e->xclient.data.l[2]; + if (e->xclient.data.l[3] != None) + real_formats[count++] = e->xclient.data.l[3]; + if (e->xclient.data.l[4] != None) + real_formats[count++] = e->xclient.data.l[4]; + + formats = real_formats; + } + + for (i = 0; i < count; i++) { + if (formats[i] == xw.XtextUriList || formats[i] == xw.XtextPlain) { + xw.XdndSourceFormat = formats[i]; + break; + } + } + + if (list) + XFree(formats); +} + +void +xdndpos(XEvent *e) +{ + const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff; + const int32_t yabs = (e->xclient.data.l[2]) & 0xffff; + Window dummy; + int32_t xpos, ypos; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + XTranslateCoordinates((Display*) xw.dpy, + XDefaultRootWindow((Display*) xw.dpy), + (Window) xw.win, + xabs, yabs, + &xpos, &ypos, + &dummy); + + reply.xclient.message_type = xw.XdndStatus; + + if (xw.XdndSourceFormat) { + reply.xclient.data.l[1] = 1; + if (xw.XdndSourceVersion >= 2) + reply.xclient.data.l[4] = xw.XdndActionCopy; + } + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, + &reply); + XFlush((Display*) xw.dpy); +} + +void +xdnddrop(XEvent *e) +{ + Time time = CurrentTime; + XEvent reply = { ClientMessage }; + + reply.xclient.window = xw.XdndSourceWin; + reply.xclient.format = 32; + reply.xclient.data.l[0] = (long) xw.win; + reply.xclient.data.l[2] = 0; + reply.xclient.data.l[3] = 0; + + if (xw.XdndSourceFormat) { + if (xw.XdndSourceVersion >= 1) + time = e->xclient.data.l[2]; + + XConvertSelection((Display*) xw.dpy, xw.XdndSelection, + xw.XdndSourceFormat, xw.XdndSelection, (Window) xw.win, time); + } else if (xw.XdndSourceVersion >= 2) { + reply.xclient.message_type = xw.XdndFinished; + + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, + False, NoEventMask, &reply); + XFlush((Display*) xw.dpy); + } +} diff --git a/patch/drag-n-drop.h b/patch/drag-n-drop.h new file mode 100644 index 0000000..ee8e82b --- /dev/null +++ b/patch/drag-n-drop.h @@ -0,0 +1,5 @@ +static void xdndenter(XEvent *); +static void xdndpos(XEvent *); +static void xdnddrop(XEvent *); +static void xdndsel(XEvent *); +static void xdndpastedata(char *); diff --git a/patch/x_include.c b/patch/x_include.c index 30b77da..20f083b 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.c" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.c" +#endif #if OPENCOPIED_PATCH #include "opencopied.c" #endif diff --git a/patch/x_include.h b/patch/x_include.h index 78290e1..fef502d 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -8,6 +8,9 @@ #if BOXDRAW_PATCH #include "boxdraw.h" #endif +#if DRAG_AND_DROP_PATCH +#include "drag-n-drop.h" +#endif #if OPENCOPIED_PATCH #include "opencopied.h" #endif diff --git a/patches.def.h b/patches.def.h index 46834e8..6f02a04 100644 --- a/patches.def.h +++ b/patches.def.h @@ -144,6 +144,11 @@ */ #define DISABLE_ROMAN_FONTS_PATCH 0 +/* Allows dragging a file into the terminal and have the path printed. + * https://st.suckless.org/patches/drag-n-drop + */ +#define DRAG_AND_DROP_PATCH 0 + /* This patch makes the cursor color the inverse of the current cell color. * https://st.suckless.org/patches/dynamic-cursor-color/ */ diff --git a/st.h b/st.h index 0682a0e..0464f24 100644 --- a/st.h +++ b/st.h @@ -37,6 +37,12 @@ #define HISTSIZE 2000 #endif // SCROLLBACK_PATCH | REFLOW_PATCH +#if DRAG_AND_DROP_PATCH +#define HEX_TO_INT(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \ + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \ + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : -1) +#endif // DRAG_AND_DROP_PATCH + enum glyph_attribute { ATTR_NULL = 0, ATTR_SET = 1 << 0, @@ -247,6 +253,14 @@ typedef struct { GlyphFontSeq *specseq; #endif // LIGATURES_PATCH Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + #if DRAG_AND_DROP_PATCH + Atom XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, + XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, + XdndActionLink, XdndActionAsk, XdndActionPrivate, XtextUriList, + XtextPlain, XdndAware; + int64_t XdndSourceWin, XdndSourceVersion; + int32_t XdndSourceFormat; + #endif // DRAG_AND_DROP_PATCH #if FULLSCREEN_PATCH Atom netwmstate, netwmfullscreen; #endif // FULLSCREEN_PATCH diff --git a/x.c b/x.c index 7bf72e9..124e30a 100644 --- a/x.c +++ b/x.c @@ -603,6 +603,13 @@ selnotify(XEvent *e) if (property == None) return; + #if DRAG_AND_DROP_PATCH + if (property == xw.XdndSelection) { + xdndsel(e); + return; + } + #endif // DRAG_AND_DROP_PATCH + do { if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ/4, False, AnyPropertyType, @@ -1683,6 +1690,28 @@ xinit(int cols, int rows) xw.netwmfullscreen = XInternAtom(xw.dpy, "_NET_WM_STATE_FULLSCREEN", False); #endif // FULLSCREEN_PATCH + #if DRAG_AND_DROP_PATCH + /* Xdnd setup */ + xw.XdndTypeList = XInternAtom(xw.dpy, "XdndTypeList", 0); + xw.XdndSelection = XInternAtom(xw.dpy, "XdndSelection", 0); + xw.XdndEnter = XInternAtom(xw.dpy, "XdndEnter", 0); + xw.XdndPosition = XInternAtom(xw.dpy, "XdndPosition", 0); + xw.XdndStatus = XInternAtom(xw.dpy, "XdndStatus", 0); + xw.XdndLeave = XInternAtom(xw.dpy, "XdndLeave", 0); + xw.XdndDrop = XInternAtom(xw.dpy, "XdndDrop", 0); + xw.XdndFinished = XInternAtom(xw.dpy, "XdndFinished", 0); + xw.XdndActionCopy = XInternAtom(xw.dpy, "XdndActionCopy", 0); + xw.XdndActionMove = XInternAtom(xw.dpy, "XdndActionMove", 0); + xw.XdndActionLink = XInternAtom(xw.dpy, "XdndActionLink", 0); + xw.XdndActionAsk = XInternAtom(xw.dpy, "XdndActionAsk", 0); + xw.XdndActionPrivate = XInternAtom(xw.dpy, "XdndActionPrivate", 0); + xw.XtextUriList = XInternAtom((Display*) xw.dpy, "text/uri-list", 0); + xw.XtextPlain = XInternAtom((Display*) xw.dpy, "text/plain", 0); + xw.XdndAware = XInternAtom(xw.dpy, "XdndAware", 0); + XChangeProperty(xw.dpy, xw.win, xw.XdndAware, 4, 32, PropModeReplace, + &XdndVersion, 1); + #endif // DRAG_AND_DROP_PATCH + win.mode = MODE_NUMLOCK; resettitle(); xhints(); @@ -3713,6 +3742,21 @@ cmessage(XEvent *e) } else if (e->xclient.data.l[0] == xw.wmdeletewin) { ttyhangup(); exit(0); + #if DRAG_AND_DROP_PATCH + } else if (e->xclient.message_type == xw.XdndEnter) { + xw.XdndSourceWin = e->xclient.data.l[0]; + xw.XdndSourceVersion = e->xclient.data.l[1] >> 24; + xw.XdndSourceFormat = None; + if (xw.XdndSourceVersion > 5) + return; + xdndenter(e); + } else if (e->xclient.message_type == xw.XdndPosition + && xw.XdndSourceVersion <= 5) { + xdndpos(e); + } else if (e->xclient.message_type == xw.XdndDrop + && xw.XdndSourceVersion <= 5) { + xdnddrop(e); + #endif // DRAG_AND_DROP_PATCH } } From c7503f57378e6d85e484a32f822ce002817dd03b Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 20 Feb 2025 22:36:51 +0100 Subject: [PATCH 33/67] Adding open selected text patch --- README.md | 5 ++++- config.def.h | 3 +++ patch/openselectedtext.c | 13 +++++++++++++ patch/openselectedtext.h | 3 +++ patch/x_include.c | 3 +++ patch/x_include.h | 3 +++ patches.def.h | 5 +++++ 7 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 patch/openselectedtext.c create mode 100644 patch/openselectedtext.h diff --git a/README.md b/README.md index fcf54db..44d7b6e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: -2025-02-20 - Added the drag-n-drop patch +2025-02-20 - Added the drag-n-drop and open-selected-text patches 2024-05-31 - Added the anygeometry patch @@ -235,6 +235,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [open-copied-url](https://st.suckless.org/patches/open_copied_url/) - open contents of the clipboard in a user-defined browser + - [open-selected-text](https://st.suckless.org/patches/open_selected_text) + - open the selected text using `xdg-open` + - [openurlonclick](https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/) - allows for URLs to be opened directly when you click on them diff --git a/config.def.h b/config.def.h index fb5d57b..3a98fb2 100644 --- a/config.def.h +++ b/config.def.h @@ -401,6 +401,9 @@ static uint forcemousemod = ShiftMask; */ static MouseShortcut mshortcuts[] = { /* mask button function argument release screen */ + #if OPEN_SELECTED_TEXT_PATCH + { ControlMask, Button2, selopen, {.i = 0}, 1 }, + #endif // OPEN_SELECTED_TEXT_PATCH #if CLIPBOARD_PATCH { XK_ANY_MOD, Button2, clippaste, {.i = 0}, 1 }, #else diff --git a/patch/openselectedtext.c b/patch/openselectedtext.c new file mode 100644 index 0000000..42d40e2 --- /dev/null +++ b/patch/openselectedtext.c @@ -0,0 +1,13 @@ +void +selopen(const Arg *dummy) +{ + pid_t chpid; + + if ((chpid = fork()) == 0) { + if (fork() == 0) + execlp("xdg-open", "xdg-open", getsel(), NULL); + exit(1); + } + if (chpid > 0) + waitpid(chpid, NULL, 0); +} diff --git a/patch/openselectedtext.h b/patch/openselectedtext.h new file mode 100644 index 0000000..3dccbc6 --- /dev/null +++ b/patch/openselectedtext.h @@ -0,0 +1,3 @@ +#include + +static void selopen(const Arg *); diff --git a/patch/x_include.c b/patch/x_include.c index 20f083b..5a0ba58 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -38,6 +38,9 @@ #elif NETWMICON_LEGACY_PATCH #include "netwmicon_legacy.c" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.c" +#endif #if OPENURLONCLICK_PATCH #include "openurlonclick.c" #endif diff --git a/patch/x_include.h b/patch/x_include.h index fef502d..ed10e8c 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -35,6 +35,9 @@ #if NETWMICON_PATCH || NETWMICON_FF_PATCH || NETWMICON_LEGACY_PATCH #include "netwmicon.h" #endif +#if OPEN_SELECTED_TEXT_PATCH +#include "openselectedtext.h" +#endif #if RIGHTCLICKTOPLUMB_PATCH #include "rightclicktoplumb_x.h" #endif diff --git a/patches.def.h b/patches.def.h index 6f02a04..b340aaa 100644 --- a/patches.def.h +++ b/patches.def.h @@ -306,6 +306,11 @@ */ #define OPENCOPIED_PATCH 0 +/* Open the selected text using xdg-open. + * https://st.suckless.org/patches/open_selected_text/ + */ +#define OPEN_SELECTED_TEXT_PATCH 0 + /* This patch allows for URLs to be opened directly when you click on them. This may not work with * all terminal applications. * From 50286bb86111af84b9a24200fe30c50179948bf5 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 21:23:09 +0100 Subject: [PATCH 34/67] reflow: addressing selection clearing bug when selection includes the prompt ref. #166 --- patch/reflow.c | 4 ++-- st.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patch/reflow.c b/patch/reflow.c index bf145a6..dac7b9d 100644 --- a/patch/reflow.c +++ b/patch/reflow.c @@ -619,8 +619,8 @@ tclearregion(int x1, int y1, int x2, int y2, int usecurattr) int x, y; /* regionselected() takes relative coordinates */ - if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) - selremove(); + if (regionselected(x1, y1+term.scr, x2, y2+term.scr)) + selclear(); for (y = y1; y <= y2; y++) { term.dirty[y] = 1; diff --git a/st.c b/st.c index 5efe122..6a7a614 100644 --- a/st.c +++ b/st.c @@ -3434,7 +3434,7 @@ check_control_code: #if REFLOW_PATCH /* selected() takes relative coordinates */ - if (selected(term.c.x + term.scr, term.c.y + term.scr)) + if (selected(term.c.x, term.c.y + term.scr)) selclear(); #else if (selected(term.c.x, term.c.y)) From 3c7bcf616d4b51c0efad016357235da8061b3b4c Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 21:58:05 +0100 Subject: [PATCH 35/67] selection colors vs dynamic cursor color patch compatibility issue ref. #167 --- x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x.c b/x.c index 124e30a..a07b8cd 100644 --- a/x.c +++ b/x.c @@ -2747,7 +2747,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if !DYNAMIC_CURSOR_COLOR_PATCH + #if !DYNAMIC_CURSOR_COLOR_PATCH || SELECTION_COLORS_PATCH /* remove the old cursor */ if (selected(ox, oy)) #if SELECTION_COLORS_PATCH @@ -2804,7 +2804,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) } #endif // SELECTION_COLORS_PATCH } else { - #if SELECTION_COLORS_PATCH + #if SELECTION_COLORS_PATCH && !DYNAMIC_CURSOR_COLOR_PATCH g.fg = defaultbg; g.bg = defaultcs; drawcol = dc.col[defaultcs]; From 9860867e1091bf5b5559d5bcdf37ff121e99bf75 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 26 Feb 2025 22:36:19 +0100 Subject: [PATCH 36/67] Adding dynamic padding patch - a variant of anysize that do not alter size hints ref. #168 --- patches.def.h | 9 +++++++++ st.h | 5 +++++ x.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/patches.def.h b/patches.def.h index b340aaa..ae7ac56 100644 --- a/patches.def.h +++ b/patches.def.h @@ -154,6 +154,15 @@ */ #define DYNAMIC_CURSOR_COLOR_PATCH 0 +/* This is a variant of the anysize patch that explicitly do not change the size increment hints, + * i.e. only keeping the dynamic padding which is the main thing the anysize patch introduces. + * In practice this means that the dynamic padding / anysize functionality only ever comes into + * effect when the size hints are intentionally ignored. + * An example of this would be dwm respecting the size hints of floating windows, but disrespecting + * the size hints when the window is tiled (provided that resizehints config is set to 0). + */ +#define DYNAMIC_PADDING_PATCH 0 + /* Reading and writing st's screen through a pipe, e.g. pass info to dmenu. * https://st.suckless.org/patches/externalpipe/ */ diff --git a/st.h b/st.h index 0464f24..4af046c 100644 --- a/st.h +++ b/st.h @@ -11,6 +11,11 @@ #include #include "patches.h" +#if DYNAMIC_PADDING_PATCH +#undef ANYSIZE_PATCH +#define ANYSIZE_PATCH 1 +#endif // DYNAMIC_PADDING_PATCH + /* 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 a07b8cd..dde2900 100644 --- a/x.c +++ b/x.c @@ -1164,7 +1164,7 @@ xhints(void) sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; sizeh->height = win.h; sizeh->width = win.w; - #if ANYSIZE_PATCH || ANYSIZE_SIMPLE_PATCH + #if ANYSIZE_PATCH && !DYNAMIC_PADDING_PATCH || ANYSIZE_SIMPLE_PATCH sizeh->height_inc = 1; sizeh->width_inc = 1; #else From 5d5fe7679504fb8ad1ceff443410fb42176894cf Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Thu, 27 Feb 2025 21:57:48 +0100 Subject: [PATCH 37/67] dynamic cursor color: visual bug on selection ref. #169 --- x.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/x.c b/x.c index dde2900..1d5d1e9 100644 --- a/x.c +++ b/x.c @@ -2747,21 +2747,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if !DYNAMIC_CURSOR_COLOR_PATCH || SELECTION_COLORS_PATCH - /* remove the old cursor */ + #if LIGATURES_PATCH + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); + #else + /* Remove the old cursor */ if (selected(ox, oy)) #if SELECTION_COLORS_PATCH og.mode |= ATTR_SELECTED; #else og.mode ^= ATTR_REVERSE; #endif // SELECTION_COLORS_PATCH - #endif // DYNAMIC_CURSOR_COLOR_PATCH - #if LIGATURES_PATCH - /* Redraw the line where cursor was previously. - * It will restore the ligatures broken by the cursor. */ - xdrawline(line, 0, oy, len); - #else xdrawglyph(og, ox, oy); #endif // LIGATURES_PATCH From 0aad70af586003c4e81571cf7677d335ca02f13b Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 4 Mar 2025 10:12:43 +0100 Subject: [PATCH 38/67] dynamic padding - add explicit dependency on the ANYSIZE_PATCH ref. #168 --- patches.def.h | 2 ++ st.h | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/patches.def.h b/patches.def.h index ae7ac56..1e92a9f 100644 --- a/patches.def.h +++ b/patches.def.h @@ -160,6 +160,8 @@ * effect when the size hints are intentionally ignored. * An example of this would be dwm respecting the size hints of floating windows, but disrespecting * the size hints when the window is tiled (provided that resizehints config is set to 0). + * + * Note that this patch depends on ANYSIZE_PATCH being enabled to have an effect. */ #define DYNAMIC_PADDING_PATCH 0 diff --git a/st.h b/st.h index 4af046c..0464f24 100644 --- a/st.h +++ b/st.h @@ -11,11 +11,6 @@ #include #include "patches.h" -#if DYNAMIC_PADDING_PATCH -#undef ANYSIZE_PATCH -#define ANYSIZE_PATCH 1 -#endif // DYNAMIC_PADDING_PATCH - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) From 49ac4d1e14a0ac9c45c44efe9ae97bf1c4971f76 Mon Sep 17 00:00:00 2001 From: veltza <106755522+veltza@users.noreply.github.com> Date: Tue, 22 Apr 2025 10:53:53 +0300 Subject: [PATCH 39/67] Prevent SelectionRequests from interfering with blinking cursor (#173) Some old clipboard managers, such as greenclip and parcellite, constantly poll applications with SelectionRequest events, which breaks the internal timer and blinking cursor. This fix prevents these events from causing any disruption. Fixes #172 --- x.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/x.c b/x.c index 1d5d1e9..249e056 100644 --- a/x.c +++ b/x.c @@ -3851,8 +3851,12 @@ run(void) xev = 0; while (XPending(xw.dpy)) { - xev = 1; XNextEvent(xw.dpy, &ev); + #if BLINKING_CURSOR_PATCH + xev = (!xev || xev == SelectionRequest) ? ev.type : xev; + #else + xev = 1; + #endif // BLINKING_CURSOR_PATCH if (XFilterEvent(&ev, None)) continue; if (handler[ev.type]) @@ -3879,10 +3883,10 @@ run(void) if (!drawing) { trigger = now; #if BLINKING_CURSOR_PATCH - if (IS_SET(MODE_BLINK)) { - win.mode ^= MODE_BLINK; + if (xev != SelectionRequest) { + win.mode &= ~MODE_BLINK; + lastblink = now; } - lastblink = now; #endif // BLINKING_CURSOR_PATCH drawing = 1; } From a12b73a36fc19941938adafdec1cd1c9f861f3b5 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 6 May 2025 14:41:20 +0200 Subject: [PATCH 40/67] Refactoring Xft clipping ref. #175 --- x.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/x.c b/x.c index 249e056..e540322 100644 --- a/x.c +++ b/x.c @@ -2281,20 +2281,9 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i else #endif // BACKGROUND_IMAGE_PATCH - #if !WIDE_GLYPHS_PATCH - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - #endif // WIDE_GLYPHS_PATCH - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - #if WIDE_GLYPHS_PATCH /* Fill the background */ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + #if WIDE_GLYPHS_PATCH } #endif // WIDE_GLYPHS_PATCH @@ -2305,13 +2294,27 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i 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); - } + #endif // BOXDRAW_PATCH + /* Set the clip region because Xft is sometimes dirty. */ + #if WIDE_GLYPHS_PATCH + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = win.w; + XftDrawSetClipRectangles(xw.draw, 0, winy, &r, 1); #else + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + #endif // WIDE_GLYPHS_PATCH + #if BOXDRAW_PATCH + } + #endif // BOXDRAW_PATCH + /* Render the glyphs. */ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - #endif // BOXDRAW_PATCH /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { From 821244c2aefdb2495e2746e84242a6992f13afb3 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Mon, 16 Jun 2025 22:53:48 +0200 Subject: [PATCH 41/67] OpenBSD compatibility changes --- config.mk | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/config.mk b/config.mk index 832bcff..260fff0 100644 --- a/config.mk +++ b/config.mk @@ -38,7 +38,7 @@ INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` \ $(LIGATURES_INC) -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ +LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` \ $(LIGATURES_LIBS) \ @@ -50,10 +50,7 @@ STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) # OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `pkg-config --libs fontconfig` \ -# `pkg-config --libs freetype2` +#CPPFLAGS = $(STCPPFLAGS) -D_XOPEN_SOURCE=600 #MANPREFIX = ${PREFIX}/man # compiler and linker From 4da3d6d87c83c70dae784da28deed9f980950e2f Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 10:27:50 +0200 Subject: [PATCH 42/67] boxdraw: fix for rendering errors following commit f8e451e ref. #180 --- x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x.c b/x.c index e540322..0de0ac7 100644 --- a/x.c +++ b/x.c @@ -2309,13 +2309,14 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i r.width = width; XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); #endif // WIDE_GLYPHS_PATCH - #if BOXDRAW_PATCH - } - #endif // BOXDRAW_PATCH /* Render the glyphs. */ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + #if BOXDRAW_PATCH + } + #endif // BOXDRAW_PATCH + /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { #if UNDERCURL_PATCH From f7354190f7a5329c3a615f3edc01cdc4123feaf9 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 10:42:24 +0200 Subject: [PATCH 43/67] sync: adding mode 2026 for the sync patch to allow syncing to be controlled by programs ref. #179 --- st.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/st.c b/st.c index 6a7a614..d5d6eca 100644 --- a/st.c +++ b/st.c @@ -2039,6 +2039,15 @@ tsetmode(int priv, int set, const int *args, int narg) MODBIT(term.mode, set, MODE_SIXEL_CUR_RT); break; #endif // SIXEL_PATCH + #if SYNC_PATCH + case 2026: + if (set == 1) { + tsync_begin(); + } else if (set == 2) { + tsync_end(); + } + break; + #endif // SYNC_PATCH default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", From 9be6da03707c2bbde735b7f84a48591159244eff Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 15:11:17 +0200 Subject: [PATCH 44/67] sync: mode 2026 correction ref. #179 --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index d5d6eca..794fdcb 100644 --- a/st.c +++ b/st.c @@ -2041,9 +2041,9 @@ tsetmode(int priv, int set, const int *args, int narg) #endif // SIXEL_PATCH #if SYNC_PATCH case 2026: - if (set == 1) { + if (set) { tsync_begin(); - } else if (set == 2) { + } else { tsync_end(); } break; From ad3c3e774cfbc3b0eaa14854cedfc6e109ee579d Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Tue, 8 Jul 2025 19:16:24 +0200 Subject: [PATCH 45/67] sync: add support for DECRQM queries for synchronization ref. #179 --- st.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/st.c b/st.c index 794fdcb..fadacf2 100644 --- a/st.c +++ b/st.c @@ -2444,6 +2444,23 @@ csihandle(void) goto unknown; } break; + #if SYNC_PATCH + case '$': /* DECRQM -- DEC Request Mode (private) */ + if (csiescseq.mode[1] == 'p' && csiescseq.priv) { + switch (csiescseq.arg[0]) { + #if SYNC_PATCH + case 2026: + /* https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 */ + ttywrite(su ? "\033[?2026;1$y" : "\033[?2026;2$y", 11, 0); + break; + #endif // SYNC_PATCH + default: + goto unknown; + } + break; + } + goto unknown; + #endif // SYNC_PATCH case 'r': /* DECSTBM -- Set Scrolling Region */ if (csiescseq.priv) { goto unknown; From 51d32a9a77d50a0c2e7730d46dc989e228b2292b Mon Sep 17 00:00:00 2001 From: Laurent Cheylus Date: Wed, 9 Jul 2025 09:45:24 +0200 Subject: [PATCH 46/67] Do not interpret CSI ? u as DECRC (#181) The kitty keyboard protocol docs recommend CSI ? u to query support for that protocol, see https://sw.kovidgoyal.net/kitty/keyboard-protocol/ For better or worse, fish shell uses this query to work around bugs in other terminals triggered by requesting that protocol via CSI = 5 u. Unfortunately, st interprets CSI ? u as DECRC (restore cursor position). reproduce with 'printf "\x1b[?u"; cat'. fish could work around this by switching to the alternate screen before running this query; but that might cause tearing on terminals that don't support Synchronized Output. I'm not sure. In the meantime, let's correct our parser. This adds a redundant else-after-return, for consistency with the surrounding code. ref. https://git.suckless.org/st/commit/98610fcd37f655d44586323dc86c1d013c2798ce.html Signed-off-by: Laurent Cheylus --- st.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index fadacf2..1be93f2 100644 --- a/st.c +++ b/st.c @@ -2524,7 +2524,11 @@ csihandle(void) break; #endif // CSI_22_23_PATCH | SIXEL_PATCH case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); + if (csiescseq.priv) { + goto unknown; + } else { + tcursor(CURSOR_LOAD); + } break; case ' ': switch (csiescseq.mode[1]) { From 02627756f1916a289b5f5f0f9c4d56764914b19d Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 9 Jul 2025 09:47:04 +0200 Subject: [PATCH 47/67] Bump to 98610fc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44d7b6e..ec590cb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (6009e6e, 2024-11-25) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (98610fc, 2025-01-26) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c From 042af42400e57abd9d1ad50f6094ea09b2679b2d Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Fri, 3 Oct 2025 13:21:56 +0200 Subject: [PATCH 48/67] change colors for light theme --- config.def.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/config.def.h b/config.def.h index 3a98fb2..7a349b2 100644 --- a/config.def.h +++ b/config.def.h @@ -162,7 +162,7 @@ unsigned int tabspaces = 8; #if ALPHA_PATCH /* bg opacity */ -float alpha = 0.8; +float alpha = 0.9; #if ALPHA_GRADIENT_PATCH float grad_alpha = 0.54; //alpha value that'll change float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha @@ -183,28 +183,28 @@ char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; /* Terminal colors (16 first used in escape sequence) */ static char *colorname[] = { - "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ - "#d3423e", - "#2aa298", - "#daaa01", - "#4876d6", - "#403f53", - "#08916a", - "#7a8181", - "#7a8181", - "#f76e6e", - "#49d0c5", - "#dac26b", - "#5ca7e4", - "#697098", - "#00c990", - "#989fb1", + "#000000", + "#ff3333", + "#86b200", + "#f19618", + "#41a6d9", + "#f07078", + "#4cbe99", + "#ffffff", + "#323232", + "#ff6565", + "#b8e532", + "#ffc849", + "#73d7ff", + "#ffa3aa", + "#7ff0cb", + "#ffffff", [255] = 0, /* more colors can be added after 255 to use with DefaultXX */ "#403f53", /* 256 -> cursor */ - "#f2f2f2", /* 257 -> rev cursor*/ - "#ffffff", /* 258 -> bg */ - "#403f53", /* 259 -> fg */ + "#f0ede4", /* 257 -> rev cursor*/ + "#fafafa", /* 258 -> bg */ + "#5b6673", /* 259 -> fg */ }; #if DARKMAN_PATCH From 1d5c8a159566a960684881a5f9932be2ba464764 Mon Sep 17 00:00:00 2001 From: Lady Alice Date: Tue, 14 Oct 2025 14:26:45 +0200 Subject: [PATCH 49/67] reflow: enable keyboard scrolling by default (#187) --- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 8e133a6..7baab30 100644 --- a/config.def.h +++ b/config.def.h @@ -439,10 +439,10 @@ static Shortcut shortcuts[] = { { XK_NO_MOD, XK_F11, fullscreen, {.i = 0} }, { MODKEY, XK_Return, fullscreen, {.i = 0} }, #endif // FULLSCREEN_PATCH - #if SCROLLBACK_PATCH + #if SCROLLBACK_PATCH || REFLOW_PATCH { ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI }, - #endif // SCROLLBACK_PATCH + #endif // SCROLLBACK_PATCH || REFLOW_PATCH #if CLIPBOARD_PATCH { TERMMOD, XK_Y, clippaste, {.i = 0} }, { ShiftMask, XK_Insert, clippaste, {.i = 0} }, From 46a5982e9d7472712b19998e852d5fe8bcb855ce Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Wed, 13 Aug 2025 15:15:21 +0200 Subject: [PATCH 50/67] Removing utils.h, leftover from the vim browse patch --- patch/utils.h | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 patch/utils.h diff --git a/patch/utils.h b/patch/utils.h deleted file mode 100644 index 5ecea0d..0000000 --- a/patch/utils.h +++ /dev/null @@ -1,23 +0,0 @@ -/// Dynamic memory-chunk, with (1) datatype size, (2/3) initialized / allocated chunk, (4) content -typedef struct { uint8_t const elSize; uint32_t init, alloc; char* content; } DynamicArray; -#define UTF8_ARRAY {4, 0, 0, NULL} - -static inline int p_alloc(DynamicArray *s, uint32_t amount) { - uint32_t const diff=s->init+s->elSize*amount-s->alloc, nas=s->alloc+max(diff,15)*s->elSize; - if (s->alloc < s->init + s->elSize * amount) { - char* tmp = realloc(s->content, nas); - if (!tmp) return 0; - s->alloc = nas, s->content = tmp; - } - return 1; -} -static inline char *view(DynamicArray * s, uint32_t i) { return s->content + i*s->elSize; } -static inline char *end(DynamicArray *s, uint32_t i) { return s->content +s->init-(i+1)*s->elSize; } -static inline uint32_t getU32(DynamicArray* s, uint32_t i, int b) { return *((uint32_t*) (b ?view(s,i) :end(s,i))); } -static char *expand(DynamicArray *s) { if (!p_alloc(s, 1)) return NULL; s->init += s->elSize; return end(s, 0); } -static inline void pop(DynamicArray* s) { s->init -= s->elSize; } -static inline void empty(DynamicArray* s) { s->init = 0; } -static inline int size(DynamicArray const * s) { return s->init / s->elSize; } -static inline void assign(DynamicArray* s, DynamicArray const *o) { - if (p_alloc(s, size(o))) memcpy(s->content, o->content, (s->init=o->init)); -} \ No newline at end of file From d12d2ad1c2616ffd81a4c107e9a1b14acf2bc8d3 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sat, 25 Oct 2025 14:04:52 +0200 Subject: [PATCH 51/67] sync patch: remove redundant inner #if for DECRQM -- DEC Request Mode case statement ref. #179 --- st.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/st.c b/st.c index 0d56e00..9359a54 100644 --- a/st.c +++ b/st.c @@ -2455,12 +2455,10 @@ csihandle(void) case '$': /* DECRQM -- DEC Request Mode (private) */ if (csiescseq.mode[1] == 'p' && csiescseq.priv) { switch (csiescseq.arg[0]) { - #if SYNC_PATCH case 2026: /* https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 */ ttywrite(su ? "\033[?2026;1$y" : "\033[?2026;2$y", 11, 0); break; - #endif // SYNC_PATCH default: goto unknown; } From e77d5e1b3b98741f2ad697ca62fc7eb7089247c6 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sun, 26 Oct 2025 00:22:53 +0200 Subject: [PATCH 52/67] sync patch: add DECRQM 80 and 8452 for sixel patch ref. #179 --- st.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 9359a54..3f1fcd6 100644 --- a/st.c +++ b/st.c @@ -2451,21 +2451,35 @@ csihandle(void) goto unknown; } break; - #if SYNC_PATCH + #if SYNC_PATCH || SIXEL_PATCH case '$': /* DECRQM -- DEC Request Mode (private) */ if (csiescseq.mode[1] == 'p' && csiescseq.priv) { switch (csiescseq.arg[0]) { + #if SIXEL_PATCH + case 80: + /* Sixel Display Mode */ + ttywrite(IS_SET(MODE_SIXEL_SDM) ? "\033[?80;1$y" + : "\033[?80;2$y", 9, 0); + break; + case 8452: + /* Sixel scrolling leaves cursor to right of graphic */ + ttywrite(IS_SET(MODE_SIXEL_CUR_RT) ? "\033[?8452;1$y" + : "\033[?8452;2$y", 11, 0); + break; + #endif // SIXEL_PATCH + #if SYNC_PATCH case 2026: /* https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 */ ttywrite(su ? "\033[?2026;1$y" : "\033[?2026;2$y", 11, 0); break; + #endif // SYNC_PATCH default: goto unknown; } break; } goto unknown; - #endif // SYNC_PATCH + #endif // SYNC_PATCH | SIXEL_PATCH case 'r': /* DECSTBM -- Set Scrolling Region */ if (csiescseq.priv) { goto unknown; From 37bc089f1d9f3c53ded68d442dac3108b3366426 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 28 Oct 2025 09:16:19 +0000 Subject: [PATCH 53/67] Add selectionbg-alpha patch (#188) --- README.md | 6 ++++++ patches.def.h | 6 ++++++ x.c | 17 +++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/README.md b/README.md index 92f9889..f1b88b8 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: +2025-10-28 - Added the selectionbg-alpha patch + 2025-02-20 - Added the drag-n-drop and open-selected-text patches 2024-05-31 - Added the anygeometry patch @@ -260,6 +262,10 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [right-click-to-plumb](https://st.suckless.org/patches/right_click_to_plumb/) - allows you to right-click on some selected text to send it to the plumbing program of choice + - [selectionbg-alpha](https://st.suckless.org/patches/selectionbg-alpha/) + - allows for the selection to have a transparent background when combined with the alpha + and selection colors patches + - [scrollback](https://st.suckless.org/patches/scrollback/) - allows you scroll back through terminal output using keyboard shortcuts or mousewheel diff --git a/patches.def.h b/patches.def.h index 466b057..691e45f 100644 --- a/patches.def.h +++ b/patches.def.h @@ -380,6 +380,12 @@ */ #define SELECTION_COLORS_PATCH 0 +/* This patch works with selectioncolors and alpha patches to make selection + * background color transparent. + * https://st.suckless.org/patches/selectionbg-alpha/ + */ +#define SELECTIONBG_ALPHA_PATCH 0 + /* This is the single drawable buffer patch as outlined in the FAQ to get images * in w3m to display. While this patch does not break the alpha patch it images * are not shown in w3m if the alpha patch is applied. diff --git a/x.c b/x.c index 627e352..e761c84 100644 --- a/x.c +++ b/x.c @@ -980,6 +980,11 @@ xloadalpha(void) dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * usedAlpha); dc.col[defaultbg].pixel &= 0x00FFFFFF; dc.col[defaultbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24; + #if SELECTION_COLORS_PATCH && SELECTIONBG_ALPHA_PATCH + dc.col[selectionbg].color.alpha = (unsigned short)(0xffff * usedAlpha); + dc.col[selectionbg].pixel &= 0x00FFFFFF; + dc.col[selectionbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24; + #endif // SELECTION_COLORS_PATCH && SELECTIONBG_ALPHA_PATCH } #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH @@ -1041,6 +1046,18 @@ xloadcols(void) dc.col[defaultbg].color.red *= alpha; dc.col[defaultbg].color.green *= alpha; dc.col[defaultbg].color.blue *= alpha; + #if SELECTION_COLORS_PATCH && SELECTIONBG_ALPHA_PATCH + /* set alpha value of selbg color */ + dc.col[selectionbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[selectionbg].pixel &= 0x00FFFFFF; + dc.col[selectionbg].pixel |= (unsigned char)(0xff * alpha) << 24; + dc.col[selectionbg].color.red = + ((unsigned short)(dc.col[selectionbg].color.red * alpha)) & 0xff00; + dc.col[selectionbg].color.green = + ((unsigned short)(dc.col[selectionbg].color.green * alpha)) & 0xff00; + dc.col[selectionbg].color.blue = + ((unsigned short)(dc.col[selectionbg].color.blue * alpha)) & 0xff00; + #endif // SELECTION_COLORS_PATCH && SELECTIONBG_ALPHA_PATCH #endif // ALPHA_PATCH loaded = 1; } From ec1b8b0ac03dce5b502d8538e88c30f99fbd1f1f Mon Sep 17 00:00:00 2001 From: ant Date: Sat, 4 Jan 2025 21:59:53 +0100 Subject: [PATCH 54/67] fontfeature patch --- hb.c | 13 +++++-------- hb.h | 4 ++++ patches.def.h | 6 +++++- x.c | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/hb.c b/hb.c index ae3dcc3..d2edd98 100644 --- a/hb.c +++ b/hb.c @@ -35,13 +35,6 @@ typedef struct { static RuneBuffer hbrunebuffer = { 0, NULL }; static hb_buffer_t *hbbuffer; -/* - * 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 hbcreatebuffer(void) { @@ -125,7 +118,11 @@ hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int star hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); /* Shape the segment. */ - hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + #if FONTFEATURES_PATCH + hb_shape(font, buffer, data->features, data->features_count); + #else + hb_shape(font, buffer, NULL, 0); + #endif /* Get new glyph info. */ hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); diff --git a/hb.h b/hb.h index cb7ea48..3517855 100644 --- a/hb.h +++ b/hb.h @@ -7,6 +7,10 @@ typedef struct { hb_glyph_info_t *glyphs; hb_glyph_position_t *positions; unsigned int count; +#if FONTFEATURES_PATCH + hb_feature_t *features; + int features_count; +#endif // FONTFEATURES_PATCH } HbTransformData; void hbcreatebuffer(void); diff --git a/patches.def.h b/patches.def.h index 691e45f..e2cd638 100644 --- a/patches.def.h +++ b/patches.def.h @@ -249,7 +249,11 @@ * https://github.com/cog1to/st-ligatures * https://st.suckless.org/patches/ligatures/ */ -#define LIGATURES_PATCH 0 +#define LIGATURES_PATCH 1 + +/* This patch add support for custom font features. It depends on the LIGATURES_PATCH patch + */ +#define FONTFEATURES_PATCH 1 /* This patch makes st ignore terminal color attributes by forcing display of the default * foreground and background colors only - making for a monochrome look. Idea ref. diff --git a/x.c b/x.c index e761c84..faae7a4 100644 --- a/x.c +++ b/x.c @@ -1770,6 +1770,26 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x xp = winx, yp = winy + font->ascent; #endif // VERTCENTER_PATCH cluster_xp = xp; cluster_yp = yp; + #if FONTFEATURES_PATCH + { // Get font features + shaped.features = (hb_feature_t *) malloc(sizeof(hb_feature_t) * 128); + FcChar8 *s; + int feature_idx = 0; + while (FcPatternGetString(font->pattern, FC_FONT_FEATURES, feature_idx, &s) == FcResultMatch) { + if (strlen(s) != 4) + die("Invalid font feature tag"); + if (feature_idx >= 128) + die("Too many font features"); + shaped.features[feature_idx].tag = HB_TAG(s[0], s[1], s[2], s[3]); + shaped.features[feature_idx].value = 1; + shaped.features[feature_idx].start = HB_FEATURE_GLOBAL_START; + shaped.features[feature_idx].end = HB_FEATURE_GLOBAL_END; + feature_idx++; + } + shaped.features_count = feature_idx; + } + #endif // FONTFEATURES_PATCH + /* Shape the segment. */ hbtransform(&shaped, font->match, glyphs, 0, len); #endif // LIGATURES_PATCH From b8131450b016732c1cd4199c6b9bb6a21c6e7ef0 Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Wed, 8 Jan 2025 14:05:15 +0100 Subject: [PATCH 55/67] config: increase scroll speed --- config.def.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 7baab30..62b69c1 100644 --- a/config.def.h +++ b/config.def.h @@ -380,8 +380,8 @@ static MouseShortcut mshortcuts[] = { { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, #endif // CLIPBOARD_PATCH #if SCROLLBACK_MOUSE_PATCH - { ShiftMask, Button4, kscrollup, {.i = 1}, 0, S_PRI}, - { ShiftMask, Button5, kscrolldown, {.i = 1}, 0, S_PRI}, + { ShiftMask, Button4, kscrollup, {.i = 4}, 0, S_PRI}, + { ShiftMask, Button5, kscrolldown, {.i = 4}, 0, S_PRI}, #elif UNIVERSCROLL_PATCH { XK_ANY_MOD, Button4, ttysend, {.s = "\033[5;2~"}, 0, S_PRI }, { XK_ANY_MOD, Button5, ttysend, {.s = "\033[6;2~"}, 0, S_PRI }, @@ -390,8 +390,8 @@ static MouseShortcut mshortcuts[] = { { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, #endif // SCROLLBACK_MOUSE_PATCH #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH || REFLOW_PATCH - { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI }, - { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI }, + { XK_ANY_MOD, Button4, kscrollup, {.i = 4}, 0, S_PRI }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 4}, 0, S_PRI }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT }, { XK_ANY_MOD, Button5, ttysend, {.s = "\005"}, 0, S_ALT }, #else From d44ab2a9a276193612908264b67fa5b90b148a06 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:02:31 +0100 Subject: [PATCH 56/67] font default to caskadia --- config.def.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/config.def.h b/config.def.h index 62b69c1..d824981 100644 --- a/config.def.h +++ b/config.def.h @@ -5,13 +5,10 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = "Cascadia Code NF:regular:pixelsize=16:fontfeatures=calt,ss01:antialias=true:autohint=true"; #if FONT2_PATCH /* 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 char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=16:antialias=true:autohint=true" }; #endif // FONT2_PATCH #if BACKGROUND_IMAGE_PATCH From 48defe07d25c9807bdca42569b9eb0bed0c7c907 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:05:02 +0100 Subject: [PATCH 57/67] Add darkman patch a patch to choose between two color themes by executing a command --- config.def.h | 38 ++++++++++++++++++++++++++++++++++++++ patches.def.h | 3 +++ x.c | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index d824981..fcf0487 100644 --- a/config.def.h +++ b/config.def.h @@ -212,6 +212,44 @@ static const char *colorname[] = { "#e5e5e5", /* 259 -> fg */ }; +#if DARKMAN_PATCH +#define colorname_len (sizeof(colorname) / sizeof(char *)) + +enum theme { + THEME_LIGHT, + THEME_DARK, + THEME_NUM, +}; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colornames[THEME_NUM][colorname_len] = { + { }, { + "#1a1a1a", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#f4005f", + "#98e024", + "#fa8419", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#c4c5b5", + "#625e4c", + "#f4005f", + "#98e024", + "#e0d561", + "#9d65ff", + "#f4005f", + "#58d1eb", + "#f6f6ef", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#aaaaaa", /* 256 -> cursor */ + "#555555", /* 257 -> rev cursor*/ + "#000000", /* 258 -> bg */ + "#ffffff", /* 259 -> fg */ +}}; + +#endif // DARKMAN_PATCH + /* * Default colors (colorname index) diff --git a/patches.def.h b/patches.def.h index e2cd638..965d0c4 100644 --- a/patches.def.h +++ b/patches.def.h @@ -255,6 +255,9 @@ */ #define FONTFEATURES_PATCH 1 +#define DARKMAN_PATCH 1 + + /* This patch makes st ignore terminal color attributes by forcing display of the default * foreground and background colors only - making for a monochrome look. Idea ref. * https://www.reddit.com/r/suckless/comments/ixbx6z/how_to_use_black_and_white_only_for_st/ diff --git a/x.c b/x.c index faae7a4..c80e772 100644 --- a/x.c +++ b/x.c @@ -802,10 +802,13 @@ setsel(char *str, Time t) #endif // CLIPBOARD_PATCH } -#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH +#if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH void sigusr1_reload(int sig) { + #if DARKMAN_PATCH + xloadcols(); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH reload_config(sig); #endif // XRESOURCES_RELOAD_PATCH @@ -988,6 +991,28 @@ xloadalpha(void) } #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH +#if DARKMAN_PATCH +void +darkmanThemeChoose() { + FILE *fp; + char path[128]; + + fp = popen("darkman get", "r"); + if (fp == NULL) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else { + /* match the stdout with the theme */ + while (fgets(path, sizeof(path)-1, fp) != NULL) { + if (strcmp(path, "light\n") == 0) { + memcpy(colorname, colornames[0], sizeof(colorname)); + } else if (strcmp(path, "dark\n") == 0) { + memcpy(colorname, colornames[1], sizeof(colorname)); + } + } + } +} +#endif // DARKMAN_PATCH + #if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH void xloadcols(void) @@ -1021,6 +1046,8 @@ xloadcols(void) static int loaded; Color *cp; + darkmanThemeChoose(); + if (loaded) { for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); @@ -4045,9 +4072,12 @@ run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH + #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH || BACKGROUND_IMAGE_PATCH && BACKGROUND_IMAGE_RELOAD_PATCH || DARKMAN_PATCH signal(SIGUSR1, sigusr1_reload); - #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH + #endif // XRESOURCES_RELOAD_PATCH | BACKGROUND_IMAGE_RELOAD_PATCH | DARKMAN_PATCH + #if DARKMAN_PATCH + memcpy(colornames[0], colorname, sizeof(colorname)); + #endif // DARKMAN_PATCH #if XRESOURCES_PATCH if (!(xw.dpy = XOpenDisplay(NULL))) die("Can't open display\n"); From 84a920d545f2cc465653ab52cecc61931564b26e Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:07:50 +0100 Subject: [PATCH 58/67] change default colors --- config.def.h | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/config.def.h b/config.def.h index fcf0487..bdaac0a 100644 --- a/config.def.h +++ b/config.def.h @@ -182,34 +182,29 @@ char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; #endif // DRAG_AND_DROP_PATCH /* 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", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#add8e6", /* 256 -> cursor */ - "#555555", /* 257 -> rev cursor*/ - "#000000", /* 258 -> bg */ - "#e5e5e5", /* 259 -> fg */ +static char *colorname[] = { + "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#d3423e", + "#2aa298", + "#daaa01", + "#4876d6", + "#403f53", + "#08916a", + "#7a8181", + "#7a8181", + "#f76e6e", + "#49d0c5", + "#dac26b", + "#5ca7e4", + "#697098", + "#00c990", + "#989fb1", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#403f53", /* 256 -> cursor */ + "#f2f2f2", /* 257 -> rev cursor*/ + "#ffffff", /* 258 -> bg */ + "#403f53", /* 259 -> fg */ }; #if DARKMAN_PATCH From 1ea9ec607ba124b8bf33040e956fc89166dd7ecc Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:09:02 +0100 Subject: [PATCH 59/67] change keys to keyboard select and zoom --- config.def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index bdaac0a..44813c9 100644 --- a/config.def.h +++ b/config.def.h @@ -452,8 +452,8 @@ 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} }, + { MODKEY | ControlMask, XK_comma, zoom, {.f = +1} }, + { MODKEY | ControlMask, XK_semicolon, zoom, {.f = -1} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, @@ -497,7 +497,7 @@ static Shortcut shortcuts[] = { #endif // EXTERNALPIPEIN_PATCH #endif // EXTERNALPIPE_PATCH #if KEYBOARDSELECT_PATCH - { TERMMOD, XK_Escape, keyboard_select, { 0 } }, + { TERMMOD, XK_space, keyboard_select, { 0 } }, #endif // KEYBOARDSELECT_PATCH #if KEYBOARDSELECT_PATCH && REFLOW_PATCH { TERMMOD, XK_F, searchforward, { 0 } }, From d0b32e19c60ad6f72b42119000b497b65dc12ec3 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:11:37 +0100 Subject: [PATCH 60/67] enable patches I want --- config.mk | 12 ++++++------ patches.def.h | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/config.mk b/config.mk index a3b94cd..fc54978 100644 --- a/config.mk +++ b/config.mk @@ -21,14 +21,14 @@ PKG_CONFIG = pkg-config #XCURSOR = `$(PKG_CONFIG) --libs xcursor` # Uncomment the lines below for the ligatures patch / LIGATURES_PATCH -#LIGATURES_C = hb.c -#LIGATURES_H = hb.h -#LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` -#LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` +LIGATURES_C = hb.c +LIGATURES_H = hb.h +LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` +LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` # Uncomment this for the SIXEL patch / SIXEL_PATCH -#SIXEL_C = sixel.c sixel_hls.c -#SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` +SIXEL_C = sixel.c sixel_hls.c +SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` # Uncomment for the netwmicon patch / NETWMICON_PATCH #NETWMICON_LIBS = `$(PKG_CONFIG) --libs gdlib` diff --git a/patches.def.h b/patches.def.h index 965d0c4..8404e4f 100644 --- a/patches.def.h +++ b/patches.def.h @@ -70,12 +70,12 @@ * This patch makes bold text rendered simply as bold, leaving the color unaffected. * https://st.suckless.org/patches/bold-is-not-bright/ */ -#define BOLD_IS_NOT_BRIGHT_PATCH 0 +#define BOLD_IS_NOT_BRIGHT_PATCH 1 /* This patch adds custom rendering of lines/blocks/braille characters for gapless alignment. * https://st.suckless.org/patches/boxdraw/ */ -#define BOXDRAW_PATCH 0 +#define BOXDRAW_PATCH 1 /* By default st only sets PRIMARY on selection. * This patch makes st set CLIPBOARD on selection. @@ -192,7 +192,7 @@ * that are available to GUI applications. * https://st.suckless.org/patches/fix_keyboard_input/ */ -#define FIXKEYBOARDINPUT_PATCH 0 +#define FIXKEYBOARDINPUT_PATCH 1 /* This patch allows you to add spare font besides the default. Some glyphs can be not present in * the default font. For this glyphs st uses font-config and try to find them in font cache first. @@ -200,7 +200,7 @@ * So they will be used first for glyphs that are absent in the default font. * https://st.suckless.org/patches/font2/ */ -#define FONT2_PATCH 0 +#define FONT2_PATCH 1 /* This patch adds the ability to toggle st into fullscreen mode. * Two key bindings are defined: F11 which is typical with other applications and Alt+Enter @@ -239,7 +239,7 @@ * * https://st.suckless.org/patches/keyboard_select/ */ -#define KEYBOARDSELECT_PATCH 0 +#define KEYBOARDSELECT_PATCH 1 /* This patch adds support for drawing ligatures using the Harfbuzz library to transform * original text of a single line to a list of glyphs with ligatures included. @@ -302,7 +302,7 @@ * same CWD (current working directory) as the original st instance. * https://st.suckless.org/patches/newterm/ */ -#define NEWTERM_PATCH 0 +#define NEWTERM_PATCH 1 /* This patch will set the _MOTIF_WM_HINTS property for the st window which, if the window manager * respects it, will show the st window without window decorations. @@ -327,7 +327,7 @@ * * https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/ */ -#define OPENURLONCLICK_PATCH 0 +#define OPENURLONCLICK_PATCH 1 /* This patch allows st to fetch the current working directory through the OSC 7 escape * sequence emitted by shells. Must be used with newterm patch. @@ -349,7 +349,7 @@ * Text wraps when the terminal window is made smaller. * Comes with scrollback. */ -#define REFLOW_PATCH 0 +#define REFLOW_PATCH 1 /* This patch allows you to specify a border that is relative in size to the width of a cell * in the terminal. @@ -366,19 +366,19 @@ /* Scroll back through terminal output using Shift+{PageUp, PageDown}. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_PATCH 0 +#define SCROLLBACK_PATCH 1 /* Scroll back through terminal output using Shift+MouseWheel. * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_PATCH 0 +#define SCROLLBACK_MOUSE_PATCH 1 /* Scroll back through terminal output using mouse wheel (when not in MODE_ALTSCREEN). * This variant depends on SCROLLBACK_PATCH being enabled. * https://st.suckless.org/patches/scrollback/ */ -#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 0 +#define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 1 /* This patch adds the two color-settings selectionfg and selectionbg to config.def.h. * Those define the fore- and background colors which are used when text on the screen is selected @@ -412,7 +412,7 @@ * * https://gist.github.com/saitoha/70e0fdf22e3e8f63ce937c7f7da71809 */ -#define SIXEL_PATCH 0 +#define SIXEL_PATCH 1 /* This patch allows clients to embed into the st window and is useful if you tend to * start X applications from the terminal. For example: @@ -472,7 +472,7 @@ * * https://st.suckless.org/patches/undercurl/ */ -#define UNDERCURL_PATCH 0 +#define UNDERCURL_PATCH 1 /* Allows mouse scroll without modifier keys for regardless of alt screen using the external * scroll program. From 7415d93cf2c0f7068bf72fbc5d2654b33fc60e63 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 12 Jan 2025 16:15:49 +0100 Subject: [PATCH 61/67] Add a nix flake --- default.nix | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ flake.lock | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..0450b6c --- /dev/null +++ b/default.nix @@ -0,0 +1,56 @@ +{ lib +, stdenv +, pkg-config +, fontconfig +, freetype +, libX11 +, libXft +, harfbuzz +, gd +, glib +, ncurses +, writeText +, conf ? null +, patches ? [] +, extraLibs ? [] +, nixosTests +, imlib2 +}: + +stdenv.mkDerivation rec { + pname = "st"; + version = "0.8.5"; + + src = ./.; + inherit patches; + + configFile = + lib.optionalString (conf != null) (writeText "config.def.h" conf); + + postPatch = lib.optionalString (conf != null) "cp ${configFile} config.def.h" + + lib.optionalString stdenv.isDarwin '' + substituteInPlace config.mk --replace "-lrt" "" + ''; + + strictDeps = true; + + makeFlags = [ "PKG_CONFIG=${stdenv.cc.targetPrefix}pkg-config" ]; + + nativeBuildInputs = [ pkg-config ncurses fontconfig freetype ]; + buildInputs = [ libX11 libXft harfbuzz gd glib imlib2 ] ++ extraLibs; + + preInstall = '' + export TERMINFO=$out/share/terminfo + ''; + + installFlags = [ "PREFIX=$(out)" ]; + + passthru.tests.test = nixosTests.terminal-emulators.st; + + meta = with lib; { + description = "st terminal"; + license = licenses.mit; + maintainers = with maintainers; [ sioodmy ]; + platforms = platforms.unix; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..586a00c --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1736549401, + "narHash": "sha256-ibkQrMHxF/7TqAYcQE+tOnIsSEzXmMegzyBWza6uHKM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1dab772dd4a68a7bba5d9460685547ff8e17d899", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a30e80d --- /dev/null +++ b/flake.nix @@ -0,0 +1,41 @@ +{ + description = "st terminal"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let pkgs = nixpkgs.legacyPackages.${system}; + in rec { + packages = flake-utils.lib.flattenTree { + st = pkgs.callPackage ./default.nix { }; + }; + defaultPackage = packages.st; + apps.st = flake-utils.lib.mkApp { + drv = packages.st; + exePath = "/bin/st"; + }; + apps.default = apps.st; + defaultApp = apps.st; + devShell = pkgs.mkShell rec { + name = "st"; + packages = with pkgs; [ + pkg-config + xorg.libX11 + xorg.libXft + fontconfig + harfbuzz.dev + imlib2 + gd + glib + # ccls + # bear + # lldb + # gdb + # valgrind + ]; + }; + + }); +} From a9d0d20213189d44902332a15807aee6f05d163f Mon Sep 17 00:00:00 2001 From: ant Date: Wed, 21 May 2025 20:49:42 +0200 Subject: [PATCH 62/67] enable boxdraw --- config.def.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 44813c9..bf02b2d 100644 --- a/config.def.h +++ b/config.def.h @@ -127,11 +127,11 @@ int hidecursor = 1; * 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; +const int boxdraw = 1; +const int boxdraw_bold = 1; /* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 0; +const int boxdraw_braille = 1; #endif // BOXDRAW_PATCH /* From 1cc56c485645421db8202da52eb418cf577f3c49 Mon Sep 17 00:00:00 2001 From: ant Date: Wed, 21 May 2025 20:41:36 +0200 Subject: [PATCH 63/67] Enable alpha patch --- patches.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches.def.h b/patches.def.h index 8404e4f..e961d95 100644 --- a/patches.def.h +++ b/patches.def.h @@ -14,7 +14,7 @@ * when including this patch. * https://st.suckless.org/patches/alpha/ */ -#define ALPHA_PATCH 0 +#define ALPHA_PATCH 1 /* The alpha focus highlight patch allows the user to specify two distinct opacity values or * background colors in order to easily differentiate between focused and unfocused terminal From ae3a9baf0dba8b24e9b21032b373c8672482118a Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Mon, 2 Jun 2025 09:17:07 +0200 Subject: [PATCH 64/67] decrease default font size --- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index bf02b2d..89b6319 100644 --- a/config.def.h +++ b/config.def.h @@ -5,10 +5,10 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Cascadia Code NF:regular:pixelsize=16:fontfeatures=calt,ss01:antialias=true:autohint=true"; +static char *font = "Cascadia Code NF:regular:pixelsize=13.5:fontfeatures=calt,ss01:antialias=true:autohint=true"; #if FONT2_PATCH /* Spare fonts */ -static char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=16:antialias=true:autohint=true" }; +static char *font2[] = { "CaskaydiaCove Nerd Font:pixelsize=13.5:antialias=true:autohint=true" }; #endif // FONT2_PATCH #if BACKGROUND_IMAGE_PATCH From f8b47f894b7144971b38064976b2088510088749 Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Fri, 18 Jul 2025 00:22:52 +0200 Subject: [PATCH 65/67] add keybinnds to scroll --- config.def.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.def.h b/config.def.h index 89b6319..6b3b9c9 100644 --- a/config.def.h +++ b/config.def.h @@ -472,6 +472,10 @@ static Shortcut shortcuts[] = { #if SCROLLBACK_PATCH || REFLOW_PATCH { ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_U, kscrollup, {.i = -1}, S_PRI }, + { TERMMOD, XK_D, kscrolldown, {.i = -1}, S_PRI }, + { TERMMOD, XK_K, kscrollup, {.i = 4}, S_PRI }, + { TERMMOD, XK_J, kscrolldown, {.i = 4}, S_PRI }, #endif // SCROLLBACK_PATCH || REFLOW_PATCH #if CLIPBOARD_PATCH { TERMMOD, XK_Y, clippaste, {.i = 0} }, From 33209c6746ed03bc56cea542bb0619fcb840bd8a Mon Sep 17 00:00:00 2001 From: Antoine Vaure Date: Fri, 3 Oct 2025 13:21:56 +0200 Subject: [PATCH 66/67] change colors for light theme --- config.def.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/config.def.h b/config.def.h index 6b3b9c9..c91e5bd 100644 --- a/config.def.h +++ b/config.def.h @@ -162,7 +162,7 @@ unsigned int tabspaces = 8; #if ALPHA_PATCH /* bg opacity */ -float alpha = 0.8; +float alpha = 0.9; #if ALPHA_GRADIENT_PATCH float grad_alpha = 0.54; //alpha value that'll change float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha @@ -183,28 +183,28 @@ char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; /* Terminal colors (16 first used in escape sequence) */ static char *colorname[] = { - "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ - "#d3423e", - "#2aa298", - "#daaa01", - "#4876d6", - "#403f53", - "#08916a", - "#7a8181", - "#7a8181", - "#f76e6e", - "#49d0c5", - "#dac26b", - "#5ca7e4", - "#697098", - "#00c990", - "#989fb1", + "#000000", + "#ff3333", + "#86b200", + "#f19618", + "#41a6d9", + "#f07078", + "#4cbe99", + "#ffffff", + "#323232", + "#ff6565", + "#b8e532", + "#ffc849", + "#73d7ff", + "#ffa3aa", + "#7ff0cb", + "#ffffff", [255] = 0, /* more colors can be added after 255 to use with DefaultXX */ "#403f53", /* 256 -> cursor */ - "#f2f2f2", /* 257 -> rev cursor*/ - "#ffffff", /* 258 -> bg */ - "#403f53", /* 259 -> fg */ + "#f0ede4", /* 257 -> rev cursor*/ + "#fafafa", /* 258 -> bg */ + "#5b6673", /* 259 -> fg */ }; #if DARKMAN_PATCH From b5498bad114f8fd3c5bc9eb54a9727ae3257f1d5 Mon Sep 17 00:00:00 2001 From: ant Date: Sun, 30 Nov 2025 15:17:14 +0100 Subject: [PATCH 67/67] Revert "change colors for light theme" This reverts commit 042af42400e57abd9d1ad50f6094ea09b2679b2d. --- config.def.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/config.def.h b/config.def.h index c91e5bd..6b3b9c9 100644 --- a/config.def.h +++ b/config.def.h @@ -162,7 +162,7 @@ unsigned int tabspaces = 8; #if ALPHA_PATCH /* bg opacity */ -float alpha = 0.9; +float alpha = 0.8; #if ALPHA_GRADIENT_PATCH float grad_alpha = 0.54; //alpha value that'll change float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha @@ -183,28 +183,28 @@ char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~"; /* Terminal colors (16 first used in escape sequence) */ static char *colorname[] = { - "#000000", - "#ff3333", - "#86b200", - "#f19618", - "#41a6d9", - "#f07078", - "#4cbe99", - "#ffffff", - "#323232", - "#ff6565", - "#b8e532", - "#ffc849", - "#73d7ff", - "#ffa3aa", - "#7ff0cb", - "#ffffff", + "#011627", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#d3423e", + "#2aa298", + "#daaa01", + "#4876d6", + "#403f53", + "#08916a", + "#7a8181", + "#7a8181", + "#f76e6e", + "#49d0c5", + "#dac26b", + "#5ca7e4", + "#697098", + "#00c990", + "#989fb1", [255] = 0, /* more colors can be added after 255 to use with DefaultXX */ "#403f53", /* 256 -> cursor */ - "#f0ede4", /* 257 -> rev cursor*/ - "#fafafa", /* 258 -> bg */ - "#5b6673", /* 259 -> fg */ + "#f2f2f2", /* 257 -> rev cursor*/ + "#ffffff", /* 258 -> bg */ + "#403f53", /* 259 -> fg */ }; #if DARKMAN_PATCH