~kris/suckless

st

c9bda1de1f3f94ba507fa0eacc96d6a4f338637f — siduck76 5 years ago 9f02112
re-add many patches , bump to 0.8.4 | This isnt based on luke smiths build :D
14 files changed, 1050 insertions(+), 266 deletions(-)

A Makefile.orig
M README.md
M config.def.h
A config.h.orig
M config.mk
A config.mk.orig
A hb.c.orig
M st.c
M st.c.orig
A st.h.orig
M st.info
M x.c
M x.c.orig
M xresources
A Makefile.orig => Makefile.orig +65 -0
@@ 0,0 1,65 @@
# st - simple terminal
# See LICENSE file for copyright and license details.
.POSIX:

include config.mk

SRC = st.c x.c boxdraw.c hb.c
OBJ = $(SRC:.c=.o)

all: options st

options:
	@echo st build options:
	@echo "CFLAGS  = $(STCFLAGS)"
	@echo "LDFLAGS = $(STLDFLAGS)"
	@echo "CC      = $(CC)"

config.h:
	cp config.def.h config.h

.c.o:
	$(CC) $(STCFLAGS) -c $<

st.o: config.h st.h win.h
x.o: arg.h config.h st.h win.h hb.h
hb.o: st.h
boxdraw.o: config.h st.h boxdraw_data.h

$(OBJ): config.h config.mk

st: $(OBJ)
	$(CC) -o $@ $(OBJ) $(STLDFLAGS)

clean:
	rm -f st $(OBJ) st-$(VERSION).tar.gz *.o *.orig *.rej

dist: clean
	mkdir -p st-$(VERSION)
	cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\
		config.def.h st.info st.1 arg.h st.h win.h $(SRC)\
		st-$(VERSION)
	tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz
	rm -rf st-$(VERSION)

install: st
	mkdir -p $(DESTDIR)$(PREFIX)/bin
	cp -f st $(DESTDIR)$(PREFIX)/bin
	cp -f st-copyout $(DESTDIR)$(PREFIX)/bin
	cp -f st-urlhandler $(DESTDIR)$(PREFIX)/bin
	chmod 755 $(DESTDIR)$(PREFIX)/bin/st
	chmod 755 $(DESTDIR)$(PREFIX)/bin/st-copyout
	chmod 755 $(DESTDIR)$(PREFIX)/bin/st-urlhandler
	mkdir -p $(DESTDIR)$(MANPREFIX)/man1
	sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1
	chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1
	tic -sx st.info
	@echo Please see the README file regarding the terminfo entry of st.

uninstall:
	rm -f $(DESTDIR)$(PREFIX)/bin/st
	rm -f $(DESTDIR)$(PREFIX)/bin/st-copyout
	rm -f $(DESTDIR)$(PREFIX)/bin/st-urlhandler
	rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1

.PHONY: all options clean dist install uninstall

M README.md => README.md +1 -1
@@ 1,6 1,6 @@
# st (Suckless Terminal)

