From 050f09d1615d4950e8ad9ceb0a473a5f845128c5 Mon Sep 17 00:00:00 2001 From: DarthMooMancer Date: Sat, 26 Jul 2025 16:39:17 -0400 Subject: [PATCH] wip --- .bashrc | 8 +- .config/nvim/init.lua | 48 +- .config/suckless/dmenu/config.def.h | 2 +- .config/suckless/dmenu/config.def.h.orig | 37 - .config/suckless/dmenu/config.h | 2 +- .config/suckless/dmenu/dmenu | Bin 46696 -> 42456 bytes .config/suckless/dmenu/dmenu.1.orig | 202 -- .config/suckless/dmenu/dmenu.c.orig | 1057 ------- .config/suckless/dmenu/dmenu.o | Bin 32736 -> 33408 bytes .config/suckless/dmenu/drw.o | Bin 12168 -> 11464 bytes .config/suckless/dmenu/stest | Bin 16448 -> 16288 bytes .config/suckless/dmenu/stest.o | Bin 5992 -> 5344 bytes .config/suckless/dmenu/util.o | Bin 2464 -> 2472 bytes .config/suckless/dwm/config.def.h | 6 +- .config/suckless/dwm/config.h | 6 +- .config/suckless/dwm/dwm | Bin 66704 -> 66512 bytes .config/suckless/dwm/dwm.o | Bin 58408 -> 57808 bytes .config/suckless/dwm/scripts/edit-suckless.sh | 6 +- .config/suckless/st/FAQ | 253 -- .config/suckless/st/LEGACY | 17 - .config/suckless/st/LICENSE | 34 - .config/suckless/st/README | 34 - .config/suckless/st/TODO | 28 - .config/suckless/st/config.def.h | 48 +- .config/suckless/st/config.def.h.rej | 11 - .config/suckless/st/config.h | 48 +- .../st/patches/st-alpha-20240814-a0274bc.diff | 129 - .../patches/st-dynamic-cursor-color-0.9.diff | 50 - .config/suckless/st/st | Bin 108544 -> 108608 bytes .config/suckless/st/st.c.orig | 2682 ----------------- .config/suckless/st/x.c.orig | 2104 ------------- .config/suckless/st/x.o | Bin 76592 -> 76696 bytes env.sh | 62 + 33 files changed, 116 insertions(+), 6758 deletions(-) delete mode 100644 .config/suckless/dmenu/config.def.h.orig delete mode 100644 .config/suckless/dmenu/dmenu.1.orig delete mode 100644 .config/suckless/dmenu/dmenu.c.orig delete mode 100644 .config/suckless/st/FAQ delete mode 100644 .config/suckless/st/LEGACY delete mode 100644 .config/suckless/st/LICENSE delete mode 100644 .config/suckless/st/README delete mode 100644 .config/suckless/st/TODO delete mode 100644 .config/suckless/st/config.def.h.rej delete mode 100644 .config/suckless/st/patches/st-alpha-20240814-a0274bc.diff delete mode 100644 .config/suckless/st/patches/st-dynamic-cursor-color-0.9.diff delete mode 100644 .config/suckless/st/st.c.orig delete mode 100644 .config/suckless/st/x.c.orig create mode 100755 env.sh diff --git a/.bashrc b/.bashrc index 6bd1315..72d210d 100644 --- a/.bashrc +++ b/.bashrc @@ -1,11 +1,9 @@ if [[ $- != *i* ]] ; then - # Shell is non-interactive. Be done now! return fi -export PATH="/usr/lib/llvm/20/bin:$PATH" - alias ls="ls -a --color" -alias comp="sudo rm -rf config.h && make && sudo make install && pkill dwm" +alias comp="doas rm -rf config.h && make && doas make install" alias edit="sh /home/andrew/.config/suckless/dwm/scripts/edit-suckless.sh" -alias update_world="sudo emerge --ask --update --newuse --deep @world" +alias update_world="doas emerge --ask --update --newuse --deep @world" +alias env="sh /home/andrew/dotfiles/env.sh" diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 1f2d7a9..5054a5d 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -1,3 +1,30 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", "https://github.com/folke/lazy.nvim.git", lazypath }) +end +vim.opt.rtp:prepend(lazypath) + +vim.g.mapleader = " " +require("lazy").setup({ + spec = { + "neovim/nvim-lspconfig", + "nvim-treesitter/nvim-treesitter", + "cohama/lexima.vim", + "DarthMoomancer/Polydev", + "nvim-telescope/telescope.nvim", + "nvim-lua/plenary.nvim", + { "saghen/blink.cmp", version = "v1.*", opts = { + completion = { + ghost_text = { + enabled = true + } + } + } + }, + checker = { enabled = true }, + }, +}) vim.opt.mouse = "" vim.opt.completeopt = "noselect" vim.opt.termguicolors = true @@ -9,7 +36,6 @@ vim.opt.hlsearch = false vim.opt.swapfile = false vim.opt.clipboard = unnamedplus -vim.g.mapleader = " " vim.keymap.set("v", "J", ":m '>+1gv=gv") vim.keymap.set("v", "K", ":m '<-2gv=gv") vim.keymap.set("x", "p", [["_dP]]) @@ -19,7 +45,7 @@ vim.keymap.set('n', 'xg', ":Telescope live_grep", { desc = 'Telescop vim.keymap.set('n', 'xh', ":Telescope help_tags", { desc = 'Telescope help tags' }) vim.keymap.set("n", "xc", "cclose") vim.keymap.set("n", "xx", function() - vim.diagnostic.setqflist({ open = true }) + vim.diagnostic.setqflist({ open = true }) end, { desc = "Show diagnostics in quickfix" }) vim.cmd.colorscheme('everforest') @@ -32,24 +58,6 @@ vim.api.nvim_create_autocmd("FileType", { end, }) - -vim.pack.add({ - "neovim/nvim-lspconfig", - "nvim-treesitter/nvim-treesitter", - "cohama/lexima.vim", - "DarthMoomancer/Polydev", - "nvim-telescope/telescope.nvim", - "nvim-lua/plenary.nvim", - { src = "saghen/blink.cmp", version = "v1.*" }, -}) - -require("blink.cmp").setup({ - completion = { - ghost_text = { - enabled = true - } - } -}) require("nvim-treesitter.configs").setup({ highlight = { enable = true }, indent = { enable = true } diff --git a/.config/suckless/dmenu/config.def.h b/.config/suckless/dmenu/config.def.h index a9bd8bc..b0dcf68 100644 --- a/.config/suckless/dmenu/config.def.h +++ b/.config/suckless/dmenu/config.def.h @@ -1,7 +1,7 @@ #include "/home/andrew/.config/suckless/dwm/themes/everforest.h" static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ static const char *fonts[] = { - "CaskaydiaCove NFM style:Regular:size=12" + "CaskaydiaCove NFM style:SemiBold:size=11" }; static const char *prompt = NULL; /* -p option; prompt to the left of input field */ static const char *colors[SchemeLast][2] = { diff --git a/.config/suckless/dmenu/config.def.h.orig b/.config/suckless/dmenu/config.def.h.orig deleted file mode 100644 index 82f05c3..0000000 --- a/.config/suckless/dmenu/config.def.h.orig +++ /dev/null @@ -1,37 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -/* Default settings; can be overriden by command line. */ - -static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -/* -fn option overrides fonts[0]; default X11 font or font set */ -static const char *fonts[] = { - "monospace:size=10" -}; -static const char *prompt = NULL; /* -p option; prompt to the left of input field */ -static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, - [SchemeCursor] = { "#222222", "#bbbbbb"}, -}; -/* -l and -g options; controls number of lines and columns in grid if > 0 */ -static unsigned int lines = 0; -static unsigned int columns = 0; - -/* - * Characters not considered part of a word while deleting words - * for example: " /?\"&[]" - */ -static const char worddelimiters[] = " "; - -/* - * -vi option; if nonzero, vi mode is always enabled and can be - * accessed with the global_esc keysym + mod mask - */ -static unsigned int vi_mode = 1; -static unsigned int start_mode = 0; /* mode to use when -vi is passed. 0 = insert mode, 1 = normal mode */ -static Key global_esc = { XK_n, Mod1Mask }; /* escape key when vi mode is not enabled explicitly */ -static Key quit_keys[] = { - /* keysym modifier */ - { XK_q, 0 } -}; diff --git a/.config/suckless/dmenu/config.h b/.config/suckless/dmenu/config.h index a9bd8bc..b0dcf68 100644 --- a/.config/suckless/dmenu/config.h +++ b/.config/suckless/dmenu/config.h @@ -1,7 +1,7 @@ #include "/home/andrew/.config/suckless/dwm/themes/everforest.h" static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ static const char *fonts[] = { - "CaskaydiaCove NFM style:Regular:size=12" + "CaskaydiaCove NFM style:SemiBold:size=11" }; static const char *prompt = NULL; /* -p option; prompt to the left of input field */ static const char *colors[SchemeLast][2] = { diff --git a/.config/suckless/dmenu/dmenu b/.config/suckless/dmenu/dmenu index ac1ae3d3b9e0574468adae3cc9c489a4a3c25d22..072a8f356879574f0c5ef4de8ebb59b2529343b1 100755 GIT binary patch literal 42456 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 Ml^AYFU|@y+3(|_W+5i9m literal 46696 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

