commit 815c964c08a7d288ac28d5f47e167c7a1e7e0418
parent d3a23b6168a830fcb69d3e2a56aacfecb73a8dbd
Author: Matsuda Kenji <contact2655@matsudakenji.xyz>
Date: Sat, 30 Jul 2022 10:12:45 +0900
patch colorschemes
Diffstat:
M | config.def.h | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
D | config.def.h.orig | | | 480 | ------------------------------------------------------------------------------- |
D | config.diff | | | 17 | ----------------- |
M | config.h | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
A | st-colorschemes-0.8.5.diff | | | 306 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | st.c | | | 22 | ++++++++++++++++++++++ |
M | st.h | | | 2 | ++ |
M | x.c | | | 52 | +++++++++++++++++++++++++++++++++++++++++++++++++++- |
D | x.c.orig | | | 2197 | ------------------------------------------------------------------------------- |
9 files changed, 551 insertions(+), 2761 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -99,46 +99,87 @@ char *termname = "st-256color";
*/
unsigned int tabspaces = 8;
-/* Terminal colors (16 first used in escape sequence) */
-static const char *colorname[] = {
- /* 8 normal colors */
- "black",
- "red3",
- "green3",
- "yellow3",
- "blue2",
- "magenta3",
- "cyan3",
- "gray90",
-
- /* 8 bright colors */
- "gray50",
- "red",
- "green",
- "yellow",
- "#5c5cff",
- "magenta",
- "cyan",
- "white",
-
- [255] = 0,
-
- /* more colors can be added after 255 to use with DefaultXX */
- "#cccccc",
- "#555555",
- "gray90", /* default foreground colour */
- "black", /* default background colour */
+typedef struct {
+ const char* const colors[258]; /* terminal colors */
+ unsigned int fg; /* foreground */
+ unsigned int bg; /* background */
+ unsigned int cs; /* cursor */
+ unsigned int rcs; /* reverse cursor */
+} ColorScheme;
+/*
+ * Terminal colors (16 first used in escape sequence,
+ * 2 last for custom cursor color),
+ * foreground, background, cursor, reverse cursor
+ */
+static const ColorScheme schemes[] = {
+ // st (dark)
+ {{"black", "red3", "green3", "yellow3",
+ "blue2", "magenta3", "cyan3", "gray90",
+ "gray50", "red", "green", "yellow",
+ "#5c5cff", "magenta", "cyan", "white",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // Alacritty (dark)
+ {{"#1d1f21", "#cc6666", "#b5bd68", "#f0c674",
+ "#81a2be", "#b294bb", "#8abeb7", "#c5c8c6",
+ "#666666", "#d54e53", "#b9ca4a", "#e7c547",
+ "#7aa6da", "#c397d8", "#70c0b1", "#eaeaea",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // One Half dark
+ {{"#282c34", "#e06c75", "#98c379", "#e5c07b",
+ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
+ "#282c34", "#e06c75", "#98c379", "#e5c07b",
+ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // One Half light
+ {{"#fafafa", "#e45649", "#50a14f", "#c18401",
+ "#0184bc", "#a626a4", "#0997b3", "#383a42",
+ "#fafafa", "#e45649", "#50a14f", "#c18401",
+ "#0184bc", "#a626a4", "#0997b3", "#383a42",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // Solarized dark
+ {{"#073642", "#dc322f", "#859900", "#b58900",
+ "#268bd2", "#d33682", "#2aa198", "#eee8d5",
+ "#002b36", "#cb4b16", "#586e75", "#657b83",
+ "#839496", "#6c71c4", "#93a1a1", "#fdf6e3",
+ [256]="#93a1a1", "#fdf6e3"}, 12, 8, 256, 257},
+
+ // Solarized light
+ {{"#eee8d5", "#dc322f", "#859900", "#b58900",
+ "#268bd2", "#d33682", "#2aa198", "#073642",
+ "#fdf6e3", "#cb4b16", "#93a1a1", "#839496",
+ "#657b83", "#6c71c4", "#586e75", "#002b36",
+ [256]="#586e75", "#002b36"}, 12, 8, 256, 257},
+
+ // Gruvbox dark
+ {{"#282828", "#cc241d", "#98971a", "#d79921",
+ "#458588", "#b16286", "#689d6a", "#a89984",
+ "#928374", "#fb4934", "#b8bb26", "#fabd2f",
+ "#83a598", "#d3869b", "#8ec07c", "#ebdbb2",
+ [256]="#ebdbb2", "#555555"}, 15, 0, 256, 257},
+
+ // Gruvbox light
+ {{"#fbf1c7", "#cc241d", "#98971a", "#d79921",
+ "#458588", "#b16286", "#689d6a", "#7c6f64",
+ "#928374", "#9d0006", "#79740e", "#b57614",
+ "#076678", "#8f3f71", "#427b58", "#3c3836",
+ [256]="#3c3836", "#555555"}, 15, 0, 256, 257},
};
+static const char * const * colorname;
+int colorscheme = 0;
/*
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
-unsigned int defaultfg = 258;
-unsigned int defaultbg = 259;
-unsigned int defaultcs = 256;
-static unsigned int defaultrcs = 257;
+unsigned int defaultfg;
+unsigned int defaultbg;
+unsigned int defaultcs;
+static unsigned int defaultrcs;
/*
* Default shape of cursor
@@ -207,6 +248,17 @@ static Shortcut shortcuts[] = {
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
+ { MODKEY, XK_1, selectscheme, {.i = 0} },
+ { MODKEY, XK_2, selectscheme, {.i = 1} },
+ { MODKEY, XK_3, selectscheme, {.i = 2} },
+ { MODKEY, XK_4, selectscheme, {.i = 3} },
+ { MODKEY, XK_5, selectscheme, {.i = 4} },
+ { MODKEY, XK_6, selectscheme, {.i = 5} },
+ { MODKEY, XK_7, selectscheme, {.i = 6} },
+ { MODKEY, XK_8, selectscheme, {.i = 7} },
+ { MODKEY, XK_9, selectscheme, {.i = 8} },
+ { MODKEY, XK_0, nextscheme, {.i = +1} },
+ { MODKEY|ControlMask, XK_0, nextscheme, {.i = -1} },
};
/*
diff --git a/config.def.h.orig b/config.def.h.orig
@@ -1,480 +0,0 @@
-/* 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";
-/* Spare fonts */
-static char *font2[] = {
-/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */
-/* "Hack Nerd Font Mono:pixelsize=11: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: scroll and/or utmp
- * 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;
-/* scroll program: to enable use a string like "scroll" */
-char *scroll = 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;
-
-/* allow certain non-interactive (insecure) window operations such as:
- setting the clipboard text */
-int allowwindowops = 0;
-
-/*
- * draw latency range in ms - from new content/keypress/etc until drawing.
- * within this range, st draws when content stops arriving (idle). mostly it's
- * near minlatency, but it waits longer for slow updates to avoid partial draw.
- * low minlatency will tear/flicker more, as it can "detect" idle too early.
- */
-static double minlatency = 8;
-static double maxlatency = 33;
-
-/*
- * blinking timeout (set to 0 to disable blinking) for the terminal blinking
- * attribute.
- */
-static unsigned int blinktimeout = 800;
-
-/*
- * thickness of underline and bar cursors
- */
-static unsigned int cursorthickness = 2;
-
-/*
- * bell volume. It must be a value between -100 and 100. Use 0 for disabling
- * it
- */
-static int bellvolume = 0;
-
-/* default TERM value */
-char *termname = "st-256color";
-
-/*
- * spaces per tab
- *
- * When you are changing this value, don't forget to adapt the »it« value in
- * the st.info and appropriately install the st.info in the environment where
- * you use this st version.
- *
- * it#$tabspaces,
- *
- * Secondly make sure your kernel is not expanding tabs. When running `stty
- * -a` »tab0« should appear. You can tell the terminal to not expand tabs by
- * running following command:
- *
- * stty tabs
- */
-unsigned int tabspaces = 8;
-
-/* Terminal colors (16 first used in escape sequence) */
-static const char *colorname[] = {
- /* 8 normal colors */
- "black",
- "red3",
- "green3",
- "yellow3",
- "blue2",
- "magenta3",
- "cyan3",
- "gray90",
-
- /* 8 bright colors */
- "gray50",
- "red",
- "green",
- "yellow",
- "#5c5cff",
- "magenta",
- "cyan",
- "white",
-
- [255] = 0,
-
- /* more colors can be added after 255 to use with DefaultXX */
- "#cccccc",
- "#555555",
- "gray90", /* default foreground colour */
- "black", /* default background colour */
-};
-
-
-/*
- * Default colors (colorname index)
- * foreground, background, cursor, reverse cursor
- */
-unsigned int defaultfg = 258;
-unsigned int defaultbg = 259;
-unsigned int defaultcs = 256;
-static unsigned int defaultrcs = 257;
-
-/*
- * Default shape of cursor
- * 2: Block ("█")
- * 4: Underline ("_")
- * 6: Bar ("|")
- * 7: Snowman ("☃")
- */
-static unsigned int cursorshape = 2;
-
-/*
- * Default columns and rows numbers
- */
-
-static unsigned int cols = 80;
-static unsigned int rows = 24;
-
-/*
- * Default colour and shape of the mouse cursor
- */
-static unsigned int mouseshape = XC_xterm;
-static unsigned int mousefg = 7;
-static unsigned int mousebg = 0;
-
-/*
- * Color used to display font attributes when fontconfig selected a font which
- * doesn't match the ones requested.
- */
-static unsigned int defaultattr = 11;
-
-/*
- * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set).
- * Note that if you want to use ShiftMask with selmasks, set this to an other
- * modifier, set to 0 to not use it.
- */
-static uint forcemousemod = ShiftMask;
-
-/*
- * Internal mouse shortcuts.
- * Beware that overloading Button1 will disable the selection.
- */
-static MouseShortcut mshortcuts[] = {
- /* mask button function argument release */
- { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
- { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
- { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
- { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
- { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
-};
-
-/* Internal keyboard shortcuts. */
-#define MODKEY Mod1Mask
-#define TERMMOD (ControlMask|ShiftMask)
-
-static Shortcut shortcuts[] = {
- /* mask keysym function argument */
- { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} },
- { ControlMask, XK_Print, toggleprinter, {.i = 0} },
- { ShiftMask, XK_Print, printscreen, {.i = 0} },
- { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
- { TERMMOD, XK_Prior, zoom, {.f = +1} },
- { TERMMOD, XK_Next, zoom, {.f = -1} },
- { TERMMOD, XK_Home, zoomreset, {.f = 0} },
- { TERMMOD, XK_C, clipcopy, {.i = 0} },
- { TERMMOD, XK_V, clippaste, {.i = 0} },
- { TERMMOD, XK_Y, selpaste, {.i = 0} },
- { ShiftMask, XK_Insert, selpaste, {.i = 0} },
- { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
-};
-
-/*
- * Special keys (change & recompile st.info accordingly)
- *
- * Mask value:
- * * Use XK_ANY_MOD to match the key no matter modifiers state
- * * Use XK_NO_MOD to match the key alone (no modifiers)
- * appkey value:
- * * 0: no value
- * * > 0: keypad application mode enabled
- * * = 2: term.numlock = 1
- * * < 0: keypad application mode disabled
- * appcursor value:
- * * 0: no value
- * * > 0: cursor application mode enabled
- * * < 0: cursor application mode disabled
- *
- * Be careful with the order of the definitions because st searches in
- * this table sequentially, so any XK_ANY_MOD must be in the last
- * position for a key.
- */
-
-/*
- * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
- * to be mapped below, add them to this array.
- */
-static KeySym mappedkeys[] = { -1 };
-
-/*
- * State bits to ignore when matching key or button events. By default,
- * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
- */
-static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;
-
-/*
- * This is the huge key array which defines all compatibility to the Linux
- * world. Please decide about changes wisely.
- */
-static Key key[] = {
- /* keysym mask string appkey appcursor */
- { XK_KP_Home, ShiftMask, "\033[2J", 0, -1},
- { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1},
- { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1},
- { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1},
- { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0},
- { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1},
- { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1},
- { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0},
- { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1},
- { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1},
- { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0},
- { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1},
- { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1},
- { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0},
- { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1},
- { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1},
- { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0},
- { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
- { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0},
- { XK_KP_End, ControlMask, "\033[J", -1, 0},
- { XK_KP_End, ControlMask, "\033[1;5F", +1, 0},
- { XK_KP_End, ShiftMask, "\033[K", -1, 0},
- { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0},
- { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0},
- { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0},
- { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0},
- { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0},
- { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0},
- { XK_KP_Insert, ControlMask, "\033[L", -1, 0},
- { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0},
- { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
- { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
- { XK_KP_Delete, ControlMask, "\033[M", -1, 0},
- { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
- { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
- { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
- { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
- { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
- { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
- { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
- { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0},
- { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0},
- { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0},
- { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0},
- { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0},
- { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0},
- { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0},
- { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0},
- { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0},
- { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0},
- { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0},
- { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0},
- { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0},
- { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0},
- { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0},
- { XK_Up, ShiftMask, "\033[1;2A", 0, 0},
- { XK_Up, Mod1Mask, "\033[1;3A", 0, 0},
- { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0},
- { XK_Up, ControlMask, "\033[1;5A", 0, 0},
- { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0},
- { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0},
- { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0},
- { XK_Up, XK_ANY_MOD, "\033[A", 0, -1},
- { XK_Up, XK_ANY_MOD, "\033OA", 0, +1},
- { XK_Down, ShiftMask, "\033[1;2B", 0, 0},
- { XK_Down, Mod1Mask, "\033[1;3B", 0, 0},
- { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0},
- { XK_Down, ControlMask, "\033[1;5B", 0, 0},
- { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0},
- { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0},
- { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0},
- { XK_Down, XK_ANY_MOD, "\033[B", 0, -1},
- { XK_Down, XK_ANY_MOD, "\033OB", 0, +1},
- { XK_Left, ShiftMask, "\033[1;2D", 0, 0},
- { XK_Left, Mod1Mask, "\033[1;3D", 0, 0},
- { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0},
- { XK_Left, ControlMask, "\033[1;5D", 0, 0},
- { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0},
- { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0},
- { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0},
- { XK_Left, XK_ANY_MOD, "\033[D", 0, -1},
- { XK_Left, XK_ANY_MOD, "\033OD", 0, +1},
- { XK_Right, ShiftMask, "\033[1;2C", 0, 0},
- { XK_Right, Mod1Mask, "\033[1;3C", 0, 0},
- { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0},
- { XK_Right, ControlMask, "\033[1;5C", 0, 0},
- { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0},
- { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0},
- { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0},
- { XK_Right, XK_ANY_MOD, "\033[C", 0, -1},
- { XK_Right, XK_ANY_MOD, "\033OC", 0, +1},
- { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0},
- { XK_Return, Mod1Mask, "\033\r", 0, 0},
- { XK_Return, XK_ANY_MOD, "\r", 0, 0},
- { XK_Insert, ShiftMask, "\033[4l", -1, 0},
- { XK_Insert, ShiftMask, "\033[2;2~", +1, 0},
- { XK_Insert, ControlMask, "\033[L", -1, 0},
- { XK_Insert, ControlMask, "\033[2;5~", +1, 0},
- { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
- { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
- { XK_Delete, ControlMask, "\033[M", -1, 0},
- { XK_Delete, ControlMask, "\033[3;5~", +1, 0},
- { XK_Delete, ShiftMask, "\033[2K", -1, 0},
- { XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
- { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
- { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
- { XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
- { XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
- { XK_Home, ShiftMask, "\033[2J", 0, -1},
- { XK_Home, ShiftMask, "\033[1;2H", 0, +1},
- { XK_Home, XK_ANY_MOD, "\033[H", 0, -1},
- { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1},
- { XK_End, ControlMask, "\033[J", -1, 0},
- { XK_End, ControlMask, "\033[1;5F", +1, 0},
- { XK_End, ShiftMask, "\033[K", -1, 0},
- { XK_End, ShiftMask, "\033[1;2F", +1, 0},
- { XK_End, XK_ANY_MOD, "\033[4~", 0, 0},
- { XK_Prior, ControlMask, "\033[5;5~", 0, 0},
- { XK_Prior, ShiftMask, "\033[5;2~", 0, 0},
- { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
- { XK_Next, ControlMask, "\033[6;5~", 0, 0},
- { XK_Next, ShiftMask, "\033[6;2~", 0, 0},
- { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0},
- { XK_F1, XK_NO_MOD, "\033OP" , 0, 0},
- { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0},
- { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0},
- { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0},
- { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0},
- { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0},
- { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0},
- { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0},
- { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0},
- { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0},
- { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0},
- { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0},
- { XK_F3, XK_NO_MOD, "\033OR" , 0, 0},
- { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0},
- { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0},
- { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0},
- { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0},
- { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0},
- { XK_F4, XK_NO_MOD, "\033OS" , 0, 0},
- { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0},
- { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0},
- { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0},
- { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0},
- { XK_F5, XK_NO_MOD, "\033[15~", 0, 0},
- { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0},
- { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0},
- { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0},
- { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0},
- { XK_F6, XK_NO_MOD, "\033[17~", 0, 0},
- { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0},
- { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0},
- { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0},
- { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0},
- { XK_F7, XK_NO_MOD, "\033[18~", 0, 0},
- { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0},
- { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0},
- { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0},
- { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0},
- { XK_F8, XK_NO_MOD, "\033[19~", 0, 0},
- { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0},
- { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0},
- { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0},
- { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0},
- { XK_F9, XK_NO_MOD, "\033[20~", 0, 0},
- { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0},
- { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0},
- { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0},
- { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0},
- { XK_F10, XK_NO_MOD, "\033[21~", 0, 0},
- { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0},
- { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0},
- { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0},
- { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0},
- { XK_F11, XK_NO_MOD, "\033[23~", 0, 0},
- { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0},
- { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0},
- { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0},
- { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0},
- { XK_F12, XK_NO_MOD, "\033[24~", 0, 0},
- { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0},
- { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0},
- { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0},
- { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0},
- { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0},
- { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0},
- { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0},
- { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0},
- { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0},
- { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0},
- { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0},
- { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0},
- { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0},
- { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0},
- { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0},
- { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0},
- { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0},
- { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0},
- { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0},
- { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0},
- { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0},
- { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0},
- { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0},
- { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0},
- { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0},
- { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0},
- { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0},
-};
-
-/*
- * Selection types' masks.
- * Use the same masks as usual.
- * Button1Mask is always unset, to make masks match between ButtonPress.
- * ButtonRelease and MotionNotify.
- * If no match is found, regular selection is used.
- */
-static uint selmasks[] = {
- [SEL_RECTANGULAR] = Mod1Mask,
-};
-
-/*
- * Printable characters in ASCII, used to estimate the advance width
- * of single wide characters.
- */
-static char ascii_printable[] =
- " !\"#$%&'()*+,-./0123456789:;<=>?"
- "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
- "`abcdefghijklmnopqrstuvwxyz{|}~";
diff --git a/config.diff b/config.diff
@@ -1,17 +0,0 @@
---- config.def.h Mon May 2 15:31:46 2022
-+++ config.h Tue Jun 14 07:22:25 2022
-@@ -5,11 +5,11 @@
- *
- * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
- */
--static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
-+static char *font = "DejaVu Sans Mono:pixelsize=12:antialias=true:autohint=true";
- /* Spare fonts */
- static char *font2[] = {
--/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */
--/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */
-+ "Noto Color Emoji:pixelsize=12:antialias=true:autohint=true",
-+ "Noto Serif CJK JP:pixelsize=12:antialias=true:autohint=true",
- };
-
- static int borderpx = 2;
diff --git a/config.h b/config.h
@@ -99,46 +99,87 @@ char *termname = "st-256color";
*/
unsigned int tabspaces = 8;
-/* Terminal colors (16 first used in escape sequence) */
-static const char *colorname[] = {
- /* 8 normal colors */
- "black",
- "red3",
- "green3",
- "yellow3",
- "blue2",
- "magenta3",
- "cyan3",
- "gray90",
-
- /* 8 bright colors */
- "gray50",
- "red",
- "green",
- "yellow",
- "#5c5cff",
- "magenta",
- "cyan",
- "white",
-
- [255] = 0,
-
- /* more colors can be added after 255 to use with DefaultXX */
- "#cccccc",
- "#555555",
- "gray90", /* default foreground colour */
- "black", /* default background colour */
+typedef struct {
+ const char* const colors[258]; /* terminal colors */
+ unsigned int fg; /* foreground */
+ unsigned int bg; /* background */
+ unsigned int cs; /* cursor */
+ unsigned int rcs; /* reverse cursor */
+} ColorScheme;
+/*
+ * Terminal colors (16 first used in escape sequence,
+ * 2 last for custom cursor color),
+ * foreground, background, cursor, reverse cursor
+ */
+static const ColorScheme schemes[] = {
+ // st (dark)
+ {{"black", "red3", "green3", "yellow3",
+ "blue2", "magenta3", "cyan3", "gray90",
+ "gray50", "red", "green", "yellow",
+ "#5c5cff", "magenta", "cyan", "white",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // Alacritty (dark)
+ {{"#1d1f21", "#cc6666", "#b5bd68", "#f0c674",
+ "#81a2be", "#b294bb", "#8abeb7", "#c5c8c6",
+ "#666666", "#d54e53", "#b9ca4a", "#e7c547",
+ "#7aa6da", "#c397d8", "#70c0b1", "#eaeaea",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // One Half dark
+ {{"#282c34", "#e06c75", "#98c379", "#e5c07b",
+ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
+ "#282c34", "#e06c75", "#98c379", "#e5c07b",
+ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // One Half light
+ {{"#fafafa", "#e45649", "#50a14f", "#c18401",
+ "#0184bc", "#a626a4", "#0997b3", "#383a42",
+ "#fafafa", "#e45649", "#50a14f", "#c18401",
+ "#0184bc", "#a626a4", "#0997b3", "#383a42",
+ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
+
+ // Solarized dark
+ {{"#073642", "#dc322f", "#859900", "#b58900",
+ "#268bd2", "#d33682", "#2aa198", "#eee8d5",
+ "#002b36", "#cb4b16", "#586e75", "#657b83",
+ "#839496", "#6c71c4", "#93a1a1", "#fdf6e3",
+ [256]="#93a1a1", "#fdf6e3"}, 12, 8, 256, 257},
+
+ // Solarized light
+ {{"#eee8d5", "#dc322f", "#859900", "#b58900",
+ "#268bd2", "#d33682", "#2aa198", "#073642",
+ "#fdf6e3", "#cb4b16", "#93a1a1", "#839496",
+ "#657b83", "#6c71c4", "#586e75", "#002b36",
+ [256]="#586e75", "#002b36"}, 12, 8, 256, 257},
+
+ // Gruvbox dark
+ {{"#282828", "#cc241d", "#98971a", "#d79921",
+ "#458588", "#b16286", "#689d6a", "#a89984",
+ "#928374", "#fb4934", "#b8bb26", "#fabd2f",
+ "#83a598", "#d3869b", "#8ec07c", "#ebdbb2",
+ [256]="#ebdbb2", "#555555"}, 15, 0, 256, 257},
+
+ // Gruvbox light
+ {{"#fbf1c7", "#cc241d", "#98971a", "#d79921",
+ "#458588", "#b16286", "#689d6a", "#7c6f64",
+ "#928374", "#9d0006", "#79740e", "#b57614",
+ "#076678", "#8f3f71", "#427b58", "#3c3836",
+ [256]="#3c3836", "#555555"}, 15, 0, 256, 257},
};
+static const char * const * colorname;
+int colorscheme = 0;
/*
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
-unsigned int defaultfg = 258;
-unsigned int defaultbg = 259;
-unsigned int defaultcs = 256;
-static unsigned int defaultrcs = 257;
+unsigned int defaultfg;
+unsigned int defaultbg;
+unsigned int defaultcs;
+static unsigned int defaultrcs;
/*
* Default shape of cursor
@@ -207,6 +248,17 @@ static Shortcut shortcuts[] = {
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
+ { MODKEY, XK_1, selectscheme, {.i = 0} },
+ { MODKEY, XK_2, selectscheme, {.i = 1} },
+ { MODKEY, XK_3, selectscheme, {.i = 2} },
+ { MODKEY, XK_4, selectscheme, {.i = 3} },
+ { MODKEY, XK_5, selectscheme, {.i = 4} },
+ { MODKEY, XK_6, selectscheme, {.i = 5} },
+ { MODKEY, XK_7, selectscheme, {.i = 6} },
+ { MODKEY, XK_8, selectscheme, {.i = 7} },
+ { MODKEY, XK_9, selectscheme, {.i = 8} },
+ { MODKEY, XK_0, nextscheme, {.i = +1} },
+ { MODKEY|ControlMask, XK_0, nextscheme, {.i = -1} },
};
/*
diff --git a/st-colorschemes-0.8.5.diff b/st-colorschemes-0.8.5.diff
@@ -0,0 +1,306 @@
+From 9bfbafa1e98c13c039bea4790941e51b3a8054b4 Mon Sep 17 00:00:00 2001
+From: Max Schillinger <maxschillinger@web.de>
+Date: Thu, 23 Jun 2022 21:58:37 +0200
+Subject: [PATCH] Add multiple color schemes and key bindings to change them
+
+This commits adds these color schemes:
+
+- the default (dark) st color scheme
+- the default (dark) alacritty color scheme
+- One Half (dark & light)
+- Solarized (dark & light)
+- Gruvbox (dark & light)
+
+Select one with Alt+1..8.
+Select the next one with Alt+0.
+Select the previous one with Ctrl+Alt+0.
+---
+ config.def.h | 118 +++++++++++++++++++++++++++++++++++++--------------
+ st.c | 22 ++++++++++
+ st.h | 2 +
+ x.c | 52 ++++++++++++++++++++++-
+ 4 files changed, 160 insertions(+), 34 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 91ab8ca..38777fe 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -93,46 +93,87 @@ char *termname = "st-256color";
+ */
+ unsigned int tabspaces = 8;
+
+-/* Terminal colors (16 first used in escape sequence) */
+-static const char *colorname[] = {
+- /* 8 normal colors */
+- "black",
+- "red3",
+- "green3",
+- "yellow3",
+- "blue2",
+- "magenta3",
+- "cyan3",
+- "gray90",
+-
+- /* 8 bright colors */
+- "gray50",
+- "red",
+- "green",
+- "yellow",
+- "#5c5cff",
+- "magenta",
+- "cyan",
+- "white",
+-
+- [255] = 0,
+-
+- /* more colors can be added after 255 to use with DefaultXX */
+- "#cccccc",
+- "#555555",
+- "gray90", /* default foreground colour */
+- "black", /* default background colour */
++typedef struct {
++ const char* const colors[258]; /* terminal colors */
++ unsigned int fg; /* foreground */
++ unsigned int bg; /* background */
++ unsigned int cs; /* cursor */
++ unsigned int rcs; /* reverse cursor */
++} ColorScheme;
++/*
++ * Terminal colors (16 first used in escape sequence,
++ * 2 last for custom cursor color),
++ * foreground, background, cursor, reverse cursor
++ */
++static const ColorScheme schemes[] = {
++ // st (dark)
++ {{"black", "red3", "green3", "yellow3",
++ "blue2", "magenta3", "cyan3", "gray90",
++ "gray50", "red", "green", "yellow",
++ "#5c5cff", "magenta", "cyan", "white",
++ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
++
++ // Alacritty (dark)
++ {{"#1d1f21", "#cc6666", "#b5bd68", "#f0c674",
++ "#81a2be", "#b294bb", "#8abeb7", "#c5c8c6",
++ "#666666", "#d54e53", "#b9ca4a", "#e7c547",
++ "#7aa6da", "#c397d8", "#70c0b1", "#eaeaea",
++ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
++
++ // One Half dark
++ {{"#282c34", "#e06c75", "#98c379", "#e5c07b",
++ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
++ "#282c34", "#e06c75", "#98c379", "#e5c07b",
++ "#61afef", "#c678dd", "#56b6c2", "#dcdfe4",
++ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
++
++ // One Half light
++ {{"#fafafa", "#e45649", "#50a14f", "#c18401",
++ "#0184bc", "#a626a4", "#0997b3", "#383a42",
++ "#fafafa", "#e45649", "#50a14f", "#c18401",
++ "#0184bc", "#a626a4", "#0997b3", "#383a42",
++ [256]="#cccccc", "#555555"}, 7, 0, 256, 257},
++
++ // Solarized dark
++ {{"#073642", "#dc322f", "#859900", "#b58900",
++ "#268bd2", "#d33682", "#2aa198", "#eee8d5",
++ "#002b36", "#cb4b16", "#586e75", "#657b83",
++ "#839496", "#6c71c4", "#93a1a1", "#fdf6e3",
++ [256]="#93a1a1", "#fdf6e3"}, 12, 8, 256, 257},
++
++ // Solarized light
++ {{"#eee8d5", "#dc322f", "#859900", "#b58900",
++ "#268bd2", "#d33682", "#2aa198", "#073642",
++ "#fdf6e3", "#cb4b16", "#93a1a1", "#839496",
++ "#657b83", "#6c71c4", "#586e75", "#002b36",
++ [256]="#586e75", "#002b36"}, 12, 8, 256, 257},
++
++ // Gruvbox dark
++ {{"#282828", "#cc241d", "#98971a", "#d79921",
++ "#458588", "#b16286", "#689d6a", "#a89984",
++ "#928374", "#fb4934", "#b8bb26", "#fabd2f",
++ "#83a598", "#d3869b", "#8ec07c", "#ebdbb2",
++ [256]="#ebdbb2", "#555555"}, 15, 0, 256, 257},
++
++ // Gruvbox light
++ {{"#fbf1c7", "#cc241d", "#98971a", "#d79921",
++ "#458588", "#b16286", "#689d6a", "#7c6f64",
++ "#928374", "#9d0006", "#79740e", "#b57614",
++ "#076678", "#8f3f71", "#427b58", "#3c3836",
++ [256]="#3c3836", "#555555"}, 15, 0, 256, 257},
+ };
+
++static const char * const * colorname;
++int colorscheme = 0;
+
+ /*
+ * Default colors (colorname index)
+ * foreground, background, cursor, reverse cursor
+ */
+-unsigned int defaultfg = 258;
+-unsigned int defaultbg = 259;
+-unsigned int defaultcs = 256;
+-static unsigned int defaultrcs = 257;
++unsigned int defaultfg;
++unsigned int defaultbg;
++unsigned int defaultcs;
++static unsigned int defaultrcs;
+
+ /*
+ * Default shape of cursor
+@@ -201,6 +242,17 @@ static Shortcut shortcuts[] = {
+ { TERMMOD, XK_Y, selpaste, {.i = 0} },
+ { ShiftMask, XK_Insert, selpaste, {.i = 0} },
+ { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
++ { MODKEY, XK_1, selectscheme, {.i = 0} },
++ { MODKEY, XK_2, selectscheme, {.i = 1} },
++ { MODKEY, XK_3, selectscheme, {.i = 2} },
++ { MODKEY, XK_4, selectscheme, {.i = 3} },
++ { MODKEY, XK_5, selectscheme, {.i = 4} },
++ { MODKEY, XK_6, selectscheme, {.i = 5} },
++ { MODKEY, XK_7, selectscheme, {.i = 6} },
++ { MODKEY, XK_8, selectscheme, {.i = 7} },
++ { MODKEY, XK_9, selectscheme, {.i = 8} },
++ { MODKEY, XK_0, nextscheme, {.i = +1} },
++ { MODKEY|ControlMask, XK_0, nextscheme, {.i = -1} },
+ };
+
+ /*
+diff --git a/st.c b/st.c
+index 51049ba..3ffe333 100644
+--- a/st.c
++++ b/st.c
+@@ -2196,6 +2196,28 @@ tstrsequence(uchar c)
+ term.esc |= ESC_STR;
+ }
+
++void
++tupdatebgcolor(int oldbg, int newbg)
++{
++ for (int y = 0; y < term.row; y++) {
++ for (int x = 0; x < term.col; x++) {
++ if (term.line[y][x].bg == oldbg)
++ term.line[y][x].bg = newbg;
++ }
++ }
++}
++
++void
++tupdatefgcolor(int oldfg, int newfg)
++{
++ for (int y = 0; y < term.row; y++) {
++ for (int x = 0; x < term.col; x++) {
++ if (term.line[y][x].fg == oldfg)
++ term.line[y][x].fg = newfg;
++ }
++ }
++}
++
+ void
+ tcontrolcode(uchar ascii)
+ {
+diff --git a/st.h b/st.h
+index 519b9bd..2700de5 100644
+--- a/st.h
++++ b/st.h
+@@ -90,6 +90,8 @@ int tattrset(int);
+ void tnew(int, int);
+ void tresize(int, int);
+ void tsetdirtattr(int);
++void tupdatebgcolor(int, int);
++void tupdatefgcolor(int, int);
+ void ttyhangup(void);
+ int ttynew(const char *, char *, const char *, char **);
+ size_t ttyread(void);
+diff --git a/x.c b/x.c
+index 8a16faa..bc0a48c 100644
+--- a/x.c
++++ b/x.c
+@@ -59,6 +59,8 @@ static void zoom(const Arg *);
+ static void zoomabs(const Arg *);
+ static void zoomreset(const Arg *);
+ static void ttysend(const Arg *);
++static void nextscheme(const Arg *);
++static void selectscheme(const Arg *);
+
+ /* config.h for applying patches and the configuration. */
+ #include "config.h"
+@@ -185,6 +187,7 @@ static void mousesel(XEvent *, int);
+ static void mousereport(XEvent *);
+ static char *kmap(KeySym, uint);
+ static int match(uint, uint);
++static void updatescheme(void);
+
+ static void run(void);
+ static void usage(void);
+@@ -785,7 +788,7 @@ xloadcols(void)
+ 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.collen = 258;
+ dc.col = xmalloc(dc.collen * sizeof(Color));
+ }
+
+@@ -2008,6 +2011,47 @@ usage(void)
+ " [stty_args ...]\n", argv0, argv0);
+ }
+
++void
++nextscheme(const Arg *arg)
++{
++ colorscheme += arg->i;
++ if (colorscheme >= (int)LEN(schemes))
++ colorscheme = 0;
++ else if (colorscheme < 0)
++ colorscheme = LEN(schemes) - 1;
++ updatescheme();
++}
++
++void
++selectscheme(const Arg *arg)
++{
++ if (BETWEEN(arg->i, 0, LEN(schemes)-1)) {
++ colorscheme = arg->i;
++ updatescheme();
++ }
++}
++
++void
++updatescheme(void)
++{
++ int oldbg, oldfg;
++
++ oldbg = defaultbg;
++ oldfg = defaultfg;
++ colorname = schemes[colorscheme].colors;
++ defaultbg = schemes[colorscheme].bg;
++ defaultfg = schemes[colorscheme].fg;
++ defaultcs = schemes[colorscheme].cs;
++ defaultrcs = schemes[colorscheme].rcs;
++ xloadcols();
++ if (defaultbg != oldbg)
++ tupdatebgcolor(oldbg, defaultbg);
++ if (defaultfg != oldfg)
++ tupdatefgcolor(oldfg, defaultfg);
++ cresize(win.w, win.h);
++ redraw();
++}
++
+ int
+ main(int argc, char *argv[])
+ {
+@@ -2060,6 +2104,12 @@ main(int argc, char *argv[])
+ } ARGEND;
+
+ run:
++ colorname = schemes[colorscheme].colors;
++ defaultbg = schemes[colorscheme].bg;
++ defaultfg = schemes[colorscheme].fg;
++ defaultcs = schemes[colorscheme].cs;
++ defaultrcs = schemes[colorscheme].rcs;
++
+ if (argc > 0) /* eat all remaining arguments */
+ opt_cmd = argv;
+
+--
+2.36.1
+
diff --git a/st.c b/st.c
@@ -2163,6 +2163,28 @@ tstrsequence(uchar c)
}
void
+tupdatebgcolor(int oldbg, int newbg)
+{
+ for (int y = 0; y < term.row; y++) {
+ for (int x = 0; x < term.col; x++) {
+ if (term.line[y][x].bg == oldbg)
+ term.line[y][x].bg = newbg;
+ }
+ }
+}
+
+void
+tupdatefgcolor(int oldfg, int newfg)
+{
+ for (int y = 0; y < term.row; y++) {
+ for (int x = 0; x < term.col; x++) {
+ if (term.line[y][x].fg == oldfg)
+ term.line[y][x].fg = newfg;
+ }
+ }
+}
+
+void
tcontrolcode(uchar ascii)
{
switch (ascii) {
diff --git a/st.h b/st.h
@@ -90,6 +90,8 @@ int tattrset(int);
void tnew(int, int);
void tresize(int, int);
void tsetdirtattr(int);
+void tupdatebgcolor(int, int);
+void tupdatefgcolor(int, int);
void ttyhangup(void);
int ttynew(const char *, char *, const char *, char **);
size_t ttyread(void);
diff --git a/x.c b/x.c
@@ -59,6 +59,8 @@ static void zoom(const Arg *);
static void zoomabs(const Arg *);
static void zoomreset(const Arg *);
static void ttysend(const Arg *);
+static void nextscheme(const Arg *);
+static void selectscheme(const Arg *);
/* config.h for applying patches and the configuration. */
#include "config.h"
@@ -187,6 +189,7 @@ static void mousesel(XEvent *, int);
static void mousereport(XEvent *);
static char *kmap(KeySym, uint);
static int match(uint, uint);
+static void updatescheme(void);
static void run(void);
static void usage(void);
@@ -804,7 +807,7 @@ xloadcols(void)
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.collen = 258;
dc.col = xmalloc(dc.collen * sizeof(Color));
}
@@ -2127,6 +2130,47 @@ usage(void)
" [stty_args ...]\n", argv0, argv0);
}
+void
+nextscheme(const Arg *arg)
+{
+ colorscheme += arg->i;
+ if (colorscheme >= (int)LEN(schemes))
+ colorscheme = 0;
+ else if (colorscheme < 0)
+ colorscheme = LEN(schemes) - 1;
+ updatescheme();
+}
+
+void
+selectscheme(const Arg *arg)
+{
+ if (BETWEEN(arg->i, 0, LEN(schemes)-1)) {
+ colorscheme = arg->i;
+ updatescheme();
+ }
+}
+
+void
+updatescheme(void)
+{
+ int oldbg, oldfg;
+
+ oldbg = defaultbg;
+ oldfg = defaultfg;
+ colorname = schemes[colorscheme].colors;
+ defaultbg = schemes[colorscheme].bg;
+ defaultfg = schemes[colorscheme].fg;
+ defaultcs = schemes[colorscheme].cs;
+ defaultrcs = schemes[colorscheme].rcs;
+ xloadcols();
+ if (defaultbg != oldbg)
+ tupdatebgcolor(oldbg, defaultbg);
+ if (defaultfg != oldfg)
+ tupdatefgcolor(oldfg, defaultfg);
+ cresize(win.w, win.h);
+ redraw();
+}
+
int
main(int argc, char *argv[])
{
@@ -2179,6 +2223,12 @@ main(int argc, char *argv[])
} ARGEND;
run:
+ colorname = schemes[colorscheme].colors;
+ defaultbg = schemes[colorscheme].bg;
+ defaultfg = schemes[colorscheme].fg;
+ defaultcs = schemes[colorscheme].cs;
+ defaultrcs = schemes[colorscheme].rcs;
+
if (argc > 0) /* eat all remaining arguments */
opt_cmd = argv;
diff --git a/x.c.orig b/x.c.orig
@@ -1,2197 +0,0 @@
-/* See LICENSE for license details. */
-#include <errno.h>
-#include <math.h>
-#include <limits.h>
-#include <locale.h>
-#include <signal.h>
-#include <sys/select.h>
-#include <time.h>
-#include <unistd.h>
-#include <libgen.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-#include <X11/Xft/Xft.h>
-#include <X11/XKBlib.h>
-
-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|1<<14)
-
-/* function definitions used in config.h */
-static void clipcopy(const Arg *);
-static void clippaste(const Arg *);
-static void numlock(const Arg *);
-static void selpaste(const Arg *);
-static void zoom(const Arg *);
-static void zoomabs(const Arg *);
-static void zoomreset(const Arg *);
-static void ttysend(const Arg *);
-
-/* config.h for applying patches and the configuration. */
-#include "config.h"
-
-/* XEMBED messages */
-#define XEMBED_FOCUS_IN 4
-#define XEMBED_FOCUS_OUT 5
-
-/* macros */
-#define IS_SET(flag) ((win.mode & (flag)) != 0)
-#define TRUERED(x) (((x) & 0xff0000) >> 8)
-#define TRUEGREEN(x) (((x) & 0xff00))
-#define TRUEBLUE(x) (((x) & 0xff) << 8)
-
-typedef XftDraw *Draw;
-typedef XftColor Color;
-typedef XftGlyphFontSpec GlyphFontSpec;
-
-/* Purely graphic info */
-typedef struct {
- int tw, th; /* tty width and height */
- int w, h; /* window width and height */
- int ch; /* char height */
- int cw; /* char width */
- int mode; /* window state/mode flags */
- int cursor; /* cursor style */
-} TermWindow;
-
-typedef struct {
- Display *dpy;
- Colormap cmap;
- Window win;
- Drawable buf;
- GlyphFontSpec *specbuf; /* font spec buffer used for rendering */
- Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid;
- struct {
- XIM xim;
- XIC xic;
- XPoint spot;
- XVaNestedList spotlist;
- } ime;
- Draw draw;
- Visual *vis;
- XSetWindowAttributes attrs;
- int scr;
- int isfixed; /* is fixed geometry? */
- int l, t; /* left and top offset */
- int gm; /* geometry mask */
-} XWindow;
-
-typedef struct {
- Atom xtarget;
- char *primary, *clipboard;
- struct timespec tclick1;
- struct timespec tclick2;
-} XSelection;
-
-/* Font structure */
-#define Font Font_
-typedef struct {
- int height;
- int width;
- int ascent;
- int descent;
- int badslant;
- int badweight;
- short lbearing;
- short rbearing;
- XftFont *match;
- FcFontSet *set;
- FcPattern *pattern;
-} Font;
-
-/* Drawing Context */
-typedef struct {
- Color *col;
- size_t collen;
- Font font, bfont, ifont, ibfont;
- GC gc;
-} DC;
-
-static inline ushort sixd_to_16bit(int);
-static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
-static void xdrawglyph(Glyph, int, int);
-static void xclear(int, int, int, int);
-static int xgeommasktogravity(int);
-static int ximopen(Display *);
-static void ximinstantiate(Display *, XPointer, XPointer);
-static void ximdestroy(XIM, XPointer, XPointer);
-static int xicdestroy(XIC, XPointer, XPointer);
-static void xinit(int, int);
-static void cresize(int, int);
-static void xresize(int, int);
-static void xhints(void);
-static int xloadcolor(int, const char *, Color *);
-static int xloadfont(Font *, FcPattern *);
-static void xloadfonts(const char *, double);
-static int xloadsparefont(FcPattern *, int);
-static void xloadsparefonts(void);
-static void xunloadfont(Font *);
-static void xunloadfonts(void);
-static void xsetenv(void);
-static void xseturgency(int);
-static int evcol(XEvent *);
-static int evrow(XEvent *);
-
-static void expose(XEvent *);
-static void visibility(XEvent *);
-static void unmap(XEvent *);
-static void kpress(XEvent *);
-static void cmessage(XEvent *);
-static void resize(XEvent *);
-static void focus(XEvent *);
-static uint buttonmask(uint);
-static int mouseaction(XEvent *, uint);
-static void brelease(XEvent *);
-static void bpress(XEvent *);
-static void bmotion(XEvent *);
-static void propnotify(XEvent *);
-static void selnotify(XEvent *);
-static void selclear_(XEvent *);
-static void selrequest(XEvent *);
-static void setsel(char *, Time);
-static void mousesel(XEvent *, int);
-static void mousereport(XEvent *);
-static char *kmap(KeySym, uint);
-static int match(uint, uint);
-
-static void run(void);
-static void usage(void);
-
-static void (*handler[LASTEvent])(XEvent *) = {
- [KeyPress] = kpress,
- [ClientMessage] = cmessage,
- [ConfigureNotify] = resize,
- [VisibilityNotify] = visibility,
- [UnmapNotify] = unmap,
- [Expose] = expose,
- [FocusIn] = focus,
- [FocusOut] = focus,
- [MotionNotify] = bmotion,
- [ButtonPress] = bpress,
- [ButtonRelease] = brelease,
-/*
- * Uncomment if you want the selection to disappear when you select something
- * different in another window.
- */
-/* [SelectionClear] = selclear_, */
- [SelectionNotify] = selnotify,
-/*
- * PropertyNotify is only turned on when there is some INCR transfer happening
- * for the selection retrieval.
- */
- [PropertyNotify] = propnotify,
- [SelectionRequest] = selrequest,
-};
-
-/* Globals */
-static DC dc;
-static XWindow xw;
-static XSelection xsel;
-static TermWindow win;
-
-/* Font Ring Cache */
-enum {
- FRC_NORMAL,
- FRC_ITALIC,
- FRC_BOLD,
- FRC_ITALICBOLD
-};
-
-typedef struct {
- XftFont *font;
- int flags;
- Rune unicodep;
-} Fontcache;
-
-/* Fontcache is an array now. A new font will be appended to the array. */
-static Fontcache *frc = NULL;
-static int frclen = 0;
-static int frccap = 0;
-static char *usedfont = NULL;
-static double usedfontsize = 0;
-static double defaultfontsize = 0;
-
-static char *opt_class = NULL;
-static char **opt_cmd = NULL;
-static char *opt_embed = NULL;
-static char *opt_font = NULL;
-static char *opt_io = NULL;
-static char *opt_line = NULL;
-static char *opt_name = NULL;
-static char *opt_title = NULL;
-
-static uint buttons; /* bit field of pressed buttons */
-
-void
-clipcopy(const Arg *dummy)
-{
- Atom clipboard;
-
- free(xsel.clipboard);
- xsel.clipboard = NULL;
-
- if (xsel.primary != NULL) {
- xsel.clipboard = xstrdup(xsel.primary);
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime);
- }
-}
-
-void
-clippaste(const Arg *dummy)
-{
- Atom clipboard;
-
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard,
- xw.win, CurrentTime);
-}
-
-void
-selpaste(const Arg *dummy)
-{
- XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY,
- xw.win, CurrentTime);
-}
-
-void
-numlock(const Arg *dummy)
-{
- win.mode ^= MODE_NUMLOCK;
-}
-
-void
-zoom(const Arg *arg)
-{
- Arg larg;
-
- larg.f = usedfontsize + arg->f;
- zoomabs(&larg);
-}
-
-void
-zoomabs(const Arg *arg)
-{
- xunloadfonts();
- xloadfonts(usedfont, arg->f);
- xloadsparefonts();
- cresize(0, 0);
- redraw();
- xhints();
-}
-
-void
-zoomreset(const Arg *arg)
-{
- Arg larg;
-
- if (defaultfontsize > 0) {
- larg.f = defaultfontsize;
- zoomabs(&larg);
- }
-}
-
-void
-ttysend(const Arg *arg)
-{
- ttywrite(arg->s, strlen(arg->s), 1);
-}
-
-int
-evcol(XEvent *e)
-{
- int x = e->xbutton.x - borderpx;
- LIMIT(x, 0, win.tw - 1);
- return x / win.cw;
-}
-
-int
-evrow(XEvent *e)
-{
- int y = e->xbutton.y - borderpx;
- LIMIT(y, 0, win.th - 1);
- return y / win.ch;
-}
-
-void
-mousesel(XEvent *e, int done)
-{
- int type, seltype = SEL_REGULAR;
- uint state = e->xbutton.state & ~(Button1Mask | forcemousemod);
-
- for (type = 1; type < LEN(selmasks); ++type) {
- if (match(selmasks[type], state)) {
- seltype = type;
- break;
- }
- }
- selextend(evcol(e), evrow(e), seltype, done);
- if (done)
- setsel(getsel(), e->xbutton.time);
-}
-
-void
-mousereport(XEvent *e)
-{
- int len, btn, code;
- int x = evcol(e), y = evrow(e);
- int state = e->xbutton.state;
- char buf[40];
- static int ox, oy;
-
- if (e->type == MotionNotify) {
- if (x == ox && y == oy)
- return;
- if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
- return;
- /* MODE_MOUSEMOTION: no reporting if no button is pressed */
- if (IS_SET(MODE_MOUSEMOTION) && buttons == 0)
- return;
- /* Set btn to lowest-numbered pressed button, or 12 if no
- * buttons are pressed. */
- for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++)
- ;
- code = 32;
- } else {
- btn = e->xbutton.button;
- /* Only buttons 1 through 11 can be encoded */
- if (btn < 1 || btn > 11)
- return;
- if (e->type == ButtonRelease) {
- /* MODE_MOUSEX10: no button release reporting */
- if (IS_SET(MODE_MOUSEX10))
- return;
- /* Don't send release events for the scroll wheel */
- if (btn == 4 || btn == 5)
- return;
- }
- code = 0;
- }
-
- ox = x;
- oy = y;
-
- /* Encode btn into code. If no button is pressed for a motion event in
- * MODE_MOUSEMANY, then encode it as a release. */
- if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12)
- code += 3;
- else if (btn >= 8)
- code += 128 + btn - 8;
- else if (btn >= 4)
- code += 64 + btn - 4;
- else
- code += btn - 1;
-
- if (!IS_SET(MODE_MOUSEX10)) {
- code += ((state & ShiftMask ) ? 4 : 0)
- + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */
- + ((state & ControlMask) ? 16 : 0);
- }
-
- if (IS_SET(MODE_MOUSESGR)) {
- len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
- code, x+1, y+1,
- e->type == ButtonRelease ? 'm' : 'M');
- } else if (x < 223 && y < 223) {
- len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
- 32+code, 32+x+1, 32+y+1);
- } else {
- return;
- }
-
- ttywrite(buf, len, 0);
-}
-
-uint
-buttonmask(uint button)
-{
- return button == Button1 ? Button1Mask
- : button == Button2 ? Button2Mask
- : button == Button3 ? Button3Mask
- : button == Button4 ? Button4Mask
- : button == Button5 ? Button5Mask
- : 0;
-}
-
-int
-mouseaction(XEvent *e, uint release)
-{
- MouseShortcut *ms;
-
- /* ignore Button<N>mask for Button<N> - it's set on release */
- uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
-
- for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
- if (ms->release == release &&
- ms->button == e->xbutton.button &&
- (match(ms->mod, state) || /* exact or forced */
- match(ms->mod, state & ~forcemousemod))) {
- ms->func(&(ms->arg));
- return 1;
- }
- }
-
- return 0;
-}
-
-void
-bpress(XEvent *e)
-{
- int btn = e->xbutton.button;
- struct timespec now;
- int snap;
-
- if (1 <= btn && btn <= 11)
- buttons |= 1 << (btn-1);
-
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- if (mouseaction(e, 0))
- return;
-
- if (btn == Button1) {
- /*
- * If the user clicks below predefined timeouts specific
- * snapping behaviour is exposed.
- */
- clock_gettime(CLOCK_MONOTONIC, &now);
- if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) {
- snap = SNAP_LINE;
- } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) {
- snap = SNAP_WORD;
- } else {
- snap = 0;
- }
- xsel.tclick2 = xsel.tclick1;
- xsel.tclick1 = now;
-
- selstart(evcol(e), evrow(e), snap);
- }
-}
-
-void
-propnotify(XEvent *e)
-{
- XPropertyEvent *xpev;
- Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
-
- xpev = &e->xproperty;
- if (xpev->state == PropertyNewValue &&
- (xpev->atom == XA_PRIMARY ||
- xpev->atom == clipboard)) {
- selnotify(e);
- }
-}
-
-void
-selnotify(XEvent *e)
-{
- ulong nitems, ofs, rem;
- int format;
- uchar *data, *last, *repl;
- Atom type, incratom, property = None;
-
- incratom = XInternAtom(xw.dpy, "INCR", 0);
-
- ofs = 0;
- if (e->type == SelectionNotify)
- property = e->xselection.property;
- else if (e->type == PropertyNotify)
- property = e->xproperty.atom;
-
- if (property == None)
- return;
-
- do {
- if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
- BUFSIZ/4, False, AnyPropertyType,
- &type, &format, &nitems, &rem,
- &data)) {
- fprintf(stderr, "Clipboard allocation failed\n");
- return;
- }
-
- if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
- /*
- * If there is some PropertyNotify with no data, then
- * this is the signal of the selection owner that all
- * data has been transferred. We won't need to receive
- * PropertyNotify events anymore.
- */
- MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
- &xw.attrs);
- }
-
- if (type == incratom) {
- /*
- * Activate the PropertyNotify events so we receive
- * when the selection owner does send us the next
- * chunk of data.
- */
- MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
- &xw.attrs);
-
- /*
- * Deleting the property is the transfer start signal.
- */
- XDeleteProperty(xw.dpy, xw.win, (int)property);
- continue;
- }
-
- /*
- * As seen in getsel:
- * Line endings are inconsistent in the terminal and GUI world
- * copy and pasting. When receiving some selection data,
- * replace all '\n' with '\r'.
- * FIXME: Fix the computer world.
- */
- repl = data;
- last = data + nitems * format / 8;
- while ((repl = memchr(repl, '\n', last - repl))) {
- *repl++ = '\r';
- }
-
- if (IS_SET(MODE_BRCKTPASTE) && ofs == 0)
- ttywrite("\033[200~", 6, 0);
- ttywrite((char *)data, nitems * format / 8, 1);
- if (IS_SET(MODE_BRCKTPASTE) && rem == 0)
- ttywrite("\033[201~", 6, 0);
- XFree(data);
- /* number of 32-bit chunks returned */
- ofs += nitems * format / 32;
- } while (rem > 0);
-
- /*
- * Deleting the property again tells the selection owner to send the
- * next data chunk in the property.
- */
- XDeleteProperty(xw.dpy, xw.win, (int)property);
-}
-
-void
-xclipcopy(void)
-{
- clipcopy(NULL);
-}
-
-void
-selclear_(XEvent *e)
-{
- selclear();
-}
-
-void
-selrequest(XEvent *e)
-{
- XSelectionRequestEvent *xsre;
- XSelectionEvent xev;
- Atom xa_targets, string, clipboard;
- char *seltext;
-
- xsre = (XSelectionRequestEvent *) e;
- xev.type = SelectionNotify;
- xev.requestor = xsre->requestor;
- xev.selection = xsre->selection;
- xev.target = xsre->target;
- xev.time = xsre->time;
- if (xsre->property == None)
- xsre->property = xsre->target;
-
- /* reject */
- xev.property = None;
-
- xa_targets = XInternAtom(xw.dpy, "TARGETS", 0);
- if (xsre->target == xa_targets) {
- /* respond with the supported type */
- string = xsel.xtarget;
- XChangeProperty(xsre->display, xsre->requestor, xsre->property,
- XA_ATOM, 32, PropModeReplace,
- (uchar *) &string, 1);
- xev.property = xsre->property;
- } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) {
- /*
- * xith XA_STRING non ascii characters may be incorrect in the
- * requestor. It is not our problem, use utf8.
- */
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- if (xsre->selection == XA_PRIMARY) {
- seltext = xsel.primary;
- } else if (xsre->selection == clipboard) {
- seltext = xsel.clipboard;
- } else {
- fprintf(stderr,
- "Unhandled clipboard selection 0x%lx\n",
- xsre->selection);
- return;
- }
- if (seltext != NULL) {
- XChangeProperty(xsre->display, xsre->requestor,
- xsre->property, xsre->target,
- 8, PropModeReplace,
- (uchar *)seltext, strlen(seltext));
- xev.property = xsre->property;
- }
- }
-
- /* all done, send a notification to the listener */
- if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev))
- fprintf(stderr, "Error sending SelectionNotify event\n");
-}
-
-void
-setsel(char *str, Time t)
-{
- if (!str)
- return;
-
- free(xsel.primary);
- xsel.primary = str;
-
- XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
- if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
- selclear();
-}
-
-void
-xsetsel(char *str)
-{
- setsel(str, CurrentTime);
-}
-
-void
-brelease(XEvent *e)
-{
- int btn = e->xbutton.button;
-
- if (1 <= btn && btn <= 11)
- buttons &= ~(1 << (btn-1));
-
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- if (mouseaction(e, 1))
- return;
- if (btn == Button1)
- mousesel(e, 1);
-}
-
-void
-bmotion(XEvent *e)
-{
- if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- mousesel(e, 0);
-}
-
-void
-cresize(int width, int height)
-{
- int col, row;
-
- if (width != 0)
- win.w = width;
- if (height != 0)
- win.h = height;
-
- col = (win.w - 2 * borderpx) / win.cw;
- row = (win.h - 2 * borderpx) / win.ch;
- col = MAX(1, col);
- row = MAX(1, row);
-
- tresize(col, row);
- xresize(col, row);
- ttyresize(win.tw, win.th);
-}
-
-void
-xresize(int col, int row)
-{
- win.tw = col * win.cw;
- win.th = row * win.ch;
-
- XFreePixmap(xw.dpy, xw.buf);
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
- DefaultDepth(xw.dpy, xw.scr));
- XftDrawChange(xw.draw, xw.buf);
- xclear(0, 0, win.w, win.h);
-
- /* resize to new width */
- xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
-}
-
-ushort
-sixd_to_16bit(int x)
-{
- return x == 0 ? 0 : 0x3737 + 0x2828 * x;
-}
-
-int
-xloadcolor(int i, const char *name, Color *ncolor)
-{
- XRenderColor color = { .alpha = 0xffff };
-
- if (!name) {
- if (BETWEEN(i, 16, 255)) { /* 256 color */
- if (i < 6*6*6+16) { /* same colors as xterm */
- color.red = sixd_to_16bit( ((i-16)/36)%6 );
- color.green = sixd_to_16bit( ((i-16)/6) %6 );
- color.blue = sixd_to_16bit( ((i-16)/1) %6 );
- } else { /* greyscale */
- color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16));
- color.green = color.blue = color.red;
- }
- return XftColorAllocValue(xw.dpy, xw.vis,
- xw.cmap, &color, ncolor);
- } else
- name = colorname[i];
- }
-
- return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
-}
-
-void
-xloadcols(void)
-{
- int i;
- static int loaded;
- Color *cp;
-
- if (loaded) {
- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp)
- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
- } else {
- dc.collen = MAX(LEN(colorname), 256);
- dc.col = xmalloc(dc.collen * sizeof(Color));
- }
-
- for (i = 0; i < dc.collen; i++)
- if (!xloadcolor(i, NULL, &dc.col[i])) {
- if (colorname[i])
- die("could not allocate color '%s'\n", colorname[i]);
- else
- die("could not allocate color %d\n", i);
- }
- loaded = 1;
-}
-
-int
-xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b)
-{
- if (!BETWEEN(x, 0, dc.collen))
- return 1;
-
- *r = dc.col[x].color.red >> 8;
- *g = dc.col[x].color.green >> 8;
- *b = dc.col[x].color.blue >> 8;
-
- return 0;
-}
-
-int
-xsetcolorname(int x, const char *name)
-{
- Color ncolor;
-
- if (!BETWEEN(x, 0, dc.collen))
- return 1;
-
- if (!xloadcolor(x, name, &ncolor))
- return 1;
-
- XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
- dc.col[x] = ncolor;
-
- return 0;
-}
-
-/*
- * Absolute coordinates.
- */
-void
-xclear(int x1, int y1, int x2, int y2)
-{
- XftDrawRect(xw.draw,
- &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg],
- x1, y1, x2-x1, y2-y1);
-}
-
-void
-xhints(void)
-{
- XClassHint class = {opt_name ? opt_name : termname,
- opt_class ? opt_class : termname};
- XWMHints wm = {.flags = InputHint, .input = 1};
- XSizeHints *sizeh;
-
- sizeh = XAllocSizeHints();
-
- sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;
- sizeh->height = win.h;
- sizeh->width = win.w;
- sizeh->height_inc = win.ch;
- sizeh->width_inc = win.cw;
- sizeh->base_height = 2 * borderpx;
- sizeh->base_width = 2 * borderpx;
- sizeh->min_height = win.ch + 2 * borderpx;
- sizeh->min_width = win.cw + 2 * borderpx;
- if (xw.isfixed) {
- sizeh->flags |= PMaxSize;
- sizeh->min_width = sizeh->max_width = win.w;
- sizeh->min_height = sizeh->max_height = win.h;
- }
- if (xw.gm & (XValue|YValue)) {
- sizeh->flags |= USPosition | PWinGravity;
- sizeh->x = xw.l;
- sizeh->y = xw.t;
- sizeh->win_gravity = xgeommasktogravity(xw.gm);
- }
-
- XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm,
- &class);
- XFree(sizeh);
-}
-
-int
-xgeommasktogravity(int mask)
-{
- switch (mask & (XNegative|YNegative)) {
- case 0:
- return NorthWestGravity;
- case XNegative:
- return NorthEastGravity;
- case YNegative:
- return SouthWestGravity;
- }
-
- return SouthEastGravity;
-}
-
-int
-xloadfont(Font *f, FcPattern *pattern)
-{
- FcPattern *configured;
- FcPattern *match;
- FcResult result;
- XGlyphInfo extents;
- int wantattr, haveattr;
-
- /*
- * Manually configure instead of calling XftMatchFont
- * so that we can use the configured pattern for
- * "missing glyph" lookups.
- */
- configured = FcPatternDuplicate(pattern);
- if (!configured)
- return 1;
-
- FcConfigSubstitute(NULL, configured, FcMatchPattern);
- XftDefaultSubstitute(xw.dpy, xw.scr, configured);
-
- match = FcFontMatch(NULL, configured, &result);
- if (!match) {
- FcPatternDestroy(configured);
- return 1;
- }
-
- if (!(f->match = XftFontOpenPattern(xw.dpy, match))) {
- FcPatternDestroy(configured);
- FcPatternDestroy(match);
- return 1;
- }
-
- if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) ==
- XftResultMatch)) {
- /*
- * Check if xft was unable to find a font with the appropriate
- * slant but gave us one anyway. Try to mitigate.
- */
- if ((XftPatternGetInteger(f->match->pattern, "slant", 0,
- &haveattr) != XftResultMatch) || haveattr < wantattr) {
- f->badslant = 1;
- fputs("font slant does not match\n", stderr);
- }
- }
-
- if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) ==
- XftResultMatch)) {
- if ((XftPatternGetInteger(f->match->pattern, "weight", 0,
- &haveattr) != XftResultMatch) || haveattr != wantattr) {
- f->badweight = 1;
- fputs("font weight does not match\n", stderr);
- }
- }
-
- XftTextExtentsUtf8(xw.dpy, f->match,
- (const FcChar8 *) ascii_printable,
- strlen(ascii_printable), &extents);
-
- f->set = NULL;
- f->pattern = configured;
-
- f->ascent = f->match->ascent;
- f->descent = f->match->descent;
- f->lbearing = 0;
- f->rbearing = f->match->max_advance_width;
-
- f->height = f->ascent + f->descent;
- f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
-
- return 0;
-}
-
-void
-xloadfonts(const char *fontstr, double fontsize)
-{
- FcPattern *pattern;
- double fontval;
-
- if (fontstr[0] == '-')
- pattern = XftXlfdParse(fontstr, False, False);
- else
- pattern = FcNameParse((const FcChar8 *)fontstr);
-
- if (!pattern)
- die("can't open font %s\n", fontstr);
-
- if (fontsize > 1) {
- FcPatternDel(pattern, FC_PIXEL_SIZE);
- FcPatternDel(pattern, FC_SIZE);
- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize);
- usedfontsize = fontsize;
- } else {
- if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) ==
- FcResultMatch) {
- usedfontsize = fontval;
- } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) ==
- FcResultMatch) {
- usedfontsize = -1;
- } else {
- /*
- * Default font size is 12, if none given. This is to
- * have a known usedfontsize value.
- */
- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12);
- usedfontsize = 12;
- }
- defaultfontsize = usedfontsize;
- }
-
- if (xloadfont(&dc.font, pattern))
- die("can't open font %s\n", fontstr);
-
- if (usedfontsize < 0) {
- FcPatternGetDouble(dc.font.match->pattern,
- FC_PIXEL_SIZE, 0, &fontval);
- usedfontsize = fontval;
- if (fontsize == 0)
- defaultfontsize = fontval;
- }
-
- /* Setting character width and height. */
- win.cw = ceilf(dc.font.width * cwscale);
- win.ch = ceilf(dc.font.height * chscale);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
- if (xloadfont(&dc.ifont, pattern))
- die("can't open font %s\n", fontstr);
-
- FcPatternDel(pattern, FC_WEIGHT);
- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
- if (xloadfont(&dc.ibfont, pattern))
- die("can't open font %s\n", fontstr);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
- if (xloadfont(&dc.bfont, pattern))
- die("can't open font %s\n", fontstr);
-
- FcPatternDestroy(pattern);
-}
-
-int
-xloadsparefont(FcPattern *pattern, int flags)
-{
- FcPattern *match;
- FcResult result;
-
- match = FcFontMatch(NULL, pattern, &result);
- if (!match) {
- return 1;
- }
-
- if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) {
- FcPatternDestroy(match);
- return 1;
- }
-
- frc[frclen].flags = flags;
- /* Believe U+0000 glyph will present in each default font */
- frc[frclen].unicodep = 0;
- frclen++;
-
- return 0;
-}
-
-void
-xloadsparefonts(void)
-{
- FcPattern *pattern;
- double sizeshift, fontval;
- int fc;
- char **fp;
-
- if (frclen != 0)
- die("can't embed spare fonts. cache isn't empty");
-
- /* Calculate count of spare fonts */
- fc = sizeof(font2) / sizeof(*font2);
- if (fc == 0)
- return;
-
- /* Allocate memory for cache entries. */
- if (frccap < 4 * fc) {
- frccap += 4 * fc - frccap;
- frc = xrealloc(frc, frccap * sizeof(Fontcache));
- }
-
- for (fp = font2; fp - font2 < fc; ++fp) {
-
- if (**fp == '-')
- pattern = XftXlfdParse(*fp, False, False);
- else
- pattern = FcNameParse((FcChar8 *)*fp);
-
- if (!pattern)
- die("can't open spare font %s\n", *fp);
-
- if (defaultfontsize > 0) {
- sizeshift = usedfontsize - defaultfontsize;
- if (sizeshift != 0 &&
- FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) ==
- FcResultMatch) {
- fontval += sizeshift;
- FcPatternDel(pattern, FC_PIXEL_SIZE);
- FcPatternDel(pattern, FC_SIZE);
- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval);
- }
- }
-
- FcPatternAddBool(pattern, FC_SCALABLE, 1);
-
- FcConfigSubstitute(NULL, pattern, FcMatchPattern);
- XftDefaultSubstitute(xw.dpy, xw.scr, pattern);
-
- if (xloadsparefont(pattern, FRC_NORMAL))
- die("can't open spare font %s\n", *fp);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
- if (xloadsparefont(pattern, FRC_ITALIC))
- die("can't open spare font %s\n", *fp);
-
- FcPatternDel(pattern, FC_WEIGHT);
- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
- if (xloadsparefont(pattern, FRC_ITALICBOLD))
- die("can't open spare font %s\n", *fp);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
- if (xloadsparefont(pattern, FRC_BOLD))
- die("can't open spare font %s\n", *fp);
-
- 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);
-
- /* spare fonts */
- xloadsparefonts();
-
- /* colors */
- xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
- xloadcols();
-
- /* adjust fixed window geometry */
- win.w = 2 * borderpx + cols * win.cw;
- win.h = 2 * borderpx + rows * win.ch;
- if (xw.gm & XNegative)
- xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
- if (xw.gm & YNegative)
- xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2;
-
- /* Events */
- xw.attrs.background_pixel = dc.col[defaultbg].pixel;
- xw.attrs.border_pixel = dc.col[defaultbg].pixel;
- xw.attrs.bit_gravity = NorthWestGravity;
- xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask
- | ExposureMask | VisibilityChangeMask | StructureNotifyMask
- | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
- xw.attrs.colormap = xw.cmap;
-
- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
- parent = XRootWindow(xw.dpy, xw.scr);
- xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
- xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
- | CWEventMask | CWColormap, &xw.attrs);
-
- memset(&gcvalues, 0, sizeof(gcvalues));
- gcvalues.graphics_exposures = False;
- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
- &gcvalues);
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
- DefaultDepth(xw.dpy, xw.scr));
- XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
- XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
-
- /* font spec buffer */
- xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
-
- /* Xft rendering context */
- xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
-
- /* input methods */
- if (!ximopen(xw.dpy)) {
- XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
- ximinstantiate, NULL);
- }
-
- /* white cursor, black outline */
- cursor = XCreateFontCursor(xw.dpy, mouseshape);
- XDefineCursor(xw.dpy, xw.win, cursor);
-
- if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
- xmousefg.red = 0xffff;
- xmousefg.green = 0xffff;
- xmousefg.blue = 0xffff;
- }
-
- if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) {
- xmousebg.red = 0x0000;
- xmousebg.green = 0x0000;
- xmousebg.blue = 0x0000;
- }
-
- XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg);
-
- xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
- xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
- xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
- xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False);
- XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
-
- xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
- XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
- PropModeReplace, (uchar *)&thispid, 1);
-
- win.mode = MODE_NUMLOCK;
- resettitle();
- xhints();
- XMapWindow(xw.dpy, xw.win);
- XSync(xw.dpy, False);
-
- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1);
- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2);
- xsel.primary = NULL;
- xsel.clipboard = NULL;
- xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
- if (xsel.xtarget == None)
- xsel.xtarget = XA_STRING;
-}
-
-int
-xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
-{
- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
- ushort mode, prevmode = USHRT_MAX;
- Font *font = &dc.font;
- int frcflags = FRC_NORMAL;
- float runewidth = win.cw;
- Rune rune;
- FT_UInt glyphidx;
- FcResult fcres;
- FcPattern *fcpattern, *fontpattern;
- FcFontSet *fcsets[] = { NULL };
- FcCharSet *fccharset;
- int i, f, numspecs = 0;
-
- for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
- /* Fetch rune and mode for current glyph. */
- rune = glyphs[i].u;
- mode = glyphs[i].mode;
-
- /* Skip dummy wide-character spacing. */
- if (mode == ATTR_WDUMMY)
- continue;
-
- /* Determine font for glyph if different from previous glyph. */
- if (prevmode != mode) {
- prevmode = mode;
- font = &dc.font;
- frcflags = FRC_NORMAL;
- runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f);
- if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
- font = &dc.ibfont;
- frcflags = FRC_ITALICBOLD;
- } else if (mode & ATTR_ITALIC) {
- font = &dc.ifont;
- frcflags = FRC_ITALIC;
- } else if (mode & ATTR_BOLD) {
- font = &dc.bfont;
- frcflags = FRC_BOLD;
- }
- yp = winy + font->ascent;
- }
-
- /* Lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, rune);
- if (glyphidx) {
- specs[numspecs].font = font->match;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- numspecs++;
- continue;
- }
-
- /* Fallback on font cache, search the font cache for match. */
- for (f = 0; f < frclen; f++) {
- glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
- /* Everything correct. */
- if (glyphidx && frc[f].flags == frcflags)
- break;
- /* We got a default font for a not found glyph. */
- if (!glyphidx && frc[f].flags == frcflags
- && frc[f].unicodep == rune) {
- break;
- }
- }
-
- /* Nothing was found. Use fontconfig to find matching font. */
- if (f >= frclen) {
- if (!font->set)
- font->set = FcFontSort(0, font->pattern,
- 1, 0, &fcres);
- fcsets[0] = font->set;
-
- /*
- * Nothing was found in the cache. Now use
- * some dozen of Fontconfig calls to get the
- * font for one single character.
- *
- * Xft and fontconfig are design failures.
- */
- fcpattern = FcPatternDuplicate(font->pattern);
- fccharset = FcCharSetCreate();
-
- FcCharSetAddChar(fccharset, rune);
- FcPatternAddCharSet(fcpattern, FC_CHARSET,
- fccharset);
- FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-
- FcConfigSubstitute(0, fcpattern,
- FcMatchPattern);
- FcDefaultSubstitute(fcpattern);
-
- fontpattern = FcFontSetMatch(0, fcsets, 1,
- fcpattern, &fcres);
-
- /* Allocate memory for the new cache entry. */
- if (frclen >= frccap) {
- frccap += 16;
- frc = xrealloc(frc, frccap * sizeof(Fontcache));
- }
-
- frc[frclen].font = XftFontOpenPattern(xw.dpy,
- fontpattern);
- if (!frc[frclen].font)
- die("XftFontOpenPattern failed seeking fallback font: %s\n",
- strerror(errno));
- frc[frclen].flags = frcflags;
- frc[frclen].unicodep = rune;
-
- glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune);
-
- f = frclen;
- frclen++;
-
- FcPatternDestroy(fcpattern);
- FcCharSetDestroy(fccharset);
- }
-
- specs[numspecs].font = frc[f].font;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- numspecs++;
- }
-
- return numspecs;
-}
-
-void
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
-{
- int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
- width = charlen * win.cw;
- Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
- XRenderColor colfg, colbg;
- XRectangle r;
-
- /* Fallback on color display for attributes not supported by the font */
- if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
- if (dc.ibfont.badslant || dc.ibfont.badweight)
- base.fg = defaultattr;
- } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) ||
- (base.mode & ATTR_BOLD && dc.bfont.badweight)) {
- base.fg = defaultattr;
- }
-
- if (IS_TRUECOL(base.fg)) {
- colfg.alpha = 0xffff;
- colfg.red = TRUERED(base.fg);
- colfg.green = TRUEGREEN(base.fg);
- colfg.blue = TRUEBLUE(base.fg);
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg);
- fg = &truefg;
- } else {
- fg = &dc.col[base.fg];
- }
-
- if (IS_TRUECOL(base.bg)) {
- colbg.alpha = 0xffff;
- colbg.green = TRUEGREEN(base.bg);
- colbg.red = TRUERED(base.bg);
- colbg.blue = TRUEBLUE(base.bg);
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg);
- bg = &truebg;
- } else {
- bg = &dc.col[base.bg];
- }
-
- /* Change basic system colors [0-7] to bright system colors [8-15] */
- if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7))
- fg = &dc.col[base.fg + 8];
-
- if (IS_SET(MODE_REVERSE)) {
- if (fg == &dc.col[defaultfg]) {
- fg = &dc.col[defaultbg];
- } else {
- colfg.red = ~fg->color.red;
- colfg.green = ~fg->color.green;
- colfg.blue = ~fg->color.blue;
- colfg.alpha = fg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg,
- &revfg);
- fg = &revfg;
- }
-
- if (bg == &dc.col[defaultbg]) {
- bg = &dc.col[defaultfg];
- } else {
- colbg.red = ~bg->color.red;
- colbg.green = ~bg->color.green;
- colbg.blue = ~bg->color.blue;
- colbg.alpha = bg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg,
- &revbg);
- bg = &revbg;
- }
- }
-
- if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) {
- colfg.red = fg->color.red / 2;
- colfg.green = fg->color.green / 2;
- colfg.blue = fg->color.blue / 2;
- colfg.alpha = fg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg);
- fg = &revfg;
- }
-
- if (base.mode & ATTR_REVERSE) {
- temp = fg;
- fg = bg;
- bg = temp;
- }
-
- if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK)
- fg = bg;
-
- if (base.mode & ATTR_INVISIBLE)
- fg = bg;
-
- /* Intelligent cleaning up of the borders. */
- if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, borderpx,
- winy + win.ch +
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
- }
- if (winx + width >= borderpx + win.tw) {
- xclear(winx + width, (y == 0)? 0 : winy, win.w,
- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
- }
- if (y == 0)
- xclear(winx, 0, winx + width, borderpx);
- if (winy + win.ch >= borderpx + win.th)
- xclear(winx, winy + win.ch, winx + width, win.h);
-
- /* Clean up the region we want to draw to. */
- XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
-
- /* Set the clip region because Xft is sometimes dirty. */
- r.x = 0;
- r.y = 0;
- r.height = win.ch;
- r.width = width;
- XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
-
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
-
- /* Render underline and strikethrough. */
- if (base.mode & ATTR_UNDERLINE) {
- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
- width, 1);
- }
-
- if (base.mode & ATTR_STRUCK) {
- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
- width, 1);
- }
-
- /* Reset clip to none. */
- XftDrawSetClip(xw.draw, 0);
-}
-
-void
-xdrawglyph(Glyph g, int x, int y)
-{
- int numspecs;
- XftGlyphFontSpec spec;
-
- numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
- xdrawglyphfontspecs(&spec, g, numspecs, x, y);
-}
-
-void
-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
-{
- Color drawcol;
-
- /* remove the old cursor */
- if (selected(ox, oy))
- og.mode ^= ATTR_REVERSE;
- xdrawglyph(og, ox, oy);
-
- if (IS_SET(MODE_HIDE))
- return;
-
- /*
- * Select the right color for the right mode.
- */
- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE;
-
- if (IS_SET(MODE_REVERSE)) {
- g.mode |= ATTR_REVERSE;
- g.bg = defaultfg;
- if (selected(cx, cy)) {
- drawcol = dc.col[defaultcs];
- g.fg = defaultrcs;
- } else {
- drawcol = dc.col[defaultrcs];
- g.fg = defaultcs;
- }
- } else {
- if (selected(cx, cy)) {
- g.fg = defaultfg;
- g.bg = defaultrcs;
- } else {
- g.fg = defaultbg;
- g.bg = defaultcs;
- }
- drawcol = dc.col[g.bg];
- }
-
- /* draw the new one */
- if (IS_SET(MODE_FOCUSED)) {
- switch (win.cursor) {
- case 7: /* st extension */
- g.u = 0x2603; /* snowman (U+2603) */
- /* FALLTHROUGH */
- case 0: /* Blinking Block */
- case 1: /* Blinking Block (Default) */
- case 2: /* Steady Block */
- xdrawglyph(g, cx, cy);
- break;
- case 3: /* Blinking Underline */
- case 4: /* Steady Underline */
- XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - \
- cursorthickness,
- win.cw, cursorthickness);
- break;
- case 5: /* Blinking bar */
- case 6: /* Steady bar */
- XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
- cursorthickness, win.ch);
- break;
- }
- } else {
- XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
- win.cw - 1, 1);
- XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
- 1, win.ch - 1);
- XftDrawRect(xw.draw, &drawcol,
- borderpx + (cx + 1) * win.cw - 1,
- borderpx + cy * win.ch,
- 1, win.ch - 1);
- XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - 1,
- win.cw, 1);
- }
-}
-
-void
-xsetenv(void)
-{
- char buf[sizeof(long) * 8 + 1];
-
- snprintf(buf, sizeof(buf), "%lu", xw.win);
- setenv("WINDOWID", buf, 1);
-}
-
-void
-xseticontitle(char *p)
-{
- XTextProperty prop;
- DEFAULT(p, opt_title);
-
- if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
- &prop) != Success)
- return;
- XSetWMIconName(xw.dpy, xw.win, &prop);
- XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname);
- XFree(prop.value);
-}
-
-void
-xsettitle(char *p)
-{
- XTextProperty prop;
- DEFAULT(p, opt_title);
-
- if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
- &prop) != Success)
- return;
- XSetWMName(xw.dpy, xw.win, &prop);
- XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
- XFree(prop.value);
-}
-
-int
-xstartdraw(void)
-{
- return IS_SET(MODE_VISIBLE);
-}
-
-void
-xdrawline(Line line, int x1, int y1, int x2)
-{
- int i, x, ox, numspecs;
- Glyph base, new;
- XftGlyphFontSpec *specs = xw.specbuf;
-
- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
- i = ox = 0;
- for (x = x1; x < x2 && i < numspecs; x++) {
- new = line[x];
- if (new.mode == ATTR_WDUMMY)
- continue;
- if (selected(x, y1))
- new.mode ^= ATTR_REVERSE;
- if (i > 0 && ATTRCMP(base, new)) {
- xdrawglyphfontspecs(specs, base, i, ox, y1);
- specs += i;
- numspecs -= i;
- i = 0;
- }
- if (i == 0) {
- ox = x;
- base = new;
- }
- i++;
- }
- if (i > 0)
- xdrawglyphfontspecs(specs, base, i, ox, y1);
-}
-
-void
-xfinishdraw(void)
-{
- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
- win.h, 0, 0);
- XSetForeground(xw.dpy, dc.gc,
- dc.col[IS_SET(MODE_REVERSE)?
- defaultfg : defaultbg].pixel);
-}
-
-void
-xximspot(int x, int y)
-{
- if (xw.ime.xic == NULL)
- return;
-
- xw.ime.spot.x = borderpx + x * win.cw;
- xw.ime.spot.y = borderpx + (y + 1) * win.ch;
-
- XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL);
-}
-
-void
-expose(XEvent *ev)
-{
- redraw();
-}
-
-void
-visibility(XEvent *ev)
-{
- XVisibilityEvent *e = &ev->xvisibility;
-
- MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE);
-}
-
-void
-unmap(XEvent *ev)
-{
- win.mode &= ~MODE_VISIBLE;
-}
-
-void
-xsetpointermotion(int set)
-{
- MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
-}
-
-void
-xsetmode(int set, unsigned int flags)
-{
- int mode = win.mode;
- MODBIT(win.mode, set, flags);
- if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE))
- redraw();
-}
-
-int
-xsetcursor(int cursor)
-{
- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
- return 1;
- win.cursor = cursor;
- return 0;
-}
-
-void
-xseturgency(int add)
-{
- XWMHints *h = XGetWMHints(xw.dpy, xw.win);
-
- MODBIT(h->flags, add, XUrgencyHint);
- XSetWMHints(xw.dpy, xw.win, h);
- XFree(h);
-}
-
-void
-xbell(void)
-{
- if (!(IS_SET(MODE_FOCUSED)))
- xseturgency(1);
- if (bellvolume)
- XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
-}
-
-void
-focus(XEvent *ev)
-{
- XFocusChangeEvent *e = &ev->xfocus;
-
- if (e->mode == NotifyGrab)
- return;
-
- if (ev->type == FocusIn) {
- if (xw.ime.xic)
- XSetICFocus(xw.ime.xic);
- win.mode |= MODE_FOCUSED;
- xseturgency(0);
- if (IS_SET(MODE_FOCUS))
- ttywrite("\033[I", 3, 0);
- } else {
- if (xw.ime.xic)
- XUnsetICFocus(xw.ime.xic);
- win.mode &= ~MODE_FOCUSED;
- if (IS_SET(MODE_FOCUS))
- ttywrite("\033[O", 3, 0);
- }
-}
-
-int
-match(uint mask, uint state)
-{
- return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
-}
-
-char*
-kmap(KeySym k, uint state)
-{
- Key *kp;
- int i;
-
- /* Check for mapped keys out of X11 function keys. */
- for (i = 0; i < LEN(mappedkeys); i++) {
- if (mappedkeys[i] == k)
- break;
- }
- if (i == LEN(mappedkeys)) {
- if ((k & 0xFFFF) < 0xFD00)
- return NULL;
- }
-
- for (kp = key; kp < key + LEN(key); kp++) {
- if (kp->k != k)
- continue;
-
- if (!match(kp->mask, state))
- continue;
-
- if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0)
- continue;
- if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2)
- continue;
-
- if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0)
- continue;
-
- return kp->s;
- }
-
- return NULL;
-}
-
-void
-kpress(XEvent *ev)
-{
- XKeyEvent *e = &ev->xkey;
- KeySym ksym;
- 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), ttyfd, xev, drawing;
- struct timespec seltv, *tv, now, lastblink, trigger;
- double timeout;
-
- /* Waiting for window mapping */
- do {
- XNextEvent(xw.dpy, &ev);
- /*
- * This XFilterEvent call is required because of XOpenIM. It
- * does filter out the key event and some client message for
- * the input method too.
- */
- if (XFilterEvent(&ev, None))
- continue;
- if (ev.type == ConfigureNotify) {
- w = ev.xconfigure.width;
- h = ev.xconfigure.height;
- }
- } while (ev.type != MapNotify);
-
- ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
- cresize(w, h);
-
- for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) {
- FD_ZERO(&rfd);
- FD_SET(ttyfd, &rfd);
- FD_SET(xfd, &rfd);
-
- if (XPending(xw.dpy))
- timeout = 0; /* existing events might not set xfd */
-
- seltv.tv_sec = timeout / 1E3;
- seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec);
- tv = timeout >= 0 ? &seltv : NULL;
-
- if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
- if (errno == EINTR)
- continue;
- die("select failed: %s\n", strerror(errno));
- }
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- if (FD_ISSET(ttyfd, &rfd))
- ttyread();
-
- xev = 0;
- while (XPending(xw.dpy)) {
- xev = 1;
- XNextEvent(xw.dpy, &ev);
- if (XFilterEvent(&ev, None))
- continue;
- if (handler[ev.type])
- (handler[ev.type])(&ev);
- }
-
- /*
- * To reduce flicker and tearing, when new content or event
- * triggers drawing, we first wait a bit to ensure we got
- * everything, and if nothing new arrives - we draw.
- * We start with trying to wait minlatency ms. If more content
- * arrives sooner, we retry with shorter and shorter periods,
- * and eventually draw even without idle after maxlatency ms.
- * Typically this results in low latency while interacting,
- * maximum latency intervals during `cat huge.txt`, and perfect
- * sync with periodic updates from animations/key-repeats/etc.
- */
- if (FD_ISSET(ttyfd, &rfd) || xev) {
- if (!drawing) {
- trigger = now;
- drawing = 1;
- }
- timeout = (maxlatency - TIMEDIFF(now, trigger)) \
- / maxlatency * minlatency;
- if (timeout > 0)
- continue; /* we have time, try to find idle */
- }
-
- /* idle detected or maxlatency exhausted -> draw */
- timeout = -1;
- if (blinktimeout && tattrset(ATTR_BLINK)) {
- timeout = blinktimeout - TIMEDIFF(now, lastblink);
- if (timeout <= 0) {
- if (-timeout > blinktimeout) /* start visible */
- win.mode |= MODE_BLINK;
- win.mode ^= MODE_BLINK;
- tsetdirtattr(ATTR_BLINK);
- lastblink = now;
- timeout = blinktimeout;
- }
- }
-
- draw();
- XFlush(xw.dpy);
- drawing = 0;
- }
-}
-
-void
-usage(void)
-{
- die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]"
- " [-n name] [-o file]\n"
- " [-T title] [-t title] [-w windowid]"
- " [[-e] command [args ...]]\n"
- " %s [-aiv] [-c class] [-f font] [-g geometry]"
- " [-n name] [-o file]\n"
- " [-T title] [-t title] [-w windowid] -l line"
- " [stty_args ...]\n", argv0, argv0);
-}
-
-int
-main(int argc, char *argv[])
-{
- xw.l = xw.t = 0;
- xw.isfixed = False;
- xsetcursor(cursorshape);
-
- ARGBEGIN {
- case 'a':
- allowaltscreen = 0;
- break;
- case 'c':
- opt_class = EARGF(usage());
- break;
- case 'e':
- if (argc > 0)
- --argc, ++argv;
- goto run;
- case 'f':
- opt_font = EARGF(usage());
- break;
- case 'g':
- xw.gm = XParseGeometry(EARGF(usage()),
- &xw.l, &xw.t, &cols, &rows);
- break;
- case 'i':
- xw.isfixed = 1;
- break;
- case 'o':
- opt_io = EARGF(usage());
- break;
- case 'l':
- opt_line = EARGF(usage());
- break;
- case 'n':
- opt_name = EARGF(usage());
- break;
- case 't':
- case 'T':
- opt_title = EARGF(usage());
- break;
- case 'w':
- opt_embed = EARGF(usage());
- break;
- case 'v':
- die("%s " VERSION "\n", argv0);
- break;
- default:
- usage();
- } ARGEND;
-
-run:
- if (argc > 0) /* eat all remaining arguments */
- opt_cmd = argv;
-
- if (!opt_title)
- opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0];
-
- setlocale(LC_CTYPE, "");
- XSetLocaleModifiers("");
- cols = MAX(cols, 1);
- rows = MAX(rows, 1);
- tnew(cols, rows);
- xinit(cols, rows);
- xsetenv();
- selinit();
- run();
-
- return 0;
-}