Compare commits

...

17 commits

Author SHA1 Message Date
ant
df11aae8c3 Revert "change colors for light theme"
This reverts commit 042af42400.
2026-02-05 10:08:37 +01:00
Antoine Vaure
87c6c244c4 change colors for light theme 2026-02-05 10:08:37 +01:00
Antoine Vaure
659b803a40 add keybinnds to scroll 2026-02-05 10:08:37 +01:00
Antoine Vaure
ccaedf3fe9 decrease default font size 2026-02-05 10:08:37 +01:00
ant
4194b515ee Enable alpha patch 2026-02-05 10:08:37 +01:00
ant
568f306b14 enable boxdraw 2026-02-05 10:08:37 +01:00
ant
bedf74d2ad Add a nix flake 2026-02-05 10:08:37 +01:00
ant
653e567b29 enable patches I want 2026-02-05 10:08:37 +01:00
ant
4d18a5e104 change keys to keyboard select and zoom 2026-02-05 10:08:37 +01:00
ant
38dcc0e866 change default colors 2026-02-05 10:08:37 +01:00
ant
d17eac914f Add darkman patch
a patch to choose between two color themes by executing a command
2026-02-05 10:08:37 +01:00
ant
81a9b451e9 font default to caskadia 2026-02-05 10:08:37 +01:00
Antoine Vaure
8ced61c5e3 config: increase scroll speed 2026-02-05 10:08:37 +01:00
ant
1252a3d79d fontfeature patch 2026-02-05 10:08:37 +01:00
step
9edb8d86fb
Add xresources-xdefaults patch (#195)
* Add xresources-xdefaults patch

This patch adds the ability to configure st via Xdefaults, in addition
to Xresources, like the rxvt-unicode terminal. At startup, st will read
and apply the system and user's local Xdefault files, the XServer's
Xresources, and the screen and per-host Xdefaults. This patch depends
on XRESOURCES_PATCH and is compatible with XRESOURCES_RELOAD_PATCH.

I used the following script to stress test this patch. You can also use
the script to demo what the patch does. To be simple, it only tests
the user's .Xdefaults and .Xresources files, without throwing in the
system and per-host files. The script cycles st's background through
red, green and blue indefinitely.

BACKUP YOUR ~/.Xdefaults and ~/.Xresources FILES BEFORE TESTING.

```sh

unset pid
if [ -n "$1" ]; then
	pid=$1
elif pid=$(pgrep -f ^valgrind) && [ -n "$pid" ]; then
	:
else
	pid=$(pgrep -n ^st$)
fi
if [ -z "$pid" -o "x$pid" = "x-h" -o "x$pid" = "x--help" ]; then
	echo "usage: $0 [pid]
	If pid is omitted valgrind's is used falling back to st's.
	---------------------------------------------------------------
	BACKUP YOUR ~/.Xdefaults and ~/.Xresources FILES BEFORE TESTING
	---------------------------------------------------------------"
	exit 0
fi
printf "Attaching pid=%d\n\t%s\n" "$pid" "$(ps -h -ocmd "$pid")" >&2

seconds=0.25 red='#800000' green='#008000' blue='#000080'
echo "St.background: $red" >> $HOME/.Xdefaults
while true; do
	sed -i "\$s/$red/$green/" $HOME/.Xdefaults
	kill -USR1 $pid
	sleep $seconds
	sed -i "\$s/$green/$red/" $HOME/.Xdefaults
	kill -USR1 $pid
	sleep $seconds

	echo "St.background: $blue" >> $HOME/.Xresources
	xrdb -load $HOME/.Xresources
	kill -USR1 $pid
	sleep $seconds
	sed -i '$d' $HOME/.Xresources
	xrdb -load $HOME/.Xresources
	kill -USR1 $pid
	sleep $seconds
done
```

* Minor refactoring and freeing / destroying the Xrm database with XrmDestroyDatabase

---------

Co-authored-by: Bakkeby <bakkeby@gmail.com>
2026-01-30 08:59:28 +01:00
Bakkeby
b8056cbf24 xresources: destroy Xrm database after resource load
st would hold on to a XrmDatabase reference for the lifetime of the
program due to how in resource_load the ret.addr of the database
would be referenced directly. This also meant that for every reload
st would be leaking another XrmDatabase reference.

This has been partially worked around by applying a strdup to make
a copy of the string in order to allow for the XrmDatabase to be
freed / destroyed. Consequently the char arrays / strings still
leak on reload.

We could pass *sdst to free beforehand, but that will only work if
that reference is guaranteed to be on the heap.
2026-01-29 21:28:16 +01:00
veltza
490d2440da
sixel: fix hls-to-rgb and color count issues (#185)
This fixes the following sixel issues:

- The HLS to RGB color conversion is broken.
  Ref. d4ade1fe3c

- Not enough color registers have been allocated for 1024 colors.
  Ref. 97f93e8436
2026-01-15 11:11:04 +01:00
15 changed files with 470 additions and 96 deletions

View file

@ -15,6 +15,8 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog:
2026-01-08 - Added the xresources-xdefaults patch
2025-10-28 - Added the selectionbg-alpha patch
2025-02-20 - Added the drag-n-drop and open-selected-text patches
@ -340,3 +342,6 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
- [xresources](https://st.suckless.org/patches/xresources/)
- adds the ability to configure st via Xresources
- during startup, st will read and apply the resources named in the resources[] array in config.h
- xresources-xdefaults
- allows .Xdefaults to be read as well in addition to the RESOURCE_MANAGER property on the root window

View file

@ -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=13.5: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=13.5:antialias=true:autohint=true" };
#endif // FONT2_PATCH
#if BACKGROUND_IMAGE_PATCH
@ -130,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
/*
@ -185,36 +182,69 @@ 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
#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)
@ -380,8 +410,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 +420,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
@ -422,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} },
@ -442,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} },
@ -467,7 +501,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 } },

View file

@ -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`

56
default.nix Normal file
View file

@ -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;
};
}

61
flake.lock generated Normal file
View file

@ -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
}

41
flake.nix Normal file
View file

@ -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
];
};
});
}

13
hb.c
View file

@ -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);

4
hb.h
View file

@ -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);

View file

@ -22,7 +22,8 @@ resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
switch (rtype) {
case STRING:
*sdst = ret.addr;
/* Note: this leaks memory */
*sdst = strdup(ret.addr);
break;
case INTEGER:
*idst = strtoul(ret.addr, NULL, 10);
@ -34,6 +35,102 @@ resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
return 0;
}
#if XRESOURCES_XDEFAULTS_PATCH
/* Returns an XrmDatabase that needs to be freed by the caller. */
static XrmDatabase
get_resources(Display *dpy)
{
/*******************************************************************/
/* Adapted from rxvt-unicode-9.31 rxvttoolkit.C get_resources() */
/*******************************************************************/
char *homedir = getenv("HOME");
char fname[1024];
char *displayResource, *xe;
XrmDatabase rdb1;
XrmDatabase database = XrmGetStringDatabase("");
/* For ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20 */
/* 6. System wide per application default file. */
/* Add in $XAPPLRESDIR/St only; not bothering with XUSERFILESEARCHPATH */
if ((xe = getenv("XAPPLRESDIR")) || (xe = "/etc/X11/app-defaults"))
{
snprintf(fname, sizeof(fname), "%s/%s", xe, "St");
if ((rdb1 = XrmGetFileDatabase(fname)))
XrmMergeDatabases(rdb1, &database);
}
/* 5. User's per application default file. None. */
/* 4. User's defaults file. */
if (homedir)
{
snprintf(fname, sizeof(fname), "%s/.Xdefaults", homedir);
if ((rdb1 = XrmGetFileDatabase(fname)))
XrmMergeDatabases(rdb1, &database);
}
/* Get any Xserver Resources (xrdb). */
displayResource = XResourceManagerString(dpy);
if (displayResource)
{
if ((rdb1 = XrmGetStringDatabase(displayResource)))
XrmMergeDatabases(rdb1, &database);
}
/* Get screen specific resources. */
displayResource = XScreenResourceString(ScreenOfDisplay(dpy, DefaultScreen(dpy)));
if (displayResource)
{
if ((rdb1 = XrmGetStringDatabase(displayResource)))
XrmMergeDatabases(rdb1, &database);
XFree(displayResource);
}
/* 3. User's per host defaults file. */
/* Add in XENVIRONMENT file */
if ((xe = getenv("XENVIRONMENT")) && (rdb1 = XrmGetFileDatabase(xe)))
XrmMergeDatabases(rdb1, &database);
else if (homedir)
{
struct utsname un;
if (!uname(&un))
{
snprintf(fname, sizeof(fname), "%s/.Xdefaults-%s", homedir, un.nodename);
if ((rdb1 = XrmGetFileDatabase(fname)))
XrmMergeDatabases(rdb1, &database);
}
}
return database;
}
void
config_init(Display *dpy)
{
XrmDatabase db;
ResourcePref *p;
XrmInitialize();
db = get_resources(dpy);
for (p = resources; p < resources + LEN(resources); p++)
resource_load(db, p->name, p->type, p->dst);
XrmDestroyDatabase(db);
}
#else // !XRESOURCES_XDEFAULTS_PATCH
void
config_init(Display *dpy)
{
@ -42,14 +139,21 @@ config_init(Display *dpy)
ResourcePref *p;
XrmInitialize();
resm = XResourceManagerString(dpy);
if (!resm)
return;
db = XrmGetStringDatabase(resm);
if (!db)
return;
for (p = resources; p < resources + LEN(resources); p++)
resource_load(db, p->name, p->type, p->dst);
XrmDestroyDatabase(db);
}
#endif // XRESOURCES_XDEFAULTS_PATCH
#if XRESOURCES_RELOAD_PATCH
void

View file

@ -1,4 +1,7 @@
#include <X11/Xresource.h>
#if XRESOURCES_XDEFAULTS_PATCH
#include <sys/utsname.h>
#endif // XRESOURCES_XDEFAULTS_PATCH
/* Xresources preferences */
enum resource_type {

View file

@ -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
@ -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.
@ -249,7 +249,14 @@
* 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
#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.
@ -295,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.
@ -320,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.
@ -342,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.
@ -359,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
@ -405,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:
@ -465,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.
@ -535,3 +542,10 @@
* Depends on the XRESOURCES_PATCH.
*/
#define XRESOURCES_RELOAD_PATCH 0
/* This patch adds the ability to configure st via Xdefaults, in addition to Xresources,
* like the rxvt-unicode terminal. At startup, st will read and apply the system and user's
* local Xdefault files, the XServer's Xresources, and the screen and per-host Xdefaults.
* This patch depends on XRESOURCES_PATCH and is compatible with XRESOURCES_RELOAD_PATCH.
*/
#define XRESOURCES_XDEFAULTS_PATCH 0

View file

@ -100,9 +100,13 @@ set_default_color(sixel_image_t *image)
image->palette[n++] = SIXEL_RGB(i * 11, i * 11, i * 11);
}
/* sixels rarely use more than 256 colors and if they do, they use a custom
* palette, so we don't need to initialize these colors */
/*
for (; n < DECSIXEL_PALETTE_MAX; n++) {
image->palette[n] = SIXEL_RGB(255, 255, 255);
}
*/
return (0);
}
@ -610,11 +614,12 @@ sixel_parser_parse(sixel_state_t *st, const unsigned char *p, size_t len)
st->param = 0;
if (st->nparams > 0) {
st->color_index = 1 + st->params[0]; /* offset 1(background color) added */
st->color_index = st->params[0];
if (st->color_index < 0)
st->color_index = 0;
else if (st->color_index >= DECSIXEL_PALETTE_MAX)
st->color_index = DECSIXEL_PALETTE_MAX - 1;
st->color_index++; /* offset by 1 (background) */
}
if (st->nparams > 4) {

View file

@ -14,7 +14,7 @@ typedef struct sixel_image_buffer {
sixel_color_no_t *data;
int width;
int height;
sixel_color_t palette[DECSIXEL_PALETTE_MAX];
sixel_color_t palette[DECSIXEL_PALETTE_MAX + 1];
sixel_color_no_t ncolors;
int palette_modified;
int use_private_register;

View file

@ -30,20 +30,18 @@
// sale, use or other dealings in this Software without prior written
// authorization.
#define SIXEL_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16) + (255 << 24))
#define SIXEL_RGB(r, g, b) ((255 << 24) + ((r) << 16) + ((g) << 8) + (b))
int
hls_to_rgb(int hue, int lum, int sat)
{
double hs = (hue + 240) % 360;
double hv = hs / 360.0;
double lv = lum / 100.0;
double sv = sat / 100.0;
double c, x, m, c2;
double r1, g1, b1;
int r, g, b;
int hpi;
int r, g, b, hs;
hue = (hue + 240) % 360;
if (sat == 0) {
r = g = b = lum * 255 / 100;
return SIXEL_RGB(r, g, b);
@ -52,12 +50,14 @@ hls_to_rgb(int hue, int lum, int sat)
if ((c2 = ((2.0 * lv) - 1.0)) < 0.0) {
c2 = -c2;
}
if ((hs = (hue % 120) - 60) < 0) {
hs = -hs;
}
c = (1.0 - c2) * sv;
hpi = (int) (hv * 6.0);
x = (hpi & 1) ? c : 0.0;
x = ((60 - hs) / 60.0) * c;
m = lv - 0.5 * c;
switch (hpi) {
switch (hue / 60) {
case 0:
r1 = c;
g1 = x;
@ -92,24 +92,24 @@ hls_to_rgb(int hue, int lum, int sat)
return SIXEL_RGB(255, 255, 255);
}
r = (int) ((r1 + m) * 100.0 + 0.5);
g = (int) ((g1 + m) * 100.0 + 0.5);
b = (int) ((b1 + m) * 100.0 + 0.5);
r = (int) ((r1 + m) * 255.0 + 0.5);
g = (int) ((g1 + m) * 255.0 + 0.5);
b = (int) ((b1 + m) * 255.0 + 0.5);
if (r < 0) {
r = 0;
} else if (r > 100) {
r = 100;
} else if (r > 255) {
r = 255;
}
if (g < 0) {
g = 0;
} else if (g > 100) {
g = 100;
} else if (g > 255) {
g = 255;
}
if (b < 0) {
b = 0;
} else if (b > 100) {
b = 100;
} else if (b > 255) {
b = 255;
}
return SIXEL_RGB(r * 255 / 100, g * 255 / 100, b * 255 / 100);
return SIXEL_RGB(r, g, b);
}

56
x.c
View file

@ -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);
@ -1770,6 +1797,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
@ -4025,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");