This is a custom suckless st build (credits to lukesmith's build as this is based on it) and I've added some additional patches like newterm , rightclick paste , desktop entry ,sixel, live-reload xresources , dynamic cursor etc!.
This is a custom suckless st build and I've added some additional patches like newterm , rightclick paste , desktop entry ,sixel, live-reload xresources , dynamic cursor etc!.

## Patches:


M config.def.h => config.def.h +2 -4
@@ 6,9 6,7 @@
 * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
 */
static char *font = "JetBrainsMono Nerd Font :pixelsize=15:antialias=true:autohint=true";
static char *font2[] = { "Iosevka Nerd Font :pixelsize=15:antialias=true:autohint=true" };
//static char *font2[] = { "blobmoji :pixelsize=15:antialias=true:autohint=true" }; enable this if u have libxft-bgra and blobmoji font!

static char *font2[] = { "JetBrainsMono Nerd Font :pixelsize=15:antialias=true:autohint=true" };
static int borderpx = 0;

/*


@@ 224,7 222,7 @@ ResourcePref resources[] = {
 * Internal mouse shortcuts.
 * Beware that overloading Button1 will disable the selection.
 */
const unsigned int mousescrollincrement = 9;
const unsigned int mousescrollincrement = 3;
static MouseShortcut mshortcuts[] = {
  /* button               mask            string */
  { Button4,              XK_NO_MOD,      "\031" },

A config.h.orig => config.h.orig +564 -0
@@ 0,0 1,564 @@
/* See LICENSE file for copyright and license details. */

/*
 * appearance
 *
 * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
 */
static char *font = "JetBrainsMono Nerd Font :pixelsize=15:antialias=true:autohint=true";
static char *font2[] = { "JetBrainsMono Nerd Font Mono:pixelsize=15:antialias=true:autohint=true" };
static int borderpx = 0;

/*
 * What program is execed by st depends of these precedence rules:
 * 1: program passed with -e
 * 2: utmp option
 * 3: SHELL environment variable
 * 4: value of shell in /etc/passwd
 * 5: value of shell in config.h
 */
static char *shell = "/bin/sh";
char *utmp = NULL;
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";

/* identification sequence returned in DA and DECID */
char *vtiden = "\033[?6c";

/* Kerning / character bounding-box multipliers */
static float cwscale = 1.0;
static float chscale = 1.0;

/*
 * word delimiter string
 *
 * More advanced example: L" `'\"()[]{}"
 */
wchar_t *worddelimiters = L" ";

/* selection timeouts (in milliseconds) */
static unsigned int doubleclicktimeout = 300;
static unsigned int tripleclicktimeout = 600;

/* alt screens */
int allowaltscreen = 1;

/*
 * draw latency range in ms - from new content/keypress/etc until drawing.
 * within this range, st draws when content stops arriving (idle). mostly it's
 * near minlatency, but it waits longer for slow updates to avoid partial draw.
 * low minlatency will tear/flicker more, as it can "detect" idle too early.
 */
static double minlatency = 8;
static double maxlatency = 33;

/*
 * blinking timeout (set to 0 to disable blinking) for the terminal blinking
 * attribute.
 */
static unsigned int blinktimeout = 800;

/*
 * interval (in milliseconds) between each successive call to ximspot. This
 * improves terminal performance while not reducing functionality to those
 * whom need XIM support.
 */
int ximspot_update_interval = 1000;

/*
 * thickness of underline and bar cursors
 */
static unsigned int cursorthickness = 2;

/*
 * 1: render most of the lines/blocks characters without using the font for
 *    perfect alignment between cells (U2500 - U259F except dashes/diagonals).
 *    Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored.
 * 0: disable (render all U25XX glyphs normally from the font).
 */
const int boxdraw = 1;
const int boxdraw_bold = 1;

/* braille (U28XX):  1: render as adjacent "pixels",  0: use font */
const int boxdraw_braille = 1;

/*
 * bell volume. It must be a value between -100 and 100. Use 0 for disabling
 * it
 */
static int bellvolume = 0;

/* default TERM value */
char *termname = "st-256color";

/*
 * spaces per tab
 *
 * When you are changing this value, don't forget to adapt the »it« value in
 * the st.info and appropriately install the st.info in the environment where
 * you use this st version.
 *
 *	it#$tabspaces,
 *
 * Secondly make sure your kernel is not expanding tabs. When running `stty
 * -a` »tab0« should appear. You can tell the terminal to not expand tabs by
 *  running following command:
 *
 *	stty tabs
 */
unsigned int tabspaces = 8;

/* bg opacity */
float alpha = 1.0;

/* Terminal colors (16 first used in escape sequence) */
static const char *colorname[] = {
  "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */
  "#cc241d",
  "#98971a",
  "#d79921",
  "#458588",
  "#b16286",
  "#689d6a",
  "#a89984",
  "#928374",
  "#fb4934",
  "#b8bb26",
  "#fabd2f",
  "#83a598",
  "#d3869b",
  "#8ec07c",
  "#ebdbb2",
  [255] = 0,
  /* more colors can be added after 255 to use with DefaultXX */
  "#add8e6", /* 256 -> cursor */
  "#555555", /* 257 -> rev cursor*/
  "#282828", /* 258 -> bg */
  "#ffffff", /* 259 -> fg */
};


/*
 * Default colors (colorname index)
 * foreground, background, cursor, reverse cursor
 */
unsigned int defaultfg = 259;
unsigned int defaultbg = 258;
unsigned int defaultcs = 256;
unsigned int defaultrcs = 257;

/*
 * Default shape of cursor
 * 2: Block ("█")
 * 4: Underline ("_")
 * 6: Bar ("|")
 * 7: Snowman ("☃")
 */
static unsigned int cursorshape = 2;

/*
 * Default columns and rows numbers
 */

static unsigned int cols = 80;
static unsigned int rows = 24;

/*
 * Default colour and shape of the mouse cursor
 */
static unsigned int mouseshape = XC_xterm;
static unsigned int mousefg = 7;
static unsigned int mousebg = 0;

/*
 * Color used to display font attributes when fontconfig selected a font which
 * doesn't match the ones requested.
 */
static unsigned int defaultattr = 11;

/*
 * Xresources preferences to load at startup
 */
ResourcePref resources[] = {
  { "font",         STRING,  &font },
  { "fontalt0",     STRING,  &font2[0] },
  { "color0",       STRING,  &colorname[0] },
  { "color1",       STRING,  &colorname[1] },
  { "color2",       STRING,  &colorname[2] },
  { "color3",       STRING,  &colorname[3] },
  { "color4",       STRING,  &colorname[4] },
  { "color5",       STRING,  &colorname[5] },
  { "color6",       STRING,  &colorname[6] },
  { "color7",       STRING,  &colorname[7] },
  { "color8",       STRING,  &colorname[8] },
  { "color9",       STRING,  &colorname[9] },
  { "color10",      STRING,  &colorname[10] },
  { "color11",      STRING,  &colorname[11] },
  { "color12",      STRING,  &colorname[12] },
  { "color13",      STRING,  &colorname[13] },
  { "color14",      STRING,  &colorname[14] },
  { "color15",      STRING,  &colorname[15] },
  { "background",   STRING,  &colorname[258] },
  { "foreground",   STRING,  &colorname[259] },
  { "cursorColor",  STRING,  &colorname[256] },
  { "termname",     STRING,  &termname },
  { "shell",        STRING,  &shell },
  { "blinktimeout", INTEGER, &blinktimeout },
  { "bellvolume",   INTEGER, &bellvolume },
  { "tabspaces",    INTEGER, &tabspaces },
  { "borderpx",     INTEGER, &borderpx },
  { "cwscale",      FLOAT,   &cwscale },
  { "chscale",      FLOAT,   &chscale },
  { "alpha",        FLOAT,   &alpha },
  { "ximspot_update_interval", INTEGER, &ximspot_update_interval },
};

/*
 * Internal mouse shortcuts.
 * Beware that overloading Button1 will disable the selection.
 */
static MouseShortcut mshortcuts[] = {
  /* button               mask            string */
  { Button4,              XK_NO_MOD,      "\031" },
  { Button5,              XK_NO_MOD,      "\005" },
};

/* Internal keyboard shortcuts. */
#define MODKEY Mod1Mask
#define TERMMOD (Mod4Mask|ShiftMask)

MouseKey mkeys[] = {
  /* button               mask            function        argument */
  { Button4,              XK_NO_MOD,      kscrollup,      {.i =  1} },
  { Button5,              XK_NO_MOD,      kscrolldown,    {.i =  1} },
  { Button4,              Mod4Mask,        zoom,           {.f =  +1} },
  { Button5,              Mod4Mask,        zoom,           {.f =  -1} },
};

static char *openurlcmd[] = { "/bin/sh", "-c", "st-urlhandler", "externalpipe", NULL };

static char *copyurlcmd[] = { "/bin/sh", "-c",
  "tmp=$(sed 's/.*│//g' | tr -d '\n' | grep -aEo '(((http|https|gopher|gemini|ftp|ftps|git)://|www\\.)[a-zA-Z0-9.]*[:]?[a-zA-Z0-9./@$&%?$#=_-~]*)|((magnet:\\?xt=urn:btih:)[a-zA-Z0-9]*)' | uniq | sed 's/^www./http:\\/\\/www\\./g' ); IFS=; [ ! -z $tmp ] && echo $tmp | dmenu -i -p 'Copy which url?' -l 10 | tr -d '\n' | xclip -selection clipboard",
  "externalpipe", NULL };

static char *copyoutput[] = { "/bin/sh", "-c", "st-copyout", "externalpipe", NULL };

static Shortcut shortcuts[] = {
  /* mask                 keysym          function        argument */
  { XK_ANY_MOD,           XK_Break,       sendbreak,      {.i =  0} },
  { ControlMask,          XK_Print,       toggleprinter,  {.i =  0} },
  { ShiftMask,            XK_Print,       printscreen,    {.i =  0} },
  { XK_ANY_MOD,           XK_Print,       printsel,       {.i =  0} },
  { MODKEY,              XK_comma,       zoom,           {.f = +1} },
  { MODKEY,              XK_period,        zoom,           {.f = -1} },
  { MODKEY,               XK_g,        zoomreset,      {.f =  0} },
  { ControlMask | ShiftMask,               XK_C,           clipcopy,       {.i =  0} },
  { ShiftMask,            XK_Insert,      clippaste,      {.i =  0} },
  { ControlMask | ShiftMask,               XK_V,           clippaste,      {.i =  0} },
  { XK_ANY_MOD,		Button2,	selpaste,	{.i =  0} },
  { MODKEY,               XK_Num_Lock,    numlock,        {.i =  0} },
  { MODKEY,               XK_Control_L,   iso14755,       {.i =  0} },
  { ShiftMask,            XK_Page_Up,     kscrollup,      {.i = -1} },
  { ShiftMask,            XK_Page_Down,   kscrolldown,    {.i = -1} },
  { MODKEY,               XK_Page_Up,     kscrollup,      {.i = -1} },
  { MODKEY,               XK_Page_Down,   kscrolldown,    {.i = -1} },
  { MODKEY,               XK_k,           kscrollup,      {.i =  1} },
  { MODKEY,               XK_j,           kscrolldown,    {.i =  1} },
  { MODKEY,               XK_Up,          kscrollup,      {.i =  1} },
  { MODKEY,               XK_Down,        kscrolldown,    {.i =  1} },
  { MODKEY,               XK_u,           kscrollup,      {.i = -1} },
  { MODKEY,               XK_d,           kscrolldown,    {.i = -1} },
  { MODKEY,		XK_s,		changealpha,	{.f = -0.05} },
  { MODKEY,		XK_a,		changealpha,	{.f = +0.05} },
  { TERMMOD,              XK_Up,          zoom,           {.f = +1} },
  { TERMMOD,              XK_Down,        zoom,           {.f = -1} },
  { TERMMOD,              XK_K,           zoom,           {.f = +1} },
  { TERMMOD,              XK_J,           zoom,           {.f = -1} },
  { TERMMOD,              XK_U,           zoom,           {.f = +2} },
  { TERMMOD,              XK_D,           zoom,           {.f = -2} },
  { MODKEY,               XK_l,           externalpipe,   {.v = openurlcmd } },
  { MODKEY,               XK_y,           externalpipe,   {.v = copyurlcmd } },
  { MODKEY,               XK_o,           externalpipe,   {.v = copyoutput } },
  { TERMMOD,              XK_Return,      newterm,        {.i =  0} },

};

/*
 * Special keys (change & recompile st.info accordingly)
 *
 * Mask value:
 * * Use XK_ANY_MOD to match the key no matter modifiers state
 * * Use XK_NO_MOD to match the key alone (no modifiers)
 * appkey value:
 * * 0: no value
 * * > 0: keypad application mode enabled
 * *   = 2: term.numlock = 1
 * * < 0: keypad application mode disabled
 * appcursor value:
 * * 0: no value
 * * > 0: cursor application mode enabled
 * * < 0: cursor application mode disabled
 * crlf value
 * * 0: no value
 * * > 0: crlf mode is enabled
 * * < 0: crlf mode is disabled
 *
 * Be careful with the order of the definitions because st searches in
 * this table sequentially, so any XK_ANY_MOD must be in the last
 * position for a key.
 */

/*
 * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
 * to be mapped below, add them to this array.
 */
static KeySym mappedkeys[] = { -1 };

/*
 * State bits to ignore when matching key or button events.  By default,
 * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
 */
static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;

/*
 * Override mouse-select while mask is active (when MODE_MOUSE is set).
 * Note that if you want to use ShiftMask with selmasks, set this to an other
 * modifier, set to 0 to not use it.
 */
static uint forceselmod = ShiftMask;

/*
 * This is the huge key array which defines all compatibility to the Linux
 * world. Please decide about changes wisely.
 */
static Key key[] = {
  /* keysym           mask            string      appkey appcursor */
  { XK_KP_Home,       ShiftMask,      "\033[2J",       0,   -1},
  { XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,   +1},
  { XK_KP_Home,       XK_ANY_MOD,     "\033[H",        0,   -1},
  { XK_KP_Home,       XK_ANY_MOD,     "\033[1~",       0,   +1},
  { XK_KP_Up,         XK_ANY_MOD,     "\033Ox",       +1,    0},
  { XK_KP_Up,         XK_ANY_MOD,     "\033[A",        0,   -1},
  { XK_KP_Up,         XK_ANY_MOD,     "\033OA",        0,   +1},
  { XK_KP_Down,       XK_ANY_MOD,     "\033Or",       +1,    0},
  { XK_KP_Down,       XK_ANY_MOD,     "\033[B",        0,   -1},
  { XK_KP_Down,       XK_ANY_MOD,     "\033OB",        0,   +1},
  { XK_KP_Left,       XK_ANY_MOD,     "\033Ot",       +1,    0},
  { XK_KP_Left,       XK_ANY_MOD,     "\033[D",        0,   -1},
  { XK_KP_Left,       XK_ANY_MOD,     "\033OD",        0,   +1},
  { XK_KP_Right,      XK_ANY_MOD,     "\033Ov",       +1,    0},
  { XK_KP_Right,      XK_ANY_MOD,     "\033[C",        0,   -1},
  { XK_KP_Right,      XK_ANY_MOD,     "\033OC",        0,   +1},
  { XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0},
  { XK_KP_Prior,      XK_ANY_MOD,     "\033[5~",       0,    0},
  { XK_KP_Begin,      XK_ANY_MOD,     "\033[E",        0,    0},
  { XK_KP_End,        ControlMask,    "\033[J",       -1,    0},
  { XK_KP_End,        ControlMask,    "\033[1;5F",    +1,    0},
  { XK_KP_End,        ShiftMask,      "\033[K",       -1,    0},
  { XK_KP_End,        ShiftMask,      "\033[1;2F",    +1,    0},
  { XK_KP_End,        XK_ANY_MOD,     "\033[4~",       0,    0},
  { XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0},
  { XK_KP_Next,       XK_ANY_MOD,     "\033[6~",       0,    0},
  { XK_KP_Insert,     ShiftMask,      "\033[2;2~",    +1,    0},
  { XK_KP_Insert,     ShiftMask,      "\033[4l",      -1,    0},
  { XK_KP_Insert,     ControlMask,    "\033[L",       -1,    0},
  { XK_KP_Insert,     ControlMask,    "\033[2;5~",    +1,    0},
  { XK_KP_Insert,     XK_ANY_MOD,     "\033[4h",      -1,    0},
  { XK_KP_Insert,     XK_ANY_MOD,     "\033[2~",      +1,    0},
  { XK_KP_Delete,     ControlMask,    "\033[M",       -1,    0},
  { XK_KP_Delete,     ControlMask,    "\033[3;5~",    +1,    0},
  { XK_KP_Delete,     ShiftMask,      "\033[2K",      -1,    0},
  { XK_KP_Delete,     ShiftMask,      "\033[3;2~",    +1,    0},
  { XK_KP_Delete,     XK_ANY_MOD,     "\033[P",       -1,    0},
  { XK_KP_Delete,     XK_ANY_MOD,     "\033[3~",      +1,    0},
  { XK_KP_Multiply,   XK_ANY_MOD,     "\033Oj",       +2,    0},
  { XK_KP_Add,        XK_ANY_MOD,     "\033Ok",       +2,    0},
  { XK_KP_Enter,      XK_ANY_MOD,     "\033OM",       +2,    0},
  { XK_KP_Enter,      XK_ANY_MOD,     "\r",           -1,    0},
  { XK_KP_Subtract,   XK_ANY_MOD,     "\033Om",       +2,    0},
  { XK_KP_Decimal,    XK_ANY_MOD,     "\033On",       +2,    0},
  { XK_KP_Divide,     XK_ANY_MOD,     "\033Oo",       +2,    0},
  { XK_KP_0,          XK_ANY_MOD,     "\033Op",       +2,    0},
  { XK_KP_1,          XK_ANY_MOD,     "\033Oq",       +2,    0},
  { XK_KP_2,          XK_ANY_MOD,     "\033Or",       +2,    0},
  { XK_KP_3,          XK_ANY_MOD,     "\033Os",       +2,    0},
  { XK_KP_4,          XK_ANY_MOD,     "\033Ot",       +2,    0},
  { XK_KP_5,          XK_ANY_MOD,     "\033Ou",       +2,    0},
  { XK_KP_6,          XK_ANY_MOD,     "\033Ov",       +2,    0},
  { XK_KP_7,          XK_ANY_MOD,     "\033Ow",       +2,    0},
  { XK_KP_8,          XK_ANY_MOD,     "\033Ox",       +2,    0},
  { XK_KP_9,          XK_ANY_MOD,     "\033Oy",       +2,    0},
  { XK_Up,            ShiftMask,      "\033[1;2A",     0,    0},
  { XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0},
  { XK_Up,         ShiftMask|Mod1Mask,"\033[1;4A",     0,    0},
  { XK_Up,            ControlMask,    "\033[1;5A",     0,    0},
  { XK_Up,      ShiftMask|ControlMask,"\033[1;6A",     0,    0},
  { XK_Up,       ControlMask|Mod1Mask,"\033[1;7A",     0,    0},
  { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A",  0,    0},
  { XK_Up,            XK_ANY_MOD,     "\033[A",        0,   -1},
  { XK_Up,            XK_ANY_MOD,     "\033OA",        0,   +1},
  { XK_Down,          ShiftMask,      "\033[1;2B",     0,    0},
  { XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0},
  { XK_Down,       ShiftMask|Mod1Mask,"\033[1;4B",     0,    0},
  { XK_Down,          ControlMask,    "\033[1;5B",     0,    0},
  { XK_Down,    ShiftMask|ControlMask,"\033[1;6B",     0,    0},
  { XK_Down,     ControlMask|Mod1Mask,"\033[1;7B",     0,    0},
  { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0,    0},
  { XK_Down,          XK_ANY_MOD,     "\033[B",        0,   -1},
  { XK_Down,          XK_ANY_MOD,     "\033OB",        0,   +1},
  { XK_Left,          ShiftMask,      "\033[1;2D",     0,    0},
  { XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0},
  { XK_Left,       ShiftMask|Mod1Mask,"\033[1;4D",     0,    0},
  { XK_Left,          ControlMask,    "\033[1;5D",     0,    0},
  { XK_Left,    ShiftMask|ControlMask,"\033[1;6D",     0,    0},
  { XK_Left,     ControlMask|Mod1Mask,"\033[1;7D",     0,    0},
  { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0,    0},
  { XK_Left,          XK_ANY_MOD,     "\033[D",        0,   -1},
  { XK_Left,          XK_ANY_MOD,     "\033OD",        0,   +1},
  { XK_Right,         ShiftMask,      "\033[1;2C",     0,    0},
  { XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0},
  { XK_Right,      ShiftMask|Mod1Mask,"\033[1;4C",     0,    0},
  { XK_Right,         ControlMask,    "\033[1;5C",     0,    0},
  { XK_Right,   ShiftMask|ControlMask,"\033[1;6C",     0,    0},
  { XK_Right,    ControlMask|Mod1Mask,"\033[1;7C",     0,    0},
  { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0,   0},
  { XK_Right,         XK_ANY_MOD,     "\033[C",        0,   -1},
  { XK_Right,         XK_ANY_MOD,     "\033OC",        0,   +1},
  { XK_ISO_Left_Tab,  ShiftMask,      "\033[Z",        0,    0},
  { XK_Return,        Mod1Mask,       "\033\r",        0,    0},
  { XK_Return,        XK_ANY_MOD,     "\r",            0,    0},
  { XK_Insert,        ShiftMask,      "\033[4l",      -1,    0},
  { XK_Insert,        ShiftMask,      "\033[2;2~",    +1,    0},
  { XK_Insert,        ControlMask,    "\033[L",       -1,    0},
  { XK_Insert,        ControlMask,    "\033[2;5~",    +1,    0},
  { XK_Insert,        XK_ANY_MOD,     "\033[4h",      -1,    0},
  { XK_Insert,        XK_ANY_MOD,     "\033[2~",      +1,    0},
  { XK_Delete,        ControlMask,    "\033[M",       -1,    0},
  { XK_Delete,        ControlMask,    "\033[3;5~",    +1,    0},
  { XK_Delete,        ShiftMask,      "\033[2K",      -1,    0},
  { XK_Delete,        ShiftMask,      "\033[3;2~",    +1,    0},
  { XK_Delete,        XK_ANY_MOD,     "\033[P",       -1,    0},
  { XK_Delete,        XK_ANY_MOD,     "\033[3~",      +1,    0},
  { XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0},
  { XK_BackSpace,     Mod1Mask,       "\033\177",      0,    0},
  { XK_Home,          ShiftMask,      "\033[2J",       0,   -1},
  { XK_Home,          ShiftMask,      "\033[1;2H",     0,   +1},
  { XK_Home,          XK_ANY_MOD,     "\033[H",        0,   -1},
  { XK_Home,          XK_ANY_MOD,     "\033[1~",       0,   +1},
  { XK_End,           ControlMask,    "\033[J",       -1,    0},
  { XK_End,           ControlMask,    "\033[1;5F",    +1,    0},
  { XK_End,           ShiftMask,      "\033[K",       -1,    0},
  { XK_End,           ShiftMask,      "\033[1;2F",    +1,    0},
  { XK_End,           XK_ANY_MOD,     "\033[4~",       0,    0},
  { XK_Prior,         ControlMask,    "\033[5;5~",     0,    0},
  { XK_Prior,         ShiftMask,      "\033[5;2~",     0,    0},
  { XK_Prior,         XK_ANY_MOD,     "\033[5~",       0,    0},
  { XK_Next,          ControlMask,    "\033[6;5~",     0,    0},
  { XK_Next,          ShiftMask,      "\033[6;2~",     0,    0},
  { XK_Next,          XK_ANY_MOD,     "\033[6~",       0,    0},
  { XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0},
  { XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0},
  { XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0},
  { XK_F1, /* F37 */  Mod4Mask,       "\033[1;6P",     0,    0},
  { XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0},
  { XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0},
  { XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0},
  { XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0},
  { XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0},
  { XK_F2, /* F38 */  Mod4Mask,       "\033[1;6Q",     0,    0},
  { XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0},
  { XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0},
  { XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0},
  { XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0},
  { XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0},
  { XK_F3, /* F39 */  Mod4Mask,       "\033[1;6R",     0,    0},
  { XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0},
  { XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0},
  { XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0},
  { XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0},
  { XK_F4, /* F28 */  ControlMask,    "\033[1;5S",     0,    0},
  { XK_F4, /* F40 */  Mod4Mask,       "\033[1;6S",     0,    0},
  { XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0},
  { XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0},
  { XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0},
  { XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0},
  { XK_F5, /* F41 */  Mod4Mask,       "\033[15;6~",    0,    0},
  { XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0},
  { XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0},
  { XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0},
  { XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0},
  { XK_F6, /* F42 */  Mod4Mask,       "\033[17;6~",    0,    0},
  { XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0},
  { XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0},
  { XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0},
  { XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0},
  { XK_F7, /* F43 */  Mod4Mask,       "\033[18;6~",    0,    0},
  { XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0},
  { XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0},
  { XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0},
  { XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0},
  { XK_F8, /* F44 */  Mod4Mask,       "\033[19;6~",    0,    0},
  { XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0},
  { XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0},
  { XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0},
  { XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0},
  { XK_F9, /* F45 */  Mod4Mask,       "\033[20;6~",    0,    0},
  { XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0},
  { XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0},
  { XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0},
  { XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0},
  { XK_F10, /* F46 */ Mod4Mask,       "\033[21;6~",    0,    0},
  { XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0},
  { XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0},
  { XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0},
  { XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0},
  { XK_F11, /* F47 */ Mod4Mask,       "\033[23;6~",    0,    0},
  { XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0},
  { XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0},
  { XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0},
  { XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0},
  { XK_F12, /* F48 */ Mod4Mask,       "\033[24;6~",    0,    0},
  { XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0},
  { XK_F13,           XK_NO_MOD,      "\033[1;2P",     0,    0},
  { XK_F14,           XK_NO_MOD,      "\033[1;2Q",     0,    0},
  { XK_F15,           XK_NO_MOD,      "\033[1;2R",     0,    0},
  { XK_F16,           XK_NO_MOD,      "\033[1;2S",     0,    0},
  { XK_F17,           XK_NO_MOD,      "\033[15;2~",    0,    0},
  { XK_F18,           XK_NO_MOD,      "\033[17;2~",    0,    0},
  { XK_F19,           XK_NO_MOD,      "\033[18;2~",    0,    0},
  { XK_F20,           XK_NO_MOD,      "\033[19;2~",    0,    0},
  { XK_F21,           XK_NO_MOD,      "\033[20;2~",    0,    0},
  { XK_F22,           XK_NO_MOD,      "\033[21;2~",    0,    0},
  { XK_F23,           XK_NO_MOD,      "\033[23;2~",    0,    0},
  { XK_F24,           XK_NO_MOD,      "\033[24;2~",    0,    0},
  { XK_F25,           XK_NO_MOD,      "\033[1;5P",     0,    0},
  { XK_F26,           XK_NO_MOD,      "\033[1;5Q",     0,    0},
  { XK_F27,           XK_NO_MOD,      "\033[1;5R",     0,    0},
  { XK_F28,           XK_NO_MOD,      "\033[1;5S",     0,    0},
  { XK_F29,           XK_NO_MOD,      "\033[15;5~",    0,    0},
  { XK_F30,           XK_NO_MOD,      "\033[17;5~",    0,    0},
  { XK_F31,           XK_NO_MOD,      "\033[18;5~",    0,    0},
  { XK_F32,           XK_NO_MOD,      "\033[19;5~",    0,    0},
  { XK_F33,           XK_NO_MOD,      "\033[20;5~",    0,    0},
  { XK_F34,           XK_NO_MOD,      "\033[21;5~",    0,    0},
  { XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0},
};

/*
 * Selection types' masks.
 * Use the same masks as usual.
 * Button1Mask is always unset, to make masks match between ButtonPress.
 * ButtonRelease and MotionNotify.
 * If no match is found, regular selection is used.
 */
static uint selmasks[] = {
  [SEL_RECTANGULAR] = Mod1Mask,
};

/*
 * Printable characters in ASCII, used to estimate the advance width
 * of single wide characters.
 */
static char ascii_printable[] =
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~";

M config.mk => config.mk +7 -11
@@ 1,18 1,14 @@
# st version
VERSION = 0.8.2
VERSION = 0.8.4

# Customize below to fit your system

# paths
PREFIX ?= /usr/local
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man

X11INC = /usr/include/X11
X11LIB = /usr/X11LIB/X11

# include X11 in Ubuntu
# X11INC = /usr/include/X11R6
# X11LIB = /usr/lib/X11R6
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib

PKG_CONFIG = pkg-config



@@ 21,7 17,7 @@ INCS = -I$(X11INC) \
       `$(PKG_CONFIG) --cflags fontconfig` \
       `$(PKG_CONFIG) --cflags freetype2` \
       `$(PKG_CONFIG) --cflags harfbuzz`
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
       `$(PKG_CONFIG) --libs fontconfig` \
       `$(PKG_CONFIG) --libs freetype2` \
       `$(PKG_CONFIG) --libs harfbuzz`


@@ 34,8 30,8 @@ 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`
#       `$(PKG_CONFIG) --libs fontconfig` \
#       `$(PKG_CONFIG) --libs freetype2`

# compiler and linker
# CC = c99

A config.mk.orig => config.mk.orig +41 -0
@@ 0,0 1,41 @@
# st version
VERSION = 0.8.2

# Customize below to fit your system

# paths
PREFIX ?= /usr/local
MANPREFIX = $(PREFIX)/share/man

X11INC = /usr/include/X11
X11LIB = /usr/X11LIB/X11

# include X11 in Ubuntu
# X11INC = /usr/include/X11R6
# X11LIB = /usr/lib/X11R6

PKG_CONFIG = pkg-config

# includes and libs
INCS = -I$(X11INC) \
       `$(PKG_CONFIG) --cflags fontconfig` \
       `$(PKG_CONFIG) --cflags freetype2` \
       `$(PKG_CONFIG) --cflags harfbuzz`
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\
       `$(PKG_CONFIG) --libs fontconfig` \
       `$(PKG_CONFIG) --libs freetype2` \
       `$(PKG_CONFIG) --libs harfbuzz`

# flags
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
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`

# compiler and linker
# CC = c99

A hb.c.orig => hb.c.orig +140 -0
@@ 0,0 1,140 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <X11/Xft/Xft.h>
#include <hb.h>
#include <hb-ft.h>

#include "st.h"

void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length);
hb_font_t *hbfindfont(XftFont *match);

typedef struct {
	XftFont *match;
	hb_font_t *font;
} HbFontMatch;

static int hbfontslen = 0;
static HbFontMatch *hbfontcache = NULL;

void
hbunloadfonts()
{
	for (int i = 0; i < hbfontslen; i++) {
		hb_font_destroy(hbfontcache[i].font);
		XftUnlockFace(hbfontcache[i].match);
	}

	if (hbfontcache != NULL) {
		free(hbfontcache);
		hbfontcache = NULL;
	}
	hbfontslen = 0;
}

hb_font_t *
hbfindfont(XftFont *match)
{
	for (int i = 0; i < hbfontslen; i++) {
		if (hbfontcache[i].match == match)
			return hbfontcache[i].font;
	}

	/* Font not found in cache, caching it now. */
	hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1));
	FT_Face face = XftLockFace(match);
	hb_font_t *font = hb_ft_font_create(face, NULL);
	if (font == NULL)
		die("Failed to load Harfbuzz font.");

	hbfontcache[hbfontslen].match = match;
	hbfontcache[hbfontslen].font = font;
	hbfontslen += 1;

	return font;
}

