diff options
-rw-r--r-- | config.def.h | 13 | ||||
-rw-r--r-- | config.h | 426 | ||||
-rw-r--r-- | st.c | 188 |
3 files changed, 576 insertions, 51 deletions
diff --git a/config.def.h b/config.def.h index fd09d72..db0bf24 100644 --- a/config.def.h +++ b/config.def.h @@ -7,6 +7,7 @@ */ static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; +#define histsize 2000 /* * What program is execed by st depends of these precedence rules: @@ -136,8 +137,14 @@ static unsigned int defaultunderline = 7; */ static MouseShortcut mshortcuts[] = { /* button mask string */ - { Button4, XK_ANY_MOD, "\031" }, - { Button5, XK_ANY_MOD, "\005" }, + { Button4, XK_NO_MOD, "\031" }, + { Button5, XK_NO_MOD, "\005" }, +}; + +static MouseKey mkeys[] = { + /* button mask function argument */ + { Button4, ShiftMask, kscrollup, {.i = 1} }, + { Button5, ShiftMask, kscrolldown, {.i = 1} }, }; /* Internal keyboard shortcuts. */ @@ -157,6 +164,8 @@ static Shortcut shortcuts[] = { { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} }, { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} }, { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; /* diff --git a/config.h b/config.h new file mode 100644 index 0000000..b5812de --- /dev/null +++ b/config.h @@ -0,0 +1,426 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static int borderpx = 2; +#define histsize 20000 + +/* + * 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"; +static char *utmp = NULL; +static char stty_args[] = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +static 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: " `'\"()[]{}" + */ +static char worddelimiters[] = " "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +static 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 */ +static char termname[] = "st-256color"; + +static unsigned int tabspaces = 4; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "#073642", + "#dc322f", + "#859900", + "#b58900", + "#268bd2", + "#d33682", + "#2aa198", + "#eee8d5", + + /* 8 bright colors */ + "#002b36", + "#cb4b16", + "#586e75", + "#657b83", + "#839496", + "#6c71c4", + "#93a1a1", + "#fdf6e3", + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#cccccc", +}; + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +static unsigned int defaultfg = 11; +static unsigned int defaultbg = 8; +static unsigned int defaultcs = 14; +static unsigned int defaultrcs = 257; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Colors used, when the specific fg == defaultfg. So in reverse mode this + * will reverse too. Another logic would only make the simple feature too + * complex. + */ +static unsigned int defaultitalic = 11; +static unsigned int defaultunderline = 7; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* button mask string */ + { Button4, XK_NO_MOD, "\031" }, + { Button5, XK_NO_MOD, "\005" }, +}; + +static MouseKey mkeys[] = { + /* button mask function argument */ + { Button4, ShiftMask, kscrollup, {.i = 1} }, + { Button5, ShiftMask, kscrolldown, {.i = 1} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { MODKEY|ShiftMask, XK_Prior, xzoom, {.f = +1} }, + { MODKEY|ShiftMask, XK_Next, xzoom, {.f = -1} }, + { MODKEY|ShiftMask, XK_Home, xzoomreset, {.f = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { MODKEY|ShiftMask, XK_Insert, clippaste, {.i = 0} }, + { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} }, + { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} }, + { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -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 + * crlf value + * * 0: no value + * * > 0: crlf mode is enabled + * * < 0: crlf mode is disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * Override mouse-select while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forceselmod = ShiftMask; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor crlf */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1, 0}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1, 0}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1, 0}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1, 0}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0, -1}, + { XK_KP_Enter, XK_ANY_MOD, "\r\n", -1, 0, +1}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1, 0}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1, 0}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1, 0}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1, 0}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1, 0}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1, 0}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1, 0}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1, 0}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0, -1}, + { XK_Return, Mod1Mask, "\033\r\n", 0, 0, +1}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0, -1}, + { XK_Return, XK_ANY_MOD, "\r\n", 0, 0, +1}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1, 0}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1, 0}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1, 0}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1, 0}, + { XK_End, ControlMask, "\033[J", -1, 0, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 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, +}; + @@ -85,6 +85,8 @@ char *argv0; #define TRUERED(x) (((x) & 0xff0000) >> 8) #define TRUEGREEN(x) (((x) & 0xff00)) #define TRUEBLUE(x) (((x) & 0xff) << 8) +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - term.scr \ + + histsize + 1) % histsize] : term.line[(y) - term.scr]) enum glyph_attribute { @@ -227,26 +229,6 @@ typedef struct { int narg; /* nb of args */ } STREscape; -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - TCursor c; /* cursor */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int numlock; /* lock numbers in keyboard */ - int *tabs; -} Term; - /* Purely graphic info */ typedef struct { Display *dpy; @@ -317,6 +299,13 @@ typedef union { } Arg; typedef struct { + uint b; + uint mask; + void (*func)(const Arg *); + const Arg arg; +} MouseKey; + +typedef struct { uint mod; KeySym keysym; void (*func)(const Arg *); @@ -326,6 +315,8 @@ typedef struct { /* function definitions used in config.h */ static void clipcopy(const Arg *); static void clippaste(const Arg *); +static void kscrolldown(const Arg *); +static void kscrollup(const Arg *); static void numlock(const Arg *); static void selpaste(const Arg *); static void xzoom(const Arg *); @@ -359,6 +350,29 @@ typedef struct { GC gc; } DC; +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + Line hist[histsize]; /* history buffer */ + int histi; /* history index */ + int scr; /* scroll back */ + int *dirty; /* dirtyness of lines */ + XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + TCursor c; /* cursor */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int numlock; /* lock numbers in keyboard */ + int *tabs; +} Term; + static void die(const char *, ...); static void draw(void); static void redraw(void); @@ -398,8 +412,8 @@ static void tputtab(int); static void tputc(Rune); static void treset(void); static void tresize(int, int); -static void tscrollup(int, int); -static void tscrolldown(int, int); +static void tscrollup(int, int, int); +static void tscrolldown(int, int, int); static void tsetattr(int *, int); static void tsetchar(Rune, Glyph *, int, int); static void tsetscroll(int, int); @@ -730,10 +744,10 @@ tlinelen(int y) { int i = term.col; - if (term.line[y][i - 1].mode & ATTR_WRAP) + if (TLINE(y)[i - 1].mode & ATTR_WRAP) return i; - while (i > 0 && term.line[y][i - 1].u == ' ') + while (i > 0 && TLINE(y)[i - 1].u == ' ') --i; return i; @@ -795,7 +809,7 @@ selsnap(int *x, int *y, int direction) * Snap around if the word wraps around at the end or * beginning of a line. */ - prevgp = &term.line[*y][*x]; + prevgp = &TLINE(*y)[*x]; prevdelim = ISDELIM(prevgp->u); for (;;) { newx = *x + direction; @@ -810,14 +824,14 @@ selsnap(int *x, int *y, int direction) yt = *y, xt = *x; else yt = newy, xt = newx; - if (!(term.line[yt][xt].mode & ATTR_WRAP)) + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) break; } if (newx >= tlinelen(newy)) break; - gp = &term.line[newy][newx]; + gp = &TLINE(newy)[newx]; delim = ISDELIM(gp->u); if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || (delim && gp->u != prevgp->u))) @@ -838,14 +852,14 @@ selsnap(int *x, int *y, int direction) *x = (direction < 0) ? 0 : term.col - 1; if (direction < 0) { for (; *y > 0; *y += direction) { - if (!(term.line[*y-1][term.col-1].mode + if (!(TLINE(*y-1)[term.col-1].mode & ATTR_WRAP)) { break; } } } else if (direction > 0) { for (; *y < term.row-1; *y += direction) { - if (!(term.line[*y][term.col-1].mode + if (!(TLINE(*y)[term.col-1].mode & ATTR_WRAP)) { break; } @@ -945,6 +959,7 @@ bpress(XEvent *e) { struct timespec now; MouseShortcut *ms; + MouseKey *mk; if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); @@ -959,6 +974,14 @@ bpress(XEvent *e) } } + for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) { + if (e->xbutton.button == mk->b + && match(mk->mask, e->xbutton.state)) { + mk->func(&mk->arg); + return; + } + } + if (e->xbutton.button == Button1) { clock_gettime(CLOCK_MONOTONIC, &now); @@ -1011,13 +1034,13 @@ getsel(void) } if (sel.type == SEL_RECTANGULAR) { - gp = &term.line[y][sel.nb.x]; + gp = &TLINE(y)[sel.nb.x]; lastx = sel.ne.x; } else { - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } - last = &term.line[y][MIN(lastx, linelen-1)]; + last = &TLINE(y)[MIN(lastx, linelen-1)]; while (last >= gp && last->u == ' ') --last; @@ -1490,6 +1513,9 @@ ttyread(void) /* keep any uncomplete utf8 char for the next call */ memmove(buf, ptr, buflen); + if (term.scr > 0 && term.scr < histsize-1) + term.scr++; + return ret; } @@ -1499,6 +1525,9 @@ ttywrite(const char *s, size_t n) fd_set wfd, rfd; ssize_t r; size_t lim = 256; + Arg arg = (Arg){ .i = term.scr }; + + kscrolldown(&arg); /* * Remember that we are using a pty, which might be a modem line. @@ -1690,13 +1719,53 @@ tswapscreen(void) } void -tscrolldown(int orig, int n) +kscrolldown(const Arg* a) +{ + int n = a->i; + + if (n < 0) + n = term.row + n; + + if (n > term.scr) + n = term.scr; + + if (term.scr > 0) { + term.scr -= n; + selscroll(0, -n); + tfulldirt(); + } +} + +void +kscrollup(const Arg* a) +{ + int n = a->i; + + if (n < 0) + n = term.row + n; + + if (term.scr <= histsize - n) { + term.scr += n; + selscroll(0, n); + tfulldirt(); + } +} + +void +tscrolldown(int orig, int n, int copyhist) { int i; Line temp; LIMIT(n, 0, term.bot-orig+1); + if (copyhist) { + term.histi = (term.histi - 1 + histsize) % histsize; + temp = term.hist[term.histi]; + term.hist[term.histi] = term.line[term.bot]; + term.line[term.bot] = temp; + } + tsetdirt(orig, term.bot-n); tclearregion(0, term.bot-n+1, term.col-1, term.bot); @@ -1710,13 +1779,20 @@ tscrolldown(int orig, int n) } void -tscrollup(int orig, int n) +tscrollup(int orig, int n, int copyhist) { int i; Line temp; LIMIT(n, 0, term.bot-orig+1); + if (copyhist) { + term.histi = (term.histi + 1) % histsize; + temp = term.hist[term.histi]; + term.hist[term.histi] = term.line[orig]; + term.line[orig] = temp; + } + tclearregion(0, orig, term.col-1, orig+n-1); tsetdirt(orig+n, term.bot); @@ -1765,7 +1841,7 @@ tnewline(int first_col) int y = term.c.y; if (y == term.bot) { - tscrollup(term.top, 1); + tscrollup(term.top, 1, 1); } else { y++; } @@ -1930,14 +2006,14 @@ void tinsertblankline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); + tscrolldown(term.c.y, n, 0); } void tdeleteline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); + tscrollup(term.c.y, n, 0); } int32_t @@ -2371,11 +2447,11 @@ csihandle(void) break; case 'S': /* SU -- Scroll <n> line up */ DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); + tscrollup(term.top, csiescseq.arg[0], 0); break; case 'T': /* SD -- Scroll <n> line down */ DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); + tscrolldown(term.top, csiescseq.arg[0], 0); break; case 'L': /* IL -- Insert <n> blank lines */ DEFAULT(csiescseq.arg[0], 1); @@ -2871,7 +2947,7 @@ eschandle(uchar ascii) return 0; case 'D': /* IND -- Linefeed */ if (term.c.y == term.bot) { - tscrollup(term.top, 1); + tscrollup(term.top, 1, 1); } else { tmoveto(term.c.x, term.c.y+1); } @@ -2884,7 +2960,7 @@ eschandle(uchar ascii) break; case 'M': /* RI -- Reverse index */ if (term.c.y == term.top) { - tscrolldown(term.top, 1); + tscrolldown(term.top, 1, 1); } else { tmoveto(term.c.x, term.c.y-1); } @@ -3047,7 +3123,7 @@ tputc(Rune u) void tresize(int col, int row) { - int i; + int i, j; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); int *bp; @@ -3087,6 +3163,14 @@ tresize(int col, int row) term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + for (i = 0; i < histsize; i++) { + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); + for (j = mincol; j < col; j++) { + term.hist[i][j] = term.c.attr; + term.hist[i][j].u = ' '; + } + } + /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); @@ -3726,7 +3810,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Change basic system colors [0-7] to bright system colors [8-15] */ if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; + fg = &dc.col[base.fg]; if (IS_SET(MODE_REVERSE)) { if (fg == &dc.col[defaultfg]) { @@ -3755,9 +3839,14 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i } if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; + if (bg == fg) { + bg = &dc.col[defaultfg]; + fg = &dc.col[defaultbg]; + } else { + temp = fg; + fg = bg; + bg = temp; + } } if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { @@ -3984,11 +4073,11 @@ drawregion(int x1, int y1, int x2, int y2) term.dirty[y] = 0; specs = term.specbuf; - numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y); + numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y); i = ox = 0; for (x = x1; x < x2 && i < numspecs; x++) { - new = term.line[y][x]; + new = TLINE(y)[x]; if (new.mode == ATTR_WDUMMY) continue; if (ena_sel && selected(x, y)) @@ -4008,7 +4097,8 @@ drawregion(int x1, int y1, int x2, int y2) if (i > 0) xdrawglyphfontspecs(specs, base, i, ox, y); } - xdrawcursor(); + if (term.scr == 0) + xdrawcursor(); } void |