Old build can be found in the previous-2 branch. This one has sixel
support among other things, not to mention it draws text properly.
This commit is contained in:
speedie 2022-11-13 22:16:04 +01:00
parent 5eb20bffed
commit 987e8cbe18
32 changed files with 2198 additions and 996 deletions

View file

@ -14,7 +14,7 @@ MIT/X Consortium License
© 2013 Michael Forney <mforney at mforney dot org>
© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de>
© 2014-2015 Laslo Hunhold <dev at frign dot de>
© 2021-2022 speedie <speedie at duck dot com>
© 2021-2022 speedie <speedie@duck.com>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -4,7 +4,7 @@
include options.mk
SRC = st.c x.c boxdraw.c hb.c
SRC = st.c x.c sixel.c sixelhls.c hb.c bd.c
OBJ = $(SRC:.c=.o)
all: options st
@ -14,67 +14,46 @@ options:
@echo "CFLAGS = $(STCFLAGS)"
@echo "LDFLAGS = $(STLDFLAGS)"
@echo "CC = $(CC)"
@echo "======================"
.c.o:
$(CC) $(STCFLAGS) -c $<
st.o: options.h st.h win.h
x.o: arg.h options.h st.h win.h
boxdraw.o: options.h st.h boxdraw_data.h
boxdraw.o: options.h st.h bd.h
hb.o: st.h
$(OBJ): options.h options.mk
$(OBJ): options.mk
st: $(OBJ)
$(CC) -o $@ $(OBJ) $(STLDFLAGS)
clean:
rm -f st $(OBJ) st-spde-$(VERSION).tar.gz
rm -f st $(OBJ) st-$(VERSION).tar.gz
dist: clean
mkdir -p st-spde-$(VERSION)
cp -R LICENSE Makefile README *.mk\
*.h *.info *.c *.png *.desktop *.ttf docs/ scripts/ \
st-spde-$(VERSION)
tar -cf - st-spde-$(VERSION) | gzip > st-spde-$(VERSION).tar.gz
rm -rf st-spde-$(VERSION)
mkdir -p st-$(VERSION)
cp -R LICENSE Makefile *.mk \
*.h *.info *.h *.c *.desktop *.png docs/ scripts/ \
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 scripts/* $(DESTDIR)$(PREFIX)/bin
chmod +x $(DESTDIR)$(PREFIX)/bin/st*
chmod 755 $(DESTDIR)$(PREFIX)/bin/st
tic -sx st.info
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
mkdir -p $(DESTDIR)$(APPPREFIX)
cp -f st.desktop $(DESTDIR)$(APPPREFIX)
rm -f *.o st
cp -f scripts/st_urllist $(DESTDIR)$(PREFIX)/bin
cp -f scripts/st_buffer $(DESTDIR)$(PREFIX)/bin
cp -f scripts/st_xurls $(DESTDIR)$(PREFIX)/bin
cp -f scripts/st_help $(DESTDIR)$(PREFIX)/bin
chmod +x $(DESTDIR)$(PREFIX)/bin/st_urllist
chmod +x $(DESTDIR)$(PREFIX)/bin/st_buffer
chmod +x $(DESTDIR)$(PREFIX)/bin/st_xurls
chmod +x $(DESTDIR)$(PREFIX)/bin/st_help
mkdir -p $(DESTDIR)$(ICONPREFIX)
[ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || :
tic -sx st.info
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/st
rm -f $(DESTDIR)$(PREFIX)/bin/st.desktop
rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1
rm -f $(DESTDIR)$(ICONPREFIX)/$(ICONNAME)
help:
@echo "st Makefile help"
@echo
@echo "install Install st."
@echo "uninstall Uninstall st."
@echo "clean Remove st tarball and binary"
@echo "options Print compilation options."
@echo "enablefont Install the font.ttf using fontctrl."
@echo "dist Create a tarball for use with package managers or for releases."
@echo "help List of all options."
enablefont:
fontctrl install font.ttf --global
fontctrl enable font.ttf --global
.PHONY: all options clean dist install uninstall enablefont help
.PHONY: all options clean dist install uninstall

34
README
View file

@ -1,34 +0,0 @@
st - simple terminal
--------------------
st is a simple terminal emulator for X which sucks less.
Requirements
------------
In order to build st you need the Xlib header files.
Installation
------------
Edit config.mk to match your local setup (st is installed into
the /usr/local namespace by default).
Afterwards enter the following command to build and install st (if
necessary as root):
make clean install
Running st
----------
If you did not install st with make clean install, you must compile
the st terminfo entry with the following command:
tic -sx st.info
See the man page for additional details.
Credits
-------
Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code.

5
arg.h
View file

@ -1,3 +1,8 @@
/*
* Copy me if you can.
* by 20h
*/
#ifndef ARG_H__
#define ARG_H__

220
array.h
View file

@ -1,220 +0,0 @@
/* st key array */
/*
* 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 };
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},
};

10
ascii.h Normal file
View file

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

View file

@ -4,8 +4,12 @@
*/
#include <X11/Xft/Xft.h>
/* included to prevent issues */
#include "sixel.h"
#include "st.h"
#include "boxdraw_data.h"
#include "bd.h"
/* Rounded non-negative integers division of n / d */
#define DIV(n, d) (((n) + (d) / 2) / (d))

View file