5232^rX5et_cc}rU9(u=@ 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 b>(Ok!8cKVZ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef XINERAMA -#include -#endif -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ - * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -/* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeCursor, SchemeLast }; /* color schemes */ - -struct item { - char *text; - struct item *left, *right; - int out; -}; - -typedef struct { - KeySym ksym; - unsigned int state; -} Key; - -static char text[BUFSIZ] = ""; -static char *embed; -static int bh, mw, mh; -static int inputw = 0, promptw; -static int lrpad; /* sum of left and right padding */ -static size_t cursor; -static struct item *items = NULL; -static struct item *matches, *matchend; -static struct item *prev, *curr, *next, *sel; -static int mon = -1, screen; -static unsigned int using_vi_mode = 0; - -static Atom clip, utf8; -static Display *dpy; -static Window root, parentwin, win; -static XIC xic; - -static Drw *drw; -static Clr *scheme[SchemeLast]; - -#include "config.h" - -static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; -static char *(*fstrstr)(const char *, const char *) = strstr; - -static unsigned int -textw_clamp(const char *str, unsigned int n) -{ - unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; - return MIN(w, n); -} - -static void -appenditem(struct item *item, struct item **list, struct item **last) -{ - if (*last) - (*last)->right = item; - else - *list = item; - - item->left = *last; - item->right = NULL; - *last = item; -} - -static void -calcoffsets(void) -{ - int i, n; - - if (lines > 0) - n = lines * columns * bh; - else - n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); - /* calculate which items will begin the next page and previous page */ - for (i = 0, next = curr; next; next = next->right) - if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) - break; - for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) - break; -} - -static void -cleanup(void) -{ - size_t i; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < SchemeLast; i++) - free(scheme[i]); - for (i = 0; items && items[i].text; ++i) - free(items[i].text); - free(items); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static char * -cistrstr(const char *h, const char *n) -{ - size_t i; - - if (!n[0]) - return (char *)h; - - for (; *h; ++h) { - for (i = 0; n[i] && tolower((unsigned char)n[i]) == - tolower((unsigned char)h[i]); ++i) - ; - if (n[i] == '\0') - return (char *)h; - } - return NULL; -} - -static int -drawitem(struct item *item, int x, int y, int w) -{ - if (item == sel) - drw_setscheme(drw, scheme[SchemeSel]); - else if (item->out) - drw_setscheme(drw, scheme[SchemeOut]); - else - drw_setscheme(drw, scheme[SchemeNorm]); - - return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -} - -static void -drawmenu(void) -{ - unsigned int curpos; - struct item *item; - int x = 0, y = 0, w; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); - - if (prompt && *prompt) { - drw_setscheme(drw, scheme[SchemeSel]); - x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); - } - /* draw input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); - - curpos = TEXTW(text) - TEXTW(&text[cursor]); - curpos += lrpad / 2 - 1; - if (using_vi_mode && text[0] != '\0') { - drw_setscheme(drw, scheme[SchemeCursor]); - char vi_char[] = {text[cursor], '\0'}; - drw_text(drw, x + curpos, 0, TEXTW(vi_char) - lrpad, bh, 0, vi_char, 0); - } else if (using_vi_mode) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2, lrpad / 2, bh - 4, 1, 0); - } else if (curpos < w) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); - } - - if (lines > 0) { - /* draw grid */ - int i = 0; - for (item = curr; item != next; item = item->right, i++) - drawitem( - item, - x + ((i / lines) * ((mw - x) / columns)), - y + (((i % lines) + 1) * bh), - (mw - x) / columns - ); - } else if (matches) { - /* draw horizontal list */ - x += inputw; - w = TEXTW("<"); - if (curr->left) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); - } - x += w; - for (item = curr; item != next; item = item->right) - x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); - if (next) { - w = TEXTW(">"); - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); - } - } - drw_map(drw, win, 0, 0, mw, mh); -} - -static void -grabfocus(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; - Window focuswin; - int i, revertwin; - - for (i = 0; i < 100; ++i) { - XGetInputFocus(dpy, &focuswin, &revertwin); - if (focuswin == win) - return; - XSetInputFocus(dpy, win, RevertToParent, CurrentTime); - nanosleep(&ts, NULL); - } - die("cannot grab focus"); -} - -static void -grabkeyboard(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; - int i; - - if (embed) - return; - /* try to grab keyboard, we may have to wait for another process to ungrab */ - for (i = 0; i < 1000; i++) { - if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, - GrabModeAsync, CurrentTime) == GrabSuccess) - return; - nanosleep(&ts, NULL); - } - die("cannot grab keyboard"); -} - -static void -match(void) -{ - static char **tokv = NULL; - static int tokn = 0; - - char buf[sizeof text], *s; - int i, tokc = 0; - size_t len, textsize; - struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; - - strcpy(buf, text); - /* separate input text into tokens to be matched individually */ - for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) - if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) - die("cannot realloc %zu bytes:", tokn * sizeof *tokv); - len = tokc ? strlen(tokv[0]) : 0; - - matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - textsize = strlen(text) + 1; - for (item = items; item && item->text; item++) { - for (i = 0; i < tokc; i++) - if (!fstrstr(item->text, tokv[i])) - break; - if (i != tokc) /* not all tokens match */ - continue; - /* exact matches go first, then prefixes, then substrings */ - if (!tokc || !fstrncmp(text, item->text, textsize)) - appenditem(item, &matches, &matchend); - else if (!fstrncmp(tokv[0], item->text, len)) - appenditem(item, &lprefix, &prefixend); - else - appenditem(item, &lsubstr, &substrend); - } - if (lprefix) { - if (matches) { - matchend->right = lprefix; - lprefix->left = matchend; - } else - matches = lprefix; - matchend = prefixend; - } - if (lsubstr) { - if (matches) { - matchend->right = lsubstr; - lsubstr->left = matchend; - } else - matches = lsubstr; - matchend = substrend; - } - curr = sel = matches; - calcoffsets(); -} - -static void -insert(const char *str, ssize_t n) -{ - if (strlen(text) + n > sizeof text - 1) - return; - /* move existing text out of the way, insert new text, and update cursor */ - memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); - if (n > 0) - memcpy(&text[cursor], str, n); - cursor += n; - match(); -} - -static size_t -nextrune(int inc) -{ - ssize_t n; - - /* return location of next utf8 rune in the given direction (+1 or -1) */ - for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) - ; - return n; -} - -static void -movewordedge(int dir) -{ - if (dir < 0) { /* move cursor to the start of the word*/ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - } else { /* move cursor to the end of the word */ - while (text[cursor] && strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - while (text[cursor] && !strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - } -} - -static void -vi_keypress(KeySym ksym, const XKeyEvent *ev) -{ - static const size_t quit_len = LENGTH(quit_keys); - if (ev->state & ControlMask) { - switch(ksym) { - /* movement */ - case XK_d: /* fallthrough */ - if (next) { - sel = curr = next; - calcoffsets(); - goto draw; - } else - ksym = XK_G; - break; - case XK_u: - if (prev) { - sel = curr = prev; - calcoffsets(); - goto draw; - } else - ksym = XK_g; - break; - case XK_p: /* fallthrough */ - case XK_P: break; - case XK_c: - cleanup(); - exit(1); - case XK_Return: /* fallthrough */ - case XK_KP_Enter: break; - default: return; - } - } - - switch(ksym) { - /* movement */ - case XK_0: - cursor = 0; - break; - case XK_dollar: - if (text[cursor + 1] != '\0') { - cursor = strlen(text) - 1; - break; - } - break; - case XK_b: - movewordedge(-1); - break; - case XK_e: - cursor = nextrune(+1); - movewordedge(+1); - if (text[cursor] == '\0') - --cursor; - else - cursor = nextrune(-1); - break; - case XK_g: - if (sel == matches) { - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_G: - if (next) { - /* jump to end of list and position items in reverse */ - curr = matchend; - calcoffsets(); - curr = prev; - calcoffsets(); - while (next && (curr = curr->right)) - calcoffsets(); - } - sel = matchend; - break; - case XK_h: - if (cursor) - cursor = nextrune(-1); - break; - case XK_j: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_k: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_l: - if (text[cursor] != '\0' && text[cursor + 1] != '\0') - cursor = nextrune(+1); - else if (text[cursor] == '\0' && cursor) - --cursor; - break; - case XK_w: - movewordedge(+1); - if (text[cursor] != '\0' && text[cursor + 1] != '\0') - cursor = nextrune(+1); - else if (cursor) - --cursor; - break; - /* insertion */ - case XK_a: - cursor = nextrune(+1); - /* fallthrough */ - case XK_i: - using_vi_mode = 0; - break; - case XK_A: - if (text[cursor] != '\0') - cursor = strlen(text); - using_vi_mode = 0; - break; - case XK_I: - cursor = using_vi_mode = 0; - break; - case XK_p: - if (text[cursor] != '\0') - cursor = nextrune(+1); - XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return; - case XK_P: - XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return; - /* deletion */ - case XK_D: - text[cursor] = '\0'; - if (cursor) - cursor = nextrune(-1); - match(); - break; - case XK_x: - cursor = nextrune(+1); - insert(NULL, nextrune(-1) - cursor); - if (text[cursor] == '\0' && text[0] != '\0') - --cursor; - match(); - break; - /* misc. */ - case XK_Return: - case XK_KP_Enter: - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); - if (!(ev->state & ControlMask)) { - cleanup(); - exit(0); - } - if (sel) - sel->out = 1; - break; - case XK_Tab: - if (!sel) - return; - strncpy(text, sel->text, sizeof text - 1); - text[sizeof text - 1] = '\0'; - cursor = strlen(text) - 1; - match(); - break; - default: - for (size_t i = 0; i < quit_len; ++i) - if (quit_keys[i].ksym == ksym && - (quit_keys[i].state & ev->state) == quit_keys[i].state) { - cleanup(); - exit(1); - } - } - -draw: - drawmenu(); -} - -static void -keypress(XKeyEvent *ev) -{ - char buf[64]; - int len; - KeySym ksym = NoSymbol; - Status status; - int i, offscreen = 0; - struct item *tmpsel; - - len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); - switch (status) { - default: /* XLookupNone, XBufferOverflow */ - return; - case XLookupChars: /* composed string from input method */ - goto insert; - case XLookupKeySym: - case XLookupBoth: /* a KeySym and a string are returned: use keysym */ - break; - } - - if (using_vi_mode) { - vi_keypress(ksym, ev); - return; - } else if (vi_mode && - (ksym == global_esc.ksym && - (ev->state & global_esc.state) == global_esc.state)) { - using_vi_mode = 1; - if (cursor) - cursor = nextrune(-1); - goto draw; - } - - if (ev->state & ControlMask) { - switch(ksym) { - case XK_a: ksym = XK_Home; break; - case XK_b: ksym = XK_Left; break; - case XK_c: ksym = XK_Escape; break; - case XK_d: ksym = XK_Delete; break; - case XK_e: ksym = XK_End; break; - case XK_f: ksym = XK_Right; break; - case XK_g: ksym = XK_Escape; break; - case XK_h: ksym = XK_BackSpace; break; - case XK_i: ksym = XK_Tab; break; - case XK_j: /* fallthrough */ - case XK_J: /* fallthrough */ - case XK_m: /* fallthrough */ - case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; - case XK_n: ksym = XK_Down; break; - case XK_p: ksym = XK_Up; break; - - case XK_k: /* delete right */ - text[cursor] = '\0'; - match(); - break; - case XK_u: /* delete left */ - insert(NULL, 0 - cursor); - break; - case XK_w: /* delete word */ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - break; - case XK_y: /* paste selection */ - case XK_Y: - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return; - case XK_Left: - case XK_KP_Left: - movewordedge(-1); - goto draw; - case XK_Right: - case XK_KP_Right: - movewordedge(+1); - goto draw; - case XK_Return: - case XK_KP_Enter: - break; - case XK_bracketleft: - cleanup(); - exit(1); - default: - return; - } - } else if (ev->state & Mod1Mask) { - switch(ksym) { - case XK_b: - movewordedge(-1); - goto draw; - case XK_f: - movewordedge(+1); - goto draw; - case XK_g: ksym = XK_Home; break; - case XK_G: ksym = XK_End; break; - case XK_h: ksym = XK_Up; break; - case XK_j: ksym = XK_Next; break; - case XK_k: ksym = XK_Prior; break; - case XK_l: ksym = XK_Down; break; - default: - return; - } - } - - switch(ksym) { - default: -insert: - if (!iscntrl((unsigned char)*buf)) - insert(buf, len); - break; - case XK_Delete: - case XK_KP_Delete: - if (text[cursor] == '\0') - return; - cursor = nextrune(+1); - /* fallthrough */ - case XK_BackSpace: - if (cursor == 0) - return; - insert(NULL, nextrune(-1) - cursor); - break; - case XK_End: - case XK_KP_End: - if (text[cursor] != '\0') { - cursor = strlen(text); - break; - } - if (next) { - /* jump to end of list and position items in reverse */ - curr = matchend; - calcoffsets(); - curr = prev; - calcoffsets(); - while (next && (curr = curr->right)) - calcoffsets(); - } - sel = matchend; - break; - case XK_Escape: - cleanup(); - exit(1); - case XK_Home: - case XK_KP_Home: - if (sel == matches) { - cursor = 0; - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_Left: - if (columns > 1) { - if (!sel) - return; - tmpsel = sel; - for (i = 0; i < lines; i++) { - if (!tmpsel->left || tmpsel->left->right != tmpsel) { - if (offscreen) - break; - return; - } - if (tmpsel == curr) - offscreen = 1; - tmpsel = tmpsel->left; - } - sel = tmpsel; - if (offscreen) { - curr = prev; - calcoffsets(); - } - break; - } - case XK_KP_Left: - if (cursor > 0 && (!sel || !sel->left || lines > 0)) { - cursor = nextrune(-1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Up: - case XK_KP_Up: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_Next: - case XK_KP_Next: - if (!next) - return; - sel = curr = next; - calcoffsets(); - break; - case XK_Prior: - case XK_KP_Prior: - if (!prev) - return; - sel = curr = prev; - calcoffsets(); - break; - case XK_Return: - case XK_KP_Enter: - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); - if (!(ev->state & ControlMask)) { - cleanup(); - exit(0); - } - if (sel) - sel->out = 1; - break; - case XK_Right: - if (columns > 1) { - if (!sel) - return; - tmpsel = sel; - for (i = 0; i < lines; i++) { - if (!tmpsel->right || tmpsel->right->left != tmpsel) { - if (offscreen) - break; - return; - } - tmpsel = tmpsel->right; - if (tmpsel == next) - offscreen = 1; - } - sel = tmpsel; - if (offscreen) { - curr = next; - calcoffsets(); - } - break; - } - case XK_KP_Right: - if (text[cursor] != '\0') { - cursor = nextrune(+1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Down: - case XK_KP_Down: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_Tab: - if (!sel) - return; - cursor = strnlen(sel->text, sizeof text - 1); - memcpy(text, sel->text, cursor); - text[cursor] = '\0'; - match(); - break; - } - -draw: - drawmenu(); -} - -static void -paste(void) -{ - char *p, *q; - int di; - unsigned long dl; - Atom da; - - /* we have been given the current selection, now insert it into input */ - if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, - utf8, &da, &di, &dl, &dl, (unsigned char **)&p) - == Success && p) { - insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); - XFree(p); - } - if (using_vi_mode && text[cursor] == '\0') - --cursor; - drawmenu(); -} - -static void -readstdin(void) -{ - char *line = NULL; - size_t i, itemsiz = 0, linesiz = 0; - ssize_t len; - - /* read each line from stdin and add it to the item list */ - for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) { - if (i + 1 >= itemsiz) { - itemsiz += 256; - if (!(items = realloc(items, itemsiz * sizeof(*items)))) - die("cannot realloc %zu bytes:", itemsiz * sizeof(*items)); - } - if (line[len - 1] == '\n') - line[len - 1] = '\0'; - if (!(items[i].text = strdup(line))) - die("strdup:"); - - items[i].out = 0; - } - free(line); - if (items) - items[i].text = NULL; - lines = MIN(lines, i); -} - -static void -run(void) -{ - XEvent ev; - - while (!XNextEvent(dpy, &ev)) { - if (XFilterEvent(&ev, win)) - continue; - switch(ev.type) { - case DestroyNotify: - if (ev.xdestroywindow.window != win) - break; - cleanup(); - exit(1); - case Expose: - if (ev.xexpose.count == 0) - drw_map(drw, win, 0, 0, mw, mh); - break; - case FocusIn: - /* regrab focus from parent window */ - if (ev.xfocus.window != win) - grabfocus(); - break; - case KeyPress: - keypress(&ev.xkey); - break; - case SelectionNotify: - if (ev.xselection.property == utf8) - paste(); - break; - case VisibilityNotify: - if (ev.xvisibility.state != VisibilityUnobscured) - XRaiseWindow(dpy, win); - break; - } - } -} - -static void -setup(void) -{ - int x, y, i, j; - unsigned int du; - XSetWindowAttributes swa; - XIM xim; - Window w, dw, *dws; - XWindowAttributes wa; - XClassHint ch = {"dmenu", "dmenu"}; -#ifdef XINERAMA - XineramaScreenInfo *info; - Window pw; - int a, di, n, area = 0; -#endif - /* init appearance */ - for (j = 0; j < SchemeLast; j++) - scheme[j] = drw_scm_create(drw, colors[j], 2); - - clip = XInternAtom(dpy, "CLIPBOARD", False); - utf8 = XInternAtom(dpy, "UTF8_STRING", False); - - /* calculate menu geometry */ - bh = drw->fonts->h + 2; - lines = MAX(lines, 0); - mh = (lines + 1) * bh; -#ifdef XINERAMA - i = 0; - if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { - XGetInputFocus(dpy, &w, &di); - if (mon >= 0 && mon < n) - i = mon; - else if (w != root && w != PointerRoot && w != None) { - /* find top-level window containing current input focus */ - do { - if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) - XFree(dws); - } while (w != root && w != pw); - /* find xinerama screen with which the window intersects most */ - if (XGetWindowAttributes(dpy, pw, &wa)) - for (j = 0; j < n; j++) - if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { - area = a; - i = j; - } - } - /* no focused window is on screen, so use pointer location instead */ - if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) - for (i = 0; i < n; i++) - if (INTERSECT(x, y, 1, 1, info[i]) != 0) - break; - - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; - } - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = mw / 3; /* input width: ~33% of monitor width */ - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, root, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - XSetClassHint(dpy, win, &ch); - - /* input methods */ - if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) - die("XOpenIM failed: could not open input device"); - - xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, win, XNFocusWindow, win, NULL); - - XMapRaised(dpy, win); - if (embed) { - XReparentWindow(dpy, win, parentwin, x, y); - XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); - if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { - for (i = 0; i < du && dws[i] != win; ++i) - XSelectInput(dpy, dws[i], FocusChangeMask); - XFree(dws); - } - grabfocus(); - } - drw_resize(drw, mw, mh); - drawmenu(); -} - -static void -usage(void) -{ - die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); -} - -int -main(int argc, char *argv[]) -{ - XWindowAttributes wa; - int i, fast = 0; - - for (i = 1; i < argc; i++) - /* these options take no arguments */ - if (!strcmp(argv[i], "-v")) { /* prints version information */ - puts("dmenu-"VERSION); - exit(0); - } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ - topbar = 0; - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; - } else if (!strcmp(argv[i], "-vi")) { - vi_mode = 1; - using_vi_mode = start_mode; - global_esc.ksym = XK_Escape; - global_esc.state = 0; - } else if (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-g")) { /* number of columns in grid */ - columns = atoi(argv[++i]); - if (lines == 0) lines = 1; - } else if (!strcmp(argv[i], "-l")) { /* number of lines in grid */ - lines = atoi(argv[++i]); - if (columns == 0) columns = 1; - } else if (!strcmp(argv[i], "-m")) - mon = atoi(argv[++i]); - else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ - prompt = argv[++i]; - else if (!strcmp(argv[i], "-fn")) /* font or font set */ - fonts[0] = argv[++i]; - else if (!strcmp(argv[i], "-nb")) /* normal background color */ - colors[SchemeNorm][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ - colors[SchemeNorm][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-sb")) /* selected background color */ - colors[SchemeSel][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ - colors[SchemeSel][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; - else - usage(); - - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("cannot open display"); - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - if (!embed || !(parentwin = strtol(embed, NULL, 0))) - parentwin = root; - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - drw = drw_create(dpy, screen, root, wa.width, wa.height); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - -#ifdef __OpenBSD__ - if (pledge("stdio rpath", NULL) == -1) - die("pledge"); -#endif - - if (fast && !isatty(0)) { - grabkeyboard(); - readstdin(); - } else { - readstdin(); - grabkeyboard(); - } - setup(); - run(); - - return 1; /* unreachable */ -} diff --git a/.config/suckless/dmenu/dmenu.o b/.config/suckless/dmenu/dmenu.o index 0319985f424298ad5bad5f8d9ec11c1a02e069fe..4ca0b32183ad6c0a907e2390a9c94c6425955ef2 100644 GIT binary patch literal 33408 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 literal 32736 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 diff --git a/.config/suckless/dmenu/drw.o b/.config/suckless/dmenu/drw.o index e9254846fa71e1e3a1b4e7d19d4b72d43239a128..69dbfa9f910b2da334855d573d810016a6cee0e0 100644 GIT binary patch literal 11464 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 TbCK}Az4Z=B(Roci-Q)ikvLk1R literal 12168 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 TyXavEh5qv=6%s={#r*#Rt;}&X diff --git a/.config/suckless/dmenu/stest b/.config/suckless/dmenu/stest index 7f0523d459b6e8ae6060cf034a74c70b4fd461ec..047c1868df1c12f564c5dd07ad934b0cffe3cac9 100755 GIT binary patch literal 16288 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 literal 16448 zcmeHOeRNajd4DC_Sb&j45&|J@&;gO+G7F1O2XG@98($GY9AeUZ02d+4wia7*q^sbh zY!Q*1<<=-8Tef9?bR#{dNw;M!=@Jg@3UvbIW9OtL+16xRPUmq}CY8`Q3#BAYeD^%> zeIM!SM(XM5diKxs`dmNn^LswtkNbXJz3*dP!Od2Sg;A(uUtq}fT&E*GA(&_r5g!DAqEw&g2A|f&y8frA4zpH4&31c)ote6XK2gf<-9J(Kev|ZigxyZz&`f(pdPFI` zyTA_X<<|}LnzxJes=WuBXn#cUePdWL6y3Xa^@^dsmZ4}YHQF-Twzg&MYELrmS;^)2 z8g7IK_4Rxm;5cF!-iZ8QSdUfy{~Exei@VW4q!)^d7`G2ko{zw)4?*XsmKVLNTK{-75pxhsd4zd13B*G%2QH6zv;>k!~6m=f% zA4x=GN}JGSGweF15UnBGHJkROhY_xz?%>dVakA0 z9iix&0l$Hif%XWz5#pi>xb$8FE{0}~?=j#sC!k=^fb;pCYcn=tz%dO9qXryaKry5Z zxL68s*^>r*c2S$LLk1jPbTK?@!0knpvBL)3VZgs`z>VY75d&@<2ag$WY9i=v!hp{+ z_^(B4HBhU8S`E}{pjHEwYTyIMEgwmlcWu&m!?#y3CXG!fR_(l$Ib}P^)wMMX0oIm& z2L3x1`55XCqNH#^)3p9WoW}{g@Mej}g-7AF5|0yk;aephC-A~oOFT~8g+D6sxIig9 zUgB{AFCsG8OFT~Gh3zFCC-6c?iN}e%u(HJC!lkgd#Nz~BxUR(G#9go!d2Q)Y z4`cm~MV*Y7Ut4;kiMN~h876+ZrQH6iiT|02zi8rrY~p`p;(uV`Pn-A?CjO|2|AvWw zzR34L!#E3^G~OnS&%u0pC-P2sA>YH7oS%c0QBCj|xl`?&s^ z?MRxZC3Q-A^=G$BuU@N@ET^S6rj;AO!6&e9MF%!*Qh#q`kL@+xJ`ZeJYWWT+)BdlZ z$t3kBN|Q9+eifMf%xO)__d&r7#vN9|%QRclf{PzsJAB-+Q-o;9cAu zNN4KZm|^Ht3;Lw-`lZXb|E${yLhpp6cDiknTJM&|XGm(pS0I64uHTl6Ytr~;8)Vs$ zZHMk8sUM`|O8?2%nO2b2^|-&SVel zhtdPa{Kv7EUAoVoe$2v@*#Yg0K;}VO&aGpbBYOn&wAcN|alJ3)*8IzI#x};3Mu_gl zVyRmG8<31YbLua>=b&KEyb5pm9guXWO@~wNE#vjegSk=5Hg)6jFZ(Rn3FT&g<`Y|L z9?!9(&<2%^KJEt}m);CoE?ugZGAC{7d%;{-udhv5U&`FVn~-G?IWuRb1L`~KCu5f# z*(Z3OcDkLJ_GchT78u{?R`%v|AMY1(M_3l9C%=MD`?_1Rm zp_xAf<5s%{tMz@e0Sl_r`Lp0DsQx0~4`yHi$*0aC{{--tnlKFsw7!bz!3e6oo;q+z z4vx1!_Ib>}d?~jd-~GjWx1Q?n-zMdDx@`gVqBIVY^!`R|R%+Ji&PENo8&{pq-^24h zpQnE{Z`TbU`yrR-zxhjOhesQxpyHvaHR(-l!$IEEQVTOv7U{sL1@Lwr@bC2R^6&P` zyH4hpgNyu8Fx=t42it5bHX`+dfI3~)T9+Z5d)fUgq@VvUP=}g+(0h49OB@nQEh*`4 z$huM2F}4l{1V|74J>cKH>tv>V1*n2x2?$O%Yyrkn!3=k)P&$KU;p-o1TBiLas5F*p zNN?~ce~@W^0Xb#JTSG=p;QX7v@S$GB&vEHEmpY`(ciq^?Ax#Izzr=AWn$3~D2Hi2!KE&aL z=nUQ;%l`>DJC1f(X>W0rttAy`5-gtp74PM-37_Mc?-yPMmE#B({u*NWTT!OvzjqCK z=YeM^N>G%9!K*|_Z~-cpL@j7{GvMz`i|z8 z-G?~+uKO_1QcF{_?(+Zya|d~=38(?5l*_s&0Sl;pn{>;9|EOjt+n6g2e#jKvp4;b@(K~lFY2&x^B_btDryh|eQl6qG$?-I}Z0+Dw~ zwMe;ncfi8w1kdp+zu-9*vk&x9Q;t#2=W4$8gR$x)II4wO4b*C&Rs*#f`2SM__{&FV zZ@4egKQK5n@=zj~dU)R`Tbf+4G|5uQ&_HCpYiZK;K+C6eb^#c3^+$&y7>iR30guPC zYZg?Y<>tB#JwRu|bLu@!!%gC;DNTD3=sy8Hh5Y-PhD*jPK!<>z{BKQr2k2k?T+=!M zUjtL?L7hD$BLz|3!Vb=%KdGxbk_Q)`difv$0gP&}=x9z~y z`vhWj@L;f}b)J56K^fL3rh)nxP#5!53$+@k)j+KVYBf-+fm#jJYM@pFwHo-pssTD* zMdzt-eTv~do$&Q4Mt^DIn}j0iFEa6XMhrufPKpP{<_P}doAihv#dBXb3pxJif?=Uf z@GCbDxPHe#@}Ey@apc>?!kf-MJt-paC6I?bLXP_}48tOSvvro?2Sg0!GefkVZxiQ= zXuUot>~UX&f!6u+b(W2a3=;mNh)}+14~2U|43z#YI$JCs{NljN2gz|$_!!OkWx^kP zmnS*5ge?>2uZn`h2W8GvIfVP)8liL9W{0h~*@55_v`5fAf{qB97W9yyhXp+%=!Br> z1)UUhN>Dn~>NFl2)06&<{@Z-IS@)(*>s`ybBQYf&cX?NPR(V=oBW=wh3a3Rwu>se^ zkwh{YkGWR1dc2->zcM{+F7@nv&8&p)-@C=~1hU*^++LjuR&FH!%P3CFXE zR=ADuv}j0tZwuHL1pbj|*nIB{*d}Z|0e&6ilkR8SD#YIeDzaW? z@EUNgGDK(I08&Z+LKXZ2#I1Hl z-&MuWgMd3L)X!)YKllx)Qh8qhe6cY>5r3_U{*M5!)aCMsTNf~=uiV)cfm8n?sl|$Z zZelK>Pvc`F;7-8Jey#_+QvN+v@DAZ;!cQscw7ZJ_PQWXbD_%wa@hbQqSHYhL9N(9@ zTz^|dKT`$&2aeBS8^z&Q{_PEl_Cv(2Fsjh_NX3T3^hw1NX8l8<0TzqwWAULrCf^@y zqtop@;T_&}BcWtcj_>{5NLZ1RaBkf@+;d0xQHHi`IHZIJ^^c)wxK5ms?`e|*cgmXs z!LCa7++3F7lb75j$(y(Pw|2===XNG{2k-3g2jx3AZ@#;$SMK$91iRowf9HMM{96N? z#36bgoo2_w>ZZg0c&xunj;Hv`06csj1+%jA`$dgaa2Ebo-Zg+i@e2fU3ho8)ivmSk zo*lfWQ1SACEcbh0S|#pe6cIfQtUAaU-fhscDdXLWq7vM2;CC%#c(w33+LL@_SPAU~sw8we zNHMs;5lM_N&p<5Y84M){nWyiO7^v%1N$3(WgO@Qf$P$sE5E_Ws$dJN3JV_5kJp*xI zF_MggnMa9?0?QklClTib@I(gXez?dHkq7(08*$7Niz^YHrI7^O1W7252*}?NXi=bJ z@w)g&5v6sv5OZCM zBgJ(Bd{W0@k_TFk6Lkxm)}b`c3z*?SG+c|5J+0S?E)xQrCo!L7PwVD2fT3@)r}aNk zTJM7j59q@faC?DkX|kvFGf_Cm$OGk{^oVW&DXz_lr}a6}J-Rvn-N2ZC0kiucf@LFn z+Ak2D5{i_*x%^>a-y!s9|3Q@YD`<~<6tn#>V3;r3FBRtxF^|x`3{-fa^$PKW5HZ@j zgdI_HgQ4k(XwqyiCSjMLq(|uyPjtV@zE#)}ogza)$&Tol$=)Rv8ASh$HgYC=ayxFa zr}ZIG+V_&ax&EFO_VoUlOK1vuzhH@&?f)DESpQ^C>u#dGWGJZF{soi$5tpt=bU!*b z1ZqD7y#x`gB1*s7y<5^Z+n+Mo?^&#C5_OTGpyvF)2{`VVsDIEsGP>_-PLFt^KL%S^ zjTi0ddjlVs04F_&@<2S%p8|?~htj8g4BcO*d&-n=vZMC54{WiD$)5H{Z7TqTa8@V9 z|71@T_a#Pq<`b%|I;C_3`l<5Z{snze`m{cE3i~6b_iy$$4YsHv)FGw^vR_SrpybX- zsqGk5CE@T{QE@mA;d`cX)A*13Xv(|Meo`d-&nD-TF6qv#V*iTR);F3AOf35!@pA*- diff --git a/.config/suckless/dmenu/stest.o b/.config/suckless/dmenu/stest.o index b3eda825e0dba63f0e1b04400529aa1a823d3701..3d5045edfe970f5f039baa0aea26733dec1da66e 100644 GIT binary patch literal 5344 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 diff --git a/.config/suckless/dmenu/util.o b/.config/suckless/dmenu/util.o index 1cfb3b660d9f7419492222ddec159d40df42488c..5dd48bf05707c29dd79ea9c028b4d6e8fb4493f5 100644 GIT binary patch literal 2472 zcmbuAO>7%Q6vy8tE(tWX(+W_eQnW%-u%)uHDTpY1$S5vZkU;@jRlvb)opoc?@tXA* zrGP{b1!)yU>VX3X4jede;J~2=4v4zyp+{~A^-{s9hf1{SjSr>oKRc5QTU$c#q_^+Q z?|tm-%58A?>VXVqQCi^Vq53LO?Iy2#I#DOiD`eUCfqAE zkt=I5tI9W?A$inKuBC$yC$|>{BKbY-oHkRf{jCR75Nwha0^eobjXNri*+3jh$M>c~x?fx8{nyD^pLGt-OiiEXdScyPe#qvp))K~}6+Rvu$8ihE-?_H0ysZ47^941aqJ5618ob3B)M9<|oYPLIi_ zfoylYCVBP6GAsBZAoEzWO)t)RtU}=J_Ubmr;-4&@cE=ER>Lm8i9`P<5$vGS+%QAHn|Mbm%3#S0ccq&fPd z#^gU@<>Qna?y?U-KGaB6JBFL{KwkgsnhZ{{m2qlUjTeWVz?0#+ByS~<0ePqTee&W6 z1Eg2H3VF?FZH+%TV>g9%cW=-t~Oe6uojw`{Xgq+ zIhMluji`oIb>;tyUMD@Y-td$hWP^3Bro)|U5s+nB*JID&nlIEGf-H}+f}8Ir7-Thb z-;}1g#)mz^ik|Zt9GEiQ~q%Q$HUC zN94ZA4DYvnR?+7RUB8ThC1(8%dY2ufX6vv2%lZ!2j@tiq{p&F6g8j#L#oXWQ|EPO& u8qMnoZRmMmAJ8&ekDl4RXGGs?*u}sS-EN2MXKz&fH+udb>|~}+w*C&KO+bzS literal 2464 zcmb_cU1%It6u!HOc5UnKB5D_uIuBFH3Xa)=rleSQLzB$5lNf&z@CT-o+1Yg4&F(ro z8`2<{&?t^;Bo96aiu6HWBn8oeK}xeyUwjY(`XKsX%!3puSoKA$5YKn#UNR2ZH^1fV zIrlq1bI!dp_tjxzBp!<~i5NS+F zRycqP`<6T2Kq`Auok(R3^-L=JoZ3ib-&YqYEtUOHUFCXB zy~Onu^%JhIsvXidNLag1Ur&(kC(-?%bw8%BEUUNps*o`Jm(xc3aayrr`@}WOp!+}Y z#Kq&xdsz2>3Kp;Q>XHRWi(meU4;Fm|ud zv4v+?Y(5=(;NZT*D(#y>{DZ>x3-oX@J(SE8lFDfER_tQ$+dZ$x;m^ZI_!NJm$*oxY zqhz8$nwFUV3<>ZM{;0-jc+q$l{78H+`+a9GcMqnF0MCijkM~G6?}PM#T+9;~SIwXQ6mpsghU7 z2G9>g;-oMnFW;+DgqP>T%omJ-a>K3Eyz;~`v-p%bQZ$Aqa{~>l*);3Z=N#KJo0SD8 zH*wltU|Oy2IoeFEr8V4o!*RU}Omm&8rFqW0$27Y>JL}Xu=FC@UWoS*$WlgW-xKJ*s zy30(HbggdERbhE_KfqIUYQ#4^%RX<~XV05ut5PLmPBaEiJeuyFM|qrhu5;EbyVk73 zN)?Bd8!gXfPH+#gmRG52HbWDhHBI`$EZ4j(Ek_0FCCjtm&(ZS#!8VnVcVf8WCJvRb zUz}&K!rky+jM5Su&N_^|SbQEyzDKp2a&Cc{QD!k%#-?K@=H4$Iv5>D zIHR!}L4G3|o)^S?xG34t`M)4;ul;{RoWCyevH!@G`Evh%B`*4Gq^t{4ez)iw??^QN EUor80{{R30 diff --git a/.config/suckless/dwm/config.def.h b/.config/suckless/dwm/config.def.h index b5e8c87..49d4108 100644 --- a/.config/suckless/dwm/config.def.h +++ b/.config/suckless/dwm/config.def.h @@ -7,7 +7,6 @@ static const int topbar = 1; static const char *barlayout = "t|s"; static const char *fonts[] = { "CaskaydiaCove NFM style:SemiBold:size=11" }; -static const char dmenufont[] = { "CaskaydiaCove NFM style:SemiBold:size=12" }; static const char *colors[][3] = { [SchemeNorm] = { foreground, background, aqua }, [SchemeSel] = { dark_gray, yellow, green }, @@ -17,7 +16,7 @@ static const char *tags[] = { "1", "2", "3", "4" }; static const Rule rules[] = { /* class instance title tags mask isfloating monitor */ { "PrismLauncher", "prismlauncher", NULL, 1 << 2, 0, -1 }, - { "mercury-browser", "mercury-browser", NULL, 1 << 1, 0, -1 }, + { "mercury-default", "Navigator", NULL, 1 << 1, 0, -1 }, { "steam", "steamwebhelper", NULL, 1 << 2, 0, -1 }, { "st-256color", "st-256color", NULL, 1, 0, -1 }, }; @@ -39,9 +38,8 @@ static const Layout layouts[] = { { "[]=", tile } }; #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } static char dmenumon[2] = "0"; -static const char *dmenucmd[] = { "dmenu_run", "-g", "6", "-l", "3", "-m", dmenumon, "-fn", dmenufont, "-nb", background, "-nf", foreground, "-sb", blue, "-sf", dark_gray, NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, NULL }; static const char *termcmd[] = { "st", NULL }; -static const char *browser[] = { "firefox-bin", NULL }; #include "movestack.c" #include "X11/XF86keysym.h" diff --git a/.config/suckless/dwm/config.h b/.config/suckless/dwm/config.h index b5e8c87..49d4108 100644 --- a/.config/suckless/dwm/config.h +++ b/.config/suckless/dwm/config.h @@ -7,7 +7,6 @@ static const int topbar = 1; static const char *barlayout = "t|s"; static const char *fonts[] = { "CaskaydiaCove NFM style:SemiBold:size=11" }; -static const char dmenufont[] = { "CaskaydiaCove NFM style:SemiBold:size=12" }; static const char *colors[][3] = { [SchemeNorm] = { foreground, background, aqua }, [SchemeSel] = { dark_gray, yellow, green }, @@ -17,7 +16,7 @@ static const char *tags[] = { "1", "2", "3", "4" }; static const Rule rules[] = { /* class instance title tags mask isfloating monitor */ { "PrismLauncher", "prismlauncher", NULL, 1 << 2, 0, -1 }, - { "mercury-browser", "mercury-browser", NULL, 1 << 1, 0, -1 }, + { "mercury-default", "Navigator", NULL, 1 << 1, 0, -1 }, { "steam", "steamwebhelper", NULL, 1 << 2, 0, -1 }, { "st-256color", "st-256color", NULL, 1, 0, -1 }, }; @@ -39,9 +38,8 @@ static const Layout layouts[] = { { "[]=", tile } }; #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } static char dmenumon[2] = "0"; -static const char *dmenucmd[] = { "dmenu_run", "-g", "6", "-l", "3", "-m", dmenumon, "-fn", dmenufont, "-nb", background, "-nf", foreground, "-sb", blue, "-sf", dark_gray, NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, NULL }; static const char *termcmd[] = { "st", NULL }; -static const char *browser[] = { "firefox-bin", NULL }; #include "movestack.c" #include "X11/XF86keysym.h" diff --git a/.config/suckless/dwm/dwm b/.config/suckless/dwm/dwm index 48cad0defb840e1869b7bc84d54002101b9baa92..c5da7d72cd0b85df2bc30922b16ca8da86159e17 100755 GIT binary patch delta 9704 zcmZu%30PFs`@ZMG7`VWo;4mNxIx4t=f`Umf2r?KdiVJQmiilvYfJ+*vppGMMpQg52 zsi|oK;{sZWVYy_vX1QxwUMwq1{bi>2|DJPaT73TZdHCLQzV|!d*}k*fxvaFho?h&_ zGMMRCg}mP|v$G_g%+9MW<+!i+*K+GAiFI|K>Z#?X(tI}1EBJtx`y1&dYfq<{F9phh z{|`GzZts=0Su685+O2ZW#w^x;*u&r<|MnhTYSG2`@IB4Q?U(~KkX$J!z~J6=la>u7 zuK)w31?Y{P9GbLe?7PwY0E5x&U`w81%~T0?j)UF$4BMY>f*t5!tDj*9*}YnJb&1lS zcC_rwe;exN=%w2;dc8xhr^7*p5Z`B5Uk4lbj6Rso1R26Y9c<_`Y^tM)kw%$R3eEK$~J?lda zW81O-3XL6Ss3Ev3g@dx%f_@fTyvY}4n~1i@4q}7ouh{21JXwv#z(t_N7VrpZTZ+YE zU3Pj22KL8DOZgk7tw^EJ-PM$3PVisE&27 zlr&9$ZxuK8i35!RsY6bgtoizS70ryB1 z@}_e8JAG=IeA!0h62j%pHv5Kz_gz^VGWTmMKV4$a?YEV&A$G6iBTQbrkiPDJhrLXn z3@Fz7mvYZO-U}p2t+nbJ+XoFCCpTJxY(m&&^sK(X;rLs&K%zF#7LXP&0^D8W=c{?q*UmE4*Mj6vFajLkL<$Q zQP+_zJRi-Lq&&3kcuKrYS3QSDj`V9@TO>*GwgQt|vQ<^`uZyAnXf`b!IXE&@xQ@<3 zDQmn*5BE7pT5O@p(w|h-rqhGBArueFm=1V!)$GH_dsL)cJDUcKG7S7>7B3O~4ZyQ> zKI{;_QJrgecFiXiTli_^(U06$vG81&TjTIG1NjaAdz4Uix6n1-Rv4Mby{w)^yGIQ$ zdVmW%YrSS3Y_8#v5O2Mg$3S-=|IvZZKf(}rmR$#d1~*1U$>kAuMJqy;5Yz?3A7GMf zeW=jys)}~MC)nuIGpT6wO#N_>Nehpx%Ly!y=O&F{O<6cY=n{Mh4mT?PZZJIF-FA8t7E#cNpyTn8K69J-xu;j1+xNPb*EsTomnMFB0(_)J!&(y+`xd3gcN%ADvkYKA1GTC9&P zQGXN~G3~Q3!HM)Rvx9dhFiPS@-amT@1_gB+DLgAg{$)C4WVMhhr_;QwXf~Y=WW})< zdYaXid68-C^YYbclr=WTt!x^~jMELEQ)7dQ1E(XRr^aGEb%Q!jvc*QG2B+5RkuI%SV#>9is{ zNPc4qRb^MnrzhKU##7`u1*Z|n1U{K!7=PUepO^`OuA0lh6 z4n#(w^QxLQ5+-plwOFr@s^9)pRe$$v`6rq@nU3ZrHh%%uO4K=3O|l+IjvD7y*v{s2 zDW6OeBYl6(L*r`AL(L!aur?1F8g@6;s#}^*1ryuId-7<*#Fi|9swehq)qz_+v>d(> zgg!+hBer1+mZ`5zcQucK@>;RRWX|)If1gOB^0JyvortJbKh+it%9Ko`FZ15@x{~{^ zqHZ?bT$-OBCclLC|aC;jc_B^i!)#e~R<5ufwfT%jF&nnNagy@Q$&PG~!3kuv+Wl(OMT?gQor? zoV0aflB|Eg^P;g-F)f&lri;@en)T=|NxyrJJeK3x^~_9f$R?dAXu7}rM;5&>ePR2{ zS-dg(c(CL#zO!PU_d!>KBg_#L@Hn27>Ejrq|-L@$3l;2f1NWnU2owA5nb5azlX-``b?BLgq=(2u9ay)VTHZrqvXcd4wbtyog}ygT#+<7~Lk1QNHYQAx`{=c2J_tF#zWnP^}n)Qo%&%G=rAZ^<|6u z)ih!KWg3;d93)d3z4!9u;^(ykn#9MX80m{2aRaIP)EaefWhj1T9(b#LSQx@?FM#MBml=!uU;*x>;(;WtB z!4_|eb+hV<=fcavTG^_b$=zM~g||NXeVFizXT%c|lH{2nAh@&R`4t*-_*!<&Vsu&?jYypYg|Jo_kqR@ z=G=IV`+1n7cmAU#xW2$h}T-zDE9lyyB&CuQ|C_G>$t`9vl?C zf5pkYtZ@f9cTwZUI=LAdSH-!HHLkD54K9zEu90tX@*RzAjr75I5fZxPTpx8-RMwE| zXKDK8Tpy(Ae;W#YxTbGF8L#*h{{fA1y*Z!h=p#t)cj0V##MHrj9_la^2f4*)Z4-F+ zUluvS!Ugx)H@HPFZei`?W+@LC&GYlV!`^ZI58j-JR4DlQiCr*y0@B)XW3FZr{r*bJ z;)PHlrnTKK6*e7&LiZSPs(A38mg{0#V<$yrK7GOQ!}c0TY^)Y*JqkQR#$4@&rYqMz zhW)}Lft<7X1jCwN0weapLLAKh)N+Ko-}SLt%>66KkVe8H-jqw8 zC2mb31T(~BflGHXl|;+uQfXXCXP-@}s5q_u$j{ER$QH3Gl{S~O_s-RrCI2u!L+M6I zXt4=IT7AMldR;?kEK!NUo@M;qcxdVYoJ-Om+wjQeeJ+EtCH5|C6m~gEcLEvDwRKjX zPm!?d4nQg`a5;AW#Ppu?Xd1QcIv^~%v3yw?F$JSJ$xe2ZI@W-*zr z&(Gpljs>l|)equJPU$8FNINvFH{sC-V zM+fm^Z0&w-7ySyITHrV09C!>`ZvoLm0m_ZNqBT)mRd%^xpv9J-X~A(6Ybh_&j%3W= z>tM~|M$V`ENy>lX1Kt}^+`>v0MfVqWV%`)~YLx#RNWDwj$tMOCK zi_EN;_AW9t8wo1C{$=Iw;L};??xGuP0)4r7i~P-tRJ0_K&7^}%!n=)p5mlE}@|q@@ zf|IOwG2*z}m3IzlfxDe8+Z5Qp>=swF^@Rd`Hrh?r7$(;z(fFnD?jIzHZoH91RZGM9 zi_g+7tS2?M#rj;p64EA0TY%{7cNWUGnOJ99X=}wMQiZK;tC_G;&VGp7rtKh~W9`QP zhBs2&yLD!|Z|eyAz-4i!UWtyECF>nrnr7mj5dAe&%DWZfmyp&AqgN!-qGcg+St3;~ zyW8~DzPx2AxMrO#=#NlY-j^!Mr{m|EHp|;HKYDR_d;R_dL{BotUJZq}lL@q7d7Qi? zf!m%1ac8`@{B?P2JS|_bN50pG5>_V52l^1L>|j{Y2i~!NAjEII&j-)j1Q)aE z{K_c&F66PwmmxM*jgqV4sB~3?$sWfCgHJQxKCx%<*iVP@pX#U5)m2f5F~jOHa;@23 zw7NNyx5m

LRa}cx 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 delta 10274 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 OPV&LOR&RG=&Ho<`OZ-*< diff --git a/.config/suckless/dwm/dwm.o b/.config/suckless/dwm/dwm.o index 774344815160b23ad66ffc4bfda16a02311eb7b9..534d5c77e47b7f0917cf3420ee623abc6cb0b631 100644 GIT binary patch delta 4552 zcmZ9Q4OCQR8prQDitD&DB_UmIiU&`yu^C;h&`zbRm5!UDa*}h}-8i$9q@}Dt;%Mp~ ztyMq;!9Rl^go4ON87Piqeu5wdZ6u^LJ?(;r#XSvMF;dh_+`9JUX z$DNs~mLcs;L-L|6BfDxJ%$zAw&_46GBNryWl9aJ@xiU9t#jA^wmM_DdnGXzkRCx?{ z7DRjIIf91@#p9ek&WZ^M<2-*z$Q&uAp(puraF|dy4fj2i0#C;)l|w}YRxMd3Cg7_j z_4kbo2)S#Bq6lS#az*hpE}c7My1(daL#5xQ`1Af}hT#u0n(+JIF#IDCpQ>sR0qSN$ zjYe(i16n@i6vb}D3_J?)9hEI&HAopYAh1<}acL@UrVbCD6rj9|cv2$LhK1Y}peV{= ztS4k0*p|%F7S23N`>xOzIK>Y@3 z>FV!)FjR}NBL1MC4gcK%ekDjo1S#PG{$c2#wrqwvFF?Hq;&oLEGt|EZsADma)JQ|! z7N9bn8zB;>!Yil=azIG5>UzQ$b5T+hs57BTlR_cI%qt;`PQ=ge=IKQe!2 z3Iu1U;%=tOjATZmG($yJMwpn+`FYGl=3?dw=9|o1W&yL3d6d~IiG~$n;yUMlV%jmz zrHZjko%sZFHq*&m%v{IJW$t3`m(&`5r6~8%DXJRlTiXg_20!AMi_B}xpO`@?U8#x? zW*BoUGm1Hp`6Tmc=JU*#nai2E%-u{6^EmS?^B>GFG42hAP!a!zDs<*kOb2rT^Cjl1 z%;n5%W+AhTS%b9Iqp@%GD6P@z8|T7jeB<<=>{fKFR<#aR2Tt<{-rtIHk!$H@USsw# zz047EWko16f*He{B|a zoGhpK8~UsLdWPs?eRSijC;cc8GT{ zWz%TuC}U%kqa$0z%1x1YYLg9Bn-);4caxK%5;v=OakCBUHZLV#-)8BH+oF=4yu~5j zL-iIX+4dY=?8lTGS?`7%2X5rr@LA3RemNxby0z8VmZ2r z2Vl>WGZB@iYX_;%{yF=_xLf5|GLe#}YPBYH<=vE_B-KMGCN+yJf7#83Dre7wwme-N zhBwb8>X4DIi}z8U?+_oLFJHDBw9QFO-lmIexVO2)QP|-S$B+OWHu}p$q;|qochNnR zp=7Kjba4`1;wi)wNIS8>L3TN@0euCkR!_11enpMqqDI+pw?mvpvRg-&+lCVN;2rSR zz2?|%w=NoCFH}W6q6!_fe^SUU!-hg#G@-80Db65tyGt}9XS-9JMc;PXSKDof-mz4) z!o5QmAEBA}cl7UYiI0)8b8ydM?lZSmyi*lzsN3lfpTN6Q7v~VO%b}e!jpR?G&G9+A z9HJeayL8ckpdwv6Y>HewW+1X2aYb9j5p)+_qQ2L?eMxLWPO)m=Y>Iyt>x)&i6i14K z=qr}virXz&y}MqVN6H>mT)>7sy68mR9*4LHFWD7{DUtpeB`)0FV?#?xB<3{QaI3_I z6D2m9fu0f-(WN$fm#L+G1edCKq12}3n7r1gf&SKFZK<4Pcd0{sj&5QTqV~GbRZ6F2 zuZ?sHVjl7pRN9RgxwEBTM}AqE zc7`nfE=qgA7wX%Aar<=IX>0clUeBKf#Z>RB6un3&cTju9ReXWi%B|sFnqt-&F|wEPrm>-?a=iE#>{Y6kYl zb|*9Ls80K9?NJxaOF!AYh&tvF-y-FhI%tPad)!x@e}_MW(qqqPH%*;dWkkra--P#= zDsCe5xIXAE{n->#kHq70xH-ppKa+g}K__&2+r*yWIX@w9+U^q$?K@K|OP=)g!*`CR zoOFoqvEk$;@gF3fa)=*Leo7bp=se{lJGNdIKO&iU0PcEuj=Jkz6q(TApqSzYC#hbt z={%oyYL%u|Rv4d7WGmG;d0Mp}F{xI>7pS;(+J+YkY~sJ@*-rOVqfM(Z#r!dnGL&Qu zmk`&eYM06KFaBdvq9kXt7;8!Wg)F~1jcl2ux*OGvD%LdG>@Tp-S7R-@smw<5_{+R% zQg6fFq}mUe)HNujT4pub>|T>M3!;fWNi^9kcNA=FdRQwpiTh0z)}pORr+w&ca?m2p zI3ssv2Jr&Q+3q~!6bfRSby|#MVlUjyPO|&ijymh07hnpp0(ED%3V|6PI_Y{Z|Ij5Y z2yfBp-PADb$LF!Xa@yF*amai>HKlkv&Zw)1S7zc2KN~YKF&kFGW z8Xf0UZM4x`YJeIA(XMLa4RuF=`UEDD`h=l21gJBS)UHmPWvJ}|>T`zwvjG1b&pYiQ zLonuoZTc182zUr@8Mb^}5AgfHlglG4lbjS8ABJ%kLip(a|C_LsDET8I5Pu;gR>nrN zUs3$O7sv=XZF7xo`hRNh`(2)nPTgvmwh@-gXT@r?UY;zTfw=NJ%i_~``pQ%>AL}Wj zw4(9KRO|fbebq<6+B12?t#)57%Yx^6CRtM#__C8xJ4eNz0}|_f?BV|d3V_yS delta 4870 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 diff --git a/.config/suckless/dwm/scripts/edit-suckless.sh b/.config/suckless/dwm/scripts/edit-suckless.sh index ce38eae..4a456c5 100755 --- a/.config/suckless/dwm/scripts/edit-suckless.sh +++ b/.config/suckless/dwm/scripts/edit-suckless.sh @@ -19,7 +19,7 @@ done shift $((OPTIND - 1)) APP="$1" -APP_DIR="$HOME/.config/suckless/$APP" +APP_DIR="/home/andrew/dotfiles/.config/suckless/$APP" CONFIG_FILE="$APP_DIR/config.def.h" if [[ -z "$APP" ]]; then @@ -52,9 +52,9 @@ AFTER_HASH=$(sha256sum config.def.h | cut -d ' ' -f1) if [[ "$BEFORE_HASH" != "$AFTER_HASH" || "$REBUILD" == true ]]; then echo "Rebuilding $APP..." - sudo rm -f config.h + doas rm -f config.h make - sudo make install + doas make install pkill dwm else echo "No changes detected. Skipping rebuild." diff --git a/.config/suckless/st/FAQ b/.config/suckless/st/FAQ deleted file mode 100644 index 6287a27..0000000 --- a/.config/suckless/st/FAQ +++ /dev/null @@ -1,253 +0,0 @@ -## Why does st not handle utmp entries? - -Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. - - -## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! - -It means that st doesn’t have any terminfo entry on your system. Chances are -you did not `make install`. If you just want to test it without installing it, -you can manually run `tic -sx st.info`. - - -## Nothing works, and nothing is said about an unknown terminal! - -* Some programs just assume they’re running in xterm i.e. they don’t rely on - terminfo. What you see is the current state of the “xterm compliance”. -* Some programs don’t complain about the lacking st description and default to - another terminal. In that case see the question about terminfo. - - -## How do I scroll back up? - -* Using a terminal multiplexer. - * `st -e tmux` using C-b [ - * `st -e screen` using C-a ESC -* Using the excellent tool of [scroll](https://git.suckless.org/scroll/). -* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/). - - -## I would like to have utmp and/or scroll functionality by default - -You can add the absolute path of both programs in your config.h file. You only -have to modify the value of utmp and scroll variables. - - -## Why doesn't the Del key work in some programs? - -Taken from the terminfo manpage: - - If the terminal has a keypad that transmits codes when the keys - are pressed, this information can be given. Note that it is not - possible to handle terminals where the keypad only works in - local (this applies, for example, to the unshifted HP 2621 keys). - If the keypad can be set to transmit or not transmit, give these - codes as smkx and rmkx. Otherwise the keypad is assumed to - always transmit. - -In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that -applications which want to test against keypad keys send these -sequences. - -But buggy applications (like bash and irssi, for example) don't do this. A fast -solution for them is to use the following command: - - $ printf '\033[?1h\033=' >/dev/tty - -or - $ tput smkx - -In the case of bash, readline is used. Readline has a different note in its -manpage about this issue: - - enable-keypad (Off) - When set to On, readline will try to enable the - application keypad when it is called. Some systems - need this to enable arrow keys. - -Adding this option to your .inputrc will fix the keypad problem for all -applications using readline. - -If you are using zsh, then read the zsh FAQ -: - - It should be noted that the O / [ confusion can occur with other keys - such as Home and End. Some systems let you query the key sequences - sent by these keys from the system's terminal database, terminfo. - Unfortunately, the key sequences given there typically apply to the - mode that is not the one zsh uses by default (it's the "application" - mode rather than the "raw" mode). Explaining the use of terminfo is - outside of the scope of this FAQ, but if you wish to use the key - sequences given there you can tell the line editor to turn on - "application" mode when it starts and turn it off when it stops: - - function zle-line-init () { echoti smkx } - function zle-line-finish () { echoti rmkx } - zle -N zle-line-init - zle -N zle-line-finish - -Putting these lines into your .zshrc will fix the problems. - - -## How can I use meta in 8bit mode? - -St supports meta in 8bit mode, but the default terminfo entry doesn't -use this capability. If you want it, you have to use the 'st-meta' value -in TERM. - - -## I cannot compile st in OpenBSD - -OpenBSD lacks librt, despite it being mandatory in POSIX -. -If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and -st will compile without any loss of functionality, because all the functions are -included in libc on this platform. - - -## The Backspace Case - -St is emulating the Linux way of handling backspace being delete and delete being -backspace. - -This is an issue that was discussed in suckless mailing list -. Here is why some old grumpy -terminal users wants its backspace to be how he feels it: - - Well, I am going to comment why I want to change the behaviour - of this key. When ASCII was defined in 1968, communication - with computers was done using punched cards, or hardcopy - terminals (basically a typewriter machine connected with the - computer using a serial port). ASCII defines DELETE as 7F, - because, in punched-card terms, it means all the holes of the - card punched; it is thus a kind of 'physical delete'. In the - same way, the BACKSPACE key was a non-destructive backspace, - as on a typewriter. So, if you wanted to delete a character, - you had to BACKSPACE and then DELETE. Another use of BACKSPACE - was to type accented characters, for example 'a BACKSPACE `'. - The VT100 had no BACKSPACE key; it was generated using the - CONTROL key as another control character (CONTROL key sets to - 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code - 0x08)), but it had a DELETE key in a similar position where - the BACKSPACE key is located today on common PC keyboards. - All the terminal emulators emulated the difference between - these keys correctly: the backspace key generated a BACKSPACE - (^H) and delete key generated a DELETE (^?). - - But a problem arose when Linus Torvalds wrote Linux. Unlike - earlier terminals, the Linux virtual terminal (the terminal - emulator integrated in the kernel) returned a DELETE when - backspace was pressed, due to the VT100 having a DELETE key in - the same position. This created a lot of problems (see [1] - and [2]). Since Linux has become the king, a lot of terminal - emulators today generate a DELETE when the backspace key is - pressed in order to avoid problems with Linux. The result is - that the only way of generating a BACKSPACE on these systems - is by using CONTROL + H. (I also think that emacs had an - important point here because the CONTROL + H prefix is used - in emacs in some commands (help commands).) - - From point of view of the kernel, you can change the key - for deleting a previous character with stty erase. When you - connect a real terminal into a machine you describe the type - of terminal, so getty configures the correct value of stty - erase for this terminal. In the case of terminal emulators, - however, you don't have any getty that can set the correct - value of stty erase, so you always get the default value. - For this reason, it is necessary to add 'stty erase ^H' to your - profile if you have changed the value of the backspace key. - Of course, another solution is for st itself to modify the - value of stty erase. I usually have the inverse problem: - when I connect to non-Unix machines, I have to press CONTROL + - h to get a BACKSPACE. The inverse problem occurs when a user - connects to my Unix machines from a different system with a - correct backspace key. - - [1] http://www.ibb.net/~anne/keyboard.html - [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html - - -## But I really want the old grumpy behaviour of my terminal - -Apply [1]. - -[1] https://st.suckless.org/patches/delkey - - -## Why do images not work in st using the w3m image hack? - -w3mimg uses a hack that draws an image on top of the terminal emulator Drawable -window. The hack relies on the terminal to use a single buffer to draw its -contents directly. - -st uses double-buffered drawing so the image is quickly replaced and may show a -short flicker effect. - -Below is a patch example to change st double-buffering to a single Drawable -buffer. - -diff --git a/x.c b/x.c ---- a/x.c -+++ b/x.c -@@ -732,10 +732,6 @@ 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 */ -@@ -1148,8 +1144,7 @@ xinit(int cols, int rows) - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, - &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = xw.win; - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2) - 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); - - -## BadLength X error in Xft when trying to render emoji - -Xft makes st crash when rendering color emojis with the following error: - -"X Error of failed request: BadLength (poly request too large or internal Xlib length error)" - Major opcode of failed request: 139 (RENDER) - Minor opcode of failed request: 20 (RenderAddGlyphs) - Serial number of failed request: 1595 - Current serial number in output stream: 1818" - -This is a known bug in Xft (not st) which happens on some platforms and -combination of particular fonts and fontconfig settings. - -See also: -https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 -https://bugs.freedesktop.org/show_bug.cgi?id=107534 -https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - -The solution is to remove color emoji fonts or disable this in the fontconfig -XML configuration. As an ugly workaround (which may work only on newer -fontconfig versions (FC_COLOR)), the following code can be used to mask color -fonts: - - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - -Please don't bother reporting this bug to st, but notify the upstream Xft -developers about fixing this bug. - -As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5: -https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS diff --git a/.config/suckless/st/LEGACY b/.config/suckless/st/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/.config/suckless/st/LEGACY +++ /dev/null @@ -1,17 +0,0 @@ -A STATEMENT ON LEGACY SUPPORT - -In the terminal world there is much cruft that comes from old and unsup‐ -ported terminals that inherit incompatible modes and escape sequences -which noone is able to know, except when he/she comes from that time and -developed a graphical vt100 emulator at that time. - -One goal of st is to only support what is really needed. When you en‐ -counter a sequence which you really need, implement it. But while you -are at it, do not add the other cruft you might encounter while sneek‐ -ing at other terminal emulators. History has bloated them and there is -no real evidence that most of the sequences are used today. - - -Christoph Lohmann <20h@r-36.net> -2012-09-13T07:00:36.081271045+02:00 - diff --git a/.config/suckless/st/LICENSE b/.config/suckless/st/LICENSE deleted file mode 100644 index 3cbf420..0000000 --- a/.config/suckless/st/LICENSE +++ /dev/null @@ -1,34 +0,0 @@ -MIT/X Consortium License - -© 2014-2022 Hiltjo Posthuma -© 2018 Devin J. Pohly -© 2014-2017 Quentin Rameau -© 2009-2012 Aurélien APTEL -© 2008-2017 Anselm R Garbe -© 2012-2017 Roberto E. Vargas Caballero -© 2012-2016 Christoph Lohmann <20h at r-36 dot net> -© 2013 Eon S. Jeon -© 2013 Alexander Sedov -© 2013 Mark Edgar -© 2013-2014 Eric Pruitt -© 2013 Michael Forney -© 2013-2014 Markus Teich -© 2014-2015 Laslo Hunhold - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/.config/suckless/st/README b/.config/suckless/st/README deleted file mode 100644 index 6a846ed..0000000 --- a/.config/suckless/st/README +++ /dev/null @@ -1,34 +0,0 @@ -st - simple terminal --------------------- -st is a simple terminal emulator for X which sucks less. - - -Requirements ------------- -In order to build st you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (st is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install st (if -necessary as root): - - make clean install - - -Running st ----------- -If you did not install st with make clean install, you must compile -the st terminfo entry with the following command: - - tic -sx st.info - -See the man page for additional details. - -Credits -------- -Based on Aurélien APTEL bt source code. - diff --git a/.config/suckless/st/TODO b/.config/suckless/st/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/.config/suckless/st/TODO +++ /dev/null @@ -1,28 +0,0 @@ -vt emulation ------------- - -* double-height support - -code & interface ----------------- - -* add a simple way to do multiplexing - -drawing -------- -* add diacritics support to xdraws() - * switch to a suckless font drawing library -* make the font cache simpler -* add better support for brightening of the upper colors - -bugs ----- - -* fix shift up/down (shift selection in emacs) -* remove DEC test sequence when appropriate - -misc ----- - - $ grep -nE 'XXX|TODO' st.c - diff --git a/.config/suckless/st/config.def.h b/.config/suckless/st/config.def.h index 6024767..2a95352 100644 --- a/.config/suckless/st/config.def.h +++ b/.config/suckless/st/config.def.h @@ -1,14 +1,4 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -// static char *font = "CaskaydiaCoveNerdFontMono-Regular:size=11:antialias=true:autohint=true"; -// static char *font = "CaskaydiaCove Nerd Font Mono:style=SemiBold:size=11:antialias=true:autohint=true"; static char *font = "CaskaydiaCove Nerd Font Mono:weight=180:size=11.5:antialias=true:autohint=true"; - static int borderpx = 10; /* @@ -76,27 +66,10 @@ static unsigned int cursorthickness = 2; */ 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 - */ +// char *termname = "st-256color"; +char *termname = "st"; unsigned int tabspaces = 8; -/* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ "#343f44", // black @@ -133,24 +106,15 @@ unsigned int defaultcs = 258; static unsigned int defaultrcs = 259; /* - * 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 = 30; +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; @@ -278,7 +242,8 @@ static Key key[] = { { 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[3~", -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}, @@ -345,7 +310,8 @@ static Key key[] = { { 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[3~", -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}, diff --git a/.config/suckless/st/config.def.h.rej b/.config/suckless/st/config.def.h.rej deleted file mode 100644 index 7b4d21e..0000000 --- a/.config/suckless/st/config.def.h.rej +++ /dev/null @@ -1,11 +0,0 @@ ---- config.def.h -+++ config.def.h -@@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, -+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, - }; - - /* diff --git a/.config/suckless/st/config.h b/.config/suckless/st/config.h index 6024767..2a95352 100644 --- a/.config/suckless/st/config.h +++ b/.config/suckless/st/config.h @@ -1,14 +1,4 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -// static char *font = "CaskaydiaCoveNerdFontMono-Regular:size=11:antialias=true:autohint=true"; -// static char *font = "CaskaydiaCove Nerd Font Mono:style=SemiBold:size=11:antialias=true:autohint=true"; static char *font = "CaskaydiaCove Nerd Font Mono:weight=180:size=11.5:antialias=true:autohint=true"; - static int borderpx = 10; /* @@ -76,27 +66,10 @@ static unsigned int cursorthickness = 2; */ 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 - */ +// char *termname = "st-256color"; +char *termname = "st"; unsigned int tabspaces = 8; -/* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ "#343f44", // black @@ -133,24 +106,15 @@ unsigned int defaultcs = 258; static unsigned int defaultrcs = 259; /* - * 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 = 30; +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; @@ -278,7 +242,8 @@ static Key key[] = { { 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[3~", -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}, @@ -345,7 +310,8 @@ static Key key[] = { { 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[3~", -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}, diff --git a/.config/suckless/st/patches/st-alpha-20240814-a0274bc.diff b/.config/suckless/st/patches/st-alpha-20240814-a0274bc.diff deleted file mode 100644 index 6913d19..0000000 --- a/.config/suckless/st/patches/st-alpha-20240814-a0274bc.diff +++ /dev/null @@ -1,129 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 2cd740a..019a4e1 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -93,6 +93,9 @@ char *termname = "st-256color"; - */ - unsigned int tabspaces = 8; - -+/* bg opacity */ -+float alpha = 0.8; -+ - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { - /* 8 normal colors */ -diff --git a/x.c b/x.c -index d73152b..f32fd6c 100644 ---- a/x.c -+++ b/x.c -@@ -105,6 +105,7 @@ typedef struct { - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ -+ int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ - } XWindow; -@@ -752,7 +753,7 @@ xresize(int col, int row) - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - -@@ -812,6 +813,10 @@ xloadcols(void) - else - die("could not allocate color %d\n", i); - } -+ -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; - } - -@@ -842,6 +847,12 @@ xsetcolorname(int x, const char *name) - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - -+ if (x == defaultbg) { -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; -+ } -+ - return 0; - } - -@@ -1134,11 +1145,25 @@ xinit(int cols, int rows) - Window parent, root; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ XWindowAttributes attr; -+ XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); -- xw.vis = XDefaultVisual(xw.dpy, xw.scr); -+ -+ root = XRootWindow(xw.dpy, xw.scr); -+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) -+ parent = root; -+ -+ if (XMatchVisualInfo(xw.dpy, xw.scr, 32, TrueColor, &vis) != 0) { -+ xw.vis = vis.visual; -+ xw.depth = vis.depth; -+ } else { -+ XGetWindowAttributes(xw.dpy, parent, &attr); -+ xw.vis = attr.visual; -+ xw.depth = attr.depth; -+ } - - /* font */ - if (!FcInit()) -@@ -1148,7 +1173,7 @@ xinit(int cols, int rows) - xloadfonts(usedfont, 0); - - /* colors */ -- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ -@@ -1168,11 +1193,8 @@ xinit(int cols, int rows) - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - -- root = XRootWindow(xw.dpy, xw.scr); -- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) -- parent = root; -- xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t, -- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, -+ xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, -+ win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - if (parent != root) -@@ -1183,7 +1205,7 @@ xinit(int cols, int rows) - dc.gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, - &gcvalues); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -2047,6 +2069,10 @@ main(int argc, char *argv[]) - case 'a': - allowaltscreen = 0; - break; -+ case 'A': -+ alpha = strtof(EARGF(usage()), NULL); -+ LIMIT(alpha, 0.0, 1.0); -+ break; - case 'c': - opt_class = EARGF(usage()); - break; diff --git a/.config/suckless/st/patches/st-dynamic-cursor-color-0.9.diff b/.config/suckless/st/patches/st-dynamic-cursor-color-0.9.diff deleted file mode 100644 index 1034595..0000000 --- a/.config/suckless/st/patches/st-dynamic-cursor-color-0.9.diff +++ /dev/null @@ -1,50 +0,0 @@ -From 215ec30d6b5fe3319f88f1c9d16a37b6e14e5a53 Mon Sep 17 00:00:00 2001 -From: Bakkeby -Date: Mon, 19 Dec 2022 10:20:47 +0100 -Subject: [PATCH] dynamic cursor color: cursor color taken from current - character - ---- - x.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/x.c b/x.c -index 2a3bd38..21aadce 100644 ---- a/x.c -+++ b/x.c -@@ -1520,6 +1520,7 @@ void - xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - { - Color drawcol; -+ XRenderColor colbg; - - /* remove the old cursor */ - if (selected(ox, oy)) -@@ -1548,11 +1549,21 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; -+ } else if (!(og.mode & ATTR_REVERSE)) { -+ unsigned long col = g.bg; -+ g.bg = g.fg; -+ g.fg = col; -+ } -+ -+ if (IS_TRUECOL(g.bg)) { -+ colbg.alpha = 0xffff; -+ colbg.red = TRUERED(g.bg); -+ colbg.green = TRUEGREEN(g.bg); -+ colbg.blue = TRUEBLUE(g.bg); -+ XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); - } else { -- g.fg = defaultbg; -- g.bg = defaultcs; -+ drawcol = dc.col[g.bg]; - } -- drawcol = dc.col[g.bg]; - } - - /* draw the new one */ --- -2.38.1 - diff --git a/.config/suckless/st/st b/.config/suckless/st/st index 4d4f06501976f99ffda5f02d6e809aacbd4c2483..ab93ea5e5b160104ba10415f2eb42f8e17e5211e 100755 GIT binary patch delta 20258 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 diff --git a/.config/suckless/st/st.c.orig b/.config/suckless/st/st.c.orig deleted file mode 100644 index 03b9bc8..0000000 --- a/.config/suckless/st/st.c.orig +++ /dev/null @@ -1,2682 +0,0 @@ -/* See LICENSE for license details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "st.h" -#include "win.h" - -#if defined(__linux) - #include -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include -#elif defined(__FreeBSD__) || defined(__DragonFly__) - #include -#endif - -/* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ - -/* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) - -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, -}; - -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; - -enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 -}; - -enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN -}; - -enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, -}; - -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - -/* 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 */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - 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 *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ -} Term; - -/* CSI Escape sequence structs */ -/* ESC '[' [[ [] [;]] []] */ -typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; -} CSIEscape; - -/* STR Escape sequence structs */ -/* ESC type [[ [] [;]] ] ESC '\' */ -typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ -} STREscape; - -static void execsh(char *, char **); -static void stty(char **); -static void sigchld(int); -static void ttywriteraw(const char *, size_t); - -static void csidump(void); -static void csihandle(void); -static void csiparse(void); -static void csireset(void); -static void osc_color_response(int, int, int); -static int eschandle(uchar); -static void strdump(void); -static void strhandle(void); -static void strparse(void); -static void strreset(void); - -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int); -static void tcursor(int); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(int); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int); -static void tscrolldown(int, int); -static void tsetattr(const int *, int); -static void tsetchar(Rune, const Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, const int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); -static void tdefutf8(char); -static int32_t tdefcolor(const int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); - -static void drawregion(int, int, int, int); - -static void selnormalize(void); -static void selscroll(int, int); -static void selsnap(int *, int *, int); - -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); - -static char *base64dec(const char *); -static char base64dec_getc(const char **); - -static ssize_t xwrite(int, const char *, size_t); - -/* Globals */ -static Term term; -static Selection sel; -static CSIEscape csiescseq; -static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; - -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; - - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } - - return aux; -} - -void * -xmalloc(size_t len) -{ - void *p; - - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); - - return p; -} - -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); - - return p; -} - -char * -xstrdup(const char *s) -{ - char *p; - - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return p; -} - -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; -} - -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; - - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); - - return len; -} - -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); -} - -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; -} - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; -} - -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - -int -tlinelen(int y) -{ - int i = term.col; - - if (term.line[y][i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && term.line[y][i - 1].u == ' ') - --i; - - return i; -} - -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; - - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } - - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; - - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; - - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -} - -void -selnormalize(void) -{ - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; -} - -int -selected(int x, int y) -{ - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; - - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) - && BETWEEN(x, sel.nb.x, sel.ne.x); - - return BETWEEN(y, sel.nb.y, sel.ne.y) - && (y != sel.nb.y || x >= sel.nb.x) - && (y != sel.ne.y || x <= sel.ne.x); -} - -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int delim, prevdelim; - const Glyph *gp, *prevgp; - - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &term.line[*y][*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; - - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(term.line[yt][xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - - gp = &term.line[newy][newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) - break; - - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(term.line[*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 - & ATTR_WRAP)) { - break; - } - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - const Glyph *gp, *last; - - if (sel.ob.x == -1) - return NULL; - - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &term.line[y][sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &term.line[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)]; - while (last >= gp && last->u == ' ') - --last; - - for ( ; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; -} - -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; - - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } - - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); -} - -void -sigchld(int a) -{ - int stat; - pid_t p; - - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); -} - -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; - - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} - -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; - - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } - - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; -} - -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; - - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } -} - -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } -} - -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; - - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); - - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; - -write_error: - die("write error on tty: %s\n", strerror(errno)); -} - -void -ttyresize(int tw, int th) -{ - struct winsize w; - - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); -} - -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); -} - -int -tattrset(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) - return 1; - } - } - - return 0; -} - -void -tsetdirt(int top, int bot) -{ - int i; - - LIMIT(top, 0, term.row-1); - LIMIT(bot, 0, term.row-1); - - for (i = top; i <= bot; i++) - term.dirty[i] = 1; -} - -void -tsetdirtattr(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) { - tsetdirt(i, i); - break; - } - } - } -} - -void -tfulldirt(void) -{ - tsetdirt(0, term.row-1); -} - -void -tcursor(int mode) -{ - static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); - - if (mode == CURSOR_SAVE) { - c[alt] = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = c[alt]; - tmoveto(c[alt].x, c[alt].y); - } -} - -void -treset(void) -{ - uint i; - - term.c = (TCursor){{ - .mode = ATTR_NULL, - .fg = defaultfg, - .bg = defaultbg - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; - - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - - for (i = 0; i < 2; i++) { - tmoveto(0, 0); - tcursor(CURSOR_SAVE); - tclearregion(0, 0, term.col-1, term.row-1); - tswapscreen(); - } -} - -void -tnew(int col, int row) -{ - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; - tresize(col, row); - treset(); -} - -void -tswapscreen(void) -{ - Line *tmp = term.line; - - term.line = term.alt; - term.alt = tmp; - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); -} - -void -tscrolldown(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); - - for (i = term.bot; i >= orig+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - - selscroll(orig, n); -} - -void -tscrollup(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - - for (i = orig; i <= term.bot-n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i+n]; - term.line[i+n] = temp; - } - - selscroll(orig, -n); -} - -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) - return; - - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || - sel.oe.y < term.top || sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } -} - -void -tnewline(int first_col) -{ - int y = term.c.y; - - if (y == term.bot) { - tscrollup(term.top, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - int sep = ';'; /* colon or semi-colon, but not both */ - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (sep == ';' && *p == ':') - sep = ':'; /* allow override to colon once */ - if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; -} - -/* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); -} - -void -tmoveto(int x, int y) -{ - int miny, maxy; - - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); -} - -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && - BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); - - if (term.line[y][x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - term.line[y][x+1].u = ' '; - term.line[y][x+1].mode &= ~ATTR_WDUMMY; - } - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x-1].u = ' '; - term.line[y][x-1].mode &= ~ATTR_WIDE; - } - - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; -} - -void -tclearregion(int x1, int y1, int x2, int y2) -{ - int x, y, temp; - Glyph *gp; - - if (x1 > x2) - temp = x1, x1 = x2, x2 = temp; - if (y1 > y2) - temp = y1, y1 = y2, y2 = temp; - - LIMIT(x1, 0, term.col-1); - LIMIT(x2, 0, term.col-1); - LIMIT(y1, 0, term.row-1); - LIMIT(y2, 0, term.row-1); - - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &term.line[y][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; - } - } -} - -void -tdeletechar(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x; - src = term.c.x + n; - size = term.col - src; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); -} - -void -tinsertblank(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x + n; - src = term.c.x; - size = term.col - dst; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); -} - -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); -} - -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; - - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - - return idx; -} - -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; - - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } -} - -void -tsetscroll(int t, int b) -{ - int temp; - - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; -} - -void -tsetmode(int priv, int set, const int *args, int narg) -{ - int alt; const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col-1, - term.row-1); - } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } -} - -void -csihandle(void) -{ - char buf[40]; - int len; - - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor Down */ - case 'e': /* VPR --Cursor Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it more times */ - LIMIT(csiescseq.arg[0], 1, 65535); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor Forward */ - case 'a': /* HPR -- Cursor Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, - term.row-1); - } - break; - case 1: /* above */ - if (term.c.y > 0) - tclearregion(0, 0, term.col-1, term.c.y-1); - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, 0, term.col-1, term.row-1); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, - term.c.y); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y); - break; - } - break; - case 'S': /* SU -- Scroll line up */ - if (csiescseq.priv) break; - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, - term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR -- Device Status Report */ - switch (csiescseq.arg[0]) { - case 5: /* Status Report "OK" `0n` */ - ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); - break; - case 6: /* Report Cursor Position (CPR) ";R" */ - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - break; - default: - goto unknown; - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - if (csiescseq.priv) { - goto unknown; - } else { - tcursor(CURSOR_LOAD); - } - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } -} - -void -csidump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); -} - -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); -} - -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } - - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } -} - -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; - - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: - case 11: - case 12: - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) { - xloadcols(); - return; /* color reset without parameter */ - } - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); -} - -void -strparse(void) -{ - int c; - char *p = strescseq.buf; - - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } -} - -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; -} - -void -printscreen(const Arg *arg) -{ - tdump(); -} - -void -printsel(const Arg *arg) -{ - tdumpsel(); -} - -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } -} - -void -tdumpline(int n) -{ - char buf[UTF_SIZ]; - const Glyph *bp, *end; - - bp = &term.line[n][0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for ( ; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); -} - -void -tdump(void) -{ - int i; - - for (i = 0; i < term.row; ++i) - tdumpline(i); -} - -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); -} - -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); -} - -/* - * returns 1 when the sequence is finished and it hasn't to read - * more characters for this sequence, otherwise 0 - */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - xsetmode(0, MODE_HIDE); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; -} - -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; - - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } - - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } - - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - -check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - /* in UTF-8 mode ignore handling C1 control characters */ - if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) - return; - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); - - gp = &term.line[term.c.y][term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - gp->mode &= ~ATTR_WIDE; - } - - if (term.c.x+width > term.col) { - if (IS_SET(MODE_WRAP)) - tnewline(1); - else - tmoveto(term.col - width, term.c.y); - gp = &term.line[term.c.y][term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } -} - -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; - - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; -} - -void -tresize(int col, int row) -{ - int i; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; - TCursor c; - - if (col < 1 || row < 1) { - fprintf(stderr, - "tresize: error resizing to %dx%d\n", col, row); - return; - } - - /* - * slide screen to keep cursor where we expect it - - * tscrollup would work here, but we can optimize to - * memmove because we're freeing the earlier lines - */ - for (i = 0; i <= term.c.y - row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - /* ensure that both src and dst are not NULL */ - if (i > 0) { - memmove(term.line, term.line + i, row * sizeof(Line)); - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } - for (i += row; i < term.row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - term.alt = xrealloc(term.alt, row * sizeof(Line)); - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - - /* 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)); - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); - } - - /* allocate any new rows */ - for (/* i = minrow */; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - term.alt[i] = xmalloc(col * sizeof(Glyph)); - } - if (col > term.col) { - bp = term.tabs + term.col; - - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - /* update terminal size */ - term.col = col; - term.row = row; - /* reset scrolling region */ - tsetscroll(0, row-1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - /* Clearing both screens (it makes dirty all lines) */ - c = term.c; - for (i = 0; i < 2; i++) { - if (mincol < col && 0 < minrow) { - tclearregion(mincol, 0, col - 1, minrow - 1); - } - if (0 < col && minrow < row) { - tclearregion(0, minrow, col - 1, row - 1); - } - tswapscreen(); - tcursor(CURSOR_LOAD); - } - term.c = c; -} - -void -resettitle(void) -{ - xsettitle(NULL); -} - -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y; - - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) - continue; - - term.dirty[y] = 0; - xdrawline(term.line[y], x1, y, x2); - } -} - -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], - term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); -} diff --git a/.config/suckless/st/x.c.orig b/.config/suckless/st/x.c.orig deleted file mode 100644 index c72f2eb..0000000 --- a/.config/suckless/st/x.c.orig +++ /dev/null @@ -1,2104 +0,0 @@ -/* See LICENSE for license details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static uint buttons; /* bit field of pressed buttons */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, btn, code; - int x = evcol(e), y = evrow(e); - int state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - if (e->type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MODE_MOUSEMOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) - return; - /* Set btn to lowest-numbered pressed button, or 12 if no - * buttons are pressed. */ - for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) - ; - code = 32; - } else { - btn = e->xbutton.button; - /* Only buttons 1 through 11 can be encoded */ - if (btn < 1 || btn > 11) - return; - if (e->type == ButtonRelease) { - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - /* Don't send release events for the scroll wheel */ - if (btn == 4 || btn == 5) - return; - } - code = 0; - } - - ox = x; - oy = y; - - /* Encode btn into code. If no button is pressed for a motion event in - * MODE_MOUSEMANY, then encode it as a release. */ - if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) - code += 3; - else if (btn >= 8) - code += 128 + btn - 8; - else if (btn >= 4) - code += 64 + btn - 4; - else - code += btn - 1; - - if (!IS_SET(MODE_MOUSEX10)) { - code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - code, x+1, y+1, - e->type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+code, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Buttonmask for Button - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - -void -bpress(XEvent *e) -{ - int btn = e->xbutton.button; - struct timespec now; - int snap; - - if (1 <= btn && btn <= 11) - buttons |= 1 << (btn-1); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (btn == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - int btn = e->xbutton.button; - - if (1 <= btn && btn <= 11) - buttons &= ~(1 << (btn-1)); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (btn == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - DefaultDepth(xw.dpy, xw.scr)); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); -} - -ushort -sixd_to_16bit(int x) -{ - return x == 0 ? 0 : 0x3737 + 0x2828 * x; -} - -int -xloadcolor(int i, const char *name, Color *ncolor) -{ - XRenderColor color = { .alpha = 0xffff }; - - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6*6*6+16) { /* same colors as xterm */ - color.red = sixd_to_16bit( ((i-16)/36)%6 ); - color.green = sixd_to_16bit( ((i-16)/6) %6 ); - color.blue = sixd_to_16bit( ((i-16)/1) %6 ); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, - xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } - - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); -} - -void -xloadcols(void) -{ - int i; - static int loaded; - Color *cp; - - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } - loaded = 1; -} - -int -xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) -{ - if (!BETWEEN(x, 0, dc.collen - 1)) - 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 - 1)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(const char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((const FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent, root; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.scr); - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - xloadcols(); - - /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask - | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - - root = XRootWindow(xw.dpy, xw.scr); - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) - parent = root; - xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t, - win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - if (parent != root) - XReparentWindow(xw.dpy, xw.win, parent, xw.l, xw.t); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, xw.win, 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]; - } - - 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 (p[0] == '\0') - 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 (p[0] == '\0') - p = opt_title; - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym = NoSymbol; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) { - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - if (status == XBufferOverflow) - return; - } else { - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - } - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), - &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s " VERSION "\n", argv0); - break; - default: - usage(); - } ARGEND; - -run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; - - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); - selinit(); - run(); - - return 0; -} diff --git a/.config/suckless/st/x.o b/.config/suckless/st/x.o index 1786ac7ee7b4cf07035bb6ebaf6dbead5808a4e9..9777e9c970c500bbd4311547edaf54e3f9e21c86 100644 GIT binary patch delta 3405 zcmZXXUu+ar6vp>%3+%RCI@6Z!PFsNrg>6;bB~jD|VGRn~2Qz(8OF&^mV$fi+Rf3QZ z=o*62AWo^_Bj5wu#PBCRY}p5@5L560XhNJdL8~!HB~ir0w3-++M7@W-$1ul9+LQf$ z=brD}xp(gDmcFVz{B^CD3@5rqdoo?&g>B{6y3Wp5iE{VqLXC3E$JeZ=Dc|ZnU=8=L zPYmZ@h?IA%-xL`h+g$xHx%osp4SH+OzFLZPdtZvF@$xG}3+kLpZK1nYq#8n<4WW=7 zst@_Y#iMaGS^nhc#aOh%Bz-ijPQ}Z|P9EOi9GO)ekW$r1!Pb8x=$ozL&MAXe349s_ z!k-%K3VZ>hv(>|D0#lU59(j>90(;Iq9)kj(MusqZcmiL*0O2o93k##c34Dtp;U9Q@ z|HBoH)vYr>&r$E!sB_p^uQsYH_@-XHslG>FgNnm#P!Zdj9jto;1!9B5T)}?AD6tYT zPq1GwMeMp}hhi$}{2s2>wdMrt|AkCU_pNHGvMX=|1B4q5_5^N4F{Tm;Lw!N-Lq!jU zAESAhokDk&7JM<(TwVA9_7!+J(u5ypUx8O4r*Y>RHWv6sl`_q(NU(n&V14;q(@o0o;z>ne&`cD`e8fp4Hf_?E$z74)8gYS9bZ zq9PerpgU$rUg$No)e@f2>yXo>9NS=D-~@&=hNrD;iw+Wf@%CDT^E9-_40Q!gV}|f! zY%K6fbk5V27tW(yCRi`}G;{jQP^&3u+>Zj`jchFN%NQlRm5l}7hAG0k4E6=y3%gb0 z{p{Tw^gf6T;UnxV@CXJ7pJH!;Poqe9jJ*XOM}_bu_HGG!`_LOI?o6_`z}Ju_{3Ck{ z{3~)AXa8Vtf&Vu8w9sqKE7qD9Y^DL{$*qOIBM97q8N!PV_5|)hXF}uU2Kxd(fj+`d zv3G0GyB7t*E_(~yk5R&#*jwN&m?E5KZ-KYNc2s=NZuX7`z4sYCCG-PEcZGhHA4s9| zgX#%=QFR?~+)=jE%ZnwFwxXhY%pNq@N(6i4{go2>HIwfOy%y;?!V1y5kU&n2O6 zH~GHM`Ba-0I-fz76KvO302;Y8VIJ3GH$GTNgm%dD7EuuY|teubE9`$56wHxo=jUQq{$7o`4)#?t0y48Yz E0hd^Qxc~qF delta 3320 zcmZ|Re`u6-90&0G-p=jjcKSTq^!B*<3?&y4a z-=2N@v-vGYjcjViZhzM3d#8b>pFi}nkH!rzJsA*#+4Ruz`Qpg2@zJ1_TH?9=@s|cq zxZ2|}Jyo8OY;p9HfcHDO_T95P#V``(B4{0-SDMx(N+S)X{5gR%@hQcd7@x(2WN{Hc zmy1=_Wi_jx%^F6eVot^Y;}eJx>x?6e&ti!9qS}0f@s}7UzM?o>>AryPQJl+NjBlI^ z`Nh#P@gXu*Vwd;~X0>=8W7WcM7SxWEN4Me{($yk}9GPA2PWb^7(uM<);*5TT2*_nN znZxW?L;_-!_!BWX#roG<+SIOaZ|=hoaaCEV9A{jEamgV|vBP+&+BFArfe1zmj8~{- zhI&r))wZa*&FbywmD^Yyx*5jzAxXSZH^X=fGLkX1fbK7|Hson(uMTD>^(f4Rl6UD~ z#?K&1yjKS^K7fSe&_Tro#vSS=85oz-qV|0E2^?0-dRYBc-3+UzAPm_IbTf>PBSQSP zZiewm#3UnS(1TXx?&Kj1N%LmQ@SY*stxr|o4x9E0inPTFlkPLK*AX(M^^n=}r9dBj z>Oe2qAX%JQ8c8yT%wcvC8M3L{dCcBNUfR0z>T2zPJMx06_prK8U0NKm8hNu)j17I| z7?O;E8ev$Esak=}eFAAYr?OA6jUp|XluOp_( zUTIdjuT+jR4j@Tfr`TcKfDG+CMLQRmH6u?;+tgB<-k|cMAG9?v7fHTX2Q%J)sAR+! z(X+;E8xpj1yINXcyaQ?Cr*v?QJGdVc#Bm+WcmQIt|6Od2BDzjt2(>RoqZj>#J}il#y63aym?w@Gxn&z zg*jIDt9pUe4df}UUa`H%-OLJ@^^%(v#~HUHO5CZ~VZ0s*;%=SIcq`Jx+jaJ0clJ(9 z5clb9#(N+v$@_IS;};MiKCH7DzlNCPLlf$&Xb0WdxAga%)tBp2VfAiRPqBKxJ|AsN`q$W9cw%SJ#kZb^WaTG^b9l>U-`erTf+Y()9MC z`s2$=bpu5i*BbsGw&&F8E%oL+eBB`0vAa?D;cpaS>n+vLAe;F+B8{RJ7aB$N>_77Q z)j6%!jGW6iim&{l3z;S{{5g7M-GiNQ<~%j37b7C1m7KIr&Jb@iF|} zBGy(GDri%WXAJAYVyzfJA}r^okfEUqMH(JJWThN7Awk0!GBjL5u{1 ${COPY_DOTS[${x}]}" + cp -r ${i} ${COPY_DOTS[${x}]} + fi + + if [[ -f ${i} ]]; then + echo "File: ${i} -> ${COPY_DOTS[${x}]}" + cp ${i} ${COPY_DOTS[${x}]} + fi + +done + +echo -e "${GREEN}Re-caching fonts${RESET}" +fc-cache -f + +echo -e "${GREEN}Rebuilding Suckless Software${RESET}" +for x in "${CONFIG}suckless"/*/; do + [[ -d "${x}" ]] || continue + cd "${x}" && doas rm -rf config.h && make && doas make install +done