void
hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y)
{
	int start = 0, length = 1, gstart = 0;
	hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t));

	for (int idx = 1, specidx = 1; idx < len; idx++) {
		if (glyphs[idx].mode & ATTR_WDUMMY) {
			length += 1;
			continue;
		}

		if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) {
			hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);

			/* Reset the sequence. */
			length = 1;
			start = specidx;
			gstart = idx;
		} else {
			length += 1;
		}

		specidx++;
	}

	/* EOL. */
	hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);

	/* Apply the transformation to glyph specs. */
	for (int i = 0, specidx = 0; i < len; i++) {
		if (glyphs[i].mode & ATTR_WDUMMY)
			continue;
		if (glyphs[i].mode & ATTR_BOXDRAW) {
			specidx++;
			continue;
		}

		if (codepoints[i] != specs[specidx].glyph)
			((Glyph *)glyphs)[i].mode |= ATTR_LIGA;

		specs[specidx++].glyph = codepoints[i];
	}

	free(codepoints);
}

void
hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length)
{
	hb_font_t *font = hbfindfont(xfont);
	if (font == NULL)
		return;

	Rune rune;
	ushort mode = USHRT_MAX;
	hb_buffer_t *buffer = hb_buffer_create();
	hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);

	/* Fill buffer with codepoints. */
	for (int i = start; i < (start+length); i++) {
		rune = string[i].u;
		mode = string[i].mode;
		if (mode & ATTR_WDUMMY)
			rune = 0x0020;
		hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
	}

	/* Shape the segment. */
	hb_shape(font, buffer, NULL, 0);

	/* Get new glyph info. */
	hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);

	/* Write new codepoints. */
	for (int i = 0; i < length; i++) {
		hb_codepoint_t gid = info[i].codepoint;
		codepoints[start+i] = gid;
	}

	/* Cleanup. */
	hb_buffer_destroy(buffer);
}