@ -1,25 +1,30 @@
/* st color array */
/* color array */
/* Terminal colors (16 first used in escape sequence) */
static char *colorname[] = {
/* 8 normal colors */
[0] = ncolor1, /* black */
[1] = ncolor2, /* red */
[2] = ncolor3, /* green */
[3] = ncolor4, /* yellow */
[4] = ncolor5, /* blue */
[5] = ncolor6, /* magenta */
[6] = ncolor7, /* cyan */
[7] = ncolor8, /* white */
/* 8 bright colors */
[8] = bcolor1, /* black */
[9] = bcolor2, /* red */
[10] = bcolor3, /* green */
[11] = bcolor4, /* yellow */
[12] = bcolor5, /* blue */
[13] = bcolor6, /* magenta */
[14] = bcolor7, /* cyan */
[15] = bcolor8, /* white */
/* special colors */
[256] = bgcolor, /* background */
[257] = fgcolor, /* foreground */
static char *colorname[] = {
col_1, /* black */
col_2, /* red3 */
col_3, /* green3 */
col_4, /* yellow3 */
col_5, /* blue2 */
col_6, /* magenta3 */
col_7, /* cyan3 */
col_8, /* gray90 */
col_9, /* gray50 */
col_10, /* red */
col_11, /* green */
col_12, /* yellow */
col_13, /* #5c5cff */
col_14, /* magenta */
col_15, /* cyan */
col_16, /* white */
[255] = 0,
"#cccccc",
"#555555",
"#c0c5ce",
"#696969",
[258] = cscolor, /* cursor color */
[259] = rcscolor, /* rev cursor color */
};

View file

@ -1,9 +0,0 @@
/* st externalpipe
*
* Externalpipe allows the user to write scripts that can read the text on the screen and perform actions on it (basically st | <script>).
*
* Below you can set the commands that will run, that can be, for example, bound to a key (see keybinds.h)
*/
char *externalpipe_sigusr1[] = { "/bin/sh", "-c", "st_buffer st_strings_read" };
static char *listurl[] = { "/bin/sh", "-c", "st_urllist", NULL };

BIN
font.ttf

Binary file not shown.

4
hb.c
View file

@ -5,6 +5,9 @@
#include <hb.h>
#include <hb-ft.h>
/* this is to prevent some issues */
#include "sixel.h"
#include "st.h"
void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length);
@ -88,6 +91,7 @@ hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int
for (int i = 0, specidx = 0; i < len; i++) {
if (glyphs[i].mode & ATTR_WDUMMY)
continue;
if (glyphs[i].mode & ATTR_BOXDRAW) {
specidx++;
continue;

View file

@ -10,25 +10,24 @@
* ANY = Any of the above modifiers
* NONE = No modifier at all
*/
static Shortcut shortcuts[] = {
/* modifier keysym function argument */
{ NONE, XK_Break, sendbreak, {.i = 0} },
{ CONTROL, XK_Print, toggleprinter, {.i = 0} },
{ SHIFT, XK_Print, printscreen, {.i = 0} },
{ NONE, XK_Print, printsel, {.i = 0} },
{ CONTROL, XK_equal, zoom, {.f = +1} },
{ CONTROL, XK_minus, zoom, {.f = -1} },
{ CONTROL, XK_0, zoomreset, {.f = 0} },
/* mask keysym function argument */
{ ANY, XK_Break, sendbreak, {.i = 0} },
{ CONTROL, XK_Print, toggleprinter, {.i = 0} },
{ SHIFT, XK_Print, printscreen, {.i = 0} },
{ ANY, XK_Print, printsel, {.i = 0} },
{ CONTROL, XK_equal, zoom, {.f = +1} },
{ CONTROL, XK_minus, zoom, {.f = -1} },
{ CONTROL, XK_0, zoomreset, {.f = 0} },
{ CONTROL, XK_y, clipcopy, {.i = 0} },
{ CONTROL, XK_p, clippaste, {.i = 0} },
{ CONTROL|SHIFT, XK_Num_Lock, numlock, {.i = 0} },
{ CONTROL|SHIFT, XK_Escape, keyboard_select,{.i = 0} },
{ CONTROL, XK_Num_Lock, numlock, {.i = 0} },
{ CONTROL, XK_Escape, keyboardselect, {.i = 0} },
{ CONTROL|SHIFT, XK_C, kexec, {.scmd = "clear" } },
{ CONTROL|SHIFT, XK_H, kexec, {.scmd = "st_help" } },
{ CONTROL|SHIFT, XK_E, kexec, {.scmd = "$EDITOR" } },
{ CONTROL|SHIFT, XK_D, kexec, {.scmd = "$PERM !!" } },
{ CONTROL|SHIFT, XK_K, kscrollup, {.i = +1} },
{ CONTROL|SHIFT, XK_J, kscrolldown, {.i = +1} },
{ CONTROL|SHIFT, XK_U, externalpipeout,{.v = listurl } },
{ CONTROL|SHIFT, XK_K, kscrollup, {.i = -1} },
{ CONTROL|SHIFT, XK_J, kscrolldown, {.i = -1} },
{ CONTROL|SHIFT, XK_U, externalpipeout,{.v = listurl } },
};

301
keys.h Normal file
View file

@ -0,0 +1,301 @@
/*
* If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
* to be mapped below, add them to this array.
*/
static KeySym mappedkeys[] = {
XK_space,
XK_m,
XK_i,
XK_A,
XK_B,
XK_C,
XK_D,
XK_E,
XK_F,
XK_G,
XK_H,
XK_I,
XK_K,
XK_J,
XK_L,
XK_M,
XK_N,
XK_O,
XK_P,
XK_Q,
XK_R,
XK_S,
XK_T,
XK_U,
XK_V,
XK_W,
XK_X,
XK_Y,
XK_Z,
XK_Z,
XK_0,
XK_1,
XK_2,
XK_3,
XK_4,
XK_5,
XK_6,
XK_7,
XK_8,
XK_9,
XK_exclam,
XK_quotedbl,
XK_numbersign,
XK_dollar,
XK_percent,
XK_ampersand,
XK_apostrophe,
XK_parenleft,
XK_parenright,
XK_asterisk,
XK_plus,
XK_comma,
XK_minus,
XK_period,
XK_slash,
XK_colon,
XK_semicolon,
XK_less,
XK_equal,
XK_greater,
XK_question,
XK_at,
XK_bracketleft,
XK_backslash,
XK_bracketright,
XK_asciicircum,
XK_underscore,
XK_grave,
XK_braceleft,
XK_bar,
XK_braceright,
XK_asciitilde,
};
/*
* State bits to ignore when matching key or button events. By default,
* numlock (Mod2Mask) and keyboard layout (SWITCH) are ignored.
*/
static uint ignoremod = Mod2Mask|SWITCH;
static uint forcemousemod = SHIFT;
static uint selmasks[] = {
[SEL_RECTANGULAR] = ALT,
};
static Key key[] = {
/* keysym mask string appkey appcursor */
{ XK_KP_Home, SHIFT, "\033[2J", 0, -1},
{ XK_KP_Home, SHIFT, "\033[1;2H", 0, +1},
{ XK_KP_Home, ANY, "\033[H", 0, -1},
{ XK_KP_Home, ANY, "\033[1~", 0, +1},
{ XK_KP_Up, ANY, "\033Ox", +1, 0},
{ XK_KP_Up, ANY, "\033[A", 0, -1},
{ XK_KP_Up, ANY, "\033OA", 0, +1},
{ XK_KP_Down, ANY, "\033Or", +1, 0},
{ XK_KP_Down, ANY, "\033[B", 0, -1},
{ XK_KP_Down, ANY, "\033OB", 0, +1},
{ XK_KP_Left, ANY, "\033Ot", +1, 0},
{ XK_KP_Left, ANY, "\033[D", 0, -1},
{ XK_KP_Left, ANY, "\033OD", 0, +1},
{ XK_KP_Right, ANY, "\033Ov", +1, 0},
{ XK_KP_Right, ANY, "\033[C", 0, -1},
{ XK_KP_Right, ANY, "\033OC", 0, +1},
{ XK_KP_Prior, SHIFT, "\033[5;2~", 0, 0},
{ XK_KP_Prior, ANY, "\033[5~", 0, 0},
{ XK_KP_Begin, ANY, "\033[E", 0, 0},
{ XK_KP_End, CONTROL, "\033[J", -1, 0},
{ XK_KP_End, CONTROL, "\033[1;5F", +1, 0},
{ XK_KP_End, SHIFT, "\033[K", -1, 0},
{ XK_KP_End, SHIFT, "\033[1;2F", +1, 0},
{ XK_KP_End, ANY, "\033[4~", 0, 0},
{ XK_KP_Next, SHIFT, "\033[6;2~", 0, 0},
{ XK_KP_Next, ANY, "\033[6~", 0, 0},
{ XK_KP_Insert, SHIFT, "\033[2;2~", +1, 0},
{ XK_KP_Insert, SHIFT, "\033[4l", -1, 0},
{ XK_KP_Insert, CONTROL, "\033[L", -1, 0},
{ XK_KP_Insert, CONTROL, "\033[2;5~", +1, 0},
{ XK_KP_Insert, ANY, "\033[4h", -1, 0},
{ XK_KP_Insert, ANY, "\033[2~", +1, 0},
{ XK_KP_Delete, CONTROL, "\033[M", -1, 0},
{ XK_KP_Delete, CONTROL, "\033[3;5~", +1, 0},
{ XK_KP_Delete, SHIFT, "\033[2K", -1, 0},
{ XK_KP_Delete, SHIFT, "\033[3;2~", +1, 0},
{ XK_KP_Delete, ANY, "\033[P", -1, 0},
{ XK_KP_Delete, ANY, "\033[3~", +1, 0},
{ XK_KP_Multiply, ANY, "\033Oj", +2, 0},
{ XK_KP_Add, ANY, "\033Ok", +2, 0},
{ XK_KP_Enter, ANY, "\033OM", +2, 0},
{ XK_KP_Enter, ANY, "\r", -1, 0},
{ XK_KP_Subtract, ANY, "\033Om", +2, 0},
{ XK_KP_Decimal, ANY, "\033On", +2, 0},
{ XK_KP_Divide, ANY, "\033Oo", +2, 0},
{ XK_KP_0, ANY, "\033Op", +2, 0},
{ XK_KP_1, ANY, "\033Oq", +2, 0},
{ XK_KP_2, ANY, "\033Or", +2, 0},
{ XK_KP_3, ANY, "\033Os", +2, 0},
{ XK_KP_4, ANY, "\033Ot", +2, 0},
{ XK_KP_5, ANY, "\033Ou", +2, 0},
{ XK_KP_6, ANY, "\033Ov", +2, 0},
{ XK_KP_7, ANY, "\033Ow", +2, 0},
{ XK_KP_8, ANY, "\033Ox", +2, 0},
{ XK_KP_9, ANY, "\033Oy", +2, 0},
{ XK_Up, SHIFT, "\033[1;2A", 0, 0},
{ XK_Up, ALT, "\033[1;3A", 0, 0},
{ XK_Up, SHIFT|ALT, "\033[1;4A", 0, 0},
{ XK_Up, CONTROL, "\033[1;5A", 0, 0},
{ XK_Up, SHIFT|CONTROL, "\033[1;6A", 0, 0},
{ XK_Up, CONTROL|ALT, "\033[1;7A", 0, 0},
{ XK_Up,SHIFT|CONTROL|ALT, "\033[1;8A", 0, 0},
{ XK_Up, ANY, "\033[A", 0, -1},
{ XK_Up, ANY, "\033OA", 0, +1},
{ XK_Down, SHIFT, "\033[1;2B", 0, 0},
{ XK_Down, ALT, "\033[1;3B", 0, 0},
{ XK_Down, SHIFT|ALT, "\033[1;4B", 0, 0},
{ XK_Down, CONTROL, "\033[1;5B", 0, 0},
{ XK_Down, SHIFT|CONTROL, "\033[1;6B", 0, 0},
{ XK_Down, CONTROL|ALT, "\033[1;7B", 0, 0},
{ XK_Down,SHIFT|CONTROL|ALT, "\033[1;8B",0, 0},
{ XK_Down, ANY, "\033[B", 0, -1},
{ XK_Down, ANY, "\033OB", 0, +1},
{ XK_Left, SHIFT, "\033[1;2D", 0, 0},
{ XK_Left, ALT, "\033[1;3D", 0, 0},
{ XK_Left, SHIFT|ALT, "\033[1;4D", 0, 0},
{ XK_Left, CONTROL, "\033[1;5D", 0, 0},
{ XK_Left, SHIFT|CONTROL, "\033[1;6D", 0, 0},
{ XK_Left, CONTROL|ALT, "\033[1;7D", 0, 0},
{ XK_Left,SHIFT|CONTROL|ALT, "\033[1;8D",0, 0},
{ XK_Left, ANY, "\033[D", 0, -1},
{ XK_Left, ANY, "\033OD", 0, +1},
{ XK_Right, SHIFT, "\033[1;2C", 0, 0},
{ XK_Right, ALT, "\033[1;3C", 0, 0},
{ XK_Right, SHIFT|ALT, "\033[1;4C", 0, 0},
{ XK_Right, CONTROL, "\033[1;5C", 0, 0},
{ XK_Right, SHIFT|CONTROL, "\033[1;6C", 0, 0},
{ XK_Right, CONTROL|ALT, "\033[1;7C", 0, 0},
{ XK_Right,SHIFT|CONTROL|ALT, "\033[1;8C",0, 0},
{ XK_Right, ANY, "\033[C", 0, -1},
{ XK_Right, ANY, "\033OC", 0, +1},
{ XK_ISO_Left_Tab, SHIFT, "\033[Z", 0, 0},
{ XK_Return, ALT, "\033\r", 0, 0},
{ XK_Return, ANY, "\r", 0, 0},
{ XK_Insert, SHIFT, "\033[4l", -1, 0},
{ XK_Insert, SHIFT, "\033[2;2~", +1, 0},
{ XK_Insert, CONTROL, "\033[L", -1, 0},
{ XK_Insert, CONTROL, "\033[2;5~", +1, 0},
{ XK_Insert, ANY, "\033[4h", -1, 0},
{ XK_Insert, ANY, "\033[2~", +1, 0},
{ XK_Delete, CONTROL, "\033[M", -1, 0},
{ XK_Delete, CONTROL, "\033[3;5~", +1, 0},
{ XK_Delete, SHIFT, "\033[2K", -1, 0},
{ XK_Delete, SHIFT, "\033[3;2~", +1, 0},
{ XK_Delete, ANY, "\033[P", -1, 0},
{ XK_Delete, ANY, "\033[3~", +1, 0},
{ XK_BackSpace, NONE, "\177", 0, 0},
{ XK_BackSpace, ALT, "\033\177", 0, 0},
{ XK_Home, SHIFT, "\033[2J", 0, -1},
{ XK_Home, SHIFT, "\033[1;2H", 0, +1},
{ XK_Home, ANY, "\033[H", 0, -1},
{ XK_Home, ANY, "\033[1~", 0, +1},
{ XK_End, CONTROL, "\033[J", -1, 0},
{ XK_End, CONTROL, "\033[1;5F", +1, 0},
{ XK_End, SHIFT, "\033[K", -1, 0},
{ XK_End, SHIFT, "\033[1;2F", +1, 0},
{ XK_End, ANY, "\033[4~", 0, 0},
{ XK_Prior, CONTROL, "\033[5;5~", 0, 0},
{ XK_Prior, SHIFT, "\033[5;2~", 0, 0},
{ XK_Prior, ANY, "\033[5~", 0, 0},
{ XK_Next, CONTROL, "\033[6;5~", 0, 0},
{ XK_Next, SHIFT, "\033[6;2~", 0, 0},
{ XK_Next, ANY, "\033[6~", 0, 0},
{ XK_F1, NONE, "\033OP" , 0, 0},
{ XK_F1, /* F13 */ SHIFT, "\033[1;2P", 0, 0},
{ XK_F1, /* F25 */ CONTROL, "\033[1;5P", 0, 0},
{ XK_F1, /* F37 */ SUPER, "\033[1;6P", 0, 0},
{ XK_F1, /* F49 */ ALT, "\033[1;3P", 0, 0},
{ XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0},
{ XK_F2, NONE, "\033OQ" , 0, 0},
{ XK_F2, /* F14 */ SHIFT, "\033[1;2Q", 0, 0},
{ XK_F2, /* F26 */ CONTROL, "\033[1;5Q", 0, 0},
{ XK_F2, /* F38 */ SUPER, "\033[1;6Q", 0, 0},
{ XK_F2, /* F50 */ ALT, "\033[1;3Q", 0, 0},
{ XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0},
{ XK_F3, NONE, "\033OR" , 0, 0},
{ XK_F3, /* F15 */ SHIFT, "\033[1;2R", 0, 0},
{ XK_F3, /* F27 */ CONTROL, "\033[1;5R", 0, 0},
{ XK_F3, /* F39 */ SUPER, "\033[1;6R", 0, 0},
{ XK_F3, /* F51 */ ALT, "\033[1;3R", 0, 0},
{ XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0},
{ XK_F4, NONE, "\033OS" , 0, 0},
{ XK_F4, /* F16 */ SHIFT, "\033[1;2S", 0, 0},
{ XK_F4, /* F28 */ CONTROL, "\033[1;5S", 0, 0},
{ XK_F4, /* F40 */ SUPER, "\033[1;6S", 0, 0},
{ XK_F4, /* F52 */ ALT, "\033[1;3S", 0, 0},
{ XK_F5, NONE, "\033[15~", 0, 0},
{ XK_F5, /* F17 */ SHIFT, "\033[15;2~", 0, 0},
{ XK_F5, /* F29 */ CONTROL, "\033[15;5~", 0, 0},
{ XK_F5, /* F41 */ SUPER, "\033[15;6~", 0, 0},
{ XK_F5, /* F53 */ ALT, "\033[15;3~", 0, 0},
{ XK_F6, NONE, "\033[17~", 0, 0},
{ XK_F6, /* F18 */ SHIFT, "\033[17;2~", 0, 0},
{ XK_F6, /* F30 */ CONTROL, "\033[17;5~", 0, 0},
{ XK_F6, /* F42 */ SUPER, "\033[17;6~", 0, 0},
{ XK_F6, /* F54 */ ALT, "\033[17;3~", 0, 0},
{ XK_F7, NONE, "\033[18~", 0, 0},
{ XK_F7, /* F19 */ SHIFT, "\033[18;2~", 0, 0},
{ XK_F7, /* F31 */ CONTROL, "\033[18;5~", 0, 0},
{ XK_F7, /* F43 */ SUPER, "\033[18;6~", 0, 0},
{ XK_F7, /* F55 */ ALT, "\033[18;3~", 0, 0},
{ XK_F8, NONE, "\033[19~", 0, 0},
{ XK_F8, /* F20 */ SHIFT, "\033[19;2~", 0, 0},
{ XK_F8, /* F32 */ CONTROL, "\033[19;5~", 0, 0},
{ XK_F8, /* F44 */ SUPER, "\033[19;6~", 0, 0},
{ XK_F8, /* F56 */ ALT, "\033[19;3~", 0, 0},
{ XK_F9, NONE, "\033[20~", 0, 0},
{ XK_F9, /* F21 */ SHIFT, "\033[20;2~", 0, 0},
{ XK_F9, /* F33 */ CONTROL, "\033[20;5~", 0, 0},
{ XK_F9, /* F45 */ SUPER, "\033[20;6~", 0, 0},
{ XK_F9, /* F57 */ ALT, "\033[20;3~", 0, 0},
{ XK_F10, NONE, "\033[21~", 0, 0},
{ XK_F10, /* F22 */ SHIFT, "\033[21;2~", 0, 0},
{ XK_F10, /* F34 */ CONTROL, "\033[21;5~", 0, 0},
{ XK_F10, /* F46 */ SUPER, "\033[21;6~", 0, 0},
{ XK_F10, /* F58 */ ALT, "\033[21;3~", 0, 0},
{ XK_F11, NONE, "\033[23~", 0, 0},
{ XK_F11, /* F23 */ SHIFT, "\033[23;2~", 0, 0},
{ XK_F11, /* F35 */ CONTROL, "\033[23;5~", 0, 0},
{ XK_F11, /* F47 */ SUPER, "\033[23;6~", 0, 0},
{ XK_F11, /* F59 */ ALT, "\033[23;3~", 0, 0},
{ XK_F12, NONE, "\033[24~", 0, 0},
{ XK_F12, /* F24 */ SHIFT, "\033[24;2~", 0, 0},
{ XK_F12, /* F36 */ CONTROL, "\033[24;5~", 0, 0},
{ XK_F12, /* F48 */ SUPER, "\033[24;6~", 0, 0},
{ XK_F12, /* F60 */ ALT, "\033[24;3~", 0, 0},
{ XK_F13, NONE, "\033[1;2P", 0, 0},
{ XK_F14, NONE, "\033[1;2Q", 0, 0},
{ XK_F15, NONE, "\033[1;2R", 0, 0},
{ XK_F16, NONE, "\033[1;2S", 0, 0},
{ XK_F17, NONE, "\033[15;2~", 0, 0},
{ XK_F18, NONE, "\033[17;2~", 0, 0},
{ XK_F19, NONE, "\033[18;2~", 0, 0},
{ XK_F20, NONE, "\033[19;2~", 0, 0},
{ XK_F21, NONE, "\033[20;2~", 0, 0},
{ XK_F22, NONE, "\033[21;2~", 0, 0},
{ XK_F23, NONE, "\033[23;2~", 0, 0},
{ XK_F24, NONE, "\033[24;2~", 0, 0},
{ XK_F25, NONE, "\033[1;5P", 0, 0},
{ XK_F26, NONE, "\033[1;5Q", 0, 0},
{ XK_F27, NONE, "\033[1;5R", 0, 0},
{ XK_F28, NONE, "\033[1;5S", 0, 0},
{ XK_F29, NONE, "\033[15;5~", 0, 0},
{ XK_F30, NONE, "\033[17;5~", 0, 0},
{ XK_F31, NONE, "\033[18;5~", 0, 0},
{ XK_F32, NONE, "\033[19;5~", 0, 0},
{ XK_F33, NONE, "\033[20;5~", 0, 0},
{ XK_F34, NONE, "\033[21;5~", 0, 0},
{ XK_F35, NONE, "\033[23;5~", 0, 0},
};

View file

@ -1,24 +0,0 @@
/*
* Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set).
* Note that if you want to use ShiftMask with selmasks, set this to an other
* modifier, set to 0 to not use it.
*/
static uint forcemousemod = SHIFT;
/* Modifier header
* 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;
/*
* 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,
};

31
mouse.h
View file

@ -1,19 +1,24 @@
/* This header file is for Mouse keybinds.
/* Mouse binds
*
* Make sure you don't overload Button1 (Left click).
* CONTROL = Left Control/Ctrl key
* SHIFT = Left Shift key
* ALT = Left Alt key
* ALTR = Right Alt key
* SUPER = Left Super/Windows/Command key
* SUPERR = Right Super/Windows/Command key
* ANY = Any of the above modifiers
* NONE = No modifier at all
*
* Mouse1 | Left Click
* Mouse2 | Middle Click
* Note that overloading Button1 will disable the selection.
*/
static MouseShortcut mshortcuts[] = {
/* mask button function argument release */
{ XK_NO_MOD, Button4, kscrollup, {.i = 1} },
{ XK_NO_MOD, Button5, kscrolldown, {.i = 1} },
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
{ ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
{ XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
/* mask button function argument release */
{ ANY, Button4, kscrollup, {.i = 1}, 0, -1 },
{ ANY, Button5, kscrolldown, {.i = 1}, 0, -1 },
{ ANY, Button3, selpaste, {.i = 0}, 1 },
{ SHIFT, Button4, ttysend, {.s = "\033[5;2~" } },
{ ANY, Button4, ttysend, {.s = "\031" } },
{ SHIFT, Button5, ttysend, {.s = "\033[6;2~" } },
{ ANY, Button5, ttysend, {.s = "\005" } },
};

244
options.h
View file

@ -1,129 +1,54 @@
/* speedie.gq's build of suckless.org's simple terminal (st).
/* speedie's build of suckless.org's simple terminal (st).
*
* This is a fork of suckless's st, a minimal in design, just works terminal emulator that by default does nothing more.
* Note that this terminal has a list of fonts (See 'Font options') that must be changed before installing.
*
* Additionally, if you use OpenBSD or FreeBSD, you must edit 'config.mk'.
* If you use GNU/Linux, you should be able to recompile st.
* Additionally, if you use OpenBSD or FreeBSD, you must edit 'options.mk'.
* If you use GNU/Linux, you should be able to recompile st provided all dependencies are installed.
*
* Note: To find out what to enter in *font, run 'fc-list | grep <fontname>'.
*
* To find out what to enter in the font and font2 chars, run 'fc-list | grep <fontname>'.
* Font options
*/
static char *font = "DejaVuSansMono Nerd Font:style=Bold:pixelsize=12:antialias=true:autohint=true"; /* Main font to use */
/* This font should be bundled with st. Install it manually or with fontctrl (available here: https://codeberg.org/speedie/fontctrl)
* If it is not available, you may need to 'fontctrl install <font file> --global'.
*/
/* Secondary fonts
*
* These will be picked if the *font does not exist, or doesn't contain the glyphs necessary.
* You can add multiple fonts if you wish.
*
* For best compatibility, have one Emoji font, one regular font, one Powerline font and one Nerd font.
* If you don't need these, you can of course omit them.
*/
static char *font2[] = { "DejaVu Sans Mono:pixelsize=12:antialias=true:autohint=true",
"Noto Color Emoji:pixelsize=12:antialias=true:autohint=true",
"fontawesome:pixelsize=12:antialias=true:autohint=true",
static char *font[] = { "Cascadia Code PL:size=8:style=Bold:antialias=true:autohint=true",
"DejaVu Sans Mono:size=8:antialias=true:autohint=true",
"Noto Color Emoji:size=8:antialias=true:autohint=true",
"fontawesome:size=8:antialias=true:autohint=true",
};
/* Window options */
static int borderpx = 0; /* Size of a small border around the text */
int allowaltscreen = 1; /* Allow alt screen */
int allowwindowops = 1; /* Allow non-interactive, insecure window operations such as setting the clipboard text */
int windowdecorations = 1; /* Use window decorations */
int borderpx = 0; /* Size of the border around the text (in pixels) */
int allowaltscreen = 1; /* Allow alt screen */
int allowwindowops = 1; /* Allow insecure operations such as setting the clipboard text */
int windowdecorations = 1; /* Display window decoration (0/1) */
/* Execution options */
static char *shell = "/bin/sh"; /* Shell to execute -e requests with. */
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
/* Character bounding-box multipliers */
static float cwscale = 1.0;
static float chscale = 1.0;
/* Text drawing options */
int boldbright = 0; /* Draw bold text using bright colors */
static unsigned int cols = 80; /* Number of columns */
static unsigned int rows = 24; /* Number of rows */
wchar_t *worddelimiters = L" ";
/* Text latency options */
static uint synctimeout = 200; /* Time before refreshing */
static double minlatency = 8; /* Minimum latency */
static double maxlatency = 33; /* Maximum latency */
static int brightbold = 0; /* Should bright text also be bold? */
static unsigned int cols = 80; /* Number of columns */
static unsigned int rows = 24; /* Number of rows */
wchar_t *worddelimiters = L" ";
/* Mouse options */
static unsigned int doubleclicktimeout = 300;
static unsigned int tripleclicktimeout = 600;
/* URL clicker options */
static char *url_opener = "xdg-open"; /* Application to open the clicked URL in */
/* Text latency options */
static uint synctimeout = 200; /* Time before refreshing in milliseconds */
static double minlatency = 8; /* Minimum latency */
static double maxlatency = 33; /* Maximum latency */
/*
* Default colour and shape of the mouse cursor
*/
static unsigned int mouseshape = XC_xterm;
static unsigned int mousefg = 7;
static unsigned int mousebg = 0;
/* Execution options */
static char *shell = "/bin/sh"; /* Shell to execute with the '-e' (execute command) flag. */
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
/* Character bounding-box multipliers */
static float cwscale = 1.0;
static float chscale = 1.0;
/* Color options
*
* Regular colors (1-8)
* Note that these can also be set in .Xresources, despite being #defined here.
*/
#define col_1 "#5c5c5c" /* regular color 1 */
#define col_2 "#e57373" /* regular color 2 */
#define col_3 "#02982e" /* regular color 3 */
#define col_4 "#fac863" /* regular color 4 */
#define col_5 "#6699cc" /* regular color 5 */
#define col_6 "#a36ac7" /* regular color 6 */
#define col_7 "#5fb3b3" /* regular color 7 */
#define col_8 "#c0c5ce" /* regular color 8 */
/* Bright colors (9-16) */
#define col_9 "#00ffaa" /* bright color 1 */
#define col_10 "#e57373" /* bright color 2 */
#define col_11 "#a6bc69" /* bright color 3 */
#define col_12 "#6699cc" /* bright color 4 */
#define col_13 "#5fb3b3" /* bright color 5 */
#define col_14 "#c594c5" /* bright color 6 */
#define col_15 "#cccccc" /* bright color 7 */
#define col_16 "#555555" /* bright color 8 */
/* Alpha options */
float alpha = 0.8;
/*
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
unsigned int defaultfg = 258; /* Foreground */
unsigned int defaultbg = 232; /* Background */
unsigned int defaultcs = 256; /* Cursor */
unsigned int defaultrc = 257; /* Reverse cursor */
unsigned int defaultattr = 11; /* Invalid font returned by fontconfig */
/* Cursor options
*
* Thickness of underline and bar cursors
*/
static unsigned int cursorthickness = 2;
static unsigned int blinktimeout = 800; /* Timeout in milliseconds between cursor blink.
* Setting this to 0 will disable the blinking cursor!
*/
/*
* 0: Blinking block
* 1: Blinking block (default)
* 2: Steady block ("")
* 3: Blinking underline
* 4: Steady underline ("_")
* 5: Blinking bar
* 6: Steady bar ("|")
* 7: Blinking ccursor cursor
* 8: Steady ccursor cursor
*/
static unsigned int cursorstyle = 1; /* Style to draw the cursor in */
static Rune ccursor = 0x2603; /* Snowman ("☃") */
/* Cursor options */
static unsigned int blinktimeout = 800; /* Cursor blink timeout in milliseconds */
static unsigned int cursorthickness = 2; /* Cursor thickness in pixels */
/* Boxdraw options
*
@ -132,13 +57,13 @@ static Rune ccursor = 0x2603; /* Snowman ("☃") */
* Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored.
* 0: Disable boxdraw (render all U25XX glyphs normally from the font).
*/
int boxdraw = 0; /* Enable boxdraw */
int boxdraw_bold = 0; /* Draw boxdraw bold */
int boxdraw_braille = 0; /* Render braille as adjecent pixels */
int boxdraw = 0; /* Enable boxdraw */
int boxdraw_bold = 0; /* Draw boxdraw bold */
int boxdraw_braille = 0; /* Render braille as adjecent pixels */
/* Undercurl options
*
* Undercurl allows your terminal and TUI software to draw undercurl instead of an underline.
* Undercurl allows your terminal to draw undercurl instead of an underline.
* This looks nice to a lot of people.
*
* Curly:
@ -169,16 +94,91 @@ int boxdraw_braille = 0; /* Render braille as adjecent pixels */
static char *understyle = "1"; /* Undercurl style to use */
/* Bell options
*/
static int bellvolume = 0; /* Bell volume value between -100 and 100. 0 will disable it! */
/* Bell options */
static int bellvolume = 0; /* Bell volume value between -100 and 100. 0 will disable it! */
/* Default $TERM value
/* Misc terminal options */
char *termname = "st-256color"; /* TERM value, underline will break if it is not set to st-* */
unsigned int tabspaces = 4; /* Number of spaces per tab. 8 is common, I prefer 4. */
/* Alpha options */
float alpha = 0.8; /* Background alpha/opacity between 0 and 1. */
float gradalpha = 0.54; /* Background gradient alpha value that will be changed */
float statalpha = 0.46; /* Alpha that will be added to gradalpha */
/* Gradient options */
static int gradient = 0; /* Enable alpha gradient (0/1) */
static int graddirection = 0; /* Direction of the gradient (0: down, 1: up) */
/* Color options
*
* If you find that you need it, you may set this to xterm-256color for extra compatibility
* Or if you prefer, you may also use no color or 16 color to disable full color support.
*/
char *termname = "st-256color"; /* $TERM value to export */
* These should be in HTML color format.
* Most terminals will have 8 regular colors followed by 8 (usually) bright colors.
*
* Bright colors have the 'b' prefix and normal colors have the 'n' prefix.
* You can also set these through .Xresources.
*
* Normal colors */
static char ncolor1[] = "#000000"; /* Normal color 1 */
static char ncolor2[] = "#ff5555"; /* Normal color 2 */
static char ncolor3[] = "#50fa7b"; /* Normal color 3 */
static char ncolor4[] = "#f1fa8c"; /* Normal color 4 */
static char ncolor5[] = "#bd93f9"; /* Normal color 5 */
static char ncolor6[] = "#ff79c6"; /* Normal color 6 */
static char ncolor7[] = "#8be9fd"; /* Normal color 7 */
static char ncolor8[] = "#bbbbbb"; /* Normal color 8 */
/* Tab spacing options */
unsigned int tabspaces = 4; /* Spaces per tab */
/* Bright colors */
static char bcolor1[] = "#44475a"; /* Bright color 1 */
static char bcolor2[] = "#ff5555"; /* Bright color 2 */
static char bcolor3[] = "#50fa7b"; /* Bright color 3 */
static char bcolor4[] = "#f1fa8c"; /* Bright color 4 */
static char bcolor5[] = "#bd93f9"; /* Bright color 5 */
static char bcolor6[] = "#ff79c6"; /* Bright color 6 */
static char bcolor7[] = "#8be9fd"; /* Bright color 7 */
static char bcolor8[] = "#ffffff"; /* Bright color 8 */
/* Misc colors */
static char bgcolor[] = "#111111"; /* Background color */
static char fgcolor[] = "#f8f8f2"; /* Foreground (text) color */
static char cscolor[] = "#ffffff"; /* Cursor color */
static char rcscolor[] = "#555555"; /* Reverse cursor color */
/* Color index */
unsigned int defaultfg = 257; /* Foreground color number */
unsigned int defaultbg = 256; /* Background color number */
unsigned int defaultcs = 258; /* Selection color number */
unsigned int defaultrc = 259; /* Reverse selection color number */
unsigned int defaultattr = 11; /* Color for invalid fonts */
unsigned int defaultitalic = 7; /* Italic color number */
unsigned int defaultunderline = 7; /* Underline color number */
unsigned int selectionbg = 257; /* Background selection color number */
unsigned int selectionfg = 1; /* Foreground selected color number */
unsigned int ignoreselfg = 1;
/* Cursor shape/style options
*
* 0: Blinking block
* 1: Blinking block (default)
* 2: Steady block ("")
* 3: Blinking underline
* 4: Steady underline ("_")
* 5: Blinking bar
* 6: Steady bar ("|")
* 7: Blinking ccursor cursor
* 8: Steady ccursor cursor
*/
static unsigned int cursorstyle = 1; /* Cursor style to use */
static Rune stcursor = 0x2603; /* snowman ("☃") */
static unsigned int mouseshape = XC_xterm; /* Mouse shape, default is xterm-like */
static unsigned int mousefg = 7; /* Foreground cursor color */
static unsigned int mousebg = 0; /* Background cursor color */
/* Externalpipe commands */
static char *listurl[] = { "/bin/sh", "-c", "st_urllist", NULL };
/* URL click command
*
* This command, followed by the URL will be run by the shell.
*/
static char *urlcmd = "xdg-open";

View file

@ -1,15 +1,11 @@
# st version
VERSION = 1.0
# compiler and linker
CC = tcc
VERSION = 1.3
# Customize below to fit your system
# paths
PREFIX = /usr/local
PREFIX = /usr
APPPREFIX = $(PREFIX)/share/applications
MANPREFIX = $(PREFIX)/share/man
ICONPREFIX = $(PREFIX)/share/pixmaps
ICONNAME = st.png
@ -30,13 +26,15 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender -lgd \
# flags
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -DICON=\"$(ICONPREFIX)/$(ICONNAME)\" -D_XOPEN_SOURCE=600
STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) -march=native -Ofast
STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) -Ofast -march=native -mtune=native
STLDFLAGS = $(LIBS) $(LDFLAGS)
# OpenBSD:
#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft -lXrender -lgd \
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft -lgd \
# `$(PKG_CONFIG) --libs fontconfig` \
# `$(PKG_CONFIG) --libs harfbuzz` \
# `$(PKG_CONFIG) --libs freetype2`
#MANPREFIX = ${PREFIX}/man
# compiler and linker
# CC = c99

0
scripts/st_help Normal file → Executable file
View file

47
scripts/st_pipebuffer Executable file
View file

@ -0,0 +1,47 @@
#!/bin/bash
# input Usage: echo st or surf content from externalpipe | ./externalpipe_buffer.sh {st,surf}_strings_read
# menus Usage: ./externalpipe_buffer.sh dmenu_{copy, type}
command -v xdotool > /dev/null || exit
BUFFER_FILE=/tmp/content_buffer
function st_strings_read() {
INPUT="$(cat)"
echo "$(
echo "$INPUT" | grep -Eo '\S+' | tr -d '[:blank:]'
echo "$INPUT" | grep -oP '"[^"]+"' | tr -d '"'
echo "$INPUT" | sed 's/^ *[0-9]\+.//g' | awk '{$1=$1};1'
)" | uniq | grep . | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- \
>> $BUFFER_FILE &
}
function surf_strings_read() {
awk '{printf "%sNEWLINE_REPLACE", $0} END {printf "\n"}' |
xmllint --html --xpath "//*" - |
awk '{ gsub("<[^>]*>", ""); print($0); }' |
sed 's/NEWLINE_REPLACE/↵/g' |
awk '{ gsub("<[^>]*>",""); print $0 }' |
sed 's/&lt;/</g' |
sed 's/&gt;/>/g' |
uniq | grep . | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- \
>> $BUFFER_FILE &
}
function trigger_sigusr1() {
USE_FIFO=F # Recomended as T but only if using dmenu-stdin patch w/ FIFO
rm -f $BUFFER_FILE
if [ $USE_FIFO == T ]; then mkfifo $BUFFER_FILE; else touch $BUFFER_FILE; fi
pkill -USR1 "surf" &
pkill -USR1 "^st$" &
if [ $USE_FIFO != T ]; then sleep 0.8; fi
}
function dmenu_copy() {
trigger_sigusr1
cat $BUFFER_FILE | dmenu -l 10 -i -w $(xdotool getactivewindow) -p 'Screen Copy' | sed 's/↵/\n/g' | xclip -i
}
function dmenu_type() {
trigger_sigusr1
cat $BUFFER_FILE | dmenu -l 10 -i -w $(xdotool getactivewindow) -p 'Screen Type' | sed 's/↵/\n/g' | xargs -IC xdotool type --delay 0 "C"
}
function pipe_combine() {
trigger_sigusr1
cat - $BUFFER_FILE
}
$1

607
sixel.c Normal file
View file

@ -0,0 +1,607 @@
// sixel.c (part of mintty)
// originally written by kmiya@cluti (https://github.com/saitoha/sixel/blob/master/fromsixel.c)
// Licensed under the terms of the GNU General Public License v3 or later.
#include <stdlib.h>
#include <string.h> /* memcpy */
#include "sixel.h"
#include "sixelhls.h"
#define SIXEL_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16))
#define SIXEL_PALVAL(n,a,m) (((n) * (a) + ((m) / 2)) / (m))
#define SIXEL_XRGB(r,g,b) SIXEL_RGB(SIXEL_PALVAL(r, 255, 100), SIXEL_PALVAL(g, 255, 100), SIXEL_PALVAL(b, 255, 100))
static sixel_color_t const sixel_default_color_table[] = {
SIXEL_XRGB( 0, 0, 0), /* 0 Black */
SIXEL_XRGB(20, 20, 80), /* 1 Blue */
SIXEL_XRGB(80, 13, 13), /* 2 Red */
SIXEL_XRGB(20, 80, 20), /* 3 Green */
SIXEL_XRGB(80, 20, 80), /* 4 Magenta */
SIXEL_XRGB(20, 80, 80), /* 5 Cyan */
SIXEL_XRGB(80, 80, 20), /* 6 Yellow */
SIXEL_XRGB(53, 53, 53), /* 7 Gray 50% */
SIXEL_XRGB(26, 26, 26), /* 8 Gray 25% */
SIXEL_XRGB(33, 33, 60), /* 9 Blue* */
SIXEL_XRGB(60, 26, 26), /* 10 Red* */
SIXEL_XRGB(33, 60, 33), /* 11 Green* */
SIXEL_XRGB(60, 33, 60), /* 12 Magenta* */
SIXEL_XRGB(33, 60, 60), /* 13 Cyan* */
SIXEL_XRGB(60, 60, 33), /* 14 Yellow* */
SIXEL_XRGB(80, 80, 80), /* 15 Gray 75% */
};
static int
set_default_color(sixel_image_t *image)
{
int i;
int n;
int r;
int g;
int b;
/* palette initialization */
for (n = 1; n < 17; n++) {
image->palette[n] = sixel_default_color_table[n - 1];
}
/* colors 17-232 are a 6x6x6 color cube */
for (r = 0; r < 6; r++) {
for (g = 0; g < 6; g++) {
for (b = 0; b < 6; b++) {
image->palette[n++] = SIXEL_RGB(r * 51, g * 51, b * 51);
}
}
}
/* colors 233-256 are a grayscale ramp, intentionally leaving out */
for (i = 0; i < 24; i++) {
image->palette[n++] = SIXEL_RGB(i * 11, i * 11, i * 11);
}
for (; n < DECSIXEL_PALETTE_MAX; n++) {
image->palette[n] = SIXEL_RGB(255, 255, 255);
}
return (0);
}
static int
sixel_image_init(
sixel_image_t *image,
int width,
int height,
int fgcolor,
int bgcolor,
int use_private_register)
{
int status = (-1);
size_t size;
size = (size_t)(width * height) * sizeof(sixel_color_no_t);
image->width = width;
image->height = height;
image->data = (sixel_color_no_t *)malloc(size);
image->ncolors = 2;
image->use_private_register = use_private_register;
if (image->data == NULL) {
status = (-1);
goto end;
}
memset(image->data, 0, size);
image->palette[0] = bgcolor;
if (image->use_private_register)
image->palette[1] = fgcolor;
image->palette_modified = 0;
status = (0);
end:
return status;
}
static int
image_buffer_resize(
sixel_image_t *image,
int width,
int height)
{
int status = (-1);
size_t size;
sixel_color_no_t *alt_buffer;
int n;
int min_height;
size = (size_t)(width * height) * sizeof(sixel_color_no_t);
alt_buffer = (sixel_color_no_t *)malloc(size);
if (alt_buffer == NULL) {
/* free source image */
free(image->data);
image->data = NULL;
status = (-1);
goto end;
}
min_height = height > image->height ? image->height: height;
if (width > image->width) { /* if width is extended */
for (n = 0; n < min_height; ++n) {
/* copy from source image */
memcpy(alt_buffer + width * n,
image->data + image->width * n,
(size_t)image->width * sizeof(sixel_color_no_t));
/* fill extended area with background color */
memset(alt_buffer + width * n + image->width,
0,
(size_t)(width - image->width) * sizeof(sixel_color_no_t));
}
} else {
for (n = 0; n < min_height; ++n) {
/* copy from source image */
memcpy(alt_buffer + width * n,
image->data + image->width * n,
(size_t)width * sizeof(sixel_color_no_t));
}
}
if (height > min_height) { /* if height is extended */
/* fill extended area with background color */
memset(alt_buffer + width * image->height,
0,
(size_t)(width * (height - image->height)) * sizeof(sixel_color_no_t));
}
/* free source image */
free(image->data);
image->data = alt_buffer;
image->width = width;
image->height = height;
status = (0);
end:
return status;
}
static void
sixel_image_deinit(sixel_image_t *image)
{
free(image->data);
image->data = NULL;
}
int
sixel_parser_init(sixel_state_t *st,
sixel_color_t fgcolor, sixel_color_t bgcolor,
unsigned char use_private_register,
int cell_width, int cell_height)
{
int status = (-1);
st->state = PS_DECSIXEL;
st->pos_x = 0;
st->pos_y = 0;
st->max_x = 0;
st->max_y = 0;
st->attributed_pan = 2;
st->attributed_pad = 1;
st->attributed_ph = 0;
st->attributed_pv = 0;
st->repeat_count = 1;
st->color_index = 16;
st->grid_width = cell_width;
st->grid_height = cell_height;
st->nparams = 0;
st->param = 0;
/* buffer initialization */
status = sixel_image_init(&st->image, 1, 1, fgcolor, bgcolor, use_private_register);
return status;
}
int
sixel_parser_set_default_color(sixel_state_t *st)
{
return set_default_color(&st->image);
}
int
sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels)
{
int status = (-1);
int sx;
int sy;
sixel_image_t *image = &st->image;
int x, y;
sixel_color_no_t *src;
unsigned char *dst;
int color;
if (++st->max_x < st->attributed_ph)
st->max_x = st->attributed_ph;
if (++st->max_y < st->attributed_pv)
st->max_y = st->attributed_pv;
sx = (st->max_x + st->grid_width - 1) / st->grid_width * st->grid_width;
sy = (st->max_y + st->grid_height - 1) / st->grid_height * st->grid_height;
if (image->width > sx || image->height > sy) {
status = image_buffer_resize(image, sx, sy);
if (status < 0)
goto end;
}
if (image->use_private_register && image->ncolors > 2 && !image->palette_modified) {
status = set_default_color(image);
if (status < 0)
goto end;
}
src = st->image.data;
dst = pixels;
for (y = 0; y < st->image.height; ++y) {
for (x = 0; x < st->image.width; ++x) {
color = st->image.palette[*src++];
*dst++ = color >> 16 & 0xff; /* b */
*dst++ = color >> 8 & 0xff; /* g */
*dst++ = color >> 0 & 0xff; /* r */
*dst++ = 255; /* a */
}
}
/* fill bottom padding with bgcolor */
for (; y < st->image.height; ++y) {
for (x = 0; x < st->image.width; ++x) {
color = st->image.palette[0]; /* bgcolor */
*dst++ = color >> 16 & 0xff; /* b */
*dst++ = color >> 8 & 0xff; /* g */
*dst++ = color >> 0 & 0xff; /* r */
*dst++ = 255; /* a */
}
}
status = (0);
end:
return status;
}
/* convert sixel data into indexed pixel bytes and palette data */
int
sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len)
{
int status = (-1);
int n;
int i;
int x;
int y;
int bits;
int sixel_vertical_mask;
int sx;
int sy;
int c;
int pos;
int newwidth, newheight;
unsigned char *p0 = p;
sixel_image_t *image = &st->image;
if (! image->data)
goto end;
while (p < p0 + len) {
switch (st->state) {
case PS_ESC:
goto end;
case PS_DECSIXEL:
switch (*p) {
case '\x1b':
st->state = PS_ESC;
p++;
break;
case '"':
st->param = 0;
st->nparams = 0;
st->state = PS_DECGRA;
p++;
break;
case '!':
st->param = 0;
st->nparams = 0;
st->state = PS_DECGRI;
p++;
break;
case '#':
st->param = 0;
st->nparams = 0;
st->state = PS_DECGCI;
p++;
break;
case '$':
/* DECGCR Graphics Carriage Return */
st->pos_x = 0;
p++;
break;
case '-':
/* DECGNL Graphics Next Line */
st->pos_x = 0;
if (st->pos_y < DECSIXEL_HEIGHT_MAX - 5 - 6)
st->pos_y += 6;
else
st->pos_y = DECSIXEL_HEIGHT_MAX + 1;
p++;
break;
default:
if (*p >= '?' && *p <= '~') { /* sixel characters */
newwidth = st->pos_x + st->repeat_count;
newheight = st->attributed_pv > 0 ? st->attributed_pv : st->pos_y + 6;
if ((image->width < newwidth || image->height < newheight) &&
image->width < DECSIXEL_WIDTH_MAX && image->height < DECSIXEL_HEIGHT_MAX) {
sx = image->width < newwidth ? newwidth : image->width;
sy = newheight;
if (sx > DECSIXEL_WIDTH_MAX)
sx = DECSIXEL_WIDTH_MAX;
if (sy > DECSIXEL_HEIGHT_MAX)
sy = DECSIXEL_HEIGHT_MAX;
status = image_buffer_resize(image, sx, sy);
if (status < 0)
goto end;
}
if (st->color_index > image->ncolors)
image->ncolors = st->color_index;
if (st->pos_x + st->repeat_count > image->width)
st->repeat_count = image->width - st->pos_x;
if (st->repeat_count > 0 && st->pos_y - 5 < image->height) {
bits = *p - '?';
if (bits != 0) {
sixel_vertical_mask = 0x01;
if (st->repeat_count <= 1) {
for (i = 0; i < 6; i++) {
if ((bits & sixel_vertical_mask) != 0) {
pos = image->width * (st->pos_y + i) + st->pos_x;
image->data[pos] = st->color_index;
if (st->max_x < st->pos_x)
st->max_x = st->pos_x;
if (st->max_y < (st->pos_y + i))
st->max_y = st->pos_y + i;
}
sixel_vertical_mask <<= 1;
}
} else {
/* st->repeat_count > 1 */
for (i = 0; i < 6; i++) {
if ((bits & sixel_vertical_mask) != 0) {
c = sixel_vertical_mask << 1;
for (n = 1; (i + n) < 6; n++) {
if ((bits & c) == 0)
break;
c <<= 1;
}
for (y = st->pos_y + i; y < st->pos_y + i + n; ++y) {
for (x = st->pos_x; x < st->pos_x + st->repeat_count; ++x)
image->data[image->width * y + x] = st->color_index;
}
if (st->max_x < (st->pos_x + st->repeat_count - 1))
st->max_x = st->pos_x + st->repeat_count - 1;
if (st->max_y < (st->pos_y + i + n - 1))
st->max_y = st->pos_y + i + n - 1;
i += (n - 1);
sixel_vertical_mask <<= (n - 1);
}
sixel_vertical_mask <<= 1;
}
}
}
}
if (st->repeat_count > 0)
st->pos_x += st->repeat_count;
st->repeat_count = 1;
}
p++;
break;
}
break;
case PS_DECGRA:
/* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */
switch (*p) {
case '\x1b':
st->state = PS_ESC;
p++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
st->param = st->param * 10 + *p - '0';
if (st->param > DECSIXEL_PARAMVALUE_MAX)
st->param = DECSIXEL_PARAMVALUE_MAX;
p++;
break;
case ';':
if (st->nparams < DECSIXEL_PARAMS_MAX)
st->params[st->nparams++] = st->param;
st->param = 0;
p++;
break;
default:
if (st->nparams < DECSIXEL_PARAMS_MAX)
st->params[st->nparams++] = st->param;
if (st->nparams > 0)
st->attributed_pad = st->params[0];
if (st->nparams > 1)
st->attributed_pan = st->params[1];
if (st->nparams > 2 && st->params[2] > 0)
st->attributed_ph = st->params[2];
if (st->nparams > 3 && st->params[3] > 0)
st->attributed_pv = st->params[3];
if (st->attributed_pan <= 0)
st->attributed_pan = 1;
if (st->attributed_pad <= 0)
st->attributed_pad = 1;
if (image->width < st->attributed_ph ||
image->height < st->attributed_pv) {
sx = st->attributed_ph;
if (image->width > st->attributed_ph)
sx = image->width;
sy = st->attributed_pv;
if (image->height > st->attributed_pv)
sy = image->height;
sx = (sx + st->grid_width - 1) / st->grid_width * st->grid_width;
sy = (sy + st->grid_height - 1) / st->grid_height * st->grid_height;
if (sx > DECSIXEL_WIDTH_MAX)
sx = DECSIXEL_WIDTH_MAX;
if (sy > DECSIXEL_HEIGHT_MAX)
sy = DECSIXEL_HEIGHT_MAX;
status = image_buffer_resize(image, sx, sy);
if (status < 0)
goto end;
}
st->state = PS_DECSIXEL;
st->param = 0;
st->nparams = 0;
}
break;
case PS_DECGRI:
/* DECGRI Graphics Repeat Introducer ! Pn Ch */
switch (*p) {
case '\x1b':
st->state = PS_ESC;
p++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
st->param = st->param * 10 + *p - '0';
if (st->param > DECSIXEL_PARAMVALUE_MAX)
st->param = DECSIXEL_PARAMVALUE_MAX;
p++;
break;
default:
st->repeat_count = st->param;
if (st->repeat_count == 0)
st->repeat_count = 1;
st->state = PS_DECSIXEL;
st->param = 0;
st->nparams = 0;
break;
}
break;
case PS_DECGCI:
/* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */
switch (*p) {
case '\x1b':
st->state = PS_ESC;
p++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
st->param = st->param * 10 + *p - '0';
if (st->param > DECSIXEL_PARAMVALUE_MAX)
st->param = DECSIXEL_PARAMVALUE_MAX;
p++;
break;
case ';':
if (st->nparams < DECSIXEL_PARAMS_MAX)
st->params[st->nparams++] = st->param;
st->param = 0;
p++;
break;
default:
st->state = PS_DECSIXEL;
if (st->nparams < DECSIXEL_PARAMS_MAX)
st->params[st->nparams++] = st->param;
st->param = 0;
if (st->nparams > 0) {
st->color_index = 1 + st->params[0]; /* offset 1(background color) added */
if (st->color_index < 0)
st->color_index = 0;
else if (st->color_index >= DECSIXEL_PALETTE_MAX)
st->color_index = DECSIXEL_PALETTE_MAX - 1;
}
if (st->nparams > 4) {
st->image.palette_modified = 1;
if (st->params[1] == 1) {
/* HLS */
if (st->params[2] > 360)
st->params[2] = 360;
if (st->params[3] > 100)
st->params[3] = 100;
if (st->params[4] > 100)
st->params[4] = 100;
image->palette[st->color_index]
= hls_to_rgb(st->params[2], st->params[3], st->params[4]);
} else if (st->params[1] == 2) {
/* RGB */
if (st->params[2] > 100)
st->params[2] = 100;
if (st->params[3] > 100)
st->params[3] = 100;
if (st->params[4] > 100)
st->params[4] = 100;
image->palette[st->color_index]
= SIXEL_XRGB(st->params[2], st->params[3], st->params[4]);
}
}
break;
}
break;
default:
break;
}
}
status = (0);
end:
return status;
}
void
sixel_parser_deinit(sixel_state_t *st)
{
if (st)
sixel_image_deinit(&st->image);
}

