From ba2724f19f8b9fca12d1acaf9a237ac5c650c9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sun, 13 Aug 2023 10:44:10 +0200 Subject: [PATCH 01/21] contrib/st: add submodule --- .gitmodules | 3 +++ contrib/st/st | 1 + 2 files changed, 4 insertions(+) create mode 160000 contrib/st/st diff --git a/.gitmodules b/.gitmodules index 62c6b308e..6d76b8942 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ path = contrib/sinit/sinit url = git://git.suckless.org/sinit ignore = dirty +[submodule "contrib/st/st"] + path = contrib/st/st + url = https://git.suckless.org/st diff --git a/contrib/st/st b/contrib/st/st new file mode 160000 index 000000000..3a6d6d740 --- /dev/null +++ b/contrib/st/st @@ -0,0 +1 @@ +Subproject commit 3a6d6d740110e6ee1b092d05ad746244eedabe4b From a11d7728a5321756ccfcf78e102b4efe7b405e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sun, 13 Aug 2023 13:05:39 +0200 Subject: [PATCH 02/21] contrib/st: add Makefile --- contrib/Makefile | 2 +- contrib/st/Makefile | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 contrib/st/Makefile diff --git a/contrib/Makefile b/contrib/Makefile index 052e58500..e9134a857 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -2,7 +2,7 @@ TOPDIR = $(realpath ..) -SUBDIR = atto lua sbase sinit # doom mish evtest +SUBDIR = atto lua sbase sinit st # doom mish evtest all: build diff --git a/contrib/st/Makefile b/contrib/st/Makefile new file mode 100644 index 000000000..043561bd6 --- /dev/null +++ b/contrib/st/Makefile @@ -0,0 +1,39 @@ +TOPDIR = $(realpath ../..) + +NEW_SRC = font.c input.c +SRC = st.c x.c +HDR = arg.h st.h win.h + +PROGRAM = st +LDLIBS = -lutil +BINDIR = bin +BUILDDIR = build/ +SOURCES = $(addprefix st/,$(SRC)) $(addprefix st/,$(NEW_SRC)) +FORMAT-EXCLUDE = $(addprefix st/,$(SRC)) $(addprefix st/,$(NEW_SRC)) $(addprefix st/,$(HDR)) + +include $(TOPDIR)/build/build.prog.mk + +# Rules for newly created source files: + +define new_src_func = +$$(addprefix st/,$(1)): build-before +endef + +$(foreach new_src,$(NEW_SRC),$(eval $(call new_src_func,$(new_src)))) + +# Main rules for downloading st and patching: + +download-here: st/.git + +build-before: quilt-patch + +clean-here: quilt-unpatch + +# Rules for generating config.h: + +$(OBJECTS): $(BUILDDIR)st/config.h + +$(BUILDDIR)%.h: %.def.h + cp $< $@ + +CPPFLAGS += -I$(BUILDDIR)/st From c693804f2342d422bf5a02dfe76c10b9b4aa6ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 17:12:49 +0200 Subject: [PATCH 03/21] contrib/st: add config.patch --- contrib/st/patches/config.patch | 455 ++++++++++++++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 456 insertions(+) create mode 100644 contrib/st/patches/config.patch create mode 100644 contrib/st/patches/series diff --git a/contrib/st/patches/config.patch b/contrib/st/patches/config.patch new file mode 100644 index 000000000..8353734e3 --- /dev/null +++ b/contrib/st/patches/config.patch @@ -0,0 +1,455 @@ +Index: st/st/config.def.h +=================================================================== +--- st.orig/st/config.def.h 2023-08-20 18:04:54.860564071 +0200 ++++ st/st/config.def.h 2023-08-20 18:43:46.493955311 +0200 +@@ -1,11 +1,14 @@ + /* See LICENSE file for copyright and license details. */ + ++static const char *fb_dev = "/dev/fb0"; ++static const char *ev_dev = "/dev/input/event0"; ++static const char *font_file = "/etc/spleen-8x16.fnt"; ++ + /* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +-static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; + static int borderpx = 2; + + /* +@@ -25,10 +28,6 @@ + /* 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 + * +@@ -36,10 +35,6 @@ + */ + wchar_t *worddelimiters = L" "; + +-/* selection timeouts (in milliseconds) */ +-static unsigned int doubleclicktimeout = 300; +-static unsigned int tripleclicktimeout = 600; +- + /* alt screens */ + int allowaltscreen = 1; + +@@ -67,12 +62,6 @@ + */ + static unsigned int cursorthickness = 2; + +-/* +- * bell volume. It must be a value between -100 and 100. Use 0 for disabling +- * it +- */ +-static int bellvolume = 0; +- + /* default TERM value */ + char *termname = "st-256color"; + +@@ -94,381 +83,34 @@ + unsigned int tabspaces = 8; + + /* Terminal colors (16 first used in escape sequence) */ +-static const char *colorname[] = { +- /* 8 normal colors */ +- "black", +- "red3", +- "green3", +- "yellow3", +- "blue2", +- "magenta3", +- "cyan3", +- "gray90", +- +- /* 8 bright colors */ +- "gray50", +- "red", +- "green", +- "yellow", +- "#5c5cff", +- "magenta", +- "cyan", +- "white", +- +- [255] = 0, +- +- /* more colors can be added after 255 to use with DefaultXX */ +- "#cccccc", +- "#555555", +- "gray90", /* default foreground colour */ +- "black", /* default background colour */ ++static const unsigned colors[] = { ++ [0x0] = 0x000000, ++ [0x1] = 0xaa0000, ++ [0x2] = 0x00aa00, ++ [0x3] = 0xaa5500, ++ [0x4] = 0x0000aa, ++ [0x5] = 0xaa00aa, ++ [0x6] = 0x00aaaa, ++ [0x7] = 0xaaaaaa, ++ [0x8] = 0x555555, ++ [0x9] = 0xff5555, ++ [0xA] = 0x55ff55, ++ [0xB] = 0xffff55, ++ [0xC] = 0x5555ff, ++ [0xD] = 0xff55ff, ++ [0xE] = 0x55ffff, ++ [0xF] = 0xffffff + }; + +- + /* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +-unsigned int defaultfg = 258; ++unsigned int defaultfg = 268; + unsigned int defaultbg = 259; + unsigned int defaultcs = 256; + static 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; +- +-/* +- * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). +- * Note that if you want to use ShiftMask with selmasks, set this to an other +- * modifier, set to 0 to not use it. +- */ +-static uint forcemousemod = ShiftMask; +- +-/* +- * Internal mouse shortcuts. +- * Beware that overloading Button1 will disable the selection. +- */ +-static MouseShortcut mshortcuts[] = { +- /* mask button function argument release */ +- { 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"} }, +-}; +- + /* Internal keyboard shortcuts. */ + #define MODKEY Mod1Mask + #define TERMMOD (ControlMask|ShiftMask) +- +-static Shortcut shortcuts[] = { +- /* mask keysym function argument */ +- { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, +- { ControlMask, XK_Print, toggleprinter, {.i = 0} }, +- { ShiftMask, XK_Print, printscreen, {.i = 0} }, +- { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, +- { TERMMOD, XK_Prior, zoom, {.f = +1} }, +- { TERMMOD, XK_Next, zoom, {.f = -1} }, +- { TERMMOD, XK_Home, zoomreset, {.f = 0} }, +- { TERMMOD, XK_C, clipcopy, {.i = 0} }, +- { TERMMOD, XK_V, clippaste, {.i = 0} }, +- { TERMMOD, XK_Y, selpaste, {.i = 0} }, +- { ShiftMask, XK_Insert, selpaste, {.i = 0} }, +- { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, +-}; +- +-/* +- * Special keys (change & recompile st.info accordingly) +- * +- * Mask value: +- * * Use XK_ANY_MOD to match the key no matter modifiers state +- * * Use XK_NO_MOD to match the key alone (no modifiers) +- * appkey value: +- * * 0: no value +- * * > 0: keypad application mode enabled +- * * = 2: term.numlock = 1 +- * * < 0: keypad application mode disabled +- * appcursor value: +- * * 0: no value +- * * > 0: cursor application mode enabled +- * * < 0: cursor application mode disabled +- * +- * Be careful with the order of the definitions because st searches in +- * this table sequentially, so any XK_ANY_MOD must be in the last +- * position for a key. +- */ +- +-/* +- * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) +- * to be mapped below, add them to this array. +- */ +-static KeySym mappedkeys[] = { -1 }; +- +-/* +- * State bits to ignore when matching key or button events. By default, +- * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. +- */ +-static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; +- +-/* +- * This is the huge key array which defines all compatibility to the Linux +- * world. Please decide about changes wisely. +- */ +-static Key key[] = { +- /* keysym mask string appkey appcursor */ +- { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, +- { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, +- { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, +- { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, +- { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, +- { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, +- { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, +- { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, +- { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, +- { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, +- { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, +- { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, +- { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, +- { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, +- { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, +- { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, +- { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, +- { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, +- { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, +- { XK_KP_End, ControlMask, "\033[J", -1, 0}, +- { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, +- { XK_KP_End, ShiftMask, "\033[K", -1, 0}, +- { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, +- { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, +- { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, +- { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, +- { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, +- { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, +- { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, +- { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, +- { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, +- { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, +- { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, +- { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, +- { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, +- { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, +- { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, +- { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, +- { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, +- { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, +- { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, +- { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, +- { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, +- { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, +- { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, +- { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, +- { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, +- { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, +- { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, +- { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, +- { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, +- { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, +- { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, +- { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, +- { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, +- { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, +- { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, +- { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, +- { XK_Up, ControlMask, "\033[1;5A", 0, 0}, +- { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, +- { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, +- { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, +- { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, +- { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, +- { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, +- { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, +- { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, +- { XK_Down, ControlMask, "\033[1;5B", 0, 0}, +- { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, +- { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, +- { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, +- { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, +- { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, +- { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, +- { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, +- { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, +- { XK_Left, ControlMask, "\033[1;5D", 0, 0}, +- { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, +- { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, +- { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, +- { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, +- { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, +- { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, +- { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, +- { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, +- { XK_Right, ControlMask, "\033[1;5C", 0, 0}, +- { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, +- { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, +- { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, +- { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, +- { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, +- { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, +- { XK_Return, Mod1Mask, "\033\r", 0, 0}, +- { XK_Return, XK_ANY_MOD, "\r", 0, 0}, +- { XK_Insert, ShiftMask, "\033[4l", -1, 0}, +- { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, +- { XK_Insert, ControlMask, "\033[L", -1, 0}, +- { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, +- { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, +- { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, +- { XK_Delete, ControlMask, "\033[M", -1, 0}, +- { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, +- { XK_Delete, ShiftMask, "\033[2K", -1, 0}, +- { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, +- { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, +- { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, +- { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, +- { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, +- { XK_Home, ShiftMask, "\033[2J", 0, -1}, +- { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, +- { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, +- { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, +- { XK_End, ControlMask, "\033[J", -1, 0}, +- { XK_End, ControlMask, "\033[1;5F", +1, 0}, +- { XK_End, ShiftMask, "\033[K", -1, 0}, +- { XK_End, ShiftMask, "\033[1;2F", +1, 0}, +- { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, +- { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, +- { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, +- { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, +- { XK_Next, ControlMask, "\033[6;5~", 0, 0}, +- { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, +- { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, +- { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, +- { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, +- { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, +- { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, +- { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, +- { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, +- { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, +- { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, +- { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, +- { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, +- { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, +- { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, +- { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, +- { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, +- { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, +- { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, +- { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, +- { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, +- { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, +- { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, +- { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, +- { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, +- { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, +- { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, +- { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, +- { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, +- { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, +- { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, +- { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, +- { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, +- { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, +- { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, +- { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, +- { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, +- { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, +- { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, +- { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, +- { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, +- { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, +- { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, +- { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, +- { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, +- { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, +- { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, +- { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, +- { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, +- { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, +- { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, +- { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, +- { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, +- { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, +- { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, +- { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, +- { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, +- { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, +- { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, +- { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, +- { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, +- { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, +- { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, +- { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, +- { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, +- { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, +- { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, +- { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, +- { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, +- { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, +- { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, +- { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, +- { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, +- { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, +- { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, +- { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, +- { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, +- { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, +- { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, +- { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, +- { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, +- { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, +- { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, +- { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, +- { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, +- { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, +- { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, +- { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, +- { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +-}; +- +-/* +- * Selection types' masks. +- * Use the same masks as usual. +- * Button1Mask is always unset, to make masks match between ButtonPress. +- * ButtonRelease and MotionNotify. +- * If no match is found, regular selection is used. +- */ +-static uint selmasks[] = { +- [SEL_RECTANGULAR] = Mod1Mask, +-}; +- +-/* +- * Printable characters in ASCII, used to estimate the advance width +- * of single wide characters. +- */ +-static char ascii_printable[] = +- " !\"#$%&'()*+,-./0123456789:;<=>?" +- "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +- "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/contrib/st/patches/series b/contrib/st/patches/series new file mode 100644 index 000000000..4462183fc --- /dev/null +++ b/contrib/st/patches/series @@ -0,0 +1 @@ +config.patch From 1e6beb61a18ffc2f6f45830d5e6919ac50446f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:23:09 +0200 Subject: [PATCH 04/21] contrib/st: add font.c.patch --- contrib/st/patches/font.c.patch | 91 +++++++++++++++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 92 insertions(+) create mode 100644 contrib/st/patches/font.c.patch diff --git a/contrib/st/patches/font.c.patch b/contrib/st/patches/font.c.patch new file mode 100644 index 000000000..f86be4755 --- /dev/null +++ b/contrib/st/patches/font.c.patch @@ -0,0 +1,91 @@ +Index: st/st/font.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/font.c 2023-08-14 18:18:48.547323716 +0200 +@@ -0,0 +1,86 @@ ++#include "font.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DEFWIDTH 8 ++#define DEFHEIGHT 16 ++ ++font_t *font_load(const char *path) { ++ int ffd, res; ++ int len; ++ struct stat st; ++ ++ if ((ffd = open(path, O_RDONLY, 0)) < 0) ++ return NULL; ++ ++ font_t *font = malloc(sizeof(font_t)); ++ ++ font->fontwidth = DEFWIDTH; ++ font->fontheight = DEFHEIGHT; ++ font->firstchar = 0; ++ font->numchars = 256; ++ font->stride = (DEFWIDTH + 7) / 8; ++ font->name = strdup(path); ++ ++ len = font->numchars * font->fontheight * font->stride; ++ if (fstat(ffd, &st) == 0) { ++ if (len != st.st_size) { ++ uint32_t foo = 0; ++ char b[65]; ++ len = st.st_size; ++ /* read header */ ++ res = read(ffd, b, 4); ++ if (strncmp(b, "WSFT", 4) != 0) ++ goto err; ++ ++ res = read(ffd, b, 64); ++ b[64] = 0; ++ free(font->name); ++ font->name = strdup(b); ++ ++ res = read(ffd, &foo, 4); ++ font->firstchar = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->numchars = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->encoding = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->fontwidth = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->fontheight = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->stride = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->bitorder = le32toh(foo); ++ res = read(ffd, &foo, 4); ++ font->byteorder = le32toh(foo); ++ len = font->numchars * font->fontheight * font->stride; ++ } ++ } ++ ++ font->data = malloc(len); ++ res = read(ffd, font->data, len); ++ if (res != len) { ++ free(font->data); ++ goto err; ++ } ++ ++ close(ffd); ++ return font; ++ ++err: ++ free(font); ++ close(ffd); ++ return NULL; ++} ++ ++char *font_glyph(font_t *font, int c) { ++ return (char *)font->data + ++ (c - font->firstchar) * font->fontheight * font->stride; ++} diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 4462183fc..7c1e788ba 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1 +1,2 @@ +font.c.patch config.patch From 0d131eec2e712c9009a7667548021f93ec877541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:23:48 +0200 Subject: [PATCH 05/21] contrib/st: add font.h.patch --- contrib/st/patches/font.h.patch | 20 ++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 21 insertions(+) create mode 100644 contrib/st/patches/font.h.patch diff --git a/contrib/st/patches/font.h.patch b/contrib/st/patches/font.h.patch new file mode 100644 index 000000000..9537095ed --- /dev/null +++ b/contrib/st/patches/font.h.patch @@ -0,0 +1,20 @@ +Index: st/st/font.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/font.h 2023-08-14 18:20:47.907326798 +0200 +@@ -0,0 +1,15 @@ ++#ifndef FONT_H ++#define FONT_H ++ ++typedef struct { ++ char *name; ++ int firstchar, numchars; ++ int fontwidth, fontheight, stride; ++ int encoding, bitorder, byteorder; ++ void *data; ++} font_t; ++ ++font_t *font_load(const char *path); ++char *font_glyph(font_t *font, int c); ++ ++#endif diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 7c1e788ba..092d77b1c 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,2 +1,3 @@ +font.h.patch font.c.patch config.patch From 13b2af51a6bea29e702ed2c37a9ffcf0228def96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:25:27 +0200 Subject: [PATCH 06/21] contrib/st: add input.c.patch --- contrib/st/patches/input.c.patch | 55 ++++++++++++++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 56 insertions(+) create mode 100644 contrib/st/patches/input.c.patch diff --git a/contrib/st/patches/input.c.patch b/contrib/st/patches/input.c.patch new file mode 100644 index 000000000..e2d61b6a6 --- /dev/null +++ b/contrib/st/patches/input.c.patch @@ -0,0 +1,55 @@ +Index: st/st/input.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/input.c 2023-08-14 18:24:56.563999968 +0200 +@@ -0,0 +1,49 @@ ++#include "input.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "kbio.h" ++#include "kdbtable.h" ++ ++#include "st.h" ++ ++struct { ++ int fd; ++} input; ++ ++static void handle_event(struct input_event *ie) { ++ char buf[64]; ++ ++ if (ie->type != EV_KEY) ++ return; ++ ++ return; ++ if (ie->value != 0) { ++ buf[0] = key_map.key[ie->code].map[0]; ++ buf[1] = 0; ++ ttywrite(buf, 1, 1); ++ } ++} ++ ++int input_init(const char *ev_dev) { ++ if ((input.fd = open(ev_dev, O_RDONLY)) < 0) ++ return 0; ++ return 1; ++} ++ ++void input_read(void) { ++ struct input_event ie; ++ int ret; ++ ++ if ((ret = read(input.fd, &ie, sizeof(struct input_event))) > 0) ++ handle_event(&ie); ++} ++ ++int input_getfd(void) { ++ return input.fd; ++} +\ No newline at end of file diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 092d77b1c..b19b5fdd5 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +input.c.patch font.h.patch font.c.patch config.patch From b4292459c0a8135d1f7fe99c61c95b56f685d033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:29:50 +0200 Subject: [PATCH 07/21] contrib/st: add input.h.patch --- contrib/st/patches/input.h.patch | 14 ++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 15 insertions(+) create mode 100644 contrib/st/patches/input.h.patch diff --git a/contrib/st/patches/input.h.patch b/contrib/st/patches/input.h.patch new file mode 100644 index 000000000..a086e4c66 --- /dev/null +++ b/contrib/st/patches/input.h.patch @@ -0,0 +1,14 @@ +Index: st/st/input.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/input.h 2023-08-14 18:29:50.274007627 +0200 +@@ -0,0 +1,8 @@ ++#ifndef INPUT_H ++#define INPUT_H ++ ++int input_init(const char *ev_dev); ++void input_read(void); ++int input_getfd(void); ++ ++#endif +\ No newline at end of file diff --git a/contrib/st/patches/series b/contrib/st/patches/series index b19b5fdd5..add5b7bb7 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +input.h.patch input.c.patch font.h.patch font.c.patch From eba05a572ba5aea013d4290a11ac9d9fed60a9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:36:18 +0200 Subject: [PATCH 08/21] contrib/st: add kbio.patch --- contrib/st/patches/kbio.patch | 125 ++++++++++++++++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 126 insertions(+) create mode 100644 contrib/st/patches/kbio.patch diff --git a/contrib/st/patches/kbio.patch b/contrib/st/patches/kbio.patch new file mode 100644 index 000000000..a906655e8 --- /dev/null +++ b/contrib/st/patches/kbio.patch @@ -0,0 +1,125 @@ +Index: st/st/kbio.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/kbio.h 2023-08-14 18:36:18.294017710 +0200 +@@ -0,0 +1,120 @@ ++/*- ++ * $FreeBSD$ ++ */ ++ ++#ifndef _KBIO_H_ ++#define _KBIO_H_ ++ ++#include ++ ++/* get/set key map/accent map/function key strings */ ++ ++#define NUM_KEYS 256 /* number of keys in table */ ++#define NUM_STATES 8 /* states per key */ ++#define ALTGR_OFFSET 128 /* offset for altlock keys */ ++ ++#define NUM_FKEYS 96 /* max number of function keys */ ++#define MAXFK 16 /* max length of a function key str */ ++ ++typedef struct { ++ unsigned int map[NUM_STATES]; ++ unsigned char spcl; ++ unsigned char flgs; ++#define FLAG_LOCK_O 0 ++#define FLAG_LOCK_C 1 ++#define FLAG_LOCK_N 2 ++} keyent_t; ++ ++typedef struct { ++ unsigned short n_keys; ++ keyent_t key[NUM_KEYS]; ++} keymap_t; ++ ++/* defines for "special" keys (spcl bit set in keymap) */ ++#define NOP 0x00 /* nothing (dead key) */ ++#define LSH 0x02 /* left shift key */ ++#define RSH 0x03 /* right shift key */ ++#define CLK 0x04 /* caps lock key */ ++#define NLK 0x05 /* num lock key */ ++#define SLK 0x06 /* scroll lock key */ ++#define LALT 0x07 /* left alt key */ ++#define BTAB 0x08 /* backwards tab */ ++#define LCTR 0x09 /* left control key */ ++#define NEXT 0x0a /* switch to next screen */ ++#define F_SCR 0x0b /* switch to first screen */ ++#define L_SCR 0x1a /* switch to last screen */ ++#define F_FN 0x1b /* first function key */ ++#define L_FN 0x7a /* last function key */ ++/* 0x7b-0x7f reserved do not use ! */ ++#define RCTR 0x80 /* right control key */ ++#define RALT 0x81 /* right alt (altgr) key */ ++#define ALK 0x82 /* alt lock key */ ++#define ASH 0x83 /* alt shift key */ ++#define META 0x84 /* meta key */ ++#define RBT 0x85 /* boot machine */ ++#define DBG 0x86 /* call debugger */ ++#define SUSP 0x87 /* suspend power (APM) */ ++#define SPSC 0x88 /* toggle splash/text screen */ ++ ++#define F_ACC DGRA /* first accent key */ ++#define DGRA 0x89 /* grave */ ++#define DACU 0x8a /* acute */ ++#define DCIR 0x8b /* circumflex */ ++#define DTIL 0x8c /* tilde */ ++#define DMAC 0x8d /* macron */ ++#define DBRE 0x8e /* breve */ ++#define DDOT 0x8f /* dot */ ++#define DUML 0x90 /* umlaut/diaresis */ ++#define DDIA 0x90 /* diaresis */ ++#define DSLA 0x91 /* slash */ ++#define DRIN 0x92 /* ring */ ++#define DCED 0x93 /* cedilla */ ++#define DAPO 0x94 /* apostrophe */ ++#define DDAC 0x95 /* double acute */ ++#define DOGO 0x96 /* ogonek */ ++#define DCAR 0x97 /* caron */ ++#define L_ACC DCAR /* last accent key */ ++ ++#define STBY 0x98 /* Go into standby mode (apm) */ ++#define PREV 0x99 /* switch to previous screen */ ++#define PNC 0x9a /* force system panic */ ++#define LSHA 0x9b /* left shift key / alt lock */ ++#define RSHA 0x9c /* right shift key / alt lock */ ++#define LCTRA 0x9d /* left ctrl key / alt lock */ ++#define RCTRA 0x9e /* right ctrl key / alt lock */ ++#define LALTA 0x9f /* left alt key / alt lock */ ++#define RALTA 0xa0 /* right alt key / alt lock */ ++#define HALT 0xa1 /* halt machine */ ++#define PDWN 0xa2 /* halt machine and power down */ ++#define PASTE 0xa3 /* paste from cut-paste buffer */ ++ ++#define F(x) ((x)+F_FN-1) ++#define S(x) ((x)+F_SCR-1) ++#define ACC(x) ((x)+F_ACC) ++ ++typedef struct { ++ unsigned char str[MAXFK]; ++ unsigned char len; ++} fkeytab_t; ++ ++/* flags set to the return value in the KD_XLATE mode */ ++ ++#define NOKEY 0x01000000 /* no key pressed marker */ ++#define FKEY 0x02000000 /* function key marker */ ++#define MKEY 0x04000000 /* meta key marker (prepend ESC)*/ ++#define BKEY 0x08000000 /* backtab (ESC [ Z) */ ++ ++#define SPCLKEY 0x80000000 /* special key */ ++#define RELKEY 0x40000000 /* key released */ ++#define ERRKEY 0x20000000 /* error */ ++ ++/* ++ * The top byte is used to store the flags. This means there are 24 ++ * bits left to store the actual character. Because UTF-8 can encode ++ * 2^21 different characters, this is good enough to get Unicode ++ * working. ++ */ ++#define KEYCHAR(c) ((c) & 0x00ffffff) ++#define KEYFLAGS(c) ((c) & ~0x00ffffff) ++ ++#endif /* !_KBIO_H_ */ diff --git a/contrib/st/patches/series b/contrib/st/patches/series index add5b7bb7..5ee0651b4 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +kbio.patch input.h.patch input.c.patch font.h.patch From 3841630682326f005382da15ab474dd45cb9706c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 14 Aug 2023 18:36:39 +0200 Subject: [PATCH 09/21] contrib/st: add kdbtable.patch --- contrib/st/patches/kdbtable.patch | 159 ++++++++++++++++++++++++++++++ contrib/st/patches/series | 1 + 2 files changed, 160 insertions(+) create mode 100644 contrib/st/patches/kdbtable.patch diff --git a/contrib/st/patches/kdbtable.patch b/contrib/st/patches/kdbtable.patch new file mode 100644 index 000000000..0ea9df2a7 --- /dev/null +++ b/contrib/st/patches/kdbtable.patch @@ -0,0 +1,159 @@ +Index: st/st/kdbtable.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ st/st/kdbtable.h 2023-08-20 18:45:45.443958288 +0200 +@@ -0,0 +1,153 @@ ++/*- ++ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD ++ * ++ * Copyright (c) 1992-1998 Sen Schmidt ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer, ++ * without modification, immediately at the beginning of the file. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * $FreeBSD$ ++ */ ++ ++#ifndef KBD_DFLT_KEYMAP ++#define KBD_DFLT_KEYMAP ++ ++static keymap_t key_map = { 0x6d, { ++/* alt ++ * scan cntrl alt alt cntrl ++ * code base shift cntrl shift alt shift cntrl shift spcl flgs ++ * --------------------------------------------------------------------------- ++ */ ++/*00*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++/*01*/{{ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, }, 0x02,0x00 }, ++/*02*/{{ '1', '!', NOP, NOP, '1', '!', NOP, NOP, }, 0x33,0x00 }, ++/*03*/{{ '2', '@', 0x00, 0x00, '2', '@', 0x00, 0x00, }, 0x00,0x00 }, ++/*04*/{{ '3', '#', NOP, NOP, '3', '#', NOP, NOP, }, 0x33,0x00 }, ++/*05*/{{ '4', '$', NOP, NOP, '4', '$', NOP, NOP, }, 0x33,0x00 }, ++/*06*/{{ '5', '%', NOP, NOP, '5', '%', NOP, NOP, }, 0x33,0x00 }, ++/*07*/{{ '6', '^', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, }, 0x00,0x00 }, ++/*08*/{{ '7', '&', NOP, NOP, '7', '&', NOP, NOP, }, 0x33,0x00 }, ++/*09*/{{ '8', '*', NOP, NOP, '8', '*', NOP, NOP, }, 0x33,0x00 }, ++/*0a*/{{ '9', '(', NOP, NOP, '9', '(', NOP, NOP, }, 0x33,0x00 }, ++/*0b*/{{ '0', ')', NOP, NOP, '0', ')', NOP, NOP, }, 0x33,0x00 }, ++/*0c*/{{ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, }, 0x00,0x00 }, ++/*0d*/{{ '=', '+', NOP, NOP, '=', '+', NOP, NOP, }, 0x33,0x00 }, ++/*0e*/{{ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, }, 0x00,0x00 }, ++/*0f*/{{ 0x09, BTAB, NOP, NOP, 0x09, BTAB, NOP, NOP, }, 0x77,0x00 }, ++/*10*/{{ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, }, 0x00,0x01 }, ++/*11*/{{ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, }, 0x00,0x01 }, ++/*12*/{{ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, }, 0x00,0x01 }, ++/*13*/{{ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, }, 0x00,0x01 }, ++/*14*/{{ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, }, 0x00,0x01 }, ++/*15*/{{ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, }, 0x00,0x01 }, ++/*16*/{{ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, }, 0x00,0x01 }, ++/*17*/{{ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, }, 0x00,0x01 }, ++/*18*/{{ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, }, 0x00,0x01 }, ++/*19*/{{ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, }, 0x00,0x01 }, ++/*1a*/{{ '[', '{', 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, }, 0x00,0x00 }, ++/*1b*/{{ ']', '}', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, }, 0x00,0x00 }, ++/*1c*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 }, ++/*1d*/{{ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, }, 0xFF,0x00 }, ++/*1e*/{{ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, }, 0x00,0x01 }, ++/*1f*/{{ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, }, 0x00,0x01 }, ++/*20*/{{ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, }, 0x00,0x01 }, ++/*21*/{{ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, }, 0x00,0x01 }, ++/*22*/{{ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, }, 0x00,0x01 }, ++/*23*/{{ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, }, 0x00,0x01 }, ++/*24*/{{ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, }, 0x00,0x01 }, ++/*25*/{{ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, }, 0x00,0x01 }, ++/*26*/{{ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, }, 0x00,0x01 }, ++/*27*/{{ ';', ':', NOP, NOP, ';', ':', NOP, NOP, }, 0x33,0x00 }, ++/*28*/{{ '\'', '"', NOP, NOP, '\'', '"', NOP, NOP, }, 0x33,0x00 }, ++/*29*/{{ '`', '~', NOP, NOP, '`', '~', NOP, NOP, }, 0x33,0x00 }, ++/*2a*/{{ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, }, 0xFF,0x00 }, ++/*2b*/{{ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, }, 0x00,0x00 }, ++/*2c*/{{ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, }, 0x00,0x01 }, ++/*2d*/{{ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, }, 0x00,0x01 }, ++/*2e*/{{ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, }, 0x00,0x01 }, ++/*2f*/{{ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, }, 0x00,0x01 }, ++/*30*/{{ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, }, 0x00,0x01 }, ++/*31*/{{ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, }, 0x00,0x01 }, ++/*32*/{{ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, }, 0x00,0x01 }, ++/*33*/{{ ',', '<', NOP, NOP, ',', '<', NOP, NOP, }, 0x33,0x00 }, ++/*34*/{{ '.', '>', NOP, NOP, '.', '>', NOP, NOP, }, 0x33,0x00 }, ++/*35*/{{ '/', '?', NOP, NOP, '/', '?', NOP, NOP, }, 0x33,0x00 }, ++/*36*/{{ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, }, 0xFF,0x00 }, ++/*37*/{{ '*', '*', '*', '*', '*', '*', '*', '*', }, 0x00,0x00 }, ++/*38*/{{ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, }, 0xFF,0x00 }, ++/*39*/{{ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', }, 0x02,0x00 }, ++/*3a*/{{ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, }, 0xFF,0x00 }, ++/*3b*/{{ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11),}, 0xFF,0x00 }, ++/*3c*/{{ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12),}, 0xFF,0x00 }, ++/*3d*/{{ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13),}, 0xFF,0x00 }, ++/*3e*/{{ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14),}, 0xFF,0x00 }, ++/*3f*/{{ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15),}, 0xFF,0x00 }, ++/*40*/{{ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16),}, 0xFF,0x00 }, ++/*41*/{{ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7),}, 0xFF,0x00 }, ++/*42*/{{ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8),}, 0xFF,0x00 }, ++/*43*/{{ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9),}, 0xFF,0x00 }, ++/*44*/{{ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10),}, 0xFF,0x00 }, ++/*45*/{{ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, }, 0xFF,0x00 }, ++/*46*/{{ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, }, 0xFF,0x00 }, ++/*47*/{{ F(49), '7', '7', '7', '7', '7', '7', '7', }, 0x80,0x02 }, ++/*48*/{{ F(50), '8', '8', '8', '8', '8', '8', '8', }, 0x80,0x02 }, ++/*49*/{{ F(51), '9', '9', '9', '9', '9', '9', '9', }, 0x80,0x02 }, ++/*4a*/{{ F(52), '-', '-', '-', '-', '-', '-', '-', }, 0x80,0x02 }, ++/*4b*/{{ F(53), '4', '4', '4', '4', '4', '4', '4', }, 0x80,0x02 }, ++/*4c*/{{ F(54), '5', '5', '5', '5', '5', '5', '5', }, 0x80,0x02 }, ++/*4d*/{{ F(55), '6', '6', '6', '6', '6', '6', '6', }, 0x80,0x02 }, ++/*4e*/{{ F(56), '+', '+', '+', '+', '+', '+', '+', }, 0x80,0x02 }, ++/*4f*/{{ F(57), '1', '1', '1', '1', '1', '1', '1', }, 0x80,0x02 }, ++/*50*/{{ F(58), '2', '2', '2', '2', '2', '2', '2', }, 0x80,0x02 }, ++/*51*/{{ F(59), '3', '3', '3', '3', '3', '3', '3', }, 0x80,0x02 }, ++/*52*/{{ F(60), '0', '0', '0', '0', '0', '0', '0', }, 0x80,0x02 }, ++/*53*/{{ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, }, 0x03,0x02 }, ++/*54*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++/*55*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++/*56*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++/*57*/{{ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11),}, 0xFF,0x00 }, ++/*58*/{{ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12),}, 0xFF,0x00 }, ++/*59*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 }, ++/*5a*/{{ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, }, 0xFF,0x00 }, ++/*5b*/{{ '/', '/', '/', '/', '/', '/', '/', '/', }, 0x00,0x02 }, ++/*5c*/{{ NEXT, PREV, DBG, DBG, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++/*5d*/{{ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, }, 0xFF,0x00 }, ++/*5e*/{{ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49),}, 0xFF,0x00 }, ++/*5f*/{{ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50),}, 0xFF,0x00 }, ++/*60*/{{ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51),}, 0xFF,0x00 }, ++/*61*/{{ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53),}, 0xFF,0x00 }, ++/*62*/{{ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55),}, 0xFF,0x00 }, ++/*63*/{{ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57),}, 0xFF,0x00 }, ++/*64*/{{ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58),}, 0xFF,0x00 }, ++/*65*/{{ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59),}, 0xFF,0x00 }, ++/*66*/{{ F(60),PASTE, F(60), F(60), F(60), F(60), F(60), F(60),}, 0xFF,0x00 }, ++/*67*/{{ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61),}, 0xFF,0x00 }, ++/*68*/{{ SLK, SPSC, SLK, SPSC, SUSP, NOP, SUSP, NOP, }, 0xFF,0x00 }, ++/*69*/{{ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62),}, 0xFF,0x00 }, ++/*6a*/{{ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63),}, 0xFF,0x00 }, ++/*6b*/{{ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64),}, 0xFF,0x00 }, ++/*6c*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, ++} }; ++ ++#endif /* !KBD_DFLT_KEYMAP */ +\ No newline at end of file diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 5ee0651b4..376dcc1c2 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +kdbtable.patch kbio.patch input.h.patch input.c.patch From f4de9eb8f63749d1b2ebf267f239e45a4643c2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Thu, 17 Aug 2023 22:16:08 +0200 Subject: [PATCH 10/21] contrib/st: add st.c.patch --- contrib/st/patches/series | 1 + contrib/st/patches/st.c.patch | 127 ++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 contrib/st/patches/st.c.patch diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 376dcc1c2..3d70f5ef0 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +st.c.patch kdbtable.patch kbio.patch input.h.patch diff --git a/contrib/st/patches/st.c.patch b/contrib/st/patches/st.c.patch new file mode 100644 index 000000000..9c0fe4ef6 --- /dev/null +++ b/contrib/st/patches/st.c.patch @@ -0,0 +1,127 @@ +Index: st/st/st.c +=================================================================== +--- st.orig/st/st.c 2023-08-20 18:28:23.003932423 +0200 ++++ st/st/st.c 2023-08-20 18:30:27.003935457 +0200 +@@ -16,18 +16,11 @@ + #include + #include + #include ++#include + + #include "st.h" + #include "win.h" + +-#if defined(__linux) +- #include +-#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +- #include +-#elif defined(__FreeBSD__) || defined(__DragonFly__) +- #include +-#endif +- + /* Arbitrary sizes */ + #define UTF_INVALID 0xFFFD + #define UTF_SIZ 4 +@@ -672,7 +665,7 @@ + } + + if ((sh = getenv("SHELL")) == NULL) +- sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; ++ sh = (pw->pw_shell[0]) ? ((char *)pw->pw_shell) : cmd; + + if (args) { + prog = args[0]; +@@ -829,6 +822,7 @@ + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); ++ break; + default: + buflen += ret; + written = twrite(buf, buflen, 0); +@@ -836,8 +830,8 @@ + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); +- return ret; + } ++ return ret; + } + + void +@@ -901,7 +895,7 @@ + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; +- if (r < n) { ++ if (r < (ssize_t)n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full +@@ -1019,7 +1013,7 @@ + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); +- for (i = tabspaces; i < term.col; i += tabspaces) ++ for (i = tabspaces; i < (uint)term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; +@@ -1299,7 +1293,7 @@ + tdefcolor(const int *attr, int *npar, int l) + { + int32_t idx = -1; +- uint r, g, b; ++ int r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ +@@ -1858,7 +1852,7 @@ + + n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + is_osc4 ? "4;" : "", num, r, r, g, g, b, b); +- if (n < 0 || n >= sizeof(buf)) { ++ if (n < 0 || n >= (int)sizeof(buf)) { + fprintf(stderr, "error: %s while printing %s response\n", + n < 0 ? "snprintf failed" : "truncation occurred", + is_osc4 ? "osc4" : "osc"); +@@ -1916,7 +1910,7 @@ + if (narg < 2) + break; + p = strescseq.args[1]; +- if ((j = par - 10) < 0 || j >= LEN(osc_table)) ++ if ((j = par - 10) < 0 || j >= (int)LEN(osc_table)) + break; /* shouldn't be possible */ + + if (!strcmp(p, "?")) { +@@ -2099,7 +2093,7 @@ + void + tputtab(int n) + { +- uint x = term.c.x; ++ int x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) +@@ -2360,10 +2354,10 @@ + { + char c[UTF_SIZ]; + int control; +- int width, len; ++ int width = 0, len; + Glyph *gp; + +- control = ISCONTROL(u); ++ control = ISCONTROL((int_least32_t)u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; +@@ -2519,7 +2513,7 @@ + u = buf[n] & 0xFF; + charsize = 1; + } +- if (show_ctrl && ISCONTROL(u)) { ++ if (show_ctrl && ISCONTROL((int_least32_t)u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); From a6f559c7a05623514a3c9457ee06239810be12c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Fri, 18 Aug 2023 23:31:17 +0200 Subject: [PATCH 11/21] contrib/st: add x.c.patch --- contrib/st/patches/series | 1 + contrib/st/patches/x.c.patch | 2544 ++++++++++++++++++++++++++++++++++ 2 files changed, 2545 insertions(+) create mode 100644 contrib/st/patches/x.c.patch diff --git a/contrib/st/patches/series b/contrib/st/patches/series index 3d70f5ef0..8c69c0612 100644 --- a/contrib/st/patches/series +++ b/contrib/st/patches/series @@ -1,3 +1,4 @@ +x.c.patch st.c.patch kdbtable.patch kbio.patch diff --git a/contrib/st/patches/x.c.patch b/contrib/st/patches/x.c.patch new file mode 100644 index 000000000..cf50b5d45 --- /dev/null +++ b/contrib/st/patches/x.c.patch @@ -0,0 +1,2544 @@ +Index: st/st/x.c +=================================================================== +--- st.orig/st/x.c 2023-08-20 18:30:36.680602366 +0200 ++++ st/st/x.c 2023-08-20 18:40:47.457284177 +0200 +@@ -1,2099 +1,457 @@ +-/* See LICENSE for license details. */ ++#include ++#include ++#include ++#include ++ + #include + #include + #include + #include + #include +-#include + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + +-char *argv0; +-#include "arg.h" + #include "st.h" ++#include "font.h" + #include "win.h" ++#include "input.h" + +-/* types used in config.h */ +-typedef struct { +- uint mod; +- KeySym keysym; +- void (*func)(const Arg *); +- const Arg arg; +-} Shortcut; +- +-typedef struct { +- uint mod; +- uint button; +- void (*func)(const Arg *); +- const Arg arg; +- uint release; +-} MouseShortcut; +- +-typedef struct { +- KeySym k; +- uint mask; +- char *s; +- /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ +- signed char appkey; /* application keypad */ +- signed char appcursor; /* application cursor */ +-} Key; +- +-/* 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 config.h */ +-static void clipcopy(const Arg *); +-static void clippaste(const Arg *); +-static void numlock(const Arg *); +-static void selpaste(const Arg *); +-static void zoom(const Arg *); +-static void zoomabs(const Arg *); +-static void zoomreset(const Arg *); +-static void ttysend(const Arg *); +- +-/* config.h for applying patches and the configuration. */ + #include "config.h" + +-/* XEMBED messages */ +-#define XEMBED_FOCUS_IN 4 +-#define XEMBED_FOCUS_OUT 5 +- + /* macros */ +-#define IS_SET(flag) ((win.mode & (flag)) != 0) +-#define TRUERED(x) (((x) & 0xff0000) >> 8) +-#define TRUEGREEN(x) (((x) & 0xff00)) +-#define TRUEBLUE(x) (((x) & 0xff) << 8) +- +-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 ch; /* char height */ +- int cw; /* char width */ +- int mode; /* window state/mode flags */ +- int cursor; /* cursor style */ +-} TermWindow; +- +-typedef struct { +- Display *dpy; +- Colormap cmap; +- Window win; +- Drawable buf; +- GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ +- Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; +- struct { +- XIM xim; +- XIC xic; +- XPoint spot; +- XVaNestedList spotlist; +- } ime; +- Draw draw; +- Visual *vis; +- XSetWindowAttributes attrs; +- int scr; +- int isfixed; /* is fixed geometry? */ +- int l, t; /* left and top offset */ +- int gm; /* geometry mask */ +-} XWindow; +- +-typedef struct { +- Atom xtarget; +- char *primary, *clipboard; +- struct timespec tclick1; +- struct timespec tclick2; +-} XSelection; +- +-/* Font structure */ +-#define Font Font_ +-typedef struct { +- int height; +- int width; +- int ascent; +- int descent; +- int badslant; +- int badweight; +- short lbearing; +- short rbearing; +- XftFont *match; +- FcFontSet *set; +- FcPattern *pattern; +-} Font; +- +-/* Drawing Context */ +-typedef struct { +- Color *col; +- size_t collen; +- Font font, bfont, ifont, ibfont; +- GC gc; +-} DC; +- +-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 xdrawglyph(Glyph, int, int); +-static void xclear(int, int, int, int); +-static int xgeommasktogravity(int); +-static int ximopen(Display *); +-static void ximinstantiate(Display *, XPointer, XPointer); +-static void ximdestroy(XIM, XPointer, XPointer); +-static int xicdestroy(XIC, XPointer, XPointer); +-static void xinit(int, int); +-static void cresize(int, int); +-static void xresize(int, int); +-static void xhints(void); +-static int xloadcolor(int, const char *, Color *); +-static int xloadfont(Font *, FcPattern *); +-static void xloadfonts(const char *, double); +-static void xunloadfont(Font *); +-static void xunloadfonts(void); +-static void xsetenv(void); +-static void xseturgency(int); +-static int evcol(XEvent *); +-static int evrow(XEvent *); +- +-static void expose(XEvent *); +-static void visibility(XEvent *); +-static void unmap(XEvent *); +-static void kpress(XEvent *); +-static void cmessage(XEvent *); +-static void resize(XEvent *); +-static void focus(XEvent *); +-static uint buttonmask(uint); +-static int mouseaction(XEvent *, uint); +-static void brelease(XEvent *); +-static void bpress(XEvent *); +-static void bmotion(XEvent *); +-static void propnotify(XEvent *); +-static void selnotify(XEvent *); +-static void selclear_(XEvent *); +-static void selrequest(XEvent *); +-static void setsel(char *, Time); +-static void mousesel(XEvent *, int); +-static void mousereport(XEvent *); +-static char *kmap(KeySym, uint); +-static int match(uint, uint); +- +-static void run(void); +-static void usage(void); +- +-static void (*handler[LASTEvent])(XEvent *) = { +- [KeyPress] = kpress, +- [ClientMessage] = cmessage, +- [ConfigureNotify] = resize, +- [VisibilityNotify] = visibility, +- [UnmapNotify] = unmap, +- [Expose] = expose, +- [FocusIn] = focus, +- [FocusOut] = focus, +- [MotionNotify] = bmotion, +- [ButtonPress] = bpress, +- [ButtonRelease] = brelease, +-/* +- * Uncomment if you want the selection to disappear when you select something +- * different in another window. +- */ +-/* [SelectionClear] = selclear_, */ +- [SelectionNotify] = selnotify, +-/* +- * PropertyNotify is only turned on when there is some INCR transfer happening +- * for the selection retrieval. +- */ +- [PropertyNotify] = propnotify, +- [SelectionRequest] = selrequest, +-}; +- +-/* Globals */ +-static DC dc; +-static XWindow xw; +-static XSelection xsel; +-static TermWindow win; +- +-/* Font Ring Cache */ +-enum { +- FRC_NORMAL, +- FRC_ITALIC, +- FRC_BOLD, +- FRC_ITALICBOLD +-}; +- +-typedef struct { +- XftFont *font; +- int flags; +- Rune unicodep; +-} Fontcache; +- +-/* Fontcache is an array now. A new font will be appended to the array. */ +-static Fontcache *frc = NULL; +-static int frclen = 0; +-static int frccap = 0; +-static char *usedfont = NULL; +-static double usedfontsize = 0; +-static double defaultfontsize = 0; +- +-static char *opt_class = NULL; +-static char **opt_cmd = NULL; +-static char *opt_embed = NULL; +-static char *opt_font = NULL; +-static char *opt_io = NULL; +-static char *opt_line = NULL; +-static char *opt_name = NULL; +-static char *opt_title = NULL; +- +-static uint buttons; /* bit field of pressed buttons */ +- +-void +-clipcopy(const Arg *dummy) +-{ +- Atom clipboard; +- +- free(xsel.clipboard); +- xsel.clipboard = NULL; +- +- if (xsel.primary != NULL) { +- xsel.clipboard = xstrdup(xsel.primary); +- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); +- XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); +- } +-} +- +-void +-clippaste(const Arg *dummy) +-{ +- Atom clipboard; +- +- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); +- XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, +- xw.win, CurrentTime); +-} +- +-void +-selpaste(const Arg *dummy) +-{ +- XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, +- xw.win, CurrentTime); +-} +- +-void +-numlock(const Arg *dummy) +-{ +- win.mode ^= MODE_NUMLOCK; +-} +- +-void +-zoom(const Arg *arg) +-{ +- Arg larg; +- +- larg.f = usedfontsize + arg->f; +- zoomabs(&larg); +-} +- +-void +-zoomabs(const Arg *arg) +-{ +- xunloadfonts(); +- xloadfonts(usedfont, arg->f); +- cresize(0, 0); +- redraw(); +- xhints(); +-} +- +-void +-zoomreset(const Arg *arg) +-{ +- Arg larg; +- +- if (defaultfontsize > 0) { +- larg.f = defaultfontsize; +- zoomabs(&larg); +- } +-} +- +-void +-ttysend(const Arg *arg) +-{ +- ttywrite(arg->s, strlen(arg->s), 1); +-} +- +-int +-evcol(XEvent *e) +-{ +- int x = e->xbutton.x - borderpx; +- LIMIT(x, 0, win.tw - 1); +- return x / win.cw; +-} +- +-int +-evrow(XEvent *e) +-{ +- int y = e->xbutton.y - borderpx; +- LIMIT(y, 0, win.th - 1); +- return y / win.ch; +-} +- +-void +-mousesel(XEvent *e, int done) +-{ +- int type, seltype = SEL_REGULAR; +- uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); +- +- for (type = 1; type < LEN(selmasks); ++type) { +- if (match(selmasks[type], state)) { +- seltype = type; +- break; +- } +- } +- selextend(evcol(e), evrow(e), seltype, done); +- if (done) +- setsel(getsel(), e->xbutton.time); +-} +- +-void +-mousereport(XEvent *e) +-{ +- int len, btn, code; +- int x = evcol(e), y = evrow(e); +- int state = e->xbutton.state; +- char buf[40]; +- static int ox, oy; +- +- if (e->type == MotionNotify) { +- if (x == ox && y == oy) +- return; +- if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) +- return; +- /* MODE_MOUSEMOTION: no reporting if no button is pressed */ +- if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) +- return; +- /* Set btn to lowest-numbered pressed button, or 12 if no +- * buttons are pressed. */ +- for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) +- ; +- code = 32; +- } else { +- btn = e->xbutton.button; +- /* Only buttons 1 through 11 can be encoded */ +- if (btn < 1 || btn > 11) +- return; +- if (e->type == ButtonRelease) { +- /* MODE_MOUSEX10: no button release reporting */ +- if (IS_SET(MODE_MOUSEX10)) +- return; +- /* Don't send release events for the scroll wheel */ +- if (btn == 4 || btn == 5) +- return; +- } +- code = 0; +- } +- +- ox = x; +- oy = y; +- +- /* Encode btn into code. If no button is pressed for a motion event in +- * MODE_MOUSEMANY, then encode it as a release. */ +- if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) +- code += 3; +- else if (btn >= 8) +- code += 128 + btn - 8; +- else if (btn >= 4) +- code += 64 + btn - 4; +- else +- code += btn - 1; +- +- if (!IS_SET(MODE_MOUSEX10)) { +- code += ((state & ShiftMask ) ? 4 : 0) +- + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ +- + ((state & ControlMask) ? 16 : 0); +- } +- +- if (IS_SET(MODE_MOUSESGR)) { +- len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", +- code, x+1, y+1, +- e->type == ButtonRelease ? 'm' : 'M'); +- } else if (x < 223 && y < 223) { +- len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", +- 32+code, 32+x+1, 32+y+1); +- } else { +- return; +- } +- +- ttywrite(buf, len, 0); +-} +- +-uint +-buttonmask(uint button) +-{ +- return button == Button1 ? Button1Mask +- : button == Button2 ? Button2Mask +- : button == Button3 ? Button3Mask +- : button == Button4 ? Button4Mask +- : button == Button5 ? Button5Mask +- : 0; +-} +- +-int +-mouseaction(XEvent *e, uint release) +-{ +- MouseShortcut *ms; +- +- /* ignore Buttonmask for Button - it's set on release */ +- uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); +- +- for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { +- if (ms->release == release && +- ms->button == e->xbutton.button && +- (match(ms->mod, state) || /* exact or forced */ +- match(ms->mod, state & ~forcemousemod))) { +- ms->func(&(ms->arg)); +- return 1; +- } +- } +- +- return 0; +-} +- +-void +-bpress(XEvent *e) +-{ +- int btn = e->xbutton.button; +- struct timespec now; +- int snap; +- +- if (1 <= btn && btn <= 11) +- buttons |= 1 << (btn-1); +- +- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { +- mousereport(e); +- return; +- } +- +- if (mouseaction(e, 0)) +- return; +- +- if (btn == Button1) { +- /* +- * If the user clicks below predefined timeouts specific +- * snapping behaviour is exposed. +- */ +- clock_gettime(CLOCK_MONOTONIC, &now); +- if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { +- snap = SNAP_LINE; +- } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { +- snap = SNAP_WORD; +- } else { +- snap = 0; +- } +- xsel.tclick2 = xsel.tclick1; +- xsel.tclick1 = now; +- +- selstart(evcol(e), evrow(e), snap); +- } +-} +- +-void +-propnotify(XEvent *e) +-{ +- XPropertyEvent *xpev; +- Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); +- +- xpev = &e->xproperty; +- if (xpev->state == PropertyNewValue && +- (xpev->atom == XA_PRIMARY || +- xpev->atom == clipboard)) { +- selnotify(e); +- } +-} +- +-void +-selnotify(XEvent *e) +-{ +- ulong nitems, ofs, rem; +- int format; +- uchar *data, *last, *repl; +- Atom type, incratom, property = None; +- +- incratom = XInternAtom(xw.dpy, "INCR", 0); +- +- ofs = 0; +- if (e->type == SelectionNotify) +- property = e->xselection.property; +- else if (e->type == PropertyNotify) +- property = e->xproperty.atom; +- +- if (property == None) +- return; +- +- do { +- if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, +- BUFSIZ/4, False, AnyPropertyType, +- &type, &format, &nitems, &rem, +- &data)) { +- fprintf(stderr, "Clipboard allocation failed\n"); +- return; +- } +- +- if (e->type == PropertyNotify && nitems == 0 && rem == 0) { +- /* +- * If there is some PropertyNotify with no data, then +- * this is the signal of the selection owner that all +- * data has been transferred. We won't need to receive +- * PropertyNotify events anymore. +- */ +- MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); +- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, +- &xw.attrs); +- } +- +- if (type == incratom) { +- /* +- * Activate the PropertyNotify events so we receive +- * when the selection owner does send us the next +- * chunk of data. +- */ +- MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); +- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, +- &xw.attrs); +- +- /* +- * Deleting the property is the transfer start signal. +- */ +- XDeleteProperty(xw.dpy, xw.win, (int)property); +- continue; +- } +- +- /* +- * As seen in getsel: +- * Line endings are inconsistent in the terminal and GUI world +- * copy and pasting. When receiving some selection data, +- * replace all '\n' with '\r'. +- * FIXME: Fix the computer world. +- */ +- repl = data; +- last = data + nitems * format / 8; +- while ((repl = memchr(repl, '\n', last - repl))) { +- *repl++ = '\r'; +- } +- +- if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) +- ttywrite("\033[200~", 6, 0); +- ttywrite((char *)data, nitems * format / 8, 1); +- if (IS_SET(MODE_BRCKTPASTE) && rem == 0) +- ttywrite("\033[201~", 6, 0); +- XFree(data); +- /* number of 32-bit chunks returned */ +- ofs += nitems * format / 32; +- } while (rem > 0); +- +- /* +- * Deleting the property again tells the selection owner to send the +- * next data chunk in the property. +- */ +- XDeleteProperty(xw.dpy, xw.win, (int)property); +-} +- +-void +-xclipcopy(void) +-{ +- clipcopy(NULL); +-} +- +-void +-selclear_(XEvent *e) +-{ +- selclear(); +-} +- +-void +-selrequest(XEvent *e) +-{ +- XSelectionRequestEvent *xsre; +- XSelectionEvent xev; +- Atom xa_targets, string, clipboard; +- char *seltext; +- +- xsre = (XSelectionRequestEvent *) e; +- xev.type = SelectionNotify; +- xev.requestor = xsre->requestor; +- xev.selection = xsre->selection; +- xev.target = xsre->target; +- xev.time = xsre->time; +- if (xsre->property == None) +- xsre->property = xsre->target; +- +- /* reject */ +- xev.property = None; +- +- xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); +- if (xsre->target == xa_targets) { +- /* respond with the supported type */ +- string = xsel.xtarget; +- XChangeProperty(xsre->display, xsre->requestor, xsre->property, +- XA_ATOM, 32, PropModeReplace, +- (uchar *) &string, 1); +- xev.property = xsre->property; +- } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { +- /* +- * xith XA_STRING non ascii characters may be incorrect in the +- * requestor. It is not our problem, use utf8. +- */ +- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); +- if (xsre->selection == XA_PRIMARY) { +- seltext = xsel.primary; +- } else if (xsre->selection == clipboard) { +- seltext = xsel.clipboard; +- } else { +- fprintf(stderr, +- "Unhandled clipboard selection 0x%lx\n", +- xsre->selection); +- return; +- } +- if (seltext != NULL) { +- XChangeProperty(xsre->display, xsre->requestor, +- xsre->property, xsre->target, +- 8, PropModeReplace, +- (uchar *)seltext, strlen(seltext)); +- xev.property = xsre->property; +- } +- } +- +- /* all done, send a notification to the listener */ +- if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) +- fprintf(stderr, "Error sending SelectionNotify event\n"); +-} +- +-void +-setsel(char *str, Time t) +-{ +- if (!str) +- return; +- +- free(xsel.primary); +- xsel.primary = str; +- +- XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); +- if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) +- selclear(); +-} +- +-void +-xsetsel(char *str) +-{ +- setsel(str, CurrentTime); +-} +- +-void +-brelease(XEvent *e) +-{ +- int btn = e->xbutton.button; +- +- if (1 <= btn && btn <= 11) +- buttons &= ~(1 << (btn-1)); +- +- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { +- mousereport(e); +- return; +- } +- +- if (mouseaction(e, 1)) +- return; +- if (btn == Button1) +- mousesel(e, 1); +-} +- +-void +-bmotion(XEvent *e) +-{ +- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { +- mousereport(e); +- return; +- } +- +- mousesel(e, 0); +-} +- +-void +-cresize(int width, int height) +-{ +- int col, row; +- +- if (width != 0) +- win.w = width; +- if (height != 0) +- win.h = height; +- +- col = (win.w - 2 * borderpx) / win.cw; +- row = (win.h - 2 * borderpx) / win.ch; +- col = MAX(1, col); +- row = MAX(1, row); +- +- tresize(col, row); +- xresize(col, row); +- ttyresize(win.tw, win.th); +-} +- +-void +-xresize(int col, int row) +-{ +- win.tw = col * win.cw; +- win.th = row * win.ch; +- +- XFreePixmap(xw.dpy, xw.buf); +- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); +- XftDrawChange(xw.draw, xw.buf); +- xclear(0, 0, win.w, win.h); +- +- /* resize to new width */ +- xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); +-} +- +-ushort +-sixd_to_16bit(int x) +-{ +- return x == 0 ? 0 : 0x3737 + 0x2828 * x; +-} +- +-int +-xloadcolor(int i, const char *name, Color *ncolor) +-{ +- XRenderColor color = { .alpha = 0xffff }; +- +- if (!name) { +- if (BETWEEN(i, 16, 255)) { /* 256 color */ +- if (i < 6*6*6+16) { /* same colors as xterm */ +- color.red = sixd_to_16bit( ((i-16)/36)%6 ); +- color.green = sixd_to_16bit( ((i-16)/6) %6 ); +- color.blue = sixd_to_16bit( ((i-16)/1) %6 ); +- } else { /* greyscale */ +- color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); +- color.green = color.blue = color.red; +- } +- return XftColorAllocValue(xw.dpy, xw.vis, +- xw.cmap, &color, ncolor); +- } else +- name = colorname[i]; +- } +- +- return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); +-} +- +-void +-xloadcols(void) +-{ +- int i; +- static int loaded; +- Color *cp; +- +- if (loaded) { +- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) +- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); +- } else { +- dc.collen = MAX(LEN(colorname), 256); +- dc.col = xmalloc(dc.collen * sizeof(Color)); +- } +- +- for (i = 0; i < dc.collen; i++) +- if (!xloadcolor(i, NULL, &dc.col[i])) { +- if (colorname[i]) +- die("could not allocate color '%s'\n", colorname[i]); +- else +- die("could not allocate color %d\n", i); +- } +- loaded = 1; +-} +- +-int +-xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +-{ +- if (!BETWEEN(x, 0, dc.collen)) +- return 1; +- +- *r = dc.col[x].color.red >> 8; +- *g = dc.col[x].color.green >> 8; +- *b = dc.col[x].color.blue >> 8; +- +- return 0; +-} +- +-int +-xsetcolorname(int x, const char *name) +-{ +- Color ncolor; +- +- if (!BETWEEN(x, 0, dc.collen)) +- return 1; +- +- if (!xloadcolor(x, name, &ncolor)) +- return 1; +- +- XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); +- dc.col[x] = ncolor; +- +- return 0; +-} +- +-/* +- * Absolute coordinates. +- */ +-void +-xclear(int x1, int y1, int x2, int y2) +-{ +- XftDrawRect(xw.draw, +- &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], +- x1, y1, x2-x1, y2-y1); +-} +- +-void +-xhints(void) +-{ +- XClassHint class = {opt_name ? opt_name : termname, +- opt_class ? opt_class : termname}; +- XWMHints wm = {.flags = InputHint, .input = 1}; +- XSizeHints *sizeh; +- +- sizeh = XAllocSizeHints(); +- +- sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; +- sizeh->height = win.h; +- sizeh->width = win.w; +- sizeh->height_inc = win.ch; +- sizeh->width_inc = win.cw; +- sizeh->base_height = 2 * borderpx; +- sizeh->base_width = 2 * borderpx; +- sizeh->min_height = win.ch + 2 * borderpx; +- sizeh->min_width = win.cw + 2 * borderpx; +- if (xw.isfixed) { +- sizeh->flags |= PMaxSize; +- sizeh->min_width = sizeh->max_width = win.w; +- sizeh->min_height = sizeh->max_height = win.h; +- } +- if (xw.gm & (XValue|YValue)) { +- sizeh->flags |= USPosition | PWinGravity; +- sizeh->x = xw.l; +- sizeh->y = xw.t; +- sizeh->win_gravity = xgeommasktogravity(xw.gm); +- } +- +- XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, +- &class); +- XFree(sizeh); +-} +- +-int +-xgeommasktogravity(int mask) +-{ +- switch (mask & (XNegative|YNegative)) { +- case 0: +- return NorthWestGravity; +- case XNegative: +- return NorthEastGravity; +- case YNegative: +- return SouthWestGravity; +- } +- +- return SouthEastGravity; +-} +- +-int +-xloadfont(Font *f, FcPattern *pattern) +-{ +- FcPattern *configured; +- FcPattern *match; +- FcResult result; +- XGlyphInfo extents; +- int wantattr, haveattr; +- +- /* +- * Manually configure instead of calling XftMatchFont +- * so that we can use the configured pattern for +- * "missing glyph" lookups. +- */ +- configured = FcPatternDuplicate(pattern); +- if (!configured) +- return 1; +- +- FcConfigSubstitute(NULL, configured, FcMatchPattern); +- XftDefaultSubstitute(xw.dpy, xw.scr, configured); +- +- match = FcFontMatch(NULL, configured, &result); +- if (!match) { +- FcPatternDestroy(configured); +- return 1; +- } +- +- if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { +- FcPatternDestroy(configured); +- FcPatternDestroy(match); +- return 1; +- } +- +- if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == +- XftResultMatch)) { +- /* +- * Check if xft was unable to find a font with the appropriate +- * slant but gave us one anyway. Try to mitigate. +- */ +- if ((XftPatternGetInteger(f->match->pattern, "slant", 0, +- &haveattr) != XftResultMatch) || haveattr < wantattr) { +- f->badslant = 1; +- fputs("font slant does not match\n", stderr); +- } +- } +- +- if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == +- XftResultMatch)) { +- if ((XftPatternGetInteger(f->match->pattern, "weight", 0, +- &haveattr) != XftResultMatch) || haveattr != wantattr) { +- f->badweight = 1; +- fputs("font weight does not match\n", stderr); +- } +- } +- +- XftTextExtentsUtf8(xw.dpy, f->match, +- (const FcChar8 *) ascii_printable, +- strlen(ascii_printable), &extents); +- +- f->set = NULL; +- f->pattern = configured; +- +- f->ascent = f->match->ascent; +- f->descent = f->match->descent; +- f->lbearing = 0; +- f->rbearing = f->match->max_advance_width; +- +- f->height = f->ascent + f->descent; +- f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); +- +- return 0; +-} +- +-void +-xloadfonts(const char *fontstr, double fontsize) +-{ +- FcPattern *pattern; +- double fontval; +- +- if (fontstr[0] == '-') +- pattern = XftXlfdParse(fontstr, False, False); +- else +- pattern = FcNameParse((const FcChar8 *)fontstr); +- +- if (!pattern) +- die("can't open font %s\n", fontstr); +- +- if (fontsize > 1) { +- FcPatternDel(pattern, FC_PIXEL_SIZE); +- FcPatternDel(pattern, FC_SIZE); +- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); +- usedfontsize = fontsize; +- } else { +- if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == +- FcResultMatch) { +- usedfontsize = fontval; +- } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == +- FcResultMatch) { +- usedfontsize = -1; +- } else { +- /* +- * Default font size is 12, if none given. This is to +- * have a known usedfontsize value. +- */ +- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); +- usedfontsize = 12; +- } +- defaultfontsize = usedfontsize; +- } +- +- if (xloadfont(&dc.font, pattern)) +- die("can't open font %s\n", fontstr); +- +- if (usedfontsize < 0) { +- FcPatternGetDouble(dc.font.match->pattern, +- FC_PIXEL_SIZE, 0, &fontval); +- usedfontsize = fontval; +- if (fontsize == 0) +- defaultfontsize = fontval; +- } +- +- /* Setting character width and height. */ +- win.cw = ceilf(dc.font.width * cwscale); +- win.ch = ceilf(dc.font.height * chscale); +- +- FcPatternDel(pattern, FC_SLANT); +- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); +- if (xloadfont(&dc.ifont, pattern)) +- die("can't open font %s\n", fontstr); +- +- FcPatternDel(pattern, FC_WEIGHT); +- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); +- if (xloadfont(&dc.ibfont, pattern)) +- die("can't open font %s\n", fontstr); +- +- FcPatternDel(pattern, FC_SLANT); +- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); +- if (xloadfont(&dc.bfont, pattern)) +- die("can't open font %s\n", fontstr); +- +- FcPatternDestroy(pattern); +-} +- +-void +-xunloadfont(Font *f) +-{ +- XftFontClose(xw.dpy, f->match); +- FcPatternDestroy(f->pattern); +- if (f->set) +- FcFontSetDestroy(f->set); +-} +- +-void +-xunloadfonts(void) +-{ +- /* Free the loaded fonts in the font cache. */ +- while (frclen > 0) +- XftFontClose(xw.dpy, frc[--frclen].font); +- +- xunloadfont(&dc.font); +- xunloadfont(&dc.bfont); +- xunloadfont(&dc.ifont); +- xunloadfont(&dc.ibfont); +-} +- +-int +-ximopen(Display *dpy) +-{ +- XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; +- XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; +- +- xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); +- if (xw.ime.xim == NULL) +- return 0; +- +- if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) +- fprintf(stderr, "XSetIMValues: " +- "Could not set XNDestroyCallback.\n"); +- +- xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, +- NULL); +- +- if (xw.ime.xic == NULL) { +- xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, +- XIMPreeditNothing | XIMStatusNothing, +- XNClientWindow, xw.win, +- XNDestroyCallback, &icdestroy, +- NULL); +- } +- if (xw.ime.xic == NULL) +- fprintf(stderr, "XCreateIC: Could not create input context.\n"); +- +- return 1; +-} +- +-void +-ximinstantiate(Display *dpy, XPointer client, XPointer call) +-{ +- if (ximopen(dpy)) +- XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, +- ximinstantiate, NULL); +-} +- +-void +-ximdestroy(XIM xim, XPointer client, XPointer call) +-{ +- xw.ime.xim = NULL; +- XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, +- ximinstantiate, NULL); +- XFree(xw.ime.spotlist); +-} +- +-int +-xicdestroy(XIC xim, XPointer client, XPointer call) +-{ +- xw.ime.xic = NULL; +- return 1; +-} +- +-void +-xinit(int cols, int rows) +-{ +- XGCValues gcvalues; +- Cursor cursor; +- Window parent; +- pid_t thispid = getpid(); +- XColor xmousefg, xmousebg; +- +- if (!(xw.dpy = XOpenDisplay(NULL))) +- die("can't open display\n"); +- xw.scr = XDefaultScreen(xw.dpy); +- xw.vis = XDefaultVisual(xw.dpy, xw.scr); +- +- /* font */ +- if (!FcInit()) +- die("could not init fontconfig.\n"); +- +- usedfont = (opt_font == NULL)? font : opt_font; +- xloadfonts(usedfont, 0); +- +- /* colors */ +- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); +- xloadcols(); +- +- /* adjust fixed window geometry */ +- win.w = 2 * borderpx + cols * win.cw; +- win.h = 2 * borderpx + rows * win.ch; +- if (xw.gm & XNegative) +- xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; +- if (xw.gm & YNegative) +- xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; +- +- /* Events */ +- xw.attrs.background_pixel = dc.col[defaultbg].pixel; +- xw.attrs.border_pixel = dc.col[defaultbg].pixel; +- xw.attrs.bit_gravity = NorthWestGravity; +- xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask +- | ExposureMask | VisibilityChangeMask | StructureNotifyMask +- | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; +- xw.attrs.colormap = xw.cmap; +- +- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) +- parent = XRootWindow(xw.dpy, xw.scr); +- xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, +- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, +- xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity +- | CWEventMask | CWColormap, &xw.attrs); +- +- memset(&gcvalues, 0, sizeof(gcvalues)); +- gcvalues.graphics_exposures = False; +- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, +- &gcvalues); +- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); +- XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); +- XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); +- +- /* font spec buffer */ +- xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); +- +- /* Xft rendering context */ +- xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); +- +- /* input methods */ +- if (!ximopen(xw.dpy)) { +- XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, +- ximinstantiate, NULL); +- } +- +- /* white cursor, black outline */ +- cursor = XCreateFontCursor(xw.dpy, mouseshape); +- XDefineCursor(xw.dpy, xw.win, cursor); +- +- if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { +- xmousefg.red = 0xffff; +- xmousefg.green = 0xffff; +- xmousefg.blue = 0xffff; +- } +- +- if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { +- xmousebg.red = 0x0000; +- xmousebg.green = 0x0000; +- xmousebg.blue = 0x0000; +- } +- +- XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); +- +- xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); +- xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); +- xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); +- xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); +- XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); +- +- xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); +- XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, +- PropModeReplace, (uchar *)&thispid, 1); +- +- win.mode = MODE_NUMLOCK; +- resettitle(); +- xhints(); +- XMapWindow(xw.dpy, xw.win); +- XSync(xw.dpy, False); +- +- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); +- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); +- xsel.primary = NULL; +- xsel.clipboard = NULL; +- xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); +- if (xsel.xtarget == None) +- xsel.xtarget = XA_STRING; +-} +- +-int +-xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +-{ +- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; +- ushort mode, prevmode = USHRT_MAX; +- Font *font = &dc.font; +- int frcflags = FRC_NORMAL; +- float runewidth = win.cw; +- Rune rune; +- FT_UInt glyphidx; +- FcResult fcres; +- FcPattern *fcpattern, *fontpattern; +- FcFontSet *fcsets[] = { NULL }; +- FcCharSet *fccharset; +- int i, f, numspecs = 0; +- +- 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; +- +- /* Skip dummy wide-character spacing. */ +- if (mode == ATTR_WDUMMY) +- continue; +- +- /* Determine font for glyph if different from previous glyph. */ +- if (prevmode != mode) { +- prevmode = mode; +- font = &dc.font; +- frcflags = FRC_NORMAL; +- runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); +- if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { +- font = &dc.ibfont; +- frcflags = FRC_ITALICBOLD; +- } else if (mode & ATTR_ITALIC) { +- font = &dc.ifont; +- frcflags = FRC_ITALIC; +- } else if (mode & ATTR_BOLD) { +- font = &dc.bfont; +- frcflags = FRC_BOLD; +- } +- yp = winy + font->ascent; +- } +- +- /* Lookup character index with default font. */ +- glyphidx = XftCharIndex(xw.dpy, font->match, rune); +- if (glyphidx) { +- specs[numspecs].font = font->match; +- specs[numspecs].glyph = glyphidx; +- specs[numspecs].x = (short)xp; +- specs[numspecs].y = (short)yp; +- xp += runewidth; +- numspecs++; +- continue; +- } +- +- /* Fallback on font cache, search the font cache for match. */ +- for (f = 0; f < frclen; f++) { +- glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); +- /* Everything correct. */ +- if (glyphidx && frc[f].flags == frcflags) +- break; +- /* We got a default font for a not found glyph. */ +- if (!glyphidx && frc[f].flags == frcflags +- && frc[f].unicodep == rune) { +- break; +- } +- } +- +- /* Nothing was found. Use fontconfig to find matching font. */ +- if (f >= frclen) { +- if (!font->set) +- font->set = FcFontSort(0, font->pattern, +- 1, 0, &fcres); +- fcsets[0] = font->set; +- +- /* +- * Nothing was found in the cache. Now use +- * some dozen of Fontconfig calls to get the +- * font for one single character. +- * +- * Xft and fontconfig are design failures. +- */ +- fcpattern = FcPatternDuplicate(font->pattern); +- fccharset = FcCharSetCreate(); +- +- FcCharSetAddChar(fccharset, rune); +- FcPatternAddCharSet(fcpattern, FC_CHARSET, +- fccharset); +- FcPatternAddBool(fcpattern, FC_SCALABLE, 1); +- +- FcConfigSubstitute(0, fcpattern, +- FcMatchPattern); +- FcDefaultSubstitute(fcpattern); +- +- fontpattern = FcFontSetMatch(0, fcsets, 1, +- fcpattern, &fcres); +- +- /* Allocate memory for the new cache entry. */ +- if (frclen >= frccap) { +- frccap += 16; +- frc = xrealloc(frc, frccap * sizeof(Fontcache)); +- } +- +- frc[frclen].font = XftFontOpenPattern(xw.dpy, +- fontpattern); +- if (!frc[frclen].font) +- die("XftFontOpenPattern failed seeking fallback font: %s\n", +- strerror(errno)); +- frc[frclen].flags = frcflags; +- frc[frclen].unicodep = rune; +- +- glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); +- +- f = frclen; +- frclen++; +- +- FcPatternDestroy(fcpattern); +- FcCharSetDestroy(fccharset); +- } +- +- specs[numspecs].font = frc[f].font; +- specs[numspecs].glyph = glyphidx; +- specs[numspecs].x = (short)xp; +- specs[numspecs].y = (short)yp; +- xp += runewidth; +- numspecs++; +- } +- +- return numspecs; +-} +- +-void +-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) +-{ +- int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); +- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, +- width = charlen * win.cw; +- Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; +- XRenderColor colfg, colbg; +- XRectangle r; +- +- /* Fallback on color display for attributes not supported by the font */ +- if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { +- if (dc.ibfont.badslant || dc.ibfont.badweight) +- base.fg = defaultattr; +- } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || +- (base.mode & ATTR_BOLD && dc.bfont.badweight)) { +- base.fg = defaultattr; +- } +- +- if (IS_TRUECOL(base.fg)) { +- colfg.alpha = 0xffff; +- colfg.red = TRUERED(base.fg); +- colfg.green = TRUEGREEN(base.fg); +- colfg.blue = TRUEBLUE(base.fg); +- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); +- fg = &truefg; +- } else { +- fg = &dc.col[base.fg]; +- } +- +- if (IS_TRUECOL(base.bg)) { +- colbg.alpha = 0xffff; +- colbg.green = TRUEGREEN(base.bg); +- colbg.red = TRUERED(base.bg); +- colbg.blue = TRUEBLUE(base.bg); +- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); +- bg = &truebg; +- } else { +- bg = &dc.col[base.bg]; +- } +- +- /* 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)) +- fg = &dc.col[base.fg + 8]; +- +- if (IS_SET(MODE_REVERSE)) { +- if (fg == &dc.col[defaultfg]) { +- fg = &dc.col[defaultbg]; +- } else { +- colfg.red = ~fg->color.red; +- colfg.green = ~fg->color.green; +- colfg.blue = ~fg->color.blue; +- colfg.alpha = fg->color.alpha; +- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, +- &revfg); +- fg = &revfg; +- } +- +- if (bg == &dc.col[defaultbg]) { +- bg = &dc.col[defaultfg]; +- } else { +- colbg.red = ~bg->color.red; +- colbg.green = ~bg->color.green; +- colbg.blue = ~bg->color.blue; +- colbg.alpha = bg->color.alpha; +- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, +- &revbg); +- bg = &revbg; +- } +- } +- +- if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { +- colfg.red = fg->color.red / 2; +- colfg.green = fg->color.green / 2; +- colfg.blue = fg->color.blue / 2; +- colfg.alpha = fg->color.alpha; +- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); +- fg = &revfg; +- } +- +- if (base.mode & ATTR_REVERSE) { +- temp = fg; +- fg = bg; +- bg = temp; +- } +- +- if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) +- fg = bg; +- +- if (base.mode & ATTR_INVISIBLE) +- fg = bg; +- +- /* Intelligent cleaning up of the borders. */ +- if (x == 0) { +- 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) { +- xclear(winx + width, (y == 0)? 0 : winy, win.w, +- ((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, winy + win.ch, winx + width, win.h); +- +- /* 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); +- +- /* Render the glyphs. */ +- XftDrawGlyphFontSpec(xw.draw, fg, specs, len); +- +- /* Render underline and strikethrough. */ +- if (base.mode & ATTR_UNDERLINE) { +- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, +- width, 1); +- } +- +- if (base.mode & ATTR_STRUCK) { +- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, +- width, 1); +- } +- +- /* Reset clip to none. */ +- XftDrawSetClip(xw.draw, 0); +-} +- +-void +-xdrawglyph(Glyph g, int x, int y) +-{ +- int numspecs; +- XftGlyphFontSpec spec; +- +- numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); +- xdrawglyphfontspecs(&spec, g, numspecs, x, y); +-} +- +-void +-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +-{ +- Color drawcol; +- +- /* remove the old cursor */ +- if (selected(ox, oy)) +- og.mode ^= ATTR_REVERSE; +- xdrawglyph(og, ox, oy); +- +- if (IS_SET(MODE_HIDE)) +- return; +- +- /* +- * Select the right color for the right mode. +- */ +- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; +- +- if (IS_SET(MODE_REVERSE)) { +- g.mode |= ATTR_REVERSE; +- g.bg = defaultfg; +- if (selected(cx, cy)) { +- drawcol = dc.col[defaultcs]; +- g.fg = defaultrcs; +- } else { +- drawcol = dc.col[defaultrcs]; +- g.fg = defaultcs; +- } +- } else { +- if (selected(cx, cy)) { +- g.fg = defaultfg; +- g.bg = defaultrcs; +- } else { +- g.fg = defaultbg; +- g.bg = defaultcs; +- } +- drawcol = dc.col[g.bg]; +- } +- +- /* draw the new one */ +- if (IS_SET(MODE_FOCUSED)) { +- switch (win.cursor) { +- case 7: /* st extension */ +- g.u = 0x2603; /* snowman (U+2603) */ +- /* FALLTHROUGH */ +- case 0: /* Blinking Block */ +- case 1: /* Blinking Block (Default) */ +- case 2: /* Steady Block */ +- xdrawglyph(g, cx, cy); +- break; +- case 3: /* Blinking Underline */ +- case 4: /* Steady Underline */ +- XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - \ +- cursorthickness, +- win.cw, cursorthickness); +- break; +- case 5: /* Blinking bar */ +- case 6: /* Steady bar */ +- XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, +- cursorthickness, win.ch); +- break; +- } +- } else { +- XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, +- win.cw - 1, 1); +- XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, +- 1, win.ch - 1); +- XftDrawRect(xw.draw, &drawcol, +- borderpx + (cx + 1) * win.cw - 1, +- borderpx + cy * win.ch, +- 1, win.ch - 1); +- XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - 1, +- win.cw, 1); +- } +-} +- +-void +-xsetenv(void) +-{ +- char buf[sizeof(long) * 8 + 1]; +- +- snprintf(buf, sizeof(buf), "%lu", xw.win); +- setenv("WINDOWID", buf, 1); +-} +- +-void +-xseticontitle(char *p) +-{ +- XTextProperty prop; +- DEFAULT(p, opt_title); +- +- if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, +- &prop) != Success) +- return; +- XSetWMIconName(xw.dpy, xw.win, &prop); +- XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); +- XFree(prop.value); +-} +- +-void +-xsettitle(char *p) +-{ +- XTextProperty prop; +- DEFAULT(p, opt_title); +- +- if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, +- &prop) != Success) +- return; +- XSetWMName(xw.dpy, xw.win, &prop); +- XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); +- XFree(prop.value); +-} +- +-int +-xstartdraw(void) +-{ +- return IS_SET(MODE_VISIBLE); +-} +- +-void +-xdrawline(Line line, int x1, int y1, int x2) +-{ +- int i, x, ox, numspecs; +- Glyph base, new; +- XftGlyphFontSpec *specs = xw.specbuf; +- +- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); +- i = ox = 0; +- for (x = x1; x < x2 && i < numspecs; x++) { +- 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; +- } +- if (i == 0) { +- ox = x; +- base = new; +- } +- i++; +- } +- if (i > 0) +- xdrawglyphfontspecs(specs, base, i, ox, y1); +-} +- +-void +-xfinishdraw(void) +-{ +- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, +- win.h, 0, 0); +- XSetForeground(xw.dpy, dc.gc, +- dc.col[IS_SET(MODE_REVERSE)? +- defaultfg : defaultbg].pixel); +-} +- +-void +-xximspot(int x, int y) +-{ +- if (xw.ime.xic == NULL) +- return; +- +- xw.ime.spot.x = borderpx + x * win.cw; +- xw.ime.spot.y = borderpx + (y + 1) * win.ch; +- +- XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); +-} +- +-void +-expose(XEvent *ev) +-{ +- redraw(); +-} +- +-void +-visibility(XEvent *ev) +-{ +- XVisibilityEvent *e = &ev->xvisibility; +- +- MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); +-} +- +-void +-unmap(XEvent *ev) +-{ +- win.mode &= ~MODE_VISIBLE; +-} +- +-void +-xsetpointermotion(int set) +-{ +- MODBIT(xw.attrs.event_mask, set, PointerMotionMask); +- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); +-} +- +-void +-xsetmode(int set, unsigned int flags) +-{ +- int mode = win.mode; +- MODBIT(win.mode, set, flags); +- if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) +- redraw(); +-} +- +-int +-xsetcursor(int cursor) +-{ +- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ +- return 1; +- win.cursor = cursor; +- return 0; +-} +- +-void +-xseturgency(int add) +-{ +- XWMHints *h = XGetWMHints(xw.dpy, xw.win); +- +- MODBIT(h->flags, add, XUrgencyHint); +- XSetWMHints(xw.dpy, xw.win, h); +- XFree(h); +-} +- +-void +-xbell(void) +-{ +- if (!(IS_SET(MODE_FOCUSED))) +- xseturgency(1); +- if (bellvolume) +- XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); +-} +- +-void +-focus(XEvent *ev) +-{ +- XFocusChangeEvent *e = &ev->xfocus; +- +- if (e->mode == NotifyGrab) +- return; +- +- if (ev->type == FocusIn) { +- if (xw.ime.xic) +- XSetICFocus(xw.ime.xic); +- win.mode |= MODE_FOCUSED; +- xseturgency(0); +- if (IS_SET(MODE_FOCUS)) +- ttywrite("\033[I", 3, 0); +- } else { +- if (xw.ime.xic) +- XUnsetICFocus(xw.ime.xic); +- win.mode &= ~MODE_FOCUSED; +- if (IS_SET(MODE_FOCUS)) +- ttywrite("\033[O", 3, 0); +- } +-} +- +-int +-match(uint mask, uint state) +-{ +- return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +-} +- +-char* +-kmap(KeySym k, uint state) +-{ +- Key *kp; +- int i; +- +- /* Check for mapped keys out of X11 function keys. */ +- for (i = 0; i < LEN(mappedkeys); i++) { +- if (mappedkeys[i] == k) +- break; +- } +- if (i == LEN(mappedkeys)) { +- if ((k & 0xFFFF) < 0xFD00) +- return NULL; +- } +- +- for (kp = key; kp < key + LEN(key); kp++) { +- if (kp->k != k) +- continue; +- +- if (!match(kp->mask, state)) +- continue; +- +- if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) +- continue; +- if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) +- continue; +- +- if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) +- continue; +- +- return kp->s; +- } +- +- return NULL; +-} +- +-void +-kpress(XEvent *ev) +-{ +- XKeyEvent *e = &ev->xkey; +- KeySym ksym = NoSymbol; +- char buf[64], *customkey; +- int len; +- Rune c; +- Status status; +- Shortcut *bp; +- +- if (IS_SET(MODE_KBDLOCK)) +- return; +- +- if (xw.ime.xic) { +- len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); +- if (status == XBufferOverflow) +- return; +- } else { +- len = XLookupString(e, buf, sizeof buf, &ksym, NULL); +- } +- /* 1. shortcuts */ +- for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { +- if (ksym == bp->keysym && match(bp->mod, e->state)) { +- bp->func(&(bp->arg)); +- return; +- } +- } +- +- /* 2. custom keys from config.h */ +- if ((customkey = kmap(ksym, e->state))) { +- ttywrite(customkey, strlen(customkey), 1); +- return; +- } +- +- /* 3. composed string from input method */ +- if (len == 0) +- return; +- if (len == 1 && e->state & Mod1Mask) { +- if (IS_SET(MODE_8BIT)) { +- if (*buf < 0177) { +- c = *buf | 0x80; +- len = utf8encode(c, buf); +- } +- } else { +- buf[1] = buf[0]; +- buf[0] = '\033'; +- len = 2; +- } +- } +- ttywrite(buf, len, 1); +-} +- +-void +-cmessage(XEvent *e) +-{ +- /* +- * See xembed specs +- * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html +- */ +- if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { +- if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { +- win.mode |= MODE_FOCUSED; +- xseturgency(0); +- } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { +- win.mode &= ~MODE_FOCUSED; +- } +- } else if (e->xclient.data.l[0] == xw.wmdeletewin) { +- ttyhangup(); +- exit(0); +- } +-} +- +-void +-resize(XEvent *e) +-{ +- if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) +- return; +- +- cresize(e->xconfigure.width, e->xconfigure.height); +-} +- +-void +-run(void) +-{ +- XEvent ev; +- int w = win.w, h = win.h; +- fd_set rfd; +- int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; +- struct timespec seltv, *tv, now, lastblink, trigger; +- double timeout; +- +- /* Waiting for window mapping */ +- do { +- XNextEvent(xw.dpy, &ev); +- /* +- * This XFilterEvent call is required because of XOpenIM. It +- * does filter out the key event and some client message for +- * the input method too. +- */ +- if (XFilterEvent(&ev, None)) +- continue; +- if (ev.type == ConfigureNotify) { +- w = ev.xconfigure.width; +- h = ev.xconfigure.height; +- } +- } while (ev.type != MapNotify); +- +- ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); +- cresize(w, h); +- +- for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { +- FD_ZERO(&rfd); +- FD_SET(ttyfd, &rfd); +- FD_SET(xfd, &rfd); +- +- if (XPending(xw.dpy)) +- timeout = 0; /* existing events might not set xfd */ +- +- seltv.tv_sec = timeout / 1E3; +- seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); +- tv = timeout >= 0 ? &seltv : NULL; +- +- if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { +- if (errno == EINTR) +- continue; +- die("select failed: %s\n", strerror(errno)); +- } +- clock_gettime(CLOCK_MONOTONIC, &now); +- +- if (FD_ISSET(ttyfd, &rfd)) +- ttyread(); +- +- xev = 0; +- while (XPending(xw.dpy)) { +- xev = 1; +- XNextEvent(xw.dpy, &ev); +- if (XFilterEvent(&ev, None)) +- continue; +- if (handler[ev.type]) +- (handler[ev.type])(&ev); +- } +- +- /* +- * To reduce flicker and tearing, when new content or event +- * triggers drawing, we first wait a bit to ensure we got +- * everything, and if nothing new arrives - we draw. +- * We start with trying to wait minlatency ms. If more content +- * arrives sooner, we retry with shorter and shorter periods, +- * and eventually draw even without idle after maxlatency ms. +- * Typically this results in low latency while interacting, +- * maximum latency intervals during `cat huge.txt`, and perfect +- * sync with periodic updates from animations/key-repeats/etc. +- */ +- if (FD_ISSET(ttyfd, &rfd) || xev) { +- if (!drawing) { +- trigger = now; +- drawing = 1; +- } +- timeout = (maxlatency - TIMEDIFF(now, trigger)) \ +- / maxlatency * minlatency; +- if (timeout > 0) +- continue; /* we have time, try to find idle */ +- } +- +- /* idle detected or maxlatency exhausted -> draw */ +- timeout = -1; +- if (blinktimeout && tattrset(ATTR_BLINK)) { +- timeout = blinktimeout - TIMEDIFF(now, lastblink); +- if (timeout <= 0) { +- if (-timeout > blinktimeout) /* start visible */ +- win.mode |= MODE_BLINK; +- win.mode ^= MODE_BLINK; +- tsetdirtattr(ATTR_BLINK); +- lastblink = now; +- timeout = blinktimeout; +- } +- } +- +- draw(); +- XFlush(xw.dpy); +- drawing = 0; +- } +-} +- +-void +-usage(void) +-{ +- die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" +- " [-n name] [-o file]\n" +- " [-T title] [-t title] [-w windowid]" +- " [[-e] command [args ...]]\n" +- " %s [-aiv] [-c class] [-f font] [-g geometry]" +- " [-n name] [-o file]\n" +- " [-T title] [-t title] [-w windowid] -l line" +- " [stty_args ...]\n", argv0, argv0); +-} +- +-int +-main(int argc, char *argv[]) +-{ +- xw.l = xw.t = 0; +- xw.isfixed = False; +- xsetcursor(cursorshape); +- +- ARGBEGIN { +- case 'a': +- allowaltscreen = 0; +- break; +- case 'c': +- opt_class = EARGF(usage()); +- break; +- case 'e': +- if (argc > 0) +- --argc, ++argv; +- goto run; +- case 'f': +- opt_font = EARGF(usage()); +- break; +- case 'g': +- xw.gm = XParseGeometry(EARGF(usage()), +- &xw.l, &xw.t, &cols, &rows); +- break; +- case 'i': +- xw.isfixed = 1; +- break; +- case 'o': +- opt_io = EARGF(usage()); +- break; +- case 'l': +- opt_line = EARGF(usage()); +- break; +- case 'n': +- opt_name = EARGF(usage()); +- break; +- case 't': +- case 'T': +- opt_title = EARGF(usage()); +- break; +- case 'w': +- opt_embed = EARGF(usage()); +- break; +- case 'v': +- die("%s " VERSION "\n", argv0); +- break; +- default: +- usage(); +- } ARGEND; +- +-run: +- if (argc > 0) /* eat all remaining arguments */ +- opt_cmd = argv; +- +- if (!opt_title) +- opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; +- +- setlocale(LC_CTYPE, ""); +- XSetLocaleModifiers(""); +- cols = MAX(cols, 1); +- rows = MAX(rows, 1); +- tnew(cols, rows); +- xinit(cols, rows); +- xsetenv(); +- selinit(); +- run(); ++#define IS_SET(flag) ((win.mode & (flag)) != 0) ++#define TRUERED(x) (((x)&0xff0000) >> 8) ++#define TRUEGREEN(x) (((x)&0xff00)) ++#define TRUEBLUE(x) (((x)&0xff) << 8) ++ ++typedef union { ++ struct { ++ unsigned char r, g, b; ++ }; ++ unsigned int val; ++} color_t; ++ ++static inline color_t get_color(int i) { ++ return (color_t){.val = colors[i]}; ++} ++ ++typedef unsigned int fbval_t; ++ ++struct { ++ int fd; ++ struct fb_var_screeninfo info; ++ void *fb; /* mmap()ed FB memory */ ++ int bpp; /* bytes per pixel */ ++ int bpr; /* bytes per row */ ++ size_t len; ++} fb; ++ ++struct { ++ int tw, th; /* tty width and height */ ++ int w, h; /* window width and height */ ++ int ch; /* char height */ ++ int cw; /* char width */ ++ int mode; /* window state/mode flags */ ++ int cursor; /* cursor style */ ++ int cols, rows; ++ font_t *font; ++} win; ++ ++static int fb_init(void) { ++ if ((fb.fd = open(fb_dev, O_RDWR)) < 0) ++ return 0; ++ if (ioctl(fb.fd, FBIOGET_VSCREENINFO, &fb.info) < 0) ++ return 0; ++ ++ fcntl(fb.fd, F_SETFD, fcntl(fb.fd, F_GETFD) | FD_CLOEXEC); ++ ++ fb.bpp = (fb.info.bits_per_pixel + 7) >> 3; ++ fb.bpr = fb.info.xres * fb.bpp; ++ fb.len = fb.bpr * fb.info.yres; ++ fb.fb = mmap(NULL, fb.len, PROT_READ | PROT_WRITE, MAP_SHARED, fb.fd, 0); ++ if (fb.fb == MAP_FAILED) ++ return 0; ++ ++ return 1; ++} ++ ++static inline void *fb_mem(int r) { ++ return fb.fb + r * fb.bpr; ++} ++ ++static void draw_rect(color_t color, int x, int y, int width, int height) { ++ for (int i = 0; i < height; i++) { ++ fbval_t *row = fb_mem(i + y); ++ for (int j = 0; j < width; j++) { ++ row[j + x] = color.val; ++ } ++ } ++} ++ ++static void clear_rect(int x1, int y1, int x2, int y2) { ++ draw_rect(get_color(IS_SET(MODE_REVERSE) ? defaultfg : defaultbg), x1, y1, ++ x2 - x1, y2 - y1); ++} ++ ++static void get_glyph_col(Glyph g, color_t *colfg, color_t *colbg) { ++ color_t temp; ++ ++ if (IS_TRUECOL(g.fg)) { ++ colfg->r = TRUERED(g.fg); ++ colfg->g = TRUEGREEN(g.fg); ++ colfg->b = TRUEBLUE(g.fg); ++ } else ++ *colfg = get_color(g.fg); ++ ++ if (IS_TRUECOL(g.bg)) { ++ colbg->r = TRUERED(g.bg); ++ colbg->g = TRUEGREEN(g.bg); ++ colbg->b = TRUEBLUE(g.bg); ++ } else ++ *colbg = get_color(g.bg); ++ ++ /* Change basic system colors [0-7] to bright system colors [8-15] */ ++ if ((g.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && g.fg < 7) ++ *colfg = get_color(g.fg + 8); ++ ++ if (IS_SET(MODE_REVERSE)) { ++ if (colfg->val == get_color(defaultfg).val) { ++ *colfg = get_color(g.bg); ++ } else { ++ colfg->r = ~colfg->r; ++ colfg->g = ~colfg->g; ++ colfg->b = ~colfg->b; ++ } ++ ++ if (colbg->val == get_color(defaultbg).val) { ++ *colbg = get_color(g.fg); ++ } else { ++ colbg->r = ~colbg->r; ++ colbg->g = ~colbg->g; ++ colbg->b = ~colbg->b; ++ } ++ } ++ ++ if ((g.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { ++ colfg->r /= 2; ++ colfg->g /= 2; ++ colfg->b /= 2; ++ } ++ ++ if (g.mode & ATTR_REVERSE) { ++ temp = *colfg; ++ *colfg = *colbg; ++ *colbg = temp; ++ } ++ ++ if (g.mode & ATTR_BLINK && win.mode & MODE_BLINK) ++ *colfg = *colbg; ++ ++ if (g.mode & ATTR_INVISIBLE) ++ *colfg = *colbg; ++} ++ ++static void draw_glyph(Glyph base, int x, int y) { ++ int charlen = ((base.mode & ATTR_WIDE) ? 2 : 1); ++ int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, ++ width = charlen * win.cw; ++ Rune rune = base.u; ++ color_t colfg, colbg; ++ ++ get_glyph_col(base, &colfg, &colbg); ++ ++ if (rune > 127) ++ rune = '?'; ++ ++ /* Intelligent cleaning up of the borders. */ ++ if (x == 0) { ++ clear_rect( ++ 0, (y == 0) ? 0 : winy, borderpx, ++ ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); ++ } ++ if (winx + width >= borderpx + win.tw) { ++ clear_rect( ++ winx + width, (y == 0) ? 0 : winy, win.w, ++ ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); ++ } ++ if (y == 0) ++ clear_rect(winx, 0, winx + width, borderpx); ++ if (winy + win.ch >= borderpx + win.th) ++ clear_rect(winx, winy + win.ch, winx + width, win.h); ++ ++ char *src = font_glyph(win.font, rune); ++ for (int j = 0; j < win.ch; j++) { ++ fbval_t *row = fb_mem(j + winy); ++ for (int i = 0; i < win.cw; i++) { ++ int b = i % 8; ++ if (b == 0 && i != 0) ++ src++; ++ ++ if ((1 << b) & *src) ++ row[(winx + win.cw - 1 - i)] = colfg.val; ++ else ++ row[(winx + win.cw - 1 - i)] = colbg.val; ++ } ++ src++; ++ } ++} ++ ++static int win_init(void) { ++ int col, row; ++ ++ win.font = font_load(font_file); ++ if (!win.font) ++ return 0; ++ ++ win.ch = win.font->fontheight; ++ win.cw = win.font->fontwidth; ++ win.w = fb.info.xres; ++ win.h = fb.info.yres; ++ ++ col = (win.w - 2 * borderpx) / win.cw; ++ row = (win.h - 2 * borderpx) / win.ch; ++ col = MAX(1, col); ++ row = MAX(1, row); ++ ++ win.cols = col; ++ win.rows = row; ++ win.tw = col * win.cw; ++ win.th = row * win.ch; ++ ++ clear_rect(0, 0, win.w, win.h); ++ ++ ttyresize(win.tw, win.th); ++ ++ win.mode |= MODE_FOCUSED; ++ ++ return 1; ++} ++ ++void xbell(void) { ++} ++ ++void xclipcopy(void) { ++} ++ ++void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) { ++ return; ++ color_t drawcol; ++ ++ /* remove the old cursor */ ++ if (selected(ox, oy)) ++ og.mode ^= ATTR_REVERSE; ++ draw_glyph(og, ox, oy); ++ ++ if (IS_SET(MODE_HIDE)) ++ return; ++ ++ /* ++ * Select the right color for the right mode. ++ */ ++ g.mode &= ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE; ++ ++ if (IS_SET(MODE_REVERSE)) { ++ g.mode |= ATTR_REVERSE; ++ g.bg = defaultfg; ++ if (selected(cx, cy)) { ++ drawcol = get_color(defaultcs); ++ g.fg = defaultrcs; ++ } else { ++ drawcol = get_color(defaultrcs); ++ g.fg = defaultcs; ++ } ++ } else { ++ if (selected(cx, cy)) { ++ g.fg = defaultfg; ++ g.bg = defaultrcs; ++ } else { ++ g.fg = defaultbg; ++ g.bg = defaultcs; ++ } ++ drawcol = get_color(g.bg); ++ } ++ ++ /* draw the new one */ ++ if (IS_SET(MODE_FOCUSED)) { ++ switch (win.cursor) { ++ case 7: /* st extension */ ++ g.u = 0x2603; /* snowman (U+2603) */ ++ /* FALLTHROUGH */ ++ case 0: /* Blinking Block */ ++ case 1: /* Blinking Block (Default) */ ++ case 2: /* Steady Block */ ++ draw_glyph(g, cx, cy); ++ break; ++ case 3: /* Blinking Underline */ ++ case 4: /* Steady Underline */ ++ draw_rect(drawcol, borderpx + cx * win.cw, ++ borderpx + (cy + 1) * win.ch - cursorthickness, win.cw, ++ cursorthickness); ++ break; ++ case 5: /* Blinking bar */ ++ case 6: /* Steady bar */ ++ draw_rect(drawcol, borderpx + cx * win.cw, borderpx + cy * win.ch, ++ cursorthickness, win.ch); ++ break; ++ } ++ } else { ++ draw_rect(drawcol, borderpx + cx * win.cw, borderpx + cy * win.ch, ++ win.cw - 1, 1); ++ draw_rect(drawcol, borderpx + cx * win.cw, borderpx + cy * win.ch, 1, ++ win.ch - 1); ++ draw_rect(drawcol, borderpx + (cx + 1) * win.cw - 1, borderpx + cy * win.ch, ++ 1, win.ch - 1); ++ draw_rect(drawcol, borderpx + cx * win.cw, borderpx + (cy + 1) * win.ch - 1, ++ win.cw, 1); ++ } ++} ++ ++void xdrawline(Line line, int x1, int y1, int x2) { ++ return; ++ for (int x = x1; x < x2; x++) { ++ draw_glyph(line[x], x, y1); ++ } ++} ++ ++void xfinishdraw(void) { ++} ++ ++void xloadcols(void) { ++} ++ ++int xsetcolorname(int x, const char *name) { ++ return 0; ++} ++ ++int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) { ++ ++ return 0; ++} ++ ++void xseticontitle(char *p) { ++} ++ ++void xsettitle(char *p) { ++} ++ ++int xsetcursor(int cursor) { ++ if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ ++ return 1; ++ win.cursor = cursor; ++ return 0; ++} ++ ++void xsetmode(int set, unsigned int flags) { ++ int mode = win.mode; ++ MODBIT(win.mode, set, flags); ++ if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) ++ redraw(); ++} ++ ++void xsetpointermotion(int set) { ++} ++ ++void xsetsel(char *str) { ++} ++ ++int xstartdraw(void) { ++ return 1; ++} ++ ++void xximspot(int x, int y) { ++} ++ ++static void run(void) { ++ fd_set rfd; ++ int ttyfd, drawing, inputfd; ++ struct timespec seltv, *tv, now, lastblink, trigger; ++ double timeout; ++ ++ ttyfd = ttynew(NULL, shell, NULL, NULL); ++ inputfd = input_getfd(); ++ ++ for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { ++ FD_ZERO(&rfd); ++ FD_SET(ttyfd, &rfd); ++ FD_SET(inputfd, &rfd); ++ ++ seltv.tv_sec = timeout / 1E3; ++ seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); ++ tv = timeout >= 0 ? &seltv : NULL; ++ ++ if (pselect(MAX(inputfd, ttyfd) + 1, &rfd, NULL, NULL, tv, NULL) < 0) { ++ if (errno == EINTR) ++ continue; ++ die("select failed: %s\n", strerror(errno)); ++ } ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ ++ if (FD_ISSET(ttyfd, &rfd)) ++ ttyread(); ++ ++ if (FD_ISSET(inputfd, &rfd)) ++ input_read(); ++ ++ /* ++ * To reduce flicker and tearing, when new content or event ++ * triggers drawing, we first wait a bit to ensure we got ++ * everything, and if nothing new arrives - we draw. ++ * We start with trying to wait minlatency ms. If more content ++ * arrives sooner, we retry with shorter and shorter periods, ++ * and eventually draw even without idle after maxlatency ms. ++ * Typically this results in low latency while interacting, ++ * maximum latency intervals during `cat huge.txt`, and perfect ++ * sync with periodic updates from animations/key-repeats/etc. ++ */ ++ if (FD_ISSET(ttyfd, &rfd) || FD_ISSET(inputfd, &rfd)) { ++ if (!drawing) { ++ trigger = now; ++ drawing = 1; ++ } ++ timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * minlatency; ++ if (timeout > 0) ++ continue; /* we have time, try to find idle */ ++ } ++ ++ /* idle detected or maxlatency exhausted -> draw */ ++ ++ timeout = -1; ++ ++ if (blinktimeout && tattrset(ATTR_BLINK)) { ++ timeout = blinktimeout - TIMEDIFF(now, lastblink); ++ if (timeout <= 0) { ++ if (-timeout > blinktimeout) ++ win.mode |= MODE_BLINK; ++ win.mode ^= MODE_BLINK; ++ tsetdirtattr(ATTR_BLINK); ++ lastblink = now; ++ timeout = blinktimeout; ++ } ++ } ++ ++ // draw(); ++ drawing = 0; ++ } ++} ++ ++int main(int argc, char *argv[]) { ++ if (!fb_init()) ++ die("frame buffer init error\n"); ++ ++ if (!input_init(ev_dev)) ++ die("input init error\n"); ++ ++ if (!win_init()) ++ die("window init error\n"); ++ ++ tnew(win.cols, win.rows); ++ selinit(); ++ run(); + +- return 0; ++ return 0; + } From 96e72ca3b48adfb074df5a50cfa120c6d3208f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sat, 19 Aug 2023 00:34:58 +0200 Subject: [PATCH 12/21] fb: add VSCREENINFO ioctls --- include/sys/fb.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/sys/fb.h b/include/sys/fb.h index c001617ea..f4083abd7 100644 --- a/include/sys/fb.h +++ b/include/sys/fb.h @@ -9,6 +9,14 @@ #define FBIOCSET_FBINFO _IOW(FB_IOC_MAGIC, 1, struct fb_info) #define FBIOCSET_PALETTE _IOW(FB_IOC_MAGIC, 2, struct fb_palette) +#define FBIOGET_VSCREENINFO _IOR(FB_IOC_MAGIC, 3, struct fb_var_screeninfo) +#define FBIOPUT_VSCREENINFO _IOW(FB_IOC_MAGIC, 3, struct fb_var_screeninfo) + +struct fb_var_screeninfo { + uint32_t xres, yres; + uint32_t bits_per_pixel; +}; + struct fb_color { uint8_t r, g, b; }; From 52227b890b15b2af6e2bfea887405b5aebfe89d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sat, 19 Aug 2023 00:36:47 +0200 Subject: [PATCH 13/21] [libc] Add pselect stub --- include/sys/select.h | 2 ++ lib/libc/sys/select.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/sys/select.h b/include/sys/select.h index 67c2b05b8..d8eed92a2 100644 --- a/include/sys/select.h +++ b/include/sys/select.h @@ -41,6 +41,8 @@ #include __BEGIN_DECLS +int pselect(int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, + const struct timespec *__restrict, const sigset_t *__restrict); int select(int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, struct timeval *__restrict); __END_DECLS diff --git a/lib/libc/sys/select.c b/lib/libc/sys/select.c index eb8b1b0fc..ff8c14be8 100644 --- a/lib/libc/sys/select.c +++ b/lib/libc/sys/select.c @@ -5,6 +5,12 @@ #include #include +int pselect(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timespec *timeout, + const sigset_t *sigmask) { + return 0; +} + int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout) { int kq; From 7509b5626fe2f9ad44e458ac5a9ab43f3b51e1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sat, 19 Aug 2023 13:24:34 +0200 Subject: [PATCH 14/21] [libc] Add tcsendbreak stub --- include/sys/termios.h | 1 + lib/libc/termios/tcsendbreak.c | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 lib/libc/termios/tcsendbreak.c diff --git a/include/sys/termios.h b/include/sys/termios.h index 2b59245c0..e96135019 100644 --- a/include/sys/termios.h +++ b/include/sys/termios.h @@ -201,6 +201,7 @@ int cfsetispeed(struct termios *, speed_t); int cfsetospeed(struct termios *, speed_t); int tcgetattr(int, struct termios *); int tcsetattr(int, int, const struct termios *); +int tcsendbreak(int, int); void cfmakeraw(struct termios *); __END_DECLS diff --git a/lib/libc/termios/tcsendbreak.c b/lib/libc/termios/tcsendbreak.c new file mode 100644 index 000000000..9be9fd119 --- /dev/null +++ b/lib/libc/termios/tcsendbreak.c @@ -0,0 +1,8 @@ +#include +#include + +int +tcsendbreak(int fd, int len) { + errno = ENOTSUP; + return -1; +} From 4d24c4a59e30d83af3023e067b15860815dd379d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sun, 27 Aug 2023 16:30:17 +0200 Subject: [PATCH 15/21] contrib/st: generate files to build/ directory Creating new files inside st/ submodule causes failures in CI environment --- contrib/st/Makefile | 16 +++++++++++----- contrib/st/patches/font.c.patch | 4 ++-- contrib/st/patches/font.h.patch | 4 ++-- contrib/st/patches/input.c.patch | 4 ++-- contrib/st/patches/input.h.patch | 4 ++-- contrib/st/patches/kbio.patch | 4 ++-- contrib/st/patches/kdbtable.patch | 4 ++-- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/contrib/st/Makefile b/contrib/st/Makefile index 043561bd6..fbec6e42e 100644 --- a/contrib/st/Makefile +++ b/contrib/st/Makefile @@ -8,18 +8,24 @@ PROGRAM = st LDLIBS = -lutil BINDIR = bin BUILDDIR = build/ -SOURCES = $(addprefix st/,$(SRC)) $(addprefix st/,$(NEW_SRC)) -FORMAT-EXCLUDE = $(addprefix st/,$(SRC)) $(addprefix st/,$(NEW_SRC)) $(addprefix st/,$(HDR)) +SOURCES = $(addprefix st/,$(SRC)) $(addprefix $(BUILDDIR)st/,$(NEW_SRC)) +FORMAT-EXCLUDE = $(addprefix st/,$(SRC)) $(addprefix st/,$(HDR)) include $(TOPDIR)/build/build.prog.mk # Rules for newly created source files: -define new_src_func = -$$(addprefix st/,$(1)): build-before +define new_src_build = +$$(addprefix $(BUILDDIR)st/,$(1)): build-before endef -$(foreach new_src,$(NEW_SRC),$(eval $(call new_src_func,$(new_src)))) +$(foreach new_src,$(NEW_SRC),$(eval $(call new_src_build,$(new_src)))) + +define new_src_include = +CFLAGS.$(BUILDDIR)st/$(1) += -Ist/ +endef + +$(foreach new_src,$(NEW_SRC),$(eval $(call new_src_include,$(new_src)))) # Main rules for downloading st and patching: diff --git a/contrib/st/patches/font.c.patch b/contrib/st/patches/font.c.patch index f86be4755..f9ddefb7c 100644 --- a/contrib/st/patches/font.c.patch +++ b/contrib/st/patches/font.c.patch @@ -1,7 +1,7 @@ -Index: st/st/font.c +Index: st/build/st/font.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/font.c 2023-08-14 18:18:48.547323716 +0200 ++++ st/build/st/font.c 2023-08-27 14:44:45.823079037 +0200 @@ -0,0 +1,86 @@ +#include "font.h" + diff --git a/contrib/st/patches/font.h.patch b/contrib/st/patches/font.h.patch index 9537095ed..5adc43ad2 100644 --- a/contrib/st/patches/font.h.patch +++ b/contrib/st/patches/font.h.patch @@ -1,7 +1,7 @@ -Index: st/st/font.h +Index: st/build/st/font.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/font.h 2023-08-14 18:20:47.907326798 +0200 ++++ st/build/st/font.h 2023-08-27 14:44:35.139745990 +0200 @@ -0,0 +1,15 @@ +#ifndef FONT_H +#define FONT_H diff --git a/contrib/st/patches/input.c.patch b/contrib/st/patches/input.c.patch index e2d61b6a6..283da8d2c 100644 --- a/contrib/st/patches/input.c.patch +++ b/contrib/st/patches/input.c.patch @@ -1,7 +1,7 @@ -Index: st/st/input.c +Index: st/build/st/input.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/input.c 2023-08-14 18:24:56.563999968 +0200 ++++ st/build/st/input.c 2023-08-27 14:45:00.029745336 +0200 @@ -0,0 +1,49 @@ +#include "input.h" + diff --git a/contrib/st/patches/input.h.patch b/contrib/st/patches/input.h.patch index a086e4c66..4ac3a5858 100644 --- a/contrib/st/patches/input.h.patch +++ b/contrib/st/patches/input.h.patch @@ -1,7 +1,7 @@ -Index: st/st/input.h +Index: st/build/st/input.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/input.h 2023-08-14 18:29:50.274007627 +0200 ++++ st/build/st/input.h 2023-08-27 14:45:08.869745103 +0200 @@ -0,0 +1,8 @@ +#ifndef INPUT_H +#define INPUT_H diff --git a/contrib/st/patches/kbio.patch b/contrib/st/patches/kbio.patch index a906655e8..e274b7f81 100644 --- a/contrib/st/patches/kbio.patch +++ b/contrib/st/patches/kbio.patch @@ -1,7 +1,7 @@ -Index: st/st/kbio.h +Index: st/build/st/kbio.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/kbio.h 2023-08-14 18:36:18.294017710 +0200 ++++ st/build/st/kbio.h 2023-08-27 14:43:32.076414338 +0200 @@ -0,0 +1,120 @@ +/*- + * $FreeBSD$ diff --git a/contrib/st/patches/kdbtable.patch b/contrib/st/patches/kdbtable.patch index 0ea9df2a7..2c3538e42 100644 --- a/contrib/st/patches/kdbtable.patch +++ b/contrib/st/patches/kdbtable.patch @@ -1,7 +1,7 @@ -Index: st/st/kdbtable.h +Index: st/build/st/kdbtable.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ st/st/kdbtable.h 2023-08-20 18:45:45.443958288 +0200 ++++ st/build/st/kdbtable.h 2023-08-27 14:44:08.709746694 +0200 @@ -0,0 +1,153 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD From 84a561ca9667869af48ab97d63bf6e3b1be39b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 27 Nov 2023 22:24:25 +0100 Subject: [PATCH 16/21] etc: add spleen font --- etc/spleen-8x16.fnt | Bin 0 -> 4096 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 etc/spleen-8x16.fnt diff --git a/etc/spleen-8x16.fnt b/etc/spleen-8x16.fnt new file mode 100644 index 0000000000000000000000000000000000000000..cb0ee9ac8db4899bfbce7f1ef64fe1834b9c49ac GIT binary patch literal 4096 zcmeHKzl+>f5Ej8KF2u2R>oX)T(QXhzL|MXPg~?KxH(qR_h#PAyzl**OOi)LL8%_-!tmWEYTr_N0K52JaJi8LbA-A zuw~=YbOlLMw=uh_a9>>!W#L@AbV5VKG<&?-`O|+{5AiH9yG~S1-*0d4_kG`}rOV&^ zA{3a9rbic-mHni8;sObJ`>q=xQ<|o#pZcylMEZufhnW9K{biY@i}*c%UN7J6>>pkw z^=QO~)qx~eW-eW6d_0l)On|7wNcG4c!^sjKKWYB@1i9@jKgOS!Pp|d|eDT*G6t|s; zg%I75{(&Z@r@i2A?te>r)AKWqhpAQZ{XM?Z{xBaN2KG{H*@SrgmuaNd>-&DcAII(1 zV~$V6#w+6!C+g4iIsXRpyD~n$`uuEJoA<@|&{pT`kU!u!eX;ySSF_iw z$MgsPlPMZJ zF5g{UUA?>1{h6o5MUl*VRcu~VL-oSjygo7tN+US=rpqPF3Wb+x+{-`I9F};&J`YWxB?ZRQ~?M_kY&2p2Y-8rLxm{BXbE) z!-+=@9bz;KoYzbI{9=hQdq?*90^_jU?RFD>yIW0IFAs2oiyl>oliP#^g7A$d8U&2^ z3ygRR%>GQT%tFfKc+#d|JD;TYpv)CHILCI1F@wB5J;i?s^L?jFK;}PT{J36V{1`KSj2SP+ ztY31O;WHTz`^T97IK()?3W)J;vrD;Ref`bx9R%xrEc`@z;U~hvPlSb^2n#F^=qy>Z=3x6++JT)PDm^R7=4C literal 0 HcmV?d00001 From e341afa6c94215b1ecff2d931ddeca358632c385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Tue, 28 Nov 2023 00:11:48 +0100 Subject: [PATCH 17/21] [libc] add pselect --- lib/libc/sys/select.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/libc/sys/select.c b/lib/libc/sys/select.c index 7a798e0a0..38a3b53cb 100644 --- a/lib/libc/sys/select.c +++ b/lib/libc/sys/select.c @@ -5,35 +5,22 @@ #include #include #include +#include int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) { - return 0; -} - -int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, - fd_set *restrict exceptfds, struct timeval *restrict timeout) { int kq; int ret; - struct timespec timeout_ts; struct kevent *events; int nevents = 0; + sigset_t sigs; if (nfds < 0) { errno = EINVAL; return -1; } - if (timeout != NULL) { - if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { - errno = EINVAL; - return -1; - } - - tv2ts(timeout, &timeout_ts); - } - kq = kqueue1(O_CLOEXEC); if (kq < 0) return -1; @@ -56,8 +43,11 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, FD_ZERO(readfds); if (writefds != NULL) FD_ZERO(writefds); - - ret = kevent(kq, events, nevents, events, nevents, timeout == NULL ? NULL : &timeout_ts); + + if (sigmask && sigprocmask(SIG_SETMASK, sigmask, &sigs)) + return -1; + + ret = kevent(kq, events, nevents, events, nevents, timeout); if (ret == -1) goto end; @@ -75,7 +65,26 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, end: free(events); + if (sigmask && sigprocmask(SIG_SETMASK, &sigs, NULL)) + ret = -1; close_kq: close(kq); return ret; } + +int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, + fd_set *restrict exceptfds, struct timeval *restrict timeout) { + struct timespec timeout_ts; + + if (timeout != NULL) { + if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { + errno = EINVAL; + return -1; + } + + tv2ts(timeout, &timeout_ts); + } + + return pselect(nfds, readfds, writefds, exceptfds, + timeout == NULL ? NULL : &timeout_ts , NULL); +} From f9ff401936c021eaaca55580fb15464f6e2a14ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Tue, 28 Nov 2023 15:21:57 +0100 Subject: [PATCH 18/21] etc/Makefile: add font file to FILES --- etc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/Makefile b/etc/Makefile index f5c24a268..343660f29 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -2,7 +2,7 @@ TOPDIR = $(realpath ..) -FILES = group master.passwd rc.init rc.shutdown .kshrc shells +FILES = group master.passwd rc.init rc.shutdown .kshrc shells spleen-8x16.fnt INSTALL-FILES = $(addprefix $(SYSROOT)/etc/, $(FILES)) all: build From 428ff7ae6f240de694bd9ff71bb960e6ed8de557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Sat, 10 Feb 2024 01:45:45 +0100 Subject: [PATCH 19/21] contrib/st: change fb_dev to /dev/vga --- contrib/st/patches/config.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/st/patches/config.patch b/contrib/st/patches/config.patch index 8353734e3..ee753a37b 100644 --- a/contrib/st/patches/config.patch +++ b/contrib/st/patches/config.patch @@ -1,11 +1,11 @@ Index: st/st/config.def.h =================================================================== ---- st.orig/st/config.def.h 2023-08-20 18:04:54.860564071 +0200 -+++ st/st/config.def.h 2023-08-20 18:43:46.493955311 +0200 +--- st.orig/st/config.def.h 2023-08-27 13:22:24.706534543 +0200 ++++ st/st/config.def.h 2024-02-10 01:44:45.170422254 +0100 @@ -1,11 +1,14 @@ /* See LICENSE file for copyright and license details. */ -+static const char *fb_dev = "/dev/fb0"; ++static const char *fb_dev = "/dev/vga"; +static const char *ev_dev = "/dev/input/event0"; +static const char *font_file = "/etc/spleen-8x16.fnt"; + From 658f3a491488755ac35aa3532c686be4b1d74131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 12 Feb 2024 02:59:44 +0100 Subject: [PATCH 20/21] Get rid of fb_var_screeninfo * remove struct fb_var_screeninfo * remove FBIO SCREENINFO ioctls definitions * use struct fb_info instead of struct fb_var_screeninfo --- contrib/st/patches/x.c.patch | 18 +++++++++--------- include/sys/fb.h | 8 -------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/contrib/st/patches/x.c.patch b/contrib/st/patches/x.c.patch index cf50b5d45..2ed096ecc 100644 --- a/contrib/st/patches/x.c.patch +++ b/contrib/st/patches/x.c.patch @@ -1,7 +1,7 @@ Index: st/st/x.c =================================================================== ---- st.orig/st/x.c 2023-08-20 18:30:36.680602366 +0200 -+++ st/st/x.c 2023-08-20 18:40:47.457284177 +0200 +--- st.orig/st/x.c 2024-02-11 17:36:04.926289838 +0100 ++++ st/st/x.c 2024-02-11 17:39:32.782949575 +0100 @@ -1,2099 +1,457 @@ -/* See LICENSE for license details. */ +#include @@ -2130,7 +2130,7 @@ Index: st/st/x.c + +struct { + int fd; -+ struct fb_var_screeninfo info; ++ struct fb_info info; + void *fb; /* mmap()ed FB memory */ + int bpp; /* bytes per pixel */ + int bpr; /* bytes per row */ @@ -2151,14 +2151,14 @@ Index: st/st/x.c +static int fb_init(void) { + if ((fb.fd = open(fb_dev, O_RDWR)) < 0) + return 0; -+ if (ioctl(fb.fd, FBIOGET_VSCREENINFO, &fb.info) < 0) ++ if (ioctl(fb.fd, FBIOCGET_FBINFO, &fb.info) < 0) + return 0; + + fcntl(fb.fd, F_SETFD, fcntl(fb.fd, F_GETFD) | FD_CLOEXEC); + -+ fb.bpp = (fb.info.bits_per_pixel + 7) >> 3; -+ fb.bpr = fb.info.xres * fb.bpp; -+ fb.len = fb.bpr * fb.info.yres; ++ fb.bpp = (fb.info.bpp + 7) >> 3; ++ fb.bpr = fb.info.width * fb.bpp; ++ fb.len = fb.bpr * fb.info.height; + fb.fb = mmap(NULL, fb.len, PROT_READ | PROT_WRITE, MAP_SHARED, fb.fd, 0); + if (fb.fb == MAP_FAILED) + return 0; @@ -2296,8 +2296,8 @@ Index: st/st/x.c + + win.ch = win.font->fontheight; + win.cw = win.font->fontwidth; -+ win.w = fb.info.xres; -+ win.h = fb.info.yres; ++ win.w = fb.info.width; ++ win.h = fb.info.height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; diff --git a/include/sys/fb.h b/include/sys/fb.h index f4083abd7..c001617ea 100644 --- a/include/sys/fb.h +++ b/include/sys/fb.h @@ -9,14 +9,6 @@ #define FBIOCSET_FBINFO _IOW(FB_IOC_MAGIC, 1, struct fb_info) #define FBIOCSET_PALETTE _IOW(FB_IOC_MAGIC, 2, struct fb_palette) -#define FBIOGET_VSCREENINFO _IOR(FB_IOC_MAGIC, 3, struct fb_var_screeninfo) -#define FBIOPUT_VSCREENINFO _IOW(FB_IOC_MAGIC, 3, struct fb_var_screeninfo) - -struct fb_var_screeninfo { - uint32_t xres, yres; - uint32_t bits_per_pixel; -}; - struct fb_color { uint8_t r, g, b; }; From 4ad3959bef7c9c5870ab96b93b6dff6ecb9c7c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Pokusi=C5=84ski?= Date: Mon, 12 Feb 2024 16:42:55 +0100 Subject: [PATCH 21/21] contrib/st: open fb_dev in O_WRONLY mode --- contrib/st/patches/x.c.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/st/patches/x.c.patch b/contrib/st/patches/x.c.patch index 2ed096ecc..47fbded4b 100644 --- a/contrib/st/patches/x.c.patch +++ b/contrib/st/patches/x.c.patch @@ -1,7 +1,7 @@ Index: st/st/x.c =================================================================== ---- st.orig/st/x.c 2024-02-11 17:36:04.926289838 +0100 -+++ st/st/x.c 2024-02-11 17:39:32.782949575 +0100 +--- st.orig/st/x.c 2024-02-12 02:59:32.226013150 +0100 ++++ st/st/x.c 2024-02-12 13:49:47.993311399 +0100 @@ -1,2099 +1,457 @@ -/* See LICENSE for license details. */ +#include @@ -2149,7 +2149,7 @@ Index: st/st/x.c +} win; + +static int fb_init(void) { -+ if ((fb.fd = open(fb_dev, O_RDWR)) < 0) ++ if ((fb.fd = open(fb_dev, O_WRONLY)) < 0) + return 0; + if (ioctl(fb.fd, FBIOCGET_FBINFO, &fb.info) < 0) + return 0;