From 7b1796958dfd0e93ea429759e2cc96c6fb89e025 Mon Sep 17 00:00:00 2001 From: TiynGER Date: Sun, 29 Mar 2020 15:21:23 +0200 Subject: [PATCH] anysize patch --- config.h | 466 ++++++++++ st | Bin 0 -> 102528 bytes st-anysize-0.8.1.diff | 152 +++ st.o | Bin 0 -> 76232 bytes x.c | 56 +- x.c.orig | 2040 +++++++++++++++++++++++++++++++++++++++++ x.o | Bin 0 -> 77200 bytes 7 files changed, 2688 insertions(+), 26 deletions(-) create mode 100644 config.h create mode 100755 st create mode 100644 st-anysize-0.8.1.diff create mode 100644 st.o create mode 100644 x.c.orig create mode 100644 x.o diff --git a/config.h b/config.h new file mode 100644 index 0000000..4793c44 --- /dev/null +++ b/config.h @@ -0,0 +1,466 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "mono:pixelsize=16:antialias=true:autohint=true"; +static char *font2[] = { "IBM Plex Mono:pixelsize=16: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 = "xterm-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.92; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "#1f1f1f", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#f81118", + "#2dc55e", + "#ecba0f", + "#2a84d2", + "#4e5ab7", + "#1081d6", + "#d6dbe5", + "#d6dbe5", + "#de352e", + "#1dd361", + "#f3bd09", + "#1081d6", + "#5350b9", + "#0f7ddb", + "#ffffff", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#282828", /* 256 -> bg */ + "#ebdbb2", /* 257 -> fg */ + "#add8e6", /* 258 -> cursor */ + + /* 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 = 257; +unsigned int defaultbg = 256; +static unsigned int defaultcs = 258; +static unsigned int defaultrcs = 0; + +/* + * 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 */ + { Button4, XK_NO_MOD, "\031" }, + { Button5, XK_NO_MOD, "\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} }, + { ShiftMask, XK_Insert, clippaste, {.i = 0} }, + { MODKEY, XK_c, clipcopy, {.i = 0} }, + { MODKEY, XK_v, clippaste, {.i = 0} }, + { MODKEY, XK_p, selpaste, {.i = 0} }, + { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, + { MODKEY, XK_k, kscrollup, {.i = 1} }, + { MODKEY, XK_j, kscrolldown, {.i = 1} }, + { TERMMOD, XK_U, zoom, {.f = +1} }, + { TERMMOD, XK_U, zoom, {.f = +1} }, + { TERMMOD, XK_I, zoom, {.f = -1} }, +}; + +/* + * 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/st b/st new file mode 100755 index 0000000000000000000000000000000000000000..0977b5e26add9d2e0b63c90dcd5b7453f955588c GIT binary patch literal 102528 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 literal 0 HcmV?d00001 diff --git a/st-anysize-0.8.1.diff b/st-anysize-0.8.1.diff new file mode 100644 index 0000000..1eaf2ba --- /dev/null +++ b/st-anysize-0.8.1.diff @@ -0,0 +1,152 @@ +diff --git a/x.c b/x.c +index 00cb6b1..8f87c0f 100644 +--- a/x.c ++++ b/x.c +@@ -78,6 +78,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; + typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ ++ int hborderpx, vborderpx; + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ +@@ -311,7 +312,7 @@ zoomreset(const Arg *arg) + int + evcol(XEvent *e) + { +- int x = e->xbutton.x - borderpx; ++ int x = e->xbutton.x - win.hborderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; + } +@@ -319,7 +320,7 @@ evcol(XEvent *e) + int + evrow(XEvent *e) + { +- int y = e->xbutton.y - borderpx; ++ int y = e->xbutton.y - win.vborderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; + } +@@ -675,6 +676,9 @@ cresize(int width, int height) + col = MAX(1, col); + row = MAX(1, row); + ++ win.hborderpx = (win.w - col * win.cw) / 2; ++ win.vborderpx = (win.h - row * win.ch) / 2; ++ + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +@@ -793,8 +797,8 @@ xhints(void) + 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->height_inc = 1; ++ sizeh->width_inc = 1; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; +@@ -1022,8 +1026,8 @@ xinit(int cols, int rows) + xloadcols(); + + /* adjust fixed window geometry */ +- win.w = 2 * borderpx + cols * win.cw; +- win.h = 2 * borderpx + rows * win.ch; ++ win.w = 2 * win.hborderpx + cols * win.cw; ++ win.h = 2 * win.vborderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) +@@ -1123,7 +1127,7 @@ xinit(int cols, int rows) + 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; ++ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; +@@ -1259,7 +1263,7 @@ 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, ++ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; +@@ -1349,17 +1353,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i + + /* Intelligent cleaning up of the borders. */ + if (x == 0) { +- xclear(0, (y == 0)? 0 : winy, borderpx, ++ xclear(0, (y == 0)? 0 : winy, win.vborderpx, + winy + win.ch + +- ((winy + win.ch >= borderpx + win.th)? win.h : 0)); ++ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + } +- if (winx + width >= borderpx + win.tw) { ++ if (winx + width >= win.hborderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, +- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); ++ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) +- xclear(winx, 0, winx + width, borderpx); +- if (winy + win.ch >= borderpx + win.th) ++ xclear(winx, 0, winx + width, win.hborderpx); ++ if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ +@@ -1452,35 +1456,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - \ ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (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, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + (cx + 1) * win.cw - 1, +- borderpx + cy * win.ch, ++ win.hborderpx + (cx + 1) * win.cw - 1, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - 1, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } + } diff --git a/st.o b/st.o new file mode 100644 index 0000000000000000000000000000000000000000..4e846b3568c515e01167561e7300dc112a4059c9 GIT binary patch literal 76232 zcmeFa3v?7!w)kD0G!QV-QE`llL#siFAcmI`K}|!W6%B}jidT?FCqRZkBIy8*Jc6Ad zWoSTU6cyh(qT~1;1Vl&(FA)_G6%`c`rJMGFs1SLW|K8{9og6kP=idAO*80}BzNtlb zSN+beefHVsed<)0(J$}HB#+19!(&};HC{2bEW3Rp%~3eVI@vnOs%l|JPsQtO@2iu~ zpz~gE-a0zp>QG-l^H6;Y%bI-V`W8p)Eo&)$T~-fYz6Yv(ORDWib#iT_ZpP&1OHqC8 zWlH#qrAc^Ebt3AmYKGt0b<;!1m*H9F`kCvufJ!^G-Y%^Ep#P{eyQc1Z=TOa|cA1+C zt2aYX=6X9+Z%5UQc2%%0-Hs02XNPL+nw?(Tv-v`bz& zlqc4ElQ1!n^&Uu`H~Zl9J+&**^29d%yGmWW13LC;tqNqXo4QnoJWp|z)T`^*wEFt` zTAPhhQP>Xss5C};phj!+gktc%UW__gkuSW;xCr?S4R zm%Y%Awpok!+nK9vXEPNMJL<2%VB*V)d%G;OsrFugWX?+JTqQGqH64SJl9 z?96p`wEHWdptbKL9auFz&DQCtnw0J+lWZ;M?5_&H(xz(aJ!!Eof3L4k{1aS|M?P-M z&vp&@Iqgh+yVh2#6a9_O!mpft&hO6p#OI1?wxuyAv)4`A>>Sj1xsIZ;e)?dY1=$-) zdqgMK+f~ZjiPY?xN$n#)cp|^ohtG;sdm#8v&T2^H1CdLuvRy#z$ZBu)hKc+14bhwG zvse4BTJu=rfsmR+N@5z znptCq-fpNI-VJfg80X#iM*N8#Bko-tKLIMHT?Hw2+6A1>c}`JAI_gy>Rb>ULT01`n zJzq~r$vz9?p792G-rMfMgZ0h_LFXIKyS~{mC`8#8qJVGi4mj^ux!X73UEhHH+JV^{ zd~-)bO-NSdGP7o8jdoCt*<5Wjn=6%shURKRx*a-T*L>?e5X@@k@m1UoQ8+)wemDfN zZuiao3tUnr?Dfq(9U^jK|EsJBu1?PjC30)N@#cEg_N$s^EyX1DtE>;F2c6%W%!9yz ze$BkT%H`+)aGS64^P~0kkUYo@;Gtjl~)J1RQoPgoG`&=#|dzE|^myUhJmMz>%o;zF9YF&(2z z%yU-%_ssa{2%BN1C%OtS+cW(&XLYhNKXc>E)w)D%v{lv-`D4uQt5q6b(o?JRvwiqzfuJl+$6j}J_Ih3=?ojXgfJqIuEOO64-| zUC^wBvm$lPd=+m3=~Fe>cZ8Fo4OCS?wL42y;?bsH^g3@Kd+RhC<-L8X@_Z>*Rt0^j zLFZ2}xB)#mz6aLN{Eg1m<)j=eyF4(n4zDNosM(cP^HoaAjlq_yoz0j5p2YLc#y^ZS z;rwB6d<<9?4J1Jme6iEK4_M;84CC_68UO*<o0lRXg93jyV>h zT&Hb@mMYt|6xAlu@QyS)+84sS5SENK*6Ofd8k0iJ$#O5;vr?DiMyqUHh%H~mClIWo zcGl)a+ryQW=X~AY`6h8L^|d+_OtGEqd6_$Nvnws=D}A#b15w|SUUukXyQ-gcAUF_A z-V~{C6+SOge_}W%Qh#Q6m~+T2hZ6t%Ljx0Y|1daS1YZ1OiK~@_Djus^H6*ezOLLu{ z);Gryx?Q=o%nM_++QzX$(6{8YptCu$v$}VAIM}aZtIv4^R4BBwH*^6H^VPoIJAD-o z@>QL3^fIXT^>3ozd++mAVsTBhT2_q=PQhhwAKcQ@ARq(3;gH`|j$BeRbrp z$2ZHX&JMxZA&^!I-@^L>Z=#C83e3vDTR3M3tW3u5RTxuZ=(2K*0YejumhHrIlu68A zwhzxyGEvdrITTom)+L(fI(z#$+rf_Nz`@P%9Xz|bWleu@#r1Y%oyX4p6mr{!0hpb= zZ_@2GUp4nF@m>;essrGYKzUtxcvVI9?L9Qu37|UMO<(MTi=E-_`l1dl_JtkW*=G!^ z`a8PK^az*4j|UJ76Ro&ABOXl=XzzI2(*{&`Xh8es;UmQd^RocCj8`yun4 zFA~oxnZ)BXyi0-69c1LM&IbW!lO0mEjk>w=6-hfT2N#rebm}6pK&0-n$!9y&4Sitm z)i#U-e0DUP;Z+qT_678=xuH!BW34tD>`*NZ;(Tv}lf0u3uCtQDqo7XoIt#Q~)6Q5Q zOiJ^^S>teR`Ra%-;y>-2e+Ox7=h|RTeb1bK1G>RtGbKC&*bd1e3&w}?|?~yL1jvp zYSj*CpI5cr9P0$}bB{c&zz)T1C#D9$(Xsn%&*ye_B0O~Rxp~q23~!$EZB;L7gVyCa zdtyZ}`h&JF&CdS3beAp%)S_OGAvmPYx4Y@s%gzGp(o_>@hxXbqz_TOYrzI9edil$q zNUT2pUq`kBst=4lT>VYz#X4PWmIY*tJVFIK)qwm6k*?6YM z7dq;i8#vR~Mkri&G6=Bg@PHWdhV*{v9T|Hg-%~t8q^*w^98lf z%9>{vWu%7t2lad===|X8uY4cO)_R>iz5&Ylv4cOrc>Xir0`$G7T6+P?S-R1TDgPz* zQkf{*l2}|znc=H=6;rS3LU!HM6g>u^<}&eH(5sT!P-8p!@|daIxl3qYnp9ze^L z2DvudX-GOQA8qhmy9IB8&^DECPnoK%GD6z)tNh+K8)vEwLBZ@;&^KT&#!XMwlW^>fNUFVURSx}&8NC=A)%M-5!K-7+SGrYlGVE2r{4V_79#(FO%!m26)*MPy z(KRab)9j7Y-ah!5^95wm^)QW8t&v(6N^y>APwD<3+z$Lz`Mt8r7gR}gzKGoe24Nk# zWmv767OH-U+SW?QiNw3C>yO+&;#l|3N8kLaH59D0Y)`Cy=gdRfuyj?P3>*eN z9vGw7t4bUXDgw2vfpkUUhr~4yKM-64f?1TRW|0j^dfix!p|qEd#9=^s5cIIj&ZCJ> z@ut*>@~tQSDFjB^qt||qzX#_KnB!ZpKF7DDeq}jOZO`ivqBWxA%Jk}EF0CBHEawkJ zQ{eW76x{lUqS*K~h;{=}zBn%W^2V@uD-c|1`3+JBdRF4BkMECvs|YlT4P+Y--8aFk zay?uaZisD*HH;8^70*MUE|HO)-W=cG)`6!Ez#ufWtbMT8RQL(Z>~%V*_EnY(HBnHL zm_Vi3Zfrt~?CSX&h%AjQ--AD{lg|sPPKg|9;WbsK%siy*n}bgv>bgFYh-ikcW z&ib8LSX%1Bl9YH^mz1N4X91THPD?zf@sEl5hIC5ePK^)7Cqc9CmYVp@7`q-IaJ}NQBK3MqkiCFE{*DY^l+y19P*m8&aS#Ab~$v9-dCaESbBLjJK&xC zjf@SuaTS#g2!OOcONOISSWR4wEIsYpdU`k%g|k1*{Ywwl*T+_V19_0}l&!d>)}Hy@ zc8JA>(glnEgEO*h7|Qg_gMmU$9-P?~)!|EgnZb;KzRbLg5x&g98702VMH%IAk1zA- zjQQ&Kg^b75@9P;atKStF)$n`F{3pFj^?Gjx)=U^tc(dTwj#gys#9xRj#f}Cu{CEaW zZFbqmt~akjr>Q0aM}hhT#t+S~uhHYRs-BvHr}Z>QO(_&RwoPpqe?9|MRd-DtRaXH| z=d{~kh0ym>UCo{(cxFgS!8{&Ns}?tq{k?DAm7pNkS(B&Zi=PiR1|l=O@SLOzvkHRGk0{^#b@~W%smtCCZs~88GU=@w*R0BS55NxR!er$}x{x4!ITAdzBQy+*G(Vvf8n;=(C}2d=4*Jq zTN|jlstpt@Z~PO82~>)QK#6U~v-m6!Wfk$+Xdx?E(1emstK;hd!=oq|W5++hQ*g`4 z@!fc)X6XsvT_3~6fxgYWW#2c>=5sx35?|nuHU&KZOCMMhj%}uFs4gi`{;kAUgLHX> zqTkVWYVGwk(5Tg`l5RU+?tjrf2&-kc!LrYnvHmcw!C$-&s`&q+*5EAouyd4#8mebA z+c_A;EW>e;iX9dtezyO?&!DN5g6dIz_|b6R$>)|Io*(X5e)y54!{7#AFqSi0)gs;8 zd({}T{P1H-hwIS9&Y5b^P!5-G4TP`6`)}QfKO6oR$$(qZk7|rTCU?JFup{?9#~28PG2D_RQ$pI6hJLH8eb{^|<`F<_8`* z%NFT)fZ5)-T!Zaex^CARp3KhtE-ejP%A-bVDl$@lL4qi1T^?-bAQgq1>+P9`>wPfK zD9v?t+s>!Ba0JP=a-(h923A;bb8hC2-1Td*7}=HIhYRhhGFa<95FSC<8rRC44fa78 z0Su|ng+>~R_V$UL^P&?y>yn_s2BimC>7VU`ALM#=*pamIE;Q^sW`Hxr%q1o@+A<{$^hIAmDJF$dVbLEOokj$X>2H8 zHQ;L3(T#naIP9$W;W)2j$xp=v(3F6RbQ#*OwsNSrpblK7PIM|Gb@k!?(AE^fGul*b z%usk(dludVmOKH&xK$^?xeAJ>9B0DuU9nc;-c{375hGBd%D)Y<>)9mRqH?DpOeJDv z>%mZ`L7>s2m{T`{uNws6L=PZT1h%slhv5{Rvz}lrJg@Rq1mHfi)Pb<#{{!~XBYuV!!s;R80R1XRp@XV& zzTo%qzd@DC)6X0GSAL%d2)AgYVV9T=W?8s4o)(`9QaXYrT6;ZM8tr&9_$-)_G#Vd+ zjD`_!a~N!{Y=gx{wF!-8KwUUhtfF^rY?d1m?D}+-mesM#(&bj^CoA#6wyNr|kURal zpk9FB9Y{I9_m2*)P6(hLHdE}kc2IK#)4m79S{4mS5I$H^DV0J?AHrz`u^AO z{;#)VD&T(QXH2High0olX9#BXNPMq1$NBZ3s2R+G8x+JA!6Lo7I%dw$GvL%iQAyKF z<<3vO0cv~#bE7tT(LCV%4y&=MCRWz_=3WW4t@40x?&a{ST(3s(`tB)#APn}>8hqP3 zri+C394yc2>*z38mE+6_X70?6P1^)(?elz~GI?l58a-0G*bXJ&aSkjysnP_ucM$6I zHLTTPpG=Q(U~3Dgu%n$mM~7iQVK~jEDQ?p=+WirA&+#|(5B&)1V*k_{p?2Ch=e-Os zwMAMjZZ4t`Wp3yr+u35*eB}*9uc{Ab?z5vsNgjMSg;gAOpuL+Y#s%}B`}6VmL1@VG zLg3Hbn%&?86&<@I+Wn$DXBW9chZrcn1lkN(qlOx#T$h`@CLDk@YFNI7xT|_+s2g$f zKtI^8`B5G`n5#OaaeE>@kURypb^0NFx)!W0`y%mD9xPU;K;Pd6x{tZNA+KOVWnMI6 zZ3>8~LSQ?e+sPNg6>J~?w@+i|^n+}04T;pkV&T_iwV=EWtnQ~xA7F<*hpA0+5K1LX zOrdDzIy>@`+iSgg#|4_+G=*{nQ<9WG_75{Q;LRzz@C0EWt9s}X)Q^fF8EHDxqGKD@ zpFj8rhB&IAQ{F!IA2$8%W8p%l)zBv!Qz#ygOwR_p>u zG%TKkv$1S^9)X8F*7T18uxAaVJE<-;2xH={u*8yBh1iLMo7?DSYX#ER=xO2TpneJm zNl($fhO_jBGk?QbhCcHx0cYveS7@eaFsb%oHVlPRVAA$0Emly*EZ=uI4OPvCkfP@2 zmOqdaW8Z$K+dvwrV#C@v<fDanxKXt~Z6ekT z2WEGoglbD+)(VRa{nzPa@_c5Y9omQugq@ta?m(cK7gh-Odgx&bEy1ZL9w6ZT$oEE$ zcXWHpI~w}b$cMB9MjpWG_;-jb2t`@d!^CB3z!?7v6a&>~CMuon$1Dr#4Zq&Ol($fm>(xXV7`0P)ozv^uNUoH1cU7en|i&luk-KcP= z21HT3ns%{kXm) zr9O*>c%U>b{#UGhPy%9q-O@0`g5LI+?hz(B#x4g~<1|qyeBMx zm%#e_1zVs0nI6C0fvlo{vG-S&;&L*%Fp;s z248Ty?R?_wb)6Re2>l~O?^MGt?*zk5)oMg)HU_?x$^~wU8n?n-3z}5JOucw~J~#nV z;hP&#ap;Z~AB&r-Q?wotfF&u|XS3@F?qj!|n#IYu{ofaa_b_5fFfGmTs8r@+f}usk z;dh!UDer>Kw9cwV{5aeG;^X>y*m=;;w-TOi!u5OlI^bK`R$Z@bxbCE`U*zj0ZCV6y zi~Zop;rj5k&i0x*Z)9h3pyu18K+ARgW|vv8u@UNCtfmg$Sn$CLV$0gV>|vhrL-pZ4 zxskQWHQzLE`C(x8c(ut!*;k1>FcV$~^aR%RLsz5qFmrAPxu=q(^L_;Q3WSmppQwRC zg10j-Kdq@eiFW~UY6=^7=f%~!tFF=9?_rPLOZC0J$cvzgYMyUN+YXhVg;%J^(eto7 ztLo$f!9K7F@vX?=R^f9ZhffUmjvPKSd^0ZNd`p$0aT1hxnoA8-p5seRqVf-e;~{X% zA4>!b32f$$E0~FkdJpqe=D>3!s9w|0F{^E&P498O%JvXsQuIBn`0>uC@z9JN^S;7a z5DP!1>^*$Oir&L!Z0bF*?7_x0$Ha<1sEKBOpj2V)o(wA?@w4DddHR^f5jMph(>(Ts z=CQt=Z`QwHf*z@#;j4H7PJ+?NQ zDes-Nuu9{rtN?=hG=5z5mh~1C8!J8$NN(s?T(Rv_;?_Z4K${MR}{*|>E0oL zYQKSP;(0LBU!3Htd;=6L&VkKEC*UJz3{3G=J`Wd*{l3aW@atQW2sk?;30T<8^WC)r zdT`$oXp~e>Zim`D2!pKpUF93gbyppq0TKI_9EK%c-(5c`?}M;zZ$jRO;Qg!moqAlg zV-uL^1!)>KOrf!6Ec+b@NWf~KF86vol7a9egsRc0`7t@N#}m8uOQ6+2wG-3AEn)-k zapxV%g^4i5yzCk%3?4q1H#CRs$uT%Qm7hqD1UtiFXulHhGY9+SNLV($T<~i%34W(t+l6p0G z0jAURc+vv=8h=R^tZBmf3AjiX?I(hcBO$YG3v{#N(UwFvvG{&W&fZ ztDszY^@{KXq+wm~Bo91%+F)m|^+mn}Lvx*Pb5}wA#bbu;ypyoksTe(Wbi60=wsLOO zeR-sY=bTv*Y2XVPi#4J96lEd;L0$-S+iemsnssao-XTjgF(Yff>4t@sR!_UnChy zxNk|WXST}3NX*~+2H#yZ5G`~hEFSXSsfr}1OT46W2I_dlJFpwdH+wgHLzRfHhhGj0 z`ufFq9IwhlF!KkR9nIVT`O*y{Z9*1yLg_UUlDz?CTY#({{x$R6bqK7~H%i-L1E8?Q zKgDpBOR*}Lk;FH`b?g(EU&O27Oc%N@KA%W8{*nLm>3FqHK*E!*HDUE{l=C}u$uCTMNodM(-lMVA?(;R|pN zc_r?^;A+<}e-uNo+1dG%wdDtJpK;wMwW}6({#ag`& zD*k~gQ~}kBa9i0=l=SmpaHOej-{1{Tn2$xLG~5!su|8Ttd!l~B!Z*w`XvSGuG3Zlu zPUpcEl)Nf^NVY zmo*3+YgkVVT+|TQV4L%kHas1}r#8e|S#9KqYI>nulH*1+fB4k zp}!+)9oc(5jT!G$bP>^^M2mpB%~50RH$wJb4HCMCYwoLD)||^-)P~^zEP8AE;5~O9 z9jxpC`G3qaSUa>&)p6cE5ibQTdN2f?<^tHO*+fxh=O;0FFt*rs7Ld+%3+oqq*RDC}#vf+Bm%=isQ1G35Iqy-=p+o00E3=&Q&ET2hU_3PL)A z^tQb4DbSUXSHD~dS~@~eSI<|~^piq9gcUEf`mFQi;8wUy0zr17)<}c)IKBd|iM~C% z4rAfGyB%X$3nGoN#P*}YSAhLb$6(Xoo>&g_J1S4qSG*9|N=POZA}lNM8yXm1YPkR~ zUF=4$gy_5Cr7Cte;pMq-xfr&Yoe96ObXW(DpM+<4J5EdODyz?d;0RC7vd%z!{oZxl zSDv=xj9nGn`tTXrF?x5+j8vTozPZnX5^`o%D-t(Fm4$#5wN( zD_7mCCw?2u5VZgDpa6^x%!IvhmPb48%gqf%qUlt`uYr3qH)q0ZZ?k%U8ais%?D6J# z_CQ6@T5~}{YrE&)YU|QyL6S~8EQC^8qnAKn0M-Fuo@rU5@vM#Ijh_uvkCS5i-h@nj z5^`MEVa$4ddec#5LBH(p`uVQ?Mz2T)U@H%;v+Jl}p_g~(W$x0CV7zwdXZ4ucvo1Gu z1XE^v^t@C@34??T7$ktZSL5vdy#Ger%Ikfi-m~qH8g1~TwyO7jo#&bK_y^+Nr{n$| z-`2+`1s=UKh=zr#0Kx;9VCEherv%V|XCTRXo@zy6IlX(p{10CIX=?t5du3>q1y@1T zOQnfF>t9_6tIIx}Jrv&ZQ7bO$OLJHznF%jPX`e0j`YPta6)dw&9BG1ADoQ~sEiv~GeNXiZX3!n&?9~%5w3kCo#bX9M^qPD({1FxC z4$19}9Z$nz0`4DjzO<87P@c0_72rJ2g_~ zCo%!m_9pV3y_uh4$-+H)cIYrvlh`B}`URZz@HoFft*jbO`8%jl8>`H>&K8%K-4q>o z5H>MPY8I(Gv1|`)as3QkN5+0}G=8cz4%}dqn#=2jO+A z@FwuSH&WMb(yQ>th{FGj4n$8+UINXs^m`;95Ha=rorr-UgCz+T<0jfKMcDE;aopU z)0=y$dPeHKzDo6KHtwJs58;8O*b>1On>+`$uYK%nKZ4stqpxR_16J%H5}o+yRae07 ziQM%ybz#O;% z|2zxa;MpSN7bqKi6)ic7VMloU2=|(}2}1k2aZNoh`y1Go0I!XI2wMP@p}8QXwi{)~ zN-u@ri5>GYf9>!2RlV@7BpS9G9j}fwtVz71_E3V;8>&ZH8t$P4!c7KkDdoqv@VE{C zVuSOck=^j%0=DTx5eLuGpvi&P2jTe&0;m`*brY9XcA7p(3Hxbg1zY0EZcdz~d>Mp? z3D9=_0)Gl5@i9JGfQyA{r5++^H1NNmL8F=r`#Z;Z)Sf<^j})OS?77I?o}0NQ{I=~R z%6pv{-T{tViM<1l&99DjIu~4L!wMX3W6Asi1G3;=+I^MP2VZwO_9&P*v7j{6p>C-tvE(9}O>^c4TdaCoA>eZIeJ!ng^=lP4UfkGQ{NV&SBb;R1hYLHHuD zupsOoUz}e6chVgkKg+wxO&(boE}SsNKN_qnDa`k`ADizVJ+iQm+#LnEAWSl{iTItCX6g! z{-+Z&47BpDy=p+9e?RMnLH(|`>}%l+LmCr>1%Gnkg#6;k zP$IE-VM26Hlom|L$JC7imyWYKOeiZV%52CyE?%QXmKI#xy)jc8vL9+8W?K6Yeh)of zAXHlDx6Zt!ePOTmh1Xjlb~3~TrD9_7cz@~Gf}$dAPia9BHX5e$u$UD1bzLZ);D=n% zq9?YpcFnp6KKH@rUii$ncHKW4J`Y*D7Dg<;wd;Xda0Mar9r(8wsQ(=Q@xXsP@E;HS#{>WIz<)gO9}oP0$OFm$&)5o2I;<Wyn6^{CjBle98F4*!4oyS_fnngKT8AI`?VtBu!99pwm9@XKRWm+#zH zS8i4B+=tiyIsSj;fvfuVz0}_!FflaNpI11cY>Gd-bGOb}7k0_iC+rK{S%Qb>uh(0i zDQTWFQ(L6qhBYi*ZB+;?G|?}zEIM}#7NqkMgAJi`){plV5z92>%IQ30umyB}mcbU& z`BMg4LFZ!(wwcZ!pkEt)chmVcY+(AdPMeq1r*-<=VYUwI z31MR?tQ5}ChA7%FCppmCKg$bIMVbX$XIc+b_ScL?aKRb||wPNyA)!I1`^HpCVxqFD!G7ZK|KzrBe?kcl)V-ND&nSpy+> zEXjU`vIGCnuff&>lb&!Xgx9xDsa?0}-S^(dy19aMR-?{oP!{u5c^lRm+J7wfJ1BfL zm4iPl_d}AO^E6fPK@X<2gBQNwz}@RIt;w05hQy-mV3N(l8z3KNVR?-t2V47#bYa!m zsq~hUY&+C@jBN6sv{n#?AWY8-Bs(6{1^)iS^bAZMoa~YwEE9F4s|CdyNlI?!ftawp zYSRq9;P@wgUDbLgir_t+h^r9+)cpavdMn#(3VR33+P}B$*(8??#&{NxuAXp?K8Ykv zQa-@2mtAbYc48BSsrFNr$1%sY6R7Kmi!KaHhrKFzRO1)qT+$Mq*c`a*PGPuB3e!3l z+p;LOr*p6^n}zLZr1@2?tNls)bqfJamC=%7x~7nhlQ17ZM-%Pgh@|I^ZxGS8*XdsT zTawDQ;o3ILyUi4)Ms<)!gTZrHr(?v&;yrNq;d6wT>OUIG9yG(c!9jg~7;oW`gI~j1 zr;VaA($nPmtMth-JA{>dF6m#`1jjn?GVxc) zZ+}<^N|G0PUFtx0&~=1#-HdTJod;P-_Oaar+T5KIa0=ds^#E)R!f77yAE{h4k*8V7 zRnTdOUJjavo_$*9T+=#B`(!~A`Z4V<5I+mcE!g{qX&;gNgx95xVY^gEx{@&w|4vuA zC;7UQU6jG?XqydN9q~w~wEv-P1Ct8ev|+oxfOI{G3RV428bQTK`T2DU|L)(_zog{% zsf#|g0)pD!@Hs+y5*Sa@`Ja$vPfY1acy@>)Ns8J84FhB--7M>2Q9A}|>=$pfow zlA(vkrkIT$tA(|b(uCy{k2Bzd9QV%R!TfAEM?HMMqe3m~0{Hbnyw&GwfG^qNf&D(p z?^aiqRYJemmLVTZNn`zei1WBFljH{wzlY>Q#BU`23vnL%o(2g<{U^~F<|&dN4!>w8 zA7}?2qv3<{uao>3MJ?+#;%8#t2?vjlZ-;Y~f0eizBLf=*cA)<9b5Xi++&>e}QGOP+ z9cmn`B;ZdNSk$4=HUA{z#z%3?g=^IFH>!tf%nWQH@sBCLO6k5Q;MW5&aEkf&?<9XU zJs})I^8X_KBylws2KE+wFkSw$wIGjE*OUAv80X`m#=r23e=!K{d_ZkqvMe>81%~4| zk3~kp`9AO$9x?b}dHaQe*dzOh|0Z}HaMbUG*LLuDP5)R)pbz;Q#50KFwhiR%PS&8B z_{qe-B(BDM5QgI_lz)N>rW(Hi$3FmveCw%Nff}p9DgHHnCaCXxJrv$dcayTIukz){{7@-s<(H&%Q&RG$OCRZ1S(6Dqgd z(BU2$Os_|6vVyvR4H6uWDS4_~aLs4WlAgy&5B*p#lOC_FZrA+@oZ{PiXlIUJb52(+ zbB!&F!Z!g&d;XQH15{r@GRa1{<=gN#*-AAp8_tt0D*O$^vbKYM3+np_gW>7t#09o? z5$F8o@I8tj-#%!2o2xMu%i`}(Bu{Q`2s%KVlH0%!6Th^9(1~gvn_E{1-i&xq@K(eJ z3a;nN&8*pi|4GR=(=Q_$VQopz^#;S!bBN;>H1p^{e4Gj4yff+FDR_61pDg&LBo9U6 zm?MYexxR5A{uxZn-wr|^-}keiJ%0&*jN^LZs||*yx_xbKtr7fIlK({TeB!?d{ukod z{+UM!@#_SiL>$`{^O#C}xZrmZFA#h-aoqQ29&?G83BG{%Uj=`N_zb}xCw{u%e<$8U z@E3^p75r7=6@sh(ViEG|Nx{{gEXZG5@HM0d|B{_~Y*f6NRU-IilK)WfkBILTd40`fZdyMDo=_UN^|iteD`aB8Mw*iU)`jnL;fGwf$0dJH0FL&* za;7q0uWiAp&qe+#7oJXfZpDcz9NqMfg?|;isdV{Wco!FbDe1q5^sDtWh$G-4e~=-*Dm8E_}TUf7^v`cHy76@SQIFTNj=Hj`=e6Je@E1>L2S@ z;;qlu;B?~nYFktJ>xBs*>N%g}$CCVs#ODzoL;MWl2Z-koKacpu9W-FxmG~s$9Z5b5 zcvJTDCiy2wK8573CjK08YIdy~iN7KEaN=u;tMy3GH3oQ7@fMT(qziR~H&eV};_nlu zX_Ga>MNbXM?;?4%)(E=rt(&Ie#kKUN_@gfTc^Ceg3tt5s^LGn%AZ-6S7x{Nx_-8Ks zYZv~#3;)%HA9mqMF!e(FpSVV6NP_a^1mI2it&IzB=fcl(;aR{j-nKMhdywMo<|5zI zh3B|%t2Ep>WR-V+} zl};X6QW~0AfHLEYCl!Q?_3ubH33cv%@g*0l+d!nasK~-Sl9{!S>K z2wTQsyR#L}FBq+Mpo7@N!U+(iRaiVa-_qNf^9w@5VdHhkg3ZeLW#dcm7xu%K7Tl&1 z0KxFefQk$E#aolYU9z%7s7xqVH0wx~hA->ZsJcupz8 zsbcA>zg1jaRb1WFc{g?5U1{sCv~^c{x+^{1m7eZ8)k<4;rKh{Px4XKxhq||iy0?dt z?4dODP#SvluqGEz%+D_`J_wof2$__bGFIjG;@;e!Kx^7;+8CWlHx zV<$pJ=EMGXt3+*rw?ak5r3KdT;i2&DB?ZGr4Tl#ZtkF8}u(H9c7+7qE4~Lf?LgR*q z#*Q0~+v%|w7EUM(<1cKnFM#4vP^8MEDxl$!Q1dWoN*G=Su%>Y7!;_L?RbR#zhq2t^ zOBa(z7Gd$ldI{AEUn?0shR;TgvBnpShubWui=`zaLj|Q)eqn(%X|$?$qpd0WB@VC< z(lenL?H{Q$V`0WOLoBF?V2U*wBCw{=YaU>ddd0)S*KpwV8&%MUkDNHB6r&53+-{ZL zUK%cdb|ic|)F<_dh6S&LbX8~YMuvrNVW3-XFP$`8zmo$A4nuv1h5%m2z*yn63;a>< zU*Ji>gh^J}1dzfLY^5f^8%$Qgl!DNt5^FfVVFI-tS__C%zqEsAQ0K-#tsYm1O%lGO zqH`W=jL@t8411>8`nU-Gv;$98~Xgw$ixs9F(AwH4vQ zFuX^DImc(1yZKmmr{K40Yo?5b(oi~9(2?sTS1`Vi3U#Jacs4trS7O`8VGBwny(-}Ob06tL&ApVNFl+8 zjM8Ad;Dd=T5`4wE8hj-98sd8eXL)`;gLa}lLrH%Qt#>eI`5RsMIKesIiGpt;du|t; z<;w+U`B{R`BRdxeK9%^Rg3l(-d!;yCbBO;_$g>_?SI2|p`MKYE!Na6SuX{JjPa*!L zkY|6^34RC3>viTvJ#7CeXoz9Ye3IAex{dPiX9?AjBjoc*{%XP5{=tH?AI1pI`YQxy z{qqE8{R;(W{mTVs|9mVs`{8rJIUidkAL}31bC%$2&-sFL{`L_3=}}rQ{z+FnFnY88 zh6QK+m4dULcLlFFSE;r33(oDp5y1zOJ(*|(9BdD#7uO}2-wr37UqgxG&m9JzWXR(w z*GF78z=QQOf5wGx7o7cx^J`NN^WOw#`&+|&#FS@0v=yBFaE;)sXR_d|=Pton&+CG- z9-M!%J*Gc*631ki{yZP%9W0MwoZf)otbc^y?B`;^S{M=S;ylz2~~{Ou;!`-n+%| zvVVFDc`gtA1ZVkyg0tUl6rBA$T5!(CBEdOb69wn;Fhy{-Cn7k@JA$+Rd4jV&wFb|D z{O5Lcqrs;dd>e6W1Ev|gCyfWu&jEv9VQ^DVE^(>nCPTiDq32eEn|j8&=;1wOXir~5 z5B|A8Jdm4uo^jE$)Q~sRwaVb8p0{1}>^9_+l?D3iB-*coewYp)_WuRM(axa3FEZq3 z7`%reZ|c9)kS{mnbA&v{JIs)uX~@51$eZb{Hh4cneyySBPJ?eUQhT!9kT>Jq zCFI+l4L8B@lfg}U4j6hOAjj#t_yl#E%J(Y`ewo2dJy#Kz<#V8m{78deW#}Jm=rR3J zY{;AOmK)qQ^i;a&xyO(<^*m|tTtm;ZE_z-wep7mIbS{( zd!HPSPVXHg-%9WYh@T=j&->a5zL@0C7o5irS%UNU;R?ao&YJ{h z`Qd`I{20NxKP?uV`{k*Ev-~WFmd_e@kw*Rd7P6fIFH9p7W`?_f0p18;^zs@ z>CFIM>q$1!w(_3C{LBFF5OYMR1m1 zE;#FdTX44X0~h|O;GEvwF8nva+0Q4^K44j%PbJRfirb~L1?PI#S#T~_Jq73WnH<5{ zKLZ43`4NJ%{?UT7e2L(!f07HIDmbq%%@Um3&-(;tdma>=^YK~1*`9w2UQPAuHNm-@ ztR^n=>pdaQ_G}lN@fc?YutBc^Q z=SsmjU-AU!e3|UR9l=@ue8Jg2&j`-)ue&NZeR<8`*MJ@_&&v&N&ac-H z$2iUPv`-EBju5s2K6vai>n&J&!|drey~8V>Z2S$+l*$28psAI{(ZGWY_6hYWtd!6zF0 z0fXOe@P!7C5J!9Z8$4>r-)rzE40*Jb=N&H!&g1RZ1?TzETY|HH-Xo5>|7OJdsgP$q zI|b)>e-?ZyjbmG$1xn$-^kN)54m?wE9?#ft{oLu_1rd;AVQg86X4)#%ZRvHF3<}o8iOprW^8Rde1Vr zsXxQurvA=`{{J%c_cY{9{g)f^$so^1UqikeAlqph{5gZ)XmGPU=ezKUF8pqTKX2%N z*x;r;PrLBv3~u`E4TJx~(7)2)FBp6aam=q<4E~WJ|4)M-Fyx0C{IDVaqQR5e!v!3u ze;9n&&n<|1ftm8H4f$IQ`BPlv&oShO8}jEH@-G?uVncp}!F##LUv0>n{<+pgez+k& z($JspB41+2zih})HuxxmPj%5#WpK0pKIFombKy%}_<9%qkqiII;IA0=Ck+0o!S@;5 zEYAlGZnguS^WbJUuv~@U!{zD(;#jWCcHlIFn|jVR^yC|QIvVn(p00*`fg#`9MSid$ z|C%8`#gMNw_`QZarh(@div;KXV42`SKimXIt)bs+XTCDH>F1ciP5$z2M)-zLZE+?~ytFmVJ`F=xw zjKLo^6Yf^)oY8hXrm_i7jUO@gyM zTU_*Pcah&CI6uey&PC79F7hW{pt4!D|CpD&UV1WdWM;ZfcahH!d>iHajRqeJy13mN zW^l9J8$%r9HQT+ZhCGI`|K}OlQZ7}3bKYS_V^Qpd^iw_Ur z;C6}ayok8;=Vd~k?aXzNzeC8g{)i!Ou0!4<xbXJ`=lb%s;9Rfc zf``d(zY5O&JSzBDl27h*te^Qg!ij?O^Mca^=XlQ+obBu+I6s%XS#Yi|lZa#fn$H)e zxyavRaPxV=t1i6S;1~zT+u_1v{lI?95}f^Zso?Clpy2Gc0fMvNh6v7n3klACyUXBn z!DMa+<{I35?(>+zF}+-_o+d8+{0|||>3UUgPS=};o@&FMPYk}s;6DgG?1!HX`E`c8 zr!!o@!RsD+^_vE_z?0#tBcUfjeZ_X{1U<0&Y<8ok$iu_*$;yRXFuF5 zIQ#il;+U=t@ZogjyU71VaE`aw(DSyTXQq&6f6f-1?U^Sy>;IeJoUS#*(f*A_yq_6- zt--xnZ~;dWeDEHAE|4mCz8?bNI9c#Izrxm8f`^G;?80XXeuU)jcH#3~_;Z3!B|R?^ z$24t%59i~*g#1vFKd}o4!GZGc!iVM0F!(zLhd-X64))s|zrMaw@CxGB75h8Wz8 zceJ6W5LB~0lMMbBgHJQKIUc*q&~J{%9(Iv`!QkTz{jV5$?lkyPLmqv{{#<47B13+i z!A(0i8~RNZX5D$9wQ${eLp}`v$*=IO;Lem1FSnhI~ImkLl0r40%(}Erxu=&@;wGeu9hq?S?$2 zjqB+w!MVQQXXu$}#JkdvH|^YD$ea1N#YKLX!LKs(?=ke4{@G{9oAG+O!_9D@|84ki zel;hKX*KnnY{;8>&NXcDtSJ^c(m!O(NHi=GjNJle|bMu8!}#?UiK z$WQe{ARKqN$UiRRkNB0i^{n7Si7ykJ_pxjiobCLOINENuZ@Ud{wr>eTkJ-K*HRLNn z7w2QY9@<{?GseN|DmM~WJ~QP1V(`rde^TgKFbV?U_@@g$Y;bHJ`0qQMc(J;zq2HWO zdO8>!<@MhKwX7=*j<)jn^IE~VA0O_*!-8|XcMHz__=ChT&Moj^e?BSX`8~mLiUKM0;rdg=vdJ5Rj?5(7sPd@yaC-p+!v{vLuqP5S#8d@JZ- z|BNS&x<4>@xgn2XZE2mP%7x!6`Ppz294`sZ`M6B*eA2&0aQ4GS!OtZ9+XQF%qk^AH z`fuu~?ZPyf^>-$5_Hz-*&k>yU-zPcA|6TC$#NRYH)|WZWv>opo9Bt}A@(CAS=fZy% zoXcU0Y#k4$i_6Jrf^)nXF8o5lSwH-dE_F!#@b|}#;pbDj1`5vc-ehp}&+g{>{t|mQ|1?P71ei#0v;B3#!1~==)cH$VPSuege+dKy>+dBv>$hF_b%L{=(Soy{QWt)^;H>8!!CB8Ug7ZB6UxIV{wwyTT$$a>5 z`?gNVvwz+dob`MuINS4`3qK$@r>l9drt|S+7oIM7C#o;)U3hQ7+0I-SKGcQZZg6v4 zcelZd4S&ufj()z=;Ex&d7{-2hMsUu@mj&m1c~fxKQzJO9lWY~7^?xro>#1|$>OTSk zySd)6J?Xsx8l3fa6`bwqB{<6u5uEd@L~yoqlHjaorr>PnJ%Y2I2L)&O7X@ee*9GTz z-xHke|ICHQ1?TsneiNMaG{5XvKQnJ5IP1v}oaMW?@Jj^e^j;=7>(3RO=LKU0&!Bob zLGZD}%LHdT?{?u2xbQ~=XZxQLob7)}aJK(l!P%ZqUHDGHIo@vt=W=yaaMpkN{j$X1 zb5Wk&OIl%Yl;`IKs|`NSkl$c%l;`IN^@5L~cw1fpLU3@q$NUr*ewGVA--UN^;k{gV zKf&2Qg9K+gN4W6uF8r@9{4N*1z=b~{INMn(IOo@U1~>C}o59We{YCJGd^EV3@6B>l zHa6rV%cl#@_H-1SR%5ySi@~QFJWL$ZI?dn}#JL>u`1~Hhx&3)e zaIWvq8~iq_(Vi8=G2U$k-(+xeoc}R#wuk4By9MX^{*wzoC^(Pn)E~pL8tWa8ADRaM z8l2?^3C{5jA&%+#5I)>)lnHsBA5C}RQG+KNdhRv!e`N4S4S9_FacWPVF}SJcC4*yo zxQN!Dml+)Oupizr_(UV#tp+#C)yKq9hgq(68}b-7pX@v+IIqJT6?_%-<0tfio8jQ{ zz~iDn3C{buOCVrb(r;ioWW}$jO$T} z!9O;5g~6)~zR-nlHTXB$qE+oc->=f4j;N^q7RCpgD@o8VkeD+Fixy9H2UyzdIme%Maj3)wUqK3qNz2zj>isNfuLN?TuwM& zIul3zHHQA6kZ1kZ2+sO%6rA;s7o6oM3C@04C^*NvSnv!gSFZ`qdX@{$@ve8_TLkBL zw+qhc+9f#0+YBGp!Xf>60&(^~>(3CJ({+*Htp8%cIbD5S_yEB<-WvqxbPX4r+Pc5nt=VHwm6k@>__bZytsZ`)#|6{2mwn zqoK!a9}Wn4wqHG*hWIevN+aH9Y`B1f{m=eP$A{2xNO?bTmhbIXV%9~HYi#utJV^4F z8Tvl~S@uJokZ1kZyYO2jr+5n`r+9C3;WLP1dLJW2A^-}2^;(&L;hZa|J{(s zIB40;ddZMC^YIshoA&g$8g7Pz{m=faB#yd2g%A7lJ{S2lF8r{eXS<;%`k}MIryKGE4Q{6QCWD*tjwFupPBQe2Gvv*9OAKzN>k)&S_2OMa zKc;!eDENY7yCJ^}t~tHCggm!<2^apW!6zGf#^zxx+RvZCFYBLeaMMmD3}5I6{QPpd zCTKGr%wIoEU(+RN^B9Pa~c$_}%3Hv4W?Qe39U7iQ^g+9_%+i zacnd3V9xn6MdJqEf#jzO-idg*;90~g1n*9Kw%|R9&k>ySWxn8?FAD?@lAeWv+r$?M zo=5y~!3Pq5TJXWd7Yn|K_zQv$CH}JDBZ$8)cs}u^f{!J>Lh#?H{8tOk<$R6ccaokB zg8xW*HVJ+=$!`{%|4!C6!TIk}Z5RB0(z8SGhluYK{88e&1%HxwOz^)G|4#7diSHA9 z8u4EQf0cNh;7f=f5qvpu_^%4p!S!e*aj)R3iSz$c&hqPsrwaLv#QE?4vHa`A+X(q_ z>DrET!Rsi0+Y0_D$@>L=mw1NYhlqC&oZGifg14b~vjpEnyu09=iT4zI8}Z(PbH8K$ ze^uxs?stMhekbYS|JR)T$^A~Akmr79py1rT4HlgHogspAeHilmj&m3=XJrk-&ra+_d6>DA42-8 z1?PTejo{qxY!ICLolSy|CHd-Cpe!{KLMQ?-qPG$;Sl$ zoaDa~{43)71iz2;{37@R#OnlqnD`OFA0w^?N?>vleSW2Qy$Fcm>2JhS1V2hVRd8O{ zP7}OYP^q=r2;P!-y5J`gZ!7po#QlQv`gn%mr;~gK!OtSzN${U2U0H&ANxr+_nZ$bv zej)MRf_EXFBX|$uLBY8^*n)GurM|`m0xx|ME-kuA^;rB&Y z&lAMcguG4b%WVWd?GkNAy5MILZ!35^;(o!;C7vPpP>Q#M;2lZ6li*L&`x{w;=M(QP z_|3$73jPrB-hw|$JV$VTza=R6JtS`n-i++e6TBtyfr1YrK3MQMsO~9PuK-i;0&AK9som|CVBzn@oI)kiUxfRKZUmUM_fqc!l715uYtM zzdtia@OdOZU-0{gFA)3z;tK_TnD`>WA0z&_;7<{MTJUFyFBbeC#9t7c-}8A{@YhKG zb-~{tzEtoxiLVfR74d4pYl*KBd_D0Eg1i;KjsC1TQ5X7JM@CDT3cYe5&9xh?ff%27?TGt@{JF$41n2i!I|$y9*=ZQ}hdg1m8n^w%`fk za|Hj9_BJWaekbwA1)oLyX~FsZ&&7hzCHWTwznA#Sg5OX4 zb-^DZzEto>iLVg+N#fOl|DE_6!Jj9-LGTxeZxZ}f;+q9uLVTOx%ZYCnd?oQ6g0CjN zQ}A`fcMHCecues3h<_(IzX!Wd@Q+CT7r{RzUMKh$#E%HRi@4SN*!KTh;$Fe`5>FBQ z2jZ!M?!FZ3G`rJYDcdh_@Ad{H5A%zu=D$&k+1w;vED(LcEjU{2q0d;7?P! zx(m*J?kRXuZ*6C9$uHA9NARu0gM#;__x)_aJCpuA!TEjWfr7tDdIk%ADd`y^_~pch z3cir+93l96;`xGKO?t)(K7e?U;MWr`5&R!ye^~JUBKawT^Lvt01s_H7<${kUULp8j zh|d;$0`WP5Pb5BH@Xx9IED-z~Du)XNpH6xf3H}1fKQ4GKy-)bG;F%=9Sn#%_{{_MS zL3X|@csc2RUGM_Zzf|x?N&gDLpCn!__}?gh*9iUw#k)c9<FSrH}STDUrpRE_z>b5f{!NN zLGX)nbox69ekt)R!7nG?UGP4{dkTIf@!o=8O*}{N0mOrXUr*c?{6^w=g8vusfr8&k ze6Zl7hz}8bG5Kw%;LC`Q5PT!?e8E2>K34Ea6mOB>`$)b-a1Y6c1wWbi6v1cxpVIC( zw9O)p1NaT{BL3-YN2h^yT{em%Z&qAi4IZO3Af9RZbqj_5{cq;g#gtp9+#|f2x{X`%^XKyV2gLCD;B` znEW-QuOrv~RD@jnQ}yK9pNf)ef2x68`%_Ki2XUS>lWTjdmHaN!w~^Q4{A?%x3j5nZ zeg@Y|7kL)t_mc01C&;y3ktF{G<)_H2aGrbQJK;m*Te1CV@~3cr876-k?a2{x?N5!8 z@56e>$hAK;L4Hb~|B&B;XULyL`C0N3v_IwQHD;3yJYqjx?n1T`lIOh_UMgSbJpm7p zC*eWz6ugGqgNMn7;OpdR_-*o6;kga8-|2q64);4K@MG{&^5gIT`8YgCJ_)ZOKM4<$ zzYC9$XW>!uX?PR4j?-!-*Ku0yrfb_%Ui||o$9j7%x zuH&>asL`PHUe0I?^waufVU6>o~2e#pMYn`bv*G|@-l4yBDtPd%j6XpXRt?rv~c#^!KOty!|)okA)&f`^ng4g=w zd)>~Na*4N-f4^0n-;Y;4EY9zXpK&)OJMsHR{rjc>J(vEdLehuHJ1fPT$xpyD~3 zJ-?@zg7bTUFX4uslN<<2IhEw&@CbR!4oROTKeSVvpO2*<73b$sn|F!xbD>>uL+$yu z;ML@};PvGDa0726KLSsY&%j5>&%m?f7vS7aybRX{ik@#r_Q?Kn`}tcqw_|^Xb9?E# z$E2J&zbv)9^OqkUei+b+EU zStc|z5KqQJUVO+iq28DmGokLmK@%G2cM+F-ZzytabgzxNJdy;FTx!c!L&^T0Ski=g z`uqCghi$Qk`@MLmvE{`*gI=uX5HiFQFTFev>x;{d{?B>P=66*!PWyamQG~{t^OOsq zTF;}q>|Iq8&5HygZ^+W$D@#{Ry1e)qjka6eW#k;yp$*Bjg!O8AbyRB_HMKV6(s2G2 zpT3A1BxRTigjzFzNQ_afsUQisirABANc8{F+afZOBi_jM*>w z@8W!wm@z>OVEKYw7CZjYUnRlf6S8#2-(Bju{d)Xk*4(!6@iSnS9txNHJ37MKZVo!L5b}sL>rb;HVxbutton.x - borderpx; + int x = e->xbutton.x - win.hborderpx; LIMIT(x, 0, win.tw - 1); return x / win.cw; } @@ -338,7 +339,7 @@ evcol(XEvent *e) int evrow(XEvent *e) { - int y = e->xbutton.y - borderpx; + int y = e->xbutton.y - win.vborderpx; LIMIT(y, 0, win.th - 1); return y / win.ch; } @@ -706,6 +707,9 @@ cresize(int width, int height) col = MAX(1, col); row = MAX(1, row); + win.hborderpx = (win.w - col * win.cw) / 2; + win.vborderpx = (win.h - row * win.ch) / 2; + tresize(col, row); xresize(col, row); ttyresize(win.tw, win.th); @@ -823,8 +827,8 @@ xhints(void) 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->height_inc = 1; + sizeh->width_inc = 1; sizeh->base_height = 2 * borderpx; sizeh->base_width = 2 * borderpx; sizeh->min_height = win.ch + 2 * borderpx; @@ -1106,8 +1110,8 @@ xinit(int cols, int rows) xloadcols(); /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; + win.w = 2 * win.hborderpx + cols * win.cw; + win.h = 2 * win.vborderpx + rows * win.ch; if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1195,7 +1199,7 @@ xinit(int cols, int rows) 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; + float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; ushort mode, prevmode = USHRT_MAX; Font *font = &dc.font; int frcflags = FRC_NORMAL; @@ -1328,7 +1332,7 @@ 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, + int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, width = charlen * win.cw; Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; @@ -1418,17 +1422,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Intelligent cleaning up of the borders. */ if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, + xclear(0, (y == 0)? 0 : winy, win.vborderpx, winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); + ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); } - if (winx + width >= borderpx + win.tw) { + if (winx + width >= win.hborderpx + win.tw) { xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); + ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); } if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) + xclear(winx, 0, winx + width, win.hborderpx); + if (winy + win.ch >= win.vborderpx + win.th) xclear(winx, winy + win.ch, winx + width, win.h); /* Clean up the region we want to draw to. */ @@ -1521,35 +1525,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) case 3: /* Blinking Underline */ case 4: /* Steady Underline */ XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - \ + win.hborderpx + cx * win.cw, + win.vborderpx + (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, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, cursorthickness, win.ch); break; } } else { XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, win.cw - 1, 1); XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, + win.hborderpx + (cx + 1) * win.cw - 1, + win.vborderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, + win.hborderpx + cx * win.cw, + win.vborderpx + (cy + 1) * win.ch - 1, win.cw, 1); } } diff --git a/x.c.orig b/x.c.orig new file mode 100644 index 0000000..48a6676 --- /dev/null +++ b/x.c.orig @@ -0,0 +1,2040 @@ +/* See LICENSE for license details. */ +#include +#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; + 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(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); +} + +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); + 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) +{ + 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) +{ + 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) { + 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; + 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); + 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), 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..a52882f4e3b152367ada5e90d47444ef7000cb83 GIT binary patch literal 77200 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
3*U( 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 literal 0 HcmV?d00001