61
sixel.h Normal file
View file

@ -0,0 +1,61 @@
#ifndef SIXEL_H
#define SIXEL_H
#include <unistd.h>
#include <stdint.h>
#define DECSIXEL_PARAMS_MAX 16
#define DECSIXEL_PALETTE_MAX 1024
#define DECSIXEL_PARAMVALUE_MAX 65535
#define DECSIXEL_WIDTH_MAX 4096
#define DECSIXEL_HEIGHT_MAX 4096
typedef uint16_t sixel_color_no_t;
typedef uint32_t sixel_color_t;
typedef struct sixel_image_buffer {
sixel_color_no_t *data;
int width;
int height;
sixel_color_t palette[DECSIXEL_PALETTE_MAX];
sixel_color_no_t ncolors;
int palette_modified;
int use_private_register;
} sixel_image_t;
typedef enum parse_state {
PS_ESC = 1, /* ESC */
PS_DECSIXEL = 2, /* DECSIXEL body part ", $, -, ? ... ~ */
PS_DECGRA = 3, /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */
PS_DECGRI = 4, /* DECGRI Graphics Repeat Introducer ! Pn Ch */
PS_DECGCI = 5, /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */
} parse_state_t;
typedef struct parser_context {
parse_state_t state;
int pos_x;
int pos_y;
int max_x;
int max_y;
int attributed_pan;
int attributed_pad;
int attributed_ph;
int attributed_pv;
int repeat_count;
int color_index;
int bgindex;
int grid_width;
int grid_height;
int param;
int nparams;
int params[DECSIXEL_PARAMS_MAX];
sixel_image_t image;
} sixel_state_t;
int sixel_parser_init(sixel_state_t *st, sixel_color_t fgcolor, sixel_color_t bgcolor, unsigned char use_private_register, int cell_width, int cell_height);
int sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len);
int sixel_parser_set_default_color(sixel_state_t *st);
int sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels);
void sixel_parser_deinit(sixel_state_t *st);
#endif