M st.c => st.c +16 -70
@@ 248,33 248,6 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
static Rune utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};

#include <time.h>
static int su = 0;
struct timespec sutv;

static void
tsync_begin()
{
	clock_gettime(CLOCK_MONOTONIC, &sutv);
	su = 1;
}

static void
tsync_end()
{
	su = 0;
}

int
tinsync(uint timeout)
{
	struct timespec now;
	if (su && !clock_gettime(CLOCK_MONOTONIC, &now)
	       && TIMEDIFF(now, sutv) >= timeout)
		su = 0;
	return su;
}

ssize_t
xwrite(int fd, const char *s, size_t len)
{


@@ 863,9 836,6 @@ ttynew(char *line, char *cmd, char *out, char **args)
	return cmdfd;
}

static int twrite_aborted = 0;
int ttyread_pending() { return twrite_aborted; }

size_t
ttyread(void)
{


@@ 875,10 845,10 @@ ttyread(void)
	int ret;

	/* append read bytes to unprocessed bytes */
	if ((ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
	if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
		die("couldn't read from shell: %s\n", strerror(errno));
    
	buflen += twrite_aborted ? 0 : ret;
	buflen += ret;

	written = twrite(buf, buflen, 0);
	buflen -= written;
	/* keep any uncomplete utf8 char for the next call */


@@ 1041,7 1011,6 @@ tsetdirtattr(int attr)
void
tfulldirt(void)
{
	tsync_end();
	tsetdirt(0, term.row-1);
}



@@ 1373,8 1342,6 @@ tclearregion(int x1, int y1, int x2, int y2)
	LIMIT(x2, 0, term.maxcol-1);
	LIMIT(y1, 0, term.row-1);
	LIMIT(y2, 0, term.row-1);
        if (x2 == term.col-1)
		x2 = term.maxcol-1;

	for (y = y1; y <= y2; y++) {
		term.dirty[y] = 1;


@@ 2042,12 2009,6 @@ strhandle(void)
		return;
	case 'P': /* DCS -- Device Control String */
		term.mode |= ESC_DCS;
		/* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */
		if (strstr(strescseq.buf, "=1s") == strescseq.buf)
			tsync_begin(), term.mode &= ~ESC_DCS;  /* BSU */
		else if (strstr(strescseq.buf, "=2s") == strescseq.buf)
			tsync_end(), term.mode &= ~ESC_DCS;  /* ESU */
		return;
	case '_': /* APC -- Application Program Command */
	case '^': /* PM -- Privacy Message */
		return;


@@ 2673,9 2634,6 @@ twrite(const char *buf, int buflen, int show_ctrl)
	Rune u;
	int n;

	int su0 = su;
	twrite_aborted = 0;

	for (n = 0; n < buflen; n += charsize) {
		if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
			/* process a complete utf8 char */


@@ 2686,10 2644,6 @@ twrite(const char *buf, int buflen, int show_ctrl)
			u = buf[n] & 0xFF;
			charsize = 1;
		}
		if (su0 && !su) {
			twrite_aborted = 1;
			break;  // ESU - allow rendering before a new BSU
		}
		if (show_ctrl && ISCONTROL(u)) {
			if (u & 0x80) {
				u &= 0x7f;


@@ 2710,10 2664,8 @@ tresize(int col, int row)
{
	int i, j;
        int tmp;
	int minrow, mincol;
        int pmaxcol = term.maxcol;
 	int minrow, mincol;
	int *bp;
        Glyph *gp;
	TCursor c;

        tmp = col;


@@ 2723,15 2675,12 @@ tresize(int col, int row)
	minrow = MIN(row, term.row);
	mincol = MIN(col, term.maxcol);


	if (col < 1 || row < 1) {
		fprintf(stderr,
		        "tresize: error resizing to %dx%d\n", col, row);
		return;
	}

       	term.maxcol = MAX(col, pmaxcol);

	/*
	 * slide screen to keep cursor where we expect it -
	 * tscrollup would work here, but we can optimize to


@@ 2758,13 2707,10 @@ tresize(int col, int row)
	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));

	for (i = 0; i < HISTSIZE; i++) {
		term.hist[i] = xrealloc(term.hist[i], term.maxcol * sizeof(Glyph));
		for (j = pmaxcol; j < term.maxcol; j++) {
			gp = &term.hist[i][j];
			gp->fg = defaultfg;
			gp->bg = defaultbg;
			gp->mode = ATTR_NULL;
			gp->u = ' ';
		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
		for (j = mincol; j < col; j++) {
			term.hist[i][j] = term.c.attr;
			term.hist[i][j].u = ' ';
		}
	}



@@ 2776,12 2722,12 @@ tresize(int col, int row)

	/* allocate any new rows */
	for (/* i = minrow */; i < row; i++) {
                term.line[i] = xmalloc(term.maxcol * sizeof(Glyph));
		term.alt[i] = xmalloc(term.maxcol * sizeof(Glyph));
		term.line[i] = xmalloc(col * sizeof(Glyph));
		term.alt[i] = xmalloc(col * sizeof(Glyph));
	}
        if (col > term.maxcol) {
		bp = term.tabs + term.maxcol;

        if (col > term.maxcol) {
 		bp = term.tabs + term.maxcol;
                memset(bp, 0, sizeof(*term.tabs) * (col - term.maxcol));
		while (--bp > term.tabs && !*bp)
			/* nothing */ ;


@@ 2789,8 2735,8 @@ tresize(int col, int row)
			*bp = 1;
	}
	/* update terminal size */
        term.col = tmp;
	term.maxcol = col;
	term.col = tmp;
        term.maxcol = col;
	term.row = row;
	/* reset scrolling region */
	tsetscroll(0, row-1);


@@ 2799,8 2745,8 @@ tresize(int col, int row)
	/* Clearing both screens (it makes dirty all lines) */
	c = term.c;
	for (i = 0; i < 2; i++) {
          	if (pmaxcol < col && 0 < minrow) {
			tclearregion(pmaxcol, 0, col - 1, minrow - 1);
		if (mincol < col && 0 < minrow) {
			tclearregion(mincol, 0, col - 1, minrow - 1);
		}
		if (0 < col && minrow < row) {
			tclearregion(0, minrow, col - 1, row - 1);

M st.c.orig => st.c.orig +16 -90
@@ 126,7 126,6 @@ typedef struct {
typedef struct {
	int row;      /* nb row */
	int col;      /* nb col */
	int maxCol;
	Line *line;   /* screen */
	Line *alt;    /* alternate screen */
	Line hist[HISTSIZE]; /* history buffer */


@@ 169,7 168,6 @@ typedef struct {
} STREscape;

static void execsh(char *, char **);
static char *getcwd_by_pid(pid_t pid);
static void stty(char **);
static void sigchld(int);
static void ttywriteraw(const char *, size_t);


@@ 248,33 246,6 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
static Rune utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};

#include <time.h>
static int su = 0;
struct timespec sutv;

static void
tsync_begin()
{
	clock_gettime(CLOCK_MONOTONIC, &sutv);
	su = 1;
}

static void
tsync_end()
{
	su = 0;
}

int
tinsync(uint timeout)
{
	struct timespec now;
	if (su && !clock_gettime(CLOCK_MONOTONIC, &now)
	       && TIMEDIFF(now, sutv) >= timeout)
		su = 0;
	return su;
}

ssize_t
xwrite(int fd, const char *s, size_t len)
{


@@ 863,9 834,6 @@ ttynew(char *line, char *cmd, char *out, char **args)
	return cmdfd;
}

static int twrite_aborted = 0;
int ttyread_pending() { return twrite_aborted; }

size_t
ttyread(void)
{


@@ 875,10 843,10 @@ ttyread(void)
	int ret;

	/* append read bytes to unprocessed bytes */
	if ((ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
	if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
		die("couldn't read from shell: %s\n", strerror(errno));
    
	buflen += twrite_aborted ? 0 : ret;
	buflen += ret;

	written = twrite(buf, buflen, 0);
	buflen -= written;
	/* keep any uncomplete utf8 char for the next call */


@@ 1041,7 1009,6 @@ tsetdirtattr(int attr)
void
tfulldirt(void)
{
	tsync_end();
	tsetdirt(0, term.row-1);
}



@@ 1113,26 1080,6 @@ tswapscreen(void)
}

void
newterm(const Arg* a)
{
	switch (fork()) {
	case -1:
		die("fork failed: %s\n", strerror(errno));
		break;
	case 0:
		chdir(getcwd_by_pid(pid));
		execlp("st", "./st", NULL);
		break;
	}
}

static char *getcwd_by_pid(pid_t pid) {
	char buf[32];
	snprintf(buf, sizeof buf, "/proc/%d/cwd", pid);
	return realpath(buf, NULL);
}

void
kscrolldown(const Arg* a)
{
	int n = a->i;


@@ 1369,8 1316,8 @@ tclearregion(int x1, int y1, int x2, int y2)
	if (y1 > y2)
		temp = y1, y1 = y2, y2 = temp;

	LIMIT(x1, 0, term.maxCol-1);
	LIMIT(x2, 0, term.maxCol-1);
	LIMIT(x1, 0, term.col-1);
	LIMIT(x2, 0, term.col-1);
	LIMIT(y1, 0, term.row-1);
	LIMIT(y2, 0, term.row-1);



@@ 2040,12 1987,6 @@ strhandle(void)
		return;
	case 'P': /* DCS -- Device Control String */
		term.mode |= ESC_DCS;
		/* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */
		if (strstr(strescseq.buf, "=1s") == strescseq.buf)
			tsync_begin(), term.mode &= ~ESC_DCS;  /* BSU */
		else if (strstr(strescseq.buf, "=2s") == strescseq.buf)
			tsync_end(), term.mode &= ~ESC_DCS;  /* ESU */
		return;
	case '_': /* APC -- Application Program Command */
	case '^': /* PM -- Privacy Message */
		return;


@@ 2671,9 2612,6 @@ twrite(const char *buf, int buflen, int show_ctrl)
	Rune u;
	int n;

	int su0 = su;
	twrite_aborted = 0;

	for (n = 0; n < buflen; n += charsize) {
		if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
			/* process a complete utf8 char */


@@ 2684,10 2622,6 @@ twrite(const char *buf, int buflen, int show_ctrl)
			u = buf[n] & 0xFF;
			charsize = 1;
		}
		if (su0 && !su) {
			twrite_aborted = 1;
			break;  // ESU - allow rendering before a new BSU
		}
		if (show_ctrl && ISCONTROL(u)) {
			if (u & 0x80) {
				u &= 0x7f;


@@ 2706,16 2640,9 @@ twrite(const char *buf, int buflen, int show_ctrl)
void
tresize(int col, int row)
{
	int i, j, pmc;
	int colSet = col;

	if(!term.maxCol) term.maxCol = 255;
	col = MAX(col, term.maxCol);

	int i, j;
	int minrow = MIN(row, term.row);
	int mincol = MIN(col, term.maxCol);
	term.maxCol = MAX(col, pmc = term.maxCol);

	int mincol = MIN(col, term.col);
	int *bp;
	TCursor c;



@@ 2751,7 2678,7 @@ tresize(int col, int row)
	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));

	for (i = 0; i < HISTSIZE; i++) {
		term.hist[i] = xrealloc(term.hist[i], term.maxCol * sizeof(Glyph));
		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
		for (j = mincol; j < col; j++) {
			term.hist[i][j] = term.c.attr;
			term.hist[i][j].u = ' ';


@@ 2766,21 2693,20 @@ tresize(int col, int row)

	/* allocate any new rows */
	for (/* i = minrow */; i < row; i++) {
		term.line[i] = xmalloc(term.maxCol * sizeof(Glyph));
		term.alt[i] = xmalloc(term.maxCol * sizeof(Glyph));
		term.line[i] = xmalloc(col * sizeof(Glyph));
		term.alt[i] = xmalloc(col * sizeof(Glyph));
	}
	if (col > term.maxCol) {
		bp = term.tabs + term.maxCol;
	if (col > term.col) {
		bp = term.tabs + term.col;

		memset(bp, 0, sizeof(*term.tabs) * (col - term.maxCol));
		/*while (--bp > term.tabs && !*bp)*/
		memset(bp, 0, sizeof(*term.tabs) * (col - term.col));
		while (--bp > term.tabs && !*bp)
			/* nothing */ ;
		for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces)
			*bp = 1;
	}
	/* update terminal size */
	term.col = colSet;
	term.maxCol = col;
	term.col = col;
	term.row = row;
	/* reset scrolling region */
	tsetscroll(0, row-1);


@@ 2790,7 2716,7 @@ tresize(int col, int row)
	c = term.c;
	for (i = 0; i < 2; i++) {
		if (mincol < col && 0 < minrow) {
			tclearregion(pmc, 0, col - 1, minrow - 1);
			tclearregion(mincol, 0, col - 1, minrow - 1);
		}
		if (0 < col && minrow < row) {
			tclearregion(0, minrow, col - 1, row - 1);

A st.h.orig => st.h.orig +157 -0
@@ 0,0 1,157 @@
/* See LICENSE for license details. */

#include <stdint.h>
#include <sys/types.h>

/* macros */
#define MIN(a, b)		((a) < (b) ? (a) : (b))
#define MAX(a, b)		((a) < (b) ? (b) : (a))
#define LEN(a)			(sizeof(a) / sizeof(a)[0])
#define BETWEEN(x, a, b)	((a) <= (x) && (x) <= (b))
#define DIVCEIL(n, d)		(((n) + ((d) - 1)) / (d))
#define DEFAULT(a, b)		(a) = (a) ? (a) : (b)
#define LIMIT(x, a, b)		(x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
#define ATTRCMP(a, b)		(((a).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) != ((b).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) || \
				(a).fg != (b).fg || \
				(a).bg != (b).bg)
#define TIMEDIFF(t1, t2)	((t1.tv_sec-t2.tv_sec)*1000 + \
				(t1.tv_nsec-t2.tv_nsec)/1E6)
#define MODBIT(x, set, bit)	((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))

#define TRUECOLOR(r,g,b)	(1 << 24 | (r) << 16 | (g) << 8 | (b))
#define IS_TRUECOL(x)		(1 << 24 & (x))

enum glyph_attribute {
	ATTR_NULL       = 0,
	ATTR_BOLD       = 1 << 0,
	ATTR_FAINT      = 1 << 1,
	ATTR_ITALIC     = 1 << 2,
	ATTR_UNDERLINE  = 1 << 3,
	ATTR_BLINK      = 1 << 4,
	ATTR_REVERSE    = 1 << 5,
	ATTR_INVISIBLE  = 1 << 6,
	ATTR_STRUCK     = 1 << 7,
	ATTR_WRAP       = 1 << 8,
	ATTR_WIDE       = 1 << 9,
	ATTR_WDUMMY     = 1 << 10,
 	ATTR_BOXDRAW    = 1 << 11,
	ATTR_LIGA       = 1 << 12,
	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};

enum drawing_mode {
	DRAW_NONE = 0,
	DRAW_BG   = 1 << 0,
	DRAW_FG   = 1 << 1,
};

enum selection_mode {
	SEL_IDLE = 0,
	SEL_EMPTY = 1,
	SEL_READY = 2
};

enum selection_type {
	SEL_REGULAR = 1,
	SEL_RECTANGULAR = 2
};

enum selection_snap {
	SNAP_WORD = 1,
	SNAP_LINE = 2
};

typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;

typedef uint_least32_t Rune;

#define Glyph Glyph_
typedef struct {
	Rune u;           /* character code */
	ushort mode;      /* attribute flags */
	uint32_t fg;      /* foreground  */
	uint32_t bg;      /* background  */
} Glyph;

typedef Glyph *Line;

typedef union {
	int i;
	uint ui;
	float f;
	const void *v;
} Arg;

typedef struct {
	uint b;
	uint mask;
	void (*func)(const Arg *);
	const Arg arg;
} MouseKey;

void die(const char *, ...);
void redraw(void);
void draw(void);

void externalpipe(const Arg *);
void iso14755(const Arg *);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void newterm(const Arg *);
void printscreen(const Arg *);
void printsel(const Arg *);
void sendbreak(const Arg *);
void toggleprinter(const Arg *);

int tattrset(int);
int tisaltscr(void);
void tnew(int, int);
void tresize(int, int);
void tsetdirtattr(int);
void ttyhangup(void);
int ttynew(char *, char *, char *, char **);
size_t ttyread(void);
void ttyresize(int, int);
void ttywrite(const char *, size_t, int);

void resettitle(void);

void selclear(void);
void selinit(void);
void selstart(int, int, int);
void selextend(int, int, int, int);
int selected(int, int);
char *getsel(void);

size_t utf8encode(Rune, char *);

void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(char *);

int isboxdraw(Rune);
ushort boxdrawindex(const Glyph *);
#ifdef XFT_VERSION
/* only exposed to x.c, otherwise we'll need Xft.h for the types */
void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *);
void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int);
#endif

/* config.h globals */
extern char *utmp;
extern char *stty_args;
extern char *vtiden;
extern wchar_t *worddelimiters;
extern int allowaltscreen;
extern char *termname;
extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
extern unsigned int defaultcs;
extern const int boxdraw, boxdraw_bold, boxdraw_braille;
extern float alpha;
extern MouseKey mkeys[];
extern int ximspot_update_interval;

M st.info => st.info +0 -1
@@ 193,7 193,6 @@ st| simpleterm,
	Ms=\E]52;%p1%s;%p2%s\007,
	Se=\E[2 q,
	Ss=\E[%p1%d q,
	Sync=\EP=%p1%ds\E\\,

st-256color| simpleterm with 256 colors,
	use=st,

M x.c => x.c +14 -32
@@ 94,6 94,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
typedef struct {
	int tw, th; /* tty width and height */
	int w, h; /* window width and height */
        int hborderpx, vborderpx;
	int ch; /* char height */
	int cw; /* char width  */
	int cyo; /* char y offset */


@@ 306,7 307,7 @@ numlock(const Arg *dummy)
void
changealpha(const Arg *arg)
{
    if(alpha > 1 && arg->f == 2 )
     if(alpha > 1 && arg->f == 2 )
      alpha = 1;
    if((alpha > 0 && arg->f < 0) || (alpha < 1 && arg->f > 0))
        alpha += arg->f;


@@ 695,8 696,7 @@ brelease(XEvent *e)
		mousereport(e);
		return;
	}

	if (e->xbutton.button == Button3)
        if (e->xbutton.button == Button3)
		selpaste(NULL);
	else if (e->xbutton.button == Button1)
		mousesel(e, 1);


@@ 1245,8 1245,8 @@ xinit(int cols, int rows)
	xloadcols();

	/* adjust fixed window geometry */
        win.w = 2 * borderpx + cols * win.cw;
	win.h = 2 * borderpx + rows * win.ch;
	win.w = 2 * win.hborderpx + cols * win.cw;
	win.h = 2 * win.vborderpx + rows * win.ch;
	if (xw.gm & XNegative)
		xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
	if (xw.gm & YNegative)


@@ 1556,17 1556,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
	if (dmode & DRAW_BG) {
		/* Intelligent cleaning up of the borders. */
		if (x == 0) {
                            	xclear(0, (y == 0)? 0 : winy, borderpx,
                        xclear(0, (y == 0)? 0 : winy, borderpx,
					winy + win.ch +
                                        ((winy + win.ch >= borderpx + win.th)? win.h : 0));
		}
                if (winx + width >= borderpx + win.tw) {
	        if (winx + width >= borderpx + win.tw) {
			xclear(winx + width, (y == 0)? 0 : winy, win.w,
                            	((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
                                ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
		}
		if (y == 0)
		xclear(winx, 0, winx + width, borderpx);
         	if (winy + win.ch >= borderpx + win.th)	
                  	xclear(winx, 0, winx + width, borderpx);
          	if (winy + win.ch >= borderpx + win.th)
			xclear(winx, winy + win.ch, winx + width, win.h);

		/* Fill the background */


@@ 1617,8 1617,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
	 * It will restore the ligatures broken by the cursor. */
	xdrawline(line, 0, oy, len);

        if (IS_SET(MODE_HIDE) || !IS_SET(MODE_FOCUSED))
		return;
        if (IS_SET(MODE_HIDE) || !IS_SET(MODE_FOCUSED)) return;

	/*
	 * Select the right color for the right mode.


@@ 1984,9 1983,6 @@ resize(XEvent *e)
	cresize(e->xconfigure.width, e->xconfigure.height);
}

int tinsync(uint);
int ttyread_pending();

void
run(void)
{


@@ 2021,7 2017,7 @@ run(void)
		FD_SET(ttyfd, &rfd);
		FD_SET(xfd, &rfd);

		if (XPending(xw.dpy) || ttyread_pending())
		if (XPending(xw.dpy))
			timeout = 0;  /* existing events might not set xfd */

		seltv.tv_sec = timeout / 1E3;


@@ 2035,8 2031,7 @@ run(void)
		}
		clock_gettime(CLOCK_MONOTONIC, &now);

		int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
		if (ttyin)
		if (FD_ISSET(ttyfd, &rfd))
			ttyread();

		xev = 0;


@@ 2060,7 2055,7 @@ run(void)
		 * maximum latency intervals during `cat huge.txt`, and perfect
		 * sync with periodic updates from animations/key-repeats/etc.
		 */
		if (ttyin || xev) {
		if (FD_ISSET(ttyfd, &rfd) || xev) {
			if (!drawing) {
				trigger = now;
				drawing = 1;


@@ 2071,18 2066,6 @@ run(void)
				continue;  /* we have time, try to find idle */
		}

		if (tinsync(su_timeout)) {
			/*
			 * on synchronized-update draw-suspension: don't reset
			 * drawing so that we draw ASAP once we can (just after
			 * ESU). it won't be too soon because we already can
			 * draw now but we skip. we set timeout > 0 to draw on
			 * SU-timeout even without new content.
			 */
			timeout = minlatency;
			continue;
		}

		/* idle detected or maxlatency exhausted -> draw */
		timeout = -1;
		if (blinktimeout && tattrset(ATTR_BLINK)) {


@@ 2227,7 2210,6 @@ reload(int sig)
	signal(SIGUSR1, reload);
}


int
resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
{

M x.c.orig => x.c.orig +6 -26
@@ 307,15 307,13 @@ numlock(const Arg *dummy)
void
changealpha(const Arg *arg)
{
    if(alpha > 1 && arg->f == 2 )
      alpha = 1;
    if((alpha > 0 && arg->f < 0) || (alpha < 1 && arg->f > 0))
        alpha += arg->f;
    if(alpha < 0)
        alpha = 0;
    if(alpha > 1)
        alpha = 1;
    

    xloadcols();
    redraw();
}


@@ 696,8 694,7 @@ brelease(XEvent *e)
		mousereport(e);
		return;
	}

	if (e->xbutton.button == Button3)
        if (e->xbutton.button == Button3)
		selpaste(NULL);
	else if (e->xbutton.button == Button1)
		mousesel(e, 1);


@@ 1621,7 1618,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
	 * It will restore the ligatures broken by the cursor. */
	xdrawline(line, 0, oy, len);

        if (IS_SET(MODE_HIDE) || !IS_SET(MODE_FOCUSED))
	if (IS_SET(MODE_HIDE))
		return;

	/*


@@ 1988,9 1985,6 @@ resize(XEvent *e)
	cresize(e->xconfigure.width, e->xconfigure.height);
}

int tinsync(uint);
int ttyread_pending();

void
run(void)
{


@@ 2025,7 2019,7 @@ run(void)
		FD_SET(ttyfd, &rfd);
		FD_SET(xfd, &rfd);

		if (XPending(xw.dpy) || ttyread_pending())
		if (XPending(xw.dpy))
			timeout = 0;  /* existing events might not set xfd */

		seltv.tv_sec = timeout / 1E3;


@@ 2039,8 2033,7 @@ run(void)
		}
		clock_gettime(CLOCK_MONOTONIC, &now);

		int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
		if (ttyin)
		if (FD_ISSET(ttyfd, &rfd))
			ttyread();

		xev = 0;


@@ 2064,7 2057,7 @@ run(void)
		 * maximum latency intervals during `cat huge.txt`, and perfect
		 * sync with periodic updates from animations/key-repeats/etc.
		 */
		if (ttyin || xev) {
		if (FD_ISSET(ttyfd, &rfd) || xev) {
			if (!drawing) {
				trigger = now;
				drawing = 1;


@@ 2075,18 2068,6 @@ run(void)
				continue;  /* we have time, try to find idle */
		}

		if (tinsync(su_timeout)) {
			/*
			 * on synchronized-update draw-suspension: don't reset
			 * drawing so that we draw ASAP once we can (just after
			 * ESU). it won't be too soon because we already can
			 * draw now but we skip. we set timeout > 0 to draw on
			 * SU-timeout even without new content.
			 */
			timeout = minlatency;
			continue;
		}

		/* idle detected or maxlatency exhausted -> draw */
		timeout = -1;
		if (blinktimeout && tattrset(ATTR_BLINK)) {


@@ 2231,7 2212,6 @@ reload(int sig)
	signal(SIGUSR1, reload);
}


int
resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
{

M xresources => xresources +21 -31
@@ 1,26 1,22 @@
!-- Xft settings -- !
Xft.antialias:	1
Xft.hinting:	1
Xft.autohint:	0
Xft.hintstyle:	hintslight
Xft.rgba:	rgb
Xft.lcdfilter:	lcddefault

!-- remove this if your DPI is ok -- !
Xft.dpi:   135  

st.font:         JetBrainsMono Nerd Font:style:medium:pixelsize=20

!-- use values like 0.60 to get proper transparency -- !
st.alpha: 1.0 
!-- Xft settings -- !
Xft.dpi:        96
Xft.antialias:  true
Xft.rgba:       rgb
Xft.hinting:    true
Xft.hintstyle:  hintfull

! window border inner
st.borderpx: 10
! window padding
st.borderpx:          15
st.font: JetBrains Mono::pixelsize=15
st.fontalt0: FuraCode Nerd Font:style=Regular:pixelsize=14
! st.font:           JetBrainsMono Nerd Font:pixelsize=15 , Material Design Icons :pixelsize =15
st.opacity: 255

! Base16 OneDark
! Scheme: Lalit Magant (http://github.com/tilal6991)

#define base00 #1e222a
#define base00 #282c34
#define base01 #353b45
#define base02 #3e4451
#define base03 #545862


@@ 63,17 59,11 @@ st.borderpx: 10
*color14:      base0C
*color15:      base07

! Note: colors beyond 15 might not be loaded (e.g., xterm, urxvt)

  *color16:      base09
  *color17:      base0F
  *color18:      base01
  *color19:      base02
  *color20:      base04
  *color21:      base06

  tabbed.selbgcolor:   #282c34
  tabbed.selfgcolor:   #d6d8eb

  tabbed.normfgcolor:  #9294a8
  tabbed.normbgcolor:  #353b45
! Note: colors beyond 15 might not be loaded (e.g., xterm, urxvt),
! use 'shell' template to set these if necessary
*color16:      base09
*color17:      base0F
*color18:      base01
*color19:      base02
*color20:      base04
*color21:      base06