From bfe1ec8013672b88e06d2602187437ebf0268873 Mon Sep 17 00:00:00 2001 From: Jonathan Hodgson Date: Sun, 8 Dec 2019 18:31:19 +0000 Subject: [PATCH] Adds alpha patch --- config.def.h | 6 +- config.h | 463 ++++++++++ config.mk | 2 +- st | Bin 0 -> 102272 bytes st-alpha-0.8.2.diff | 163 ++++ st.h | 1 + st.h.orig | 123 +++ st.o | Bin 0 -> 73168 bytes x.c | 40 +- x.c.orig | 2008 +++++++++++++++++++++++++++++++++++++++++++ x.o | Bin 0 -> 74536 bytes 11 files changed, 2794 insertions(+), 12 deletions(-) create mode 100644 config.h create mode 100755 st create mode 100644 st-alpha-0.8.2.diff create mode 100644 st.h.orig create mode 100644 st.o create mode 100644 x.c.orig create mode 100644 x.o diff --git a/config.def.h b/config.def.h index 546edda..4f3e806 100644 --- a/config.def.h +++ b/config.def.h @@ -82,6 +82,9 @@ char *termname = "st-256color"; */ unsigned int tabspaces = 8; +/* bg opacity */ +float alpha = 0.8; + /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ @@ -109,6 +112,7 @@ static const char *colorname[] = { /* more colors can be added after 255 to use with DefaultXX */ "#cccccc", "#555555", + "black", }; @@ -117,7 +121,7 @@ static const char *colorname[] = { * foreground, background, cursor, reverse cursor */ unsigned int defaultfg = 7; -unsigned int defaultbg = 0; +unsigned int defaultbg = 258; static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; diff --git a/config.h b/config.h new file mode 100644 index 0000000..4f3e806 --- /dev/null +++ b/config.h @@ -0,0 +1,463 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * 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; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: utmp option + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* frames per second st should at maximum draw to the screen */ +static unsigned int xfps = 120; +static unsigned int actionfps = 30; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +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"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* bg opacity */ +float alpha = 0.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", + "black", +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 7; +unsigned int defaultbg = 258; +static 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 }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { 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/config.mk b/config.mk index 0cbb002..1d2f0e2 100644 --- a/config.mk +++ b/config.mk @@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` diff --git a/st b/st new file mode 100755 index 0000000000000000000000000000000000000000..90b63777408efddc6c2a4b120322c25fcfdbdbdb GIT binary patch literal 102272 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 Ypwd^oL{@oMID)%)pL((`g6>xPKUZr~i~s-t literal 0 HcmV?d00001 diff --git a/st-alpha-0.8.2.diff b/st-alpha-0.8.2.diff new file mode 100644 index 0000000..dad6615 --- /dev/null +++ b/st-alpha-0.8.2.diff @@ -0,0 +1,163 @@ +diff --git a/config.def.h b/config.def.h +index 0e01717..e116631 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -82,6 +82,9 @@ char *termname = "st-256color"; + */ + unsigned int tabspaces = 8; + ++/* bg opacity */ ++float alpha = 0.8; ++ + /* Terminal colors (16 first used in escape sequence) */ + static const char *colorname[] = { + /* 8 normal colors */ +@@ -109,6 +112,7 @@ static const char *colorname[] = { + /* more colors can be added after 255 to use with DefaultXX */ + "#cccccc", + "#555555", ++ "black", + }; + + +@@ -117,7 +121,7 @@ static const char *colorname[] = { + * foreground, background, cursor, reverse cursor + */ + unsigned int defaultfg = 7; +-unsigned int defaultbg = 0; ++unsigned int defaultbg = 258; + static unsigned int defaultcs = 256; + static unsigned int defaultrcs = 257; + +diff --git a/config.mk b/config.mk +index 0cbb002..1d2f0e2 100644 +--- a/config.mk ++++ b/config.mk +@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config + INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +-LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ ++LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +diff --git a/st.h b/st.h +index 38c61c4..b7634ab 100644 +--- a/st.h ++++ b/st.h +@@ -120,3 +120,4 @@ extern char *termname; + extern unsigned int tabspaces; + extern unsigned int defaultfg; + extern unsigned int defaultbg; ++extern float alpha; +diff --git a/x.c b/x.c +index 0422421..588dec3 100644 +--- a/x.c ++++ b/x.c +@@ -98,6 +98,7 @@ typedef struct { + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ ++ int depth; /* bit depth */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ + } XWindow; +@@ -229,6 +230,7 @@ static char *usedfont = NULL; + static double usedfontsize = 0; + static double defaultfontsize = 0; + ++static char *opt_alpha = NULL; + static char *opt_class = NULL; + static char **opt_cmd = NULL; + static char *opt_embed = NULL; +@@ -688,7 +690,7 @@ xresize(int col, int row) + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); ++ xw.depth); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + +@@ -748,6 +750,13 @@ xloadcols(void) + else + die("could not allocate color %d\n", i); + } ++ ++ /* set alpha value of bg color */ ++ if (opt_alpha) ++ alpha = strtof(opt_alpha, NULL); ++ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); ++ dc.col[defaultbg].pixel &= 0x00FFFFFF; ++ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + loaded = 1; + } + +@@ -1004,11 +1013,23 @@ xinit(int cols, int rows) + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; ++ XWindowAttributes attr; ++ XVisualInfo vis; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); +- xw.vis = XDefaultVisual(xw.dpy, xw.scr); ++ ++ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { ++ parent = XRootWindow(xw.dpy, xw.scr); ++ xw.depth = 32; ++ } else { ++ XGetWindowAttributes(xw.dpy, parent, &attr); ++ xw.depth = attr.depth; ++ } ++ ++ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); ++ xw.vis = vis.visual; + + /* font */ + if (!FcInit()) +@@ -1018,7 +1039,7 @@ xinit(int cols, int rows) + xloadfonts(usedfont, 0); + + /* colors */ +- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); ++ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xloadcols(); + + /* adjust fixed window geometry */ +@@ -1038,19 +1059,15 @@ xinit(int cols, int rows) + | 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, ++ win.w, win.h, 0, xw.depth, 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)); ++ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); ++ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + +@@ -1894,6 +1911,9 @@ main(int argc, char *argv[]) + case 'a': + allowaltscreen = 0; + break; ++ case 'A': ++ opt_alpha = EARGF(usage()); ++ break; + case 'c': + opt_class = EARGF(usage()); + break; diff --git a/st.h b/st.h index a1928ca..64e6ea3 100644 --- a/st.h +++ b/st.h @@ -121,3 +121,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern float alpha; diff --git a/st.h.orig b/st.h.orig new file mode 100644 index 0000000..a1928ca --- /dev/null +++ b/st.h.orig @@ -0,0 +1,123 @@ +/* See LICENSE for license details. */ + +#include +#include + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ + (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +#define Glyph Glyph_ +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef union { + int i; + uint ui; + float f; + const void *v; + const char *s; +} Arg; + +void die(const char *, ...); +void redraw(void); +void draw(void); + +void printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + +int tattrset(int); +void tnew(int, int); +void tresize(int, int); +void tsetdirtattr(int); +void ttyhangup(void); +int ttynew(char *, char *, char *, char **); +size_t ttyread(void); +void ttyresize(int, int); +void ttywrite(const char *, size_t, int); + +void resettitle(void); + +void selclear(void); +void selinit(void); +void selstart(int, int, int); +void selextend(int, int, int, int); +int selected(int, int); +char *getsel(void); + +size_t utf8encode(Rune, char *); + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(char *); + +/* config.h globals */ +extern char *utmp; +extern char *stty_args; +extern char *vtiden; +extern wchar_t *worddelimiters; +extern int allowaltscreen; +extern char *termname; +extern unsigned int tabspaces; +extern unsigned int defaultfg; +extern unsigned int defaultbg; diff --git a/st.o b/st.o new file mode 100644 index 0000000000000000000000000000000000000000..ddfeb655b29144638985f943520a46790cf3eea7 GIT binary patch literal 73168 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *argv0; +#include "arg.h" +#include "st.h" +#include "win.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) + +/* 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, netwmpid; + XIM xim; + XIC xic; + 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 void ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, 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(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 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 int oldbutton = 3; /* button event on startup: 3 = release */ + +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, x = evcol(e), y = evrow(e), + button = e->xbutton.button, state = e->xbutton.state; + char buf[40]; + static int ox, oy; + + /* from urxvt */ + if (e->xbutton.type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MOUSE_MOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + return; + + button = oldbutton + 32; + ox = x; + oy = y; + } else { + if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { + button = 3; + } else { + button -= Button1; + if (button >= 3) + button += 64 - 3; + } + if (e->xbutton.type == ButtonPress) { + oldbutton = button; + ox = x; + oy = y; + } else if (e->xbutton.type == ButtonRelease) { + oldbutton = 3; + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + if (button == 64 || button == 65) + return; + } + } + + if (!IS_SET(MODE_MOUSEX10)) { + button += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + button, x+1, y+1, + e->xbutton.type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+button, 32+x+1, 32+y+1); + } else { + return; + } + + ttywrite(buf, len, 0); +} + +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (match(ms->mod, e->xbutton.state) || /* exact or forced */ + match(ms->mod, e->xbutton.state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + +void +bpress(XEvent *e) +{ + struct timespec now; + int snap; + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 0)) + return; + + if (e->xbutton.button == 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) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 1)) + return; + if (e->xbutton.button == 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 +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(char *fontstr, double fontsize) +{ + FcPattern *pattern; + double fontval; + + if (fontstr[0] == '-') + pattern = XftXlfdParse(fontstr, False, False); + else + pattern = FcNameParse((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); +} + +void +ximopen(Display *dpy) +{ + XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; + + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im=local"); + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im="); + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed. Could not open input device.\n"); + } + } + if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL) + die("XSetIMValues failed. Could not set input method value.\n"); + xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); + if (xw.xic == NULL) + die("XCreateIC failed. Could not obtain input method.\n"); +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + ximopen(dpy); + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +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 */ + ximopen(xw.dpy); + + /* 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); + 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 + 1, + width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 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: snowman (U+2603) */ + g.u = 0x2603; + 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 +xsettitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop); + 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) +{ + XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch }; + XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + + XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL); + XFree(attr); +} + +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) +{ + DEFAULT(cursor, 1); + if (!BETWEEN(cursor, 0, 6)) + 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) { + XSetICFocus(xw.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + XUnsetICFocus(xw.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; + char buf[32], *customkey; + int len; + Rune c; + Status status; + Shortcut *bp; + + if (IS_SET(MODE_KBDLOCK)) + return; + + len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); + /* 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), xev, blinkset = 0, dodraw = 0; + int ttyfd; + struct timespec drawtimeout, *tv = NULL, now, last, lastblink; + long deltatime; + + /* 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); + + clock_gettime(CLOCK_MONOTONIC, &last); + lastblink = last; + + for (xev = actionfps;;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(ttyfd, &rfd)) { + ttyread(); + if (blinktimeout) { + blinkset = tattrset(ATTR_BLINK); + if (!blinkset) + MODBIT(win.mode, 0, MODE_BLINK); + } + } + + if (FD_ISSET(xfd, &rfd)) + xev = actionfps; + + clock_gettime(CLOCK_MONOTONIC, &now); + drawtimeout.tv_sec = 0; + drawtimeout.tv_nsec = (1000 * 1E6)/ xfps; + tv = &drawtimeout; + + dodraw = 0; + if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { + tsetdirtattr(ATTR_BLINK); + win.mode ^= MODE_BLINK; + lastblink = now; + dodraw = 1; + } + deltatime = TIMEDIFF(now, last); + if (deltatime > 1000 / (xev ? xfps : actionfps)) { + dodraw = 1; + last = now; + } + + if (dodraw) { + while (XPending(xw.dpy)) { + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + draw(); + XFlush(xw.dpy); + + if (xev && !FD_ISSET(xfd, &rfd)) + xev--; + if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) { + if (blinkset) { + if (TIMEDIFF(now, lastblink) \ + > blinktimeout) { + drawtimeout.tv_nsec = 1000; + } else { + drawtimeout.tv_nsec = (1E6 * \ + (blinktimeout - \ + TIMEDIFF(now, + lastblink))); + } + drawtimeout.tv_sec = \ + drawtimeout.tv_nsec / 1E9; + drawtimeout.tv_nsec %= (long)1E9; + } else { + tv = NULL; + } + } + } + } +} + +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; + win.cursor = 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(); + + return 0; +} diff --git a/x.o b/x.o new file mode 100644 index 0000000000000000000000000000000000000000..733390004062f4bb7c2833b4a21eda78d794e86c GIT binary patch literal 74536 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