116
sixelhls.c Normal file
View file

@ -0,0 +1,116 @@
/* sixel.c (part of mintty)
* this function is derived from a part of graphics.c
* in Xterm pl#310 originally written by Ross Combs.
*
* Copyright 2013,2014 by Ross Combs
*
* All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the
* sale, use or other dealings in this Software without prior written
* authorization.
*/
#define SIXEL_RGB(r, g, b) (((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;
if (sat == 0) {
r = g = b = lum * 255 / 100;
return SIXEL_RGB(r, g, b);
}
if ((c2 = ((2.0 * lv) - 1.0)) < 0.0) {
c2 = -c2;
}
c = (1.0 - c2) * sv;
hpi = (int) (hv * 6.0);
x = (hpi & 1) ? c : 0.0;
m = lv - 0.5 * c;
switch (hpi) {
case 0:
r1 = c;
g1 = x;
b1 = 0.0;
break;
case 1:
r1 = x;
g1 = c;
b1 = 0.0;
break;
case 2:
r1 = 0.0;
g1 = c;
b1 = x;
break;
case 3:
r1 = 0.0;
g1 = x;
b1 = c;
break;
case 4:
r1 = x;
g1 = 0.0;
b1 = c;
break;
case 5:
r1 = c;
g1 = 0.0;
b1 = x;
break;
default:
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);
if (r < 0) {
r = 0;
} else if (r > 100) {
r = 100;
}
if (g < 0) {
g = 0;
} else if (g > 100) {
g = 100;
}
if (b < 0) {
b = 0;
} else if (b > 100) {
b = 100;
}
return SIXEL_RGB(r * 255 / 100, g * 255 / 100, b * 255 / 100);
}

7
sixelhls.h Normal file
View file

@ -0,0 +1,7 @@
/*
* Primary color hues:
* blue: 0 degrees
* red: 120 degrees
* green: 240 degrees
*/
int hls_to_rgb(int hue, int lum, int sat);

736
st.c

File diff suppressed because it is too large Load diff

50
st.h
View file

@ -22,7 +22,6 @@
#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
#define IS_TRUECOL(x) (1 << 24 & (x))
#define HISTSIZE 2000
enum glyph_attribute {
ATTR_NULL = 0,
@ -37,10 +36,19 @@ enum glyph_attribute {
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,
ATTR_SIXEL = 1 << 11,
ATTR_SELECTED = 1 << 12,
ATTR_LIGA = 1 << 13,
ATTR_BOXDRAW = 1 << 14,
ATTR_DIRTYUNDERLINE = 1 << 15,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
enum drawing_mode {
DRAW_NONE = 0,
DRAW_BG = 1 << 0,
DRAW_FG = 1 << 1,
};
enum selection_mode {
@ -78,6 +86,23 @@ typedef struct {
typedef Glyph *Line;
typedef struct _ImageList {
struct _ImageList *next, *prev;
unsigned char *pixels;
void *pixmap;
int width;
int height;
int x;
int y;
int should_delete;
} ImageList;
typedef struct _SixelContext {
sixel_state_t state;
ImageList *images; /* sixel images */
ImageList *images_alt; /* sixel images for alternate screen */
} SixelContext;
typedef union {
int i;
uint ui;
@ -91,17 +116,20 @@ void die(const char *, ...);
void redraw(void);
void draw(void);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void kexec(const Arg *);
void kwrite(const Arg *);
void externalpipe(const Arg *, int in);
void externalpipein(const Arg *);
void externalpipeout(const Arg *);
void kexec(const Arg *);
void kwrite(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);
@ -127,6 +155,8 @@ void *xrealloc(void *, size_t);
char *xstrdup(const char *);
int trt_kbdselect(KeySym, char *, int);
void openUrlOnClick(int, int, char *);
int isboxdraw(Rune);
ushort boxdrawindex(const Glyph *);
#ifdef XFT_VERSION
@ -135,11 +165,8 @@ void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *);
void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int);
#endif
void openUrlOnClick(int, int, char *);
/* config.h globals */
extern char *utmp;
extern char *scroll;
/* options.h globals */
extern char *externalpipe_sigusr1[];
extern char *stty_args;
extern char *vtiden;
extern wchar_t *worddelimiters;
@ -150,6 +177,5 @@ extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
extern unsigned int defaultcs;
extern int uexternalpipe;
extern int boxdraw, boxdraw_bold, boxdraw_braille;
extern float alpha;

View file

@ -209,7 +209,7 @@ st-256color| simpleterm with 256 colors,
colors#256,
oc=\E]104\007,
pairs#32767,
# Nicked from xterm-256color
# Nicked from st-256color
initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,

7
text.h
View file

@ -1,7 +0,0 @@
/* Miscellanious text related options that you probably do not need to change. */
/* Ascii characters used to estimate the advance width of single wide characters */
static char ascii_printable[] =
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~";

3
toggle.h Normal file
View file

@ -0,0 +1,3 @@
/* Toggle features */
#define USEXRESOURCES 1 /* Include Xresources support (0/1) */

22
win.h
View file

@ -23,10 +23,29 @@ enum win_mode {
|MODE_MOUSEMANY,
MODE_KBDSELECT = 1 << 18,
};
/* Purely graphic info */
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 */
int mode; /* window state/mode flags */
int cursor; /* cursor style */
} TermWindow;
TermWindow gettermwindow(void);
void xbell(void);
void xclipcopy(void);
int xsixelinit(SixelContext *);
void xsixelscrolldown(SixelContext *, int, int);
void xsixelscrollup(SixelContext *, int, int);
void xsixelnewimage(SixelContext *, int, int);
int xsixelparse(SixelContext *, unsigned char *, int);
void xsixeldeleteimage(SixelContext *, ImageList *);
void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
void xdrawsixel(SixelContext *, Line *, int, int);
void xdrawline(Line, int, int, int);
void xfinishdraw(void);
void xloadcols(void);
@ -42,5 +61,6 @@ void xsetpointermotion(int);
void xsetsel(char *);
int xstartdraw(void);
void toggle_winmode(int);
void keyboard_select(const Arg *);
void keyboardselect(const Arg *);
void xximspot(int, int);
void xclearwin(void);

480
x.c
View file

@ -14,10 +14,17 @@
#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
#include <X11/XKBlib.h>
/* include user toggle */
#include "toggle.h"
#if USEXRESOURCES
#include <X11/Xresource.h>
#endif
char *argv0;
#include "arg.h"
#include "sixel.h"
#include "st.h"
#include "win.h"
#include "hb.h"
@ -36,6 +43,7 @@ typedef struct {
void (*func)(const Arg *);
const Arg arg;
uint release;
int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */
} MouseShortcut;
typedef struct {
@ -68,11 +76,6 @@ enum undercurl_slope_type {
UNDERCURL_SLOPE_BOTTOM_CAP = 3
};
/* X modifiers */
#define XK_ANY_MOD UINT_MAX
#define XK_NO_MOD 0
#define XK_SWITCH_MOD (1<<13|1<<14)
/* function definitions used in options.h */
static void clipcopy(const Arg *);
static void clippaste(const Arg *);
@ -82,8 +85,6 @@ static void zoom(const Arg *);
static void zoomabs(const Arg *);
static void zoomreset(const Arg *);
static void ttysend(const Arg *);
void kscrollup(const Arg *);
void kscrolldown(const Arg *);
/* define keys */
#define CONTROL ControlMask
@ -93,18 +94,22 @@ void kscrolldown(const Arg *);
#define SUPER Mod4Mask
#define SUPERR Mod5Mask
#define ANY UINT_MAX
#define SWITCH (1<<13|1<<14)
#define NONE 0
/* headers */
#include "options.h" /* include user options */
#include "text.h" /* include text related misc options */
#include "external.h" /* include externalpipe chars */
#include "modifiers.h" /* include modifiers */
#include "keybinds.h" /* include keybinds */
#include "mouse.h" /* include mouse options */
#include "colors.h" /* include color array */
#include "xresources.h" /* include xresources options */
#include "array.h" /* include key array */
/* user modified headers */
#include "options.h" /* main options, such as integers */
#include "keys.h" /* key array */
#include "colors.h" /* color array */
#include "ascii.h" /* ascii stuff */
#include "mouse.h" /* mouse binds */
#include "keybinds.h" /* keybinds */
#if USEXRESOURCES
#include "xresources.h" /* include xresources */
#endif
char *vtiden = "\033[?12;4c"; /* identification sequence */
/* size of title stack */
#define TITLESTACKSIZE 8
@ -123,18 +128,6 @@ typedef XftDraw *Draw;
typedef XftColor Color;
typedef XftGlyphFontSpec GlyphFontSpec;
/* Purely graphic info */
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 */
int mode; /* window state/mode flags */
int cursor; /* cursor style */
} TermWindow;
typedef struct {
Display *dpy;
Colormap cmap;
@ -191,7 +184,7 @@ typedef struct {
static inline ushort sixd_to_16bit(int);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
@ -307,8 +300,15 @@ static char *opt_name = NULL;
static char *opt_title = NULL;
static int cursorblinks = 0;
static uint buttons; /* bit field of pressed buttons */
TermWindow
gettermwindow()
{
return win;
}
void
clipcopy(const Arg *dummy)
{
@ -511,6 +511,7 @@ mouseaction(XEvent *e, uint release)
for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
if (ms->release == release &&
ms->button == e->xbutton.button &&
(!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) &&
(match(ms->mod, state) || /* exact or forced */
match(ms->mod, state & ~forcemousemod))) {
ms->func(&(ms->arg));
@ -742,7 +743,8 @@ setsel(char *str, Time t)
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
selclear();
clipcopy(NULL);
xclipcopy();
}
void
@ -768,7 +770,7 @@ brelease(XEvent *e)
return;
if (btn == Button1)
mousesel(e, 1);
openUrlOnClick(evcol(e), evrow(e), url_opener);
openUrlOnClick(evcol(e), evrow(e), urlcmd);
}
void
@ -880,6 +882,18 @@ xloadcols(void)
dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
dc.col[defaultbg].pixel &= 0x00FFFFFF;
dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24;
/* set alpha value of selbg color */
dc.col[selectionbg].color.alpha = (unsigned short)(0xffff * alpha);
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;
dc.col[selectionbg].pixel &= 0x00FFFFFF;
dc.col[selectionbg].pixel |= (unsigned char)(0xff * alpha) << 24;
loaded = 1;
}
@ -924,6 +938,12 @@ xclear(int x1, int y1, int x2, int y2)
x1, y1, x2-x1, y2-y1);
}
void
xclearwin(void)
{
xclear(0, 0, win.w, win.h);
}
void
xhints(void)
{
@ -1099,7 +1119,6 @@ xloadfonts(const char *fontstr, double fontsize)
/* Setting character width and height. */
win.cw = ceilf(dc.font.width * cwscale);
win.ch = ceilf(dc.font.height * chscale);
win.cyo = ceilf(dc.font.height * (chscale - 1) / 2);
FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
@ -1155,7 +1174,7 @@ xloadsparefonts(void)
die("can't embed spare fonts. cache isn't empty");
/* Calculate count of spare fonts */
fc = sizeof(font2) / sizeof(*font2);
fc = sizeof(font) / sizeof(*font);
if (fc == 0)
return;
@ -1165,7 +1184,7 @@ xloadsparefonts(void)
frc = xrealloc(frc, frccap * sizeof(Fontcache));
}
for (fp = font2; fp - font2 < fc; ++fp) {
for (fp = font; fp - font < fc; ++fp) {
if (**fp == '-')
pattern = XftXlfdParse(*fp, False, False);
@ -1321,7 +1340,7 @@ xinit(int cols, int rows)
if (!FcInit())
die("could not init fontconfig.\n");
usedfont = (opt_font == NULL)? font : opt_font;
usedfont = (opt_font == NULL)? font[0] : opt_font;
xloadfonts(usedfont, 0);
/* spare fonts */
@ -1475,7 +1494,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
FcCharSet *fccharset;
int i, f, numspecs = 0;
for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) {
for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
/* Fetch rune and mode for current glyph. */
rune = glyphs[i].u;
mode = glyphs[i].mode;
@ -1500,7 +1519,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
font = &dc.bfont;
frcflags = FRC_BOLD;
}
yp = winy + font->ascent + win.cyo;
yp = winy + font->ascent;
}
if (mode & ATTR_BOXDRAW) {
@ -1645,7 +1664,7 @@ static int getSlope (int x, int iPoint, int waveWidth)
}
void
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
{
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
@ -1686,9 +1705,8 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
}
/* Change basic system colors [0-7] to bright system colors [8-15] */
if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7))
if (boldbright)
fg = &dc.col[base.fg + 8];
if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7) && brightbold)
fg = &dc.col[base.fg + 8];
if (IS_SET(MODE_REVERSE)) {
if (fg == &dc.col[defaultfg]) {
@ -1731,44 +1749,51 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
bg = temp;
}
if (base.mode & ATTR_SELECTED) {
bg = &dc.col[selectionbg];
if (!ignoreselfg)
fg = &dc.col[selectionfg];
}
if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK)
fg = bg;
if (!graddirection && gradient)
bg->color.alpha = gradalpha * 0xffff * (win.h - y*win.ch) / win.h + statalpha * 0xffff;
else if (graddirection && gradient)
bg->color.alpha = gradalpha * 0xffff * (y*win.ch) / win.h + statalpha * 0xffff;
if (base.mode & ATTR_INVISIBLE)
fg = bg;
/* Intelligent cleaning up of the borders. */
if (x == 0) {
xclear(0, (y == 0)? 0 : winy, win.hborderpx,
winy + win.ch +
((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
}
if (winx + width >= win.hborderpx + win.tw) {
xclear(winx + width, (y == 0)? 0 : winy, win.w,
((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
}
if (y == 0)
xclear(winx, 0, winx + width, win.vborderpx);
if (winy + win.ch >= win.vborderpx + win.th)
xclear(winx, winy + win.ch, winx + width, win.h);
if (dmode & DRAW_BG) {
/* Intelligent cleaning up of the borders. */
if (x == 0) {
xclear(0, (y == 0)? 0 : winy, win.hborderpx,
winy + win.ch +
((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
}
if (winx + width >= win.vborderpx + win.tw) {
xclear(winx + width, (y == 0)? 0 : winy, win.w,
((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
}
if (y == 0)
xclear(winx, 0, winx + width, win.vborderpx);
if (winy + win.ch >= win.vborderpx + win.th)
xclear(winx, winy + win.ch, winx + width, win.h);
/* Fill the background */
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
}
/* Clean up the region we want to draw to. */
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
/* 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 (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);
}
if (dmode & DRAW_FG) {
if (base.mode & ATTR_BOXDRAW) {
drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
} else {
/* Render the glyphs. */
XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
}
/* Render underline and strikethrough. */
if (base.mode & ATTR_UNDERLINE) {
// Underline Color
@ -2124,12 +2149,11 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
}
if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent * chscale / 3,
width, 1);
}
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
width, 1);
}
}
/* Reset clip to none. */
XftDrawSetClip(xw.draw, 0);
}
void
@ -2139,7 +2163,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
xdrawglyphfontspecs(&spec, g, numspecs, x, y);
xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
}
void
@ -2150,8 +2174,8 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
/* remove the old cursor */
if (selected(ox, oy))
og.mode ^= ATTR_REVERSE;
xdrawline(line, 0, oy, len);
og.mode |= ATTR_SELECTED;
xdrawglyph(og, ox, oy);
if (IS_SET(MODE_HIDE))
return;
@ -2163,37 +2187,26 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
g.fg = defaultcs;
g.bg = defaultfg;
if (selected(cx, cy)) {
drawcol = dc.col[defaultcs];
g.fg = defaultrc;
} else {
drawcol = dc.col[defaultrc];
g.fg = defaultcs;
}
drawcol = dc.col[defaultrc];
} else {
if (selected(cx, cy)) {
g.fg = defaultfg;
g.bg = defaultrc;
} else {
/** this is the main part of the dynamic cursor color patch */
g.bg = g.fg;
g.fg = defaultbg;
}
g.bg = g.fg;
g.fg = defaultbg;
}
/**
* and this is the second part of the dynamic cursor color patch.
* it handles the `drawcol` variable
*/
if (IS_TRUECOL(g.bg)) {
colbg.alpha = 0xffff;
colbg.red = TRUERED(g.bg);
colbg.green = TRUEGREEN(g.bg);
colbg.blue = TRUEBLUE(g.bg);
XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol);
} else {
drawcol = dc.col[g.bg];
}
/**
* and this is the second part of the dynamic cursor color patch.
* it handles the `drawcol` variable
*/
if (IS_TRUECOL(g.bg)) {
colbg.alpha = 0xffff;
colbg.red = TRUERED(g.bg);
colbg.green = TRUEGREEN(g.bg);
colbg.blue = TRUEBLUE(g.bg);
XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol);
} else {
drawcol = dc.col[g.bg];
}
/* draw the new one */
@ -2234,7 +2247,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
break;
/* FALLTHROUGH */
case 8: /* steady st cursor */
g.u = ccursor;
g.u = stcursor;
xdrawglyph(g, cx, cy);
break;
}
@ -2315,6 +2328,87 @@ xsettitle(char *p, int pop)
XFree(prop.value);
}
int
xsixelinit(SixelContext *ctx)
{
return sixel_parser_init(&ctx->state, 0, dc.col[defaultbg].pixel, 1, win.cw, win.ch);
}
int
xsixelparse(SixelContext *ctx, unsigned char *u, int len)
{
return sixel_parser_parse(&ctx->state, u, len);
}
void
xsixelnewimage(SixelContext *ctx, int tx, int ty)
{
ImageList *new_image;
int i;
new_image = malloc(sizeof(ImageList));
memset(new_image, 0, sizeof(ImageList));
new_image->x = tx;
new_image->y = ty;
new_image->width = ctx->state.image.width;
new_image->height = ctx->state.image.height;
new_image->pixels = malloc(new_image->width * new_image->height * 4);
if (sixel_parser_finalize(&ctx->state, new_image->pixels) != 0) {
perror("sixel_parser_finalize() failed");
sixel_parser_deinit(&ctx->state);
return;
}
sixel_parser_deinit(&ctx->state);
if (ctx->images) {
ImageList *im;
for (im = ctx->images; im->next;)
im = im->next;
im->next = new_image;
new_image->prev = im;
} else {
ctx->images = new_image;
}
}
void
xsixeldeleteimage(SixelContext *ctx, ImageList *im)
{
if (im->prev)
im->prev->next = im->next;
else
ctx->images = im->next;
if (im->next)
im->next->prev = im->prev;
if (im->pixmap)
XFreePixmap(xw.dpy, (Drawable)im->pixmap);
free(im->pixels);
free(im);
}
void
xsixelscrolldown(SixelContext *ctx, int n, int bottom)
{
ImageList *im;
for (im = ctx->images; im; im = im->next) {
if (im->y < bottom)
im->y += n;
if (im->y > bottom)
im->should_delete = 1;
}
}
void
xsixelscrollup(SixelContext *ctx, int n, int top)
{
ImageList *im;
for (im = ctx->images; im; im = im->next) {
if (im->y+im->height/win.ch > top)
im->y -= n;
if (im->y+im->height/win.ch < top)
im->should_delete = 1;
}
}
void
xpushtitle(void)
{
@ -2328,40 +2422,129 @@ xpushtitle(void)
int
xstartdraw(void)
{
if (IS_SET(MODE_VISIBLE))
XCopyArea(xw.dpy, xw.win, xw.buf, dc.gc, 0, 0, win.w, win.h, 0, 0);
return IS_SET(MODE_VISIBLE);
}
void
xdrawline(Line line, int x1, int y1, int x2)
{
int i, x, ox, numspecs;
int i, x, ox, numspecs, numspecs_cached;
Glyph base, new;
XftGlyphFontSpec *specs = xw.specbuf;
XftGlyphFontSpec *specs;
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) {
new = line[x];
if (new.mode == ATTR_WDUMMY)
continue;
if (selected(x, y1))
new.mode ^= ATTR_REVERSE;
if (i > 0 && ATTRCMP(base, new)) {
xdrawglyphfontspecs(specs, base, i, ox, y1);
specs += i;
numspecs -= i;
i = 0;
numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
/* Draw line in 2 passes: background and foreground. This way wide glyphs
won't get truncated (#223) */
for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
specs = xw.specbuf;
numspecs = numspecs_cached;
i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) {
new = line[x];
if (new.mode == ATTR_WDUMMY)
continue;
if (selected(x, y1))
new.mode ^= ATTR_REVERSE;
if (i > 0 && ATTRCMP(base, new)) {
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
specs += i;
numspecs -= i;
i = 0;
}
if (i == 0) {
ox = x;
base = new;
}
i++;
}
if (i == 0) {
ox = x;
base = new;
}
i++;
if (i > 0)
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
}
if (i > 0)
xdrawglyphfontspecs(specs, base, i, ox, y1);
}
void
xdrawsixel(SixelContext *ctx, Line *line, int row, int col)
{
ImageList *im, *tmp;
int x, y;
int n = 0;
int nlimit = 256;
XRectangle *rects = NULL;
XGCValues gcvalues = { 0 };
GC gc;
for (im = ctx->images; im;) {
if (im->should_delete) {
tmp = im;
im = im->next;
xsixeldeleteimage(ctx, tmp);
continue;
}
if (!im->pixmap) {
im->pixmap = (void *)XCreatePixmap(xw.dpy, xw.win, im->width, im->height, xw.depth);
XImage ximage = {
.format = ZPixmap,
.data = (char *)im->pixels,
.width = im->width,
.height = im->height,
.xoffset = 0,
.byte_order = LSBFirst,
.bitmap_bit_order = MSBFirst,
.bits_per_pixel = 32,
.bytes_per_line = im->width * 4,
.bitmap_unit = 32,
.bitmap_pad = 32,
.depth = xw.depth
};
XPutImage(xw.dpy, (Drawable)im->pixmap, dc.gc, &ximage, 0, 0, 0, 0, im->width, im->height);
free(im->pixels);
im->pixels = NULL;
}
n = 0;
for (y = im->y; y < (im->y + (im->height + win.ch - 1) / win.ch) && y < row; y++) {
if (y >= 0) {
for (x = im->x; x < (im->x + (im->width + win.cw - 1) / win.cw) && x < col; x++) {
if (!rects)
rects = xmalloc(sizeof(XRectangle) * nlimit);
if (line[y][x].mode & ATTR_SIXEL) {
if (n > 0 && rects[n-1].x+rects[n-1].width == borderpx+x*win.cw && rects[n-1].y == borderpx+y*win.ch) {
rects[n-1].width += win.cw;
} else {
rects[n].x = borderpx+x*win.cw;
rects[n].y = borderpx+y*win.ch;
rects[n].width = win.cw;
rects[n].height = win.ch;
if (++n == nlimit && (rects = realloc(rects, sizeof(XRectangle) * (nlimit *= 2))) == NULL)
die("Out of memory\n");
}
}
}
}
if (n > 1 && rects[n-2].x == rects[n-1].x && rects[n-2].width == rects[n-1].width) {
if (rects[n-2].y+rects[n-2].height == rects[n-1].y) {
rects[n-2].height += win.ch;
n--;
}
}
}
if (n == 0) {
tmp = im;
im = im->next;
xsixeldeleteimage(ctx, tmp);
continue;
}
gc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues);
if (n > 1)
XSetClipRectangles(xw.dpy, gc, 0, 0, rects, n, YXSorted);
XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, im->width, im->height, win.hborderpx + im->x * win.cw, win.vborderpx + im->y * win.ch);
XFreeGC(xw.dpy, gc);
im = im->next;
}
free(rects);
}
void
@ -2480,7 +2663,7 @@ focus(XEvent *ev)
int
match(uint mask, uint state)
{
return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
return mask == ANY || mask == (state & ~ignoremod);
}
char*
@ -2524,7 +2707,7 @@ void
kpress(XEvent *ev)
{
XKeyEvent *e = &ev->xkey;
KeySym ksym;
KeySym ksym = NoSymbol;
char buf[64], *customkey;
int len;
Rune c;
@ -2534,16 +2717,22 @@ kpress(XEvent *ev)
if (IS_SET(MODE_KBDLOCK))
return;
if (xw.ime.xic)
if (xw.ime.xic) {
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
else
if (status == XBufferOverflow)
return;
} else {
len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
if ( IS_SET(MODE_KBDSELECT) ) {
if ( match(XK_NO_MOD, e->state) ||
}
if ( IS_SET(MODE_KBDSELECT) ) {
if ( match(NONE, e->state) ||
(XK_Shift_L | XK_Shift_R) & e->state )
win.mode ^= trt_kbdselect(ksym, buf, len);
return;
}
/* 1. shortcuts */
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
if (ksym == bp->keysym && match(bp->mod, e->state)) {
@ -2728,6 +2917,7 @@ run(void)
}
}
#if USEXRESOURCES
int
resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
{
@ -2780,6 +2970,7 @@ config_init(void)
for (p = resources; p < resources + LEN(resources); p++)
resource_load(db, p->name, p->type, p->dst);
}
#endif
void
usage(void)
@ -2798,13 +2989,15 @@ void toggle_winmode(int flag) {
win.mode ^= flag;
}
void keyboard_select(const Arg *dummy) {
void keyboardselect(const Arg *dummy) {
win.mode ^= trt_kbdselect(-1, NULL, 0);
}
int
main(int argc, char *argv[])
{
int i;
char *colval;
xw.l = xw.t = 0;
xw.isfixed = False;
xsetcursor(cursorstyle);
@ -2852,6 +3045,11 @@ main(int argc, char *argv[])
case 'v':
die("%s " VERSION "\n", argv0);
break;
case 'C':
colval = strtok(EARGF(usage()), "@");
i = atoi(strtok(NULL, "@"));
colorname[i] = colval;
break;
default:
usage();
} ARGEND;
@ -2869,7 +3067,9 @@ run:
if(!(xw.dpy = XOpenDisplay(NULL)))
die("Can't open display\n");
#if USEXRESOURCES
config_init();
#endif
cols = MAX(cols, 1);
rows = MAX(rows, 1);
tnew(cols, rows);

View file

@ -1,3 +1,4 @@
/* .Xresources array, you can add values to it that will be read on startup */
ResourcePref resources[] = {
{ "font", STRING, &font },
{ "color0", STRING, &colorname[0] },
@ -16,13 +17,15 @@ ResourcePref resources[] = {
{ "color13", STRING, &colorname[13] },
{ "color14", STRING, &colorname[14] },
{ "color15", STRING, &colorname[15] },
{ "background", STRING, &colorname[259] },
{ "foreground", STRING, &colorname[258] },
{ "cursorColor", STRING, &colorname[257] },
{ "background", STRING, &colorname[256] },
{ "foreground", STRING, &colorname[257] },
{ "curcolor", STRING, &colorname[258] },
{ "termname", STRING, &termname },
{ "shell", STRING, &shell },
{ "understyle", STRING, &understyle },
{ "url_opener", STRING, &url_opener },
{ "urlcmd", STRING, &urlcmd },
{ "gradient", INTEGER, &gradient },
{ "graddirection", INTEGER, &graddirection },
{ "minlatency", INTEGER, &minlatency },
{ "synctimeout", INTEGER, &synctimeout },
{ "maxlatency", INTEGER, &maxlatency },
@ -38,8 +41,10 @@ ResourcePref resources[] = {
{ "defaultcs", INTEGER, &defaultcs },
{ "defaultrc", INTEGER, &defaultrc },
{ "cursorstyle", INTEGER, &cursorstyle },
{ "boldbright", INTEGER, &boldbright },
{ "brightbold", INTEGER, &brightbold },
{ "alpha", FLOAT, &alpha },
{ "gradalpha", FLOAT, &gradalpha },
{ "statalpha", FLOAT, &statalpha },
{ "cwscale", FLOAT, &cwscale },
{ "chscale", FLOAT, &chscale },
};