From 76924a4ae09b44022d2beb4bf545db7a99d0f163 Mon Sep 17 00:00:00 2001 From: CoolnsX Date: Tue, 13 Sep 2022 22:39:11 +0530 Subject: [PATCH] lol --- ani-new | 19 +- dmenu-5.0/LICENSE | 30 - dmenu-5.0/Makefile | 64 - dmenu-5.0/README | 24 - dmenu-5.0/arg.h | 49 - dmenu-5.0/config.def.h | 29 - dmenu-5.0/config.h | 29 - dmenu-5.0/config.mk | 31 - dmenu-5.0/dmenu | Bin 43208 -> 0 bytes dmenu-5.0/dmenu.1 | 199 -- dmenu-5.0/dmenu.1.orig | 199 -- dmenu-5.0/dmenu.c | 904 -------- dmenu-5.0/dmenu.c.orig | 903 -------- dmenu-5.0/dmenu.c.rej | 12 - dmenu-5.0/dmenu.o | Bin 36400 -> 0 bytes dmenu-5.0/dmenu_path | 13 - dmenu-5.0/dmenu_run | 2 - dmenu-5.0/drw.c | 423 ---- dmenu-5.0/drw.h | 57 - dmenu-5.0/drw.o | Bin 10328 -> 0 bytes dmenu-5.0/stest | Bin 16928 -> 0 bytes dmenu-5.0/stest.1 | 90 - dmenu-5.0/stest.c | 109 - dmenu-5.0/stest.o | Bin 5248 -> 0 bytes dmenu-5.0/util.c | 35 - dmenu-5.0/util.h | 8 - dmenu-5.0/util.o | Bin 2216 -> 0 bytes st-0.8.4/FAQ | 250 --- st-0.8.4/LEGACY | 17 - st-0.8.4/LICENSE | 34 - st-0.8.4/Makefile | 60 - st-0.8.4/README | 34 - st-0.8.4/TODO | 28 - st-0.8.4/arg.h | 50 - st-0.8.4/config.def.h | 482 ---- st-0.8.4/config.def.h.orig | 485 ---- st-0.8.4/config.def.h.rej | 15 - st-0.8.4/config.h | 482 ---- st-0.8.4/config.mk | 35 - st-0.8.4/st | Bin 106752 -> 0 bytes st-0.8.4/st-font2-20190416-ba72400.diff | 167 -- st-0.8.4/st.1 | 177 -- st-0.8.4/st.c | 2668 ----------------------- st-0.8.4/st.c.orig | 2597 ---------------------- st-0.8.4/st.c.rej | 13 - st-0.8.4/st.desktop | 8 - st-0.8.4/st.h | 128 -- st-0.8.4/st.h.orig | 125 -- st-0.8.4/st.info | 239 -- st-0.8.4/st.o | Bin 77064 -> 0 bytes st-0.8.4/win.h | 39 - st-0.8.4/x.c | 2070 ------------------ st-0.8.4/x.c.orig | 2171 ------------------ st-0.8.4/x.o | Bin 74800 -> 0 bytes 54 files changed, 5 insertions(+), 15598 deletions(-) delete mode 100644 dmenu-5.0/LICENSE delete mode 100644 dmenu-5.0/Makefile delete mode 100644 dmenu-5.0/README delete mode 100644 dmenu-5.0/arg.h delete mode 100644 dmenu-5.0/config.def.h delete mode 100644 dmenu-5.0/config.h delete mode 100644 dmenu-5.0/config.mk delete mode 100755 dmenu-5.0/dmenu delete mode 100644 dmenu-5.0/dmenu.1 delete mode 100644 dmenu-5.0/dmenu.1.orig delete mode 100644 dmenu-5.0/dmenu.c delete mode 100644 dmenu-5.0/dmenu.c.orig delete mode 100644 dmenu-5.0/dmenu.c.rej delete mode 100644 dmenu-5.0/dmenu.o delete mode 100755 dmenu-5.0/dmenu_path delete mode 100755 dmenu-5.0/dmenu_run delete mode 100644 dmenu-5.0/drw.c delete mode 100644 dmenu-5.0/drw.h delete mode 100644 dmenu-5.0/drw.o delete mode 100755 dmenu-5.0/stest delete mode 100644 dmenu-5.0/stest.1 delete mode 100644 dmenu-5.0/stest.c delete mode 100644 dmenu-5.0/stest.o delete mode 100644 dmenu-5.0/util.c delete mode 100644 dmenu-5.0/util.h delete mode 100644 dmenu-5.0/util.o delete mode 100644 st-0.8.4/FAQ delete mode 100644 st-0.8.4/LEGACY delete mode 100644 st-0.8.4/LICENSE delete mode 100644 st-0.8.4/Makefile delete mode 100644 st-0.8.4/README delete mode 100644 st-0.8.4/TODO delete mode 100644 st-0.8.4/arg.h delete mode 100644 st-0.8.4/config.def.h delete mode 100644 st-0.8.4/config.def.h.orig delete mode 100644 st-0.8.4/config.def.h.rej delete mode 100644 st-0.8.4/config.h delete mode 100644 st-0.8.4/config.mk delete mode 100755 st-0.8.4/st delete mode 100644 st-0.8.4/st-font2-20190416-ba72400.diff delete mode 100644 st-0.8.4/st.1 delete mode 100644 st-0.8.4/st.c delete mode 100644 st-0.8.4/st.c.orig delete mode 100644 st-0.8.4/st.c.rej delete mode 100644 st-0.8.4/st.desktop delete mode 100644 st-0.8.4/st.h delete mode 100644 st-0.8.4/st.h.orig delete mode 100644 st-0.8.4/st.info delete mode 100644 st-0.8.4/st.o delete mode 100644 st-0.8.4/win.h delete mode 100644 st-0.8.4/x.c delete mode 100644 st-0.8.4/x.c.orig delete mode 100644 st-0.8.4/x.o diff --git a/ani-new b/ani-new index 38e9166..8cc0ae6 100755 --- a/ani-new +++ b/ani-new @@ -20,7 +20,7 @@ run () { curl -s "$base_url?page=2" -A "$agent" | sed -nE 's_.*_\1_p' & } -base_url=https://goload.pro +base_url="https://gogohd.net" agent="Mozilla/5.0 (Linux; Android 11; moto g(9) power) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36" trap "exit 0" INT HUP tmp=$(notify-send "Parsing $base_url.. Please wait..." -t 1500 -p) @@ -38,10 +38,10 @@ mp4up_link=$(printf "$links" | grep "mp4upload") notify-send "Fetching doodstream links" -r $tmp dood_id=$(printf "$links" | sed -n "s_.*dood.*/e/__p") -[ -z "$dood_id" ] || dood_link=$(curl -A "$agent" -s "https://dood.ws/d/$dood_id" | sed -nE 's/ -© 2006-2008 Sander van Dijk -© 2006-2007 Michał Janeczek -© 2007 Kris Maglione -© 2009 Gottox -© 2009 Markus Schnalke -© 2009 Evan Gates -© 2010-2012 Connor Lane Smith -© 2014-2020 Hiltjo Posthuma -© 2015-2019 Quentin Rameau - -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/dmenu-5.0/Makefile b/dmenu-5.0/Makefile deleted file mode 100644 index a03a95c..0000000 --- a/dmenu-5.0/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# dmenu - dynamic menu -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = drw.c dmenu.c stest.c util.c -OBJ = $(SRC:.c=.o) - -all: options dmenu stest - -options: - @echo dmenu build options: - @echo "CFLAGS = $(CFLAGS)" - @echo "LDFLAGS = $(LDFLAGS)" - @echo "CC = $(CC)" - -.c.o: - $(CC) -c $(CFLAGS) $< - -config.h: - cp config.def.h $@ - -$(OBJ): arg.h config.h config.mk drw.h - -dmenu: dmenu.o drw.o util.o - $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) - -stest: stest.o - $(CC) -o $@ stest.o $(LDFLAGS) - -clean: - rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz - -dist: clean - mkdir -p dmenu-$(VERSION) - cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\ - drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ - dmenu-$(VERSION) - tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) - gzip dmenu-$(VERSION).tar - rm -rf dmenu-$(VERSION) - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run - chmod 755 $(DESTDIR)$(PREFIX)/bin/stest - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 - sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1 - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ - $(DESTDIR)$(PREFIX)/bin/dmenu_path\ - $(DESTDIR)$(PREFIX)/bin/dmenu_run\ - $(DESTDIR)$(PREFIX)/bin/stest\ - $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ - $(DESTDIR)$(MANPREFIX)/man1/stest.1 - -.PHONY: all options clean dist install uninstall diff --git a/dmenu-5.0/README b/dmenu-5.0/README deleted file mode 100644 index a8fcdfe..0000000 --- a/dmenu-5.0/README +++ /dev/null @@ -1,24 +0,0 @@ -dmenu - dynamic menu -==================== -dmenu is an efficient dynamic menu for X. - - -Requirements ------------- -In order to build dmenu you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dmenu is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dmenu -(if necessary as root): - - make clean install - - -Running dmenu -------------- -See the man page for details. diff --git a/dmenu-5.0/arg.h b/dmenu-5.0/arg.h deleted file mode 100644 index e94e02b..0000000 --- a/dmenu-5.0/arg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - for (brk_ = 0, argv[0]++, argv_ = argv;\ - argv[0][0] && !brk_;\ - argv[0]++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][0];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/dmenu-5.0/config.def.h b/dmenu-5.0/config.def.h deleted file mode 100644 index d1d0761..0000000 --- a/dmenu-5.0/config.def.h +++ /dev/null @@ -1,29 +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[] = { - "Roboto:size=13" -}; -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", "#8800aa" }, - [SchemeOut] = { "#000000", "#C000FF" }, -}; -/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ -static unsigned int lines = 10; -/* -h option; minimum height of a menu line */ -static unsigned int lineheight = 0; -static unsigned int min_lineheight = 8; - -/* - * Characters not considered part of a word while deleting words - * for example: " /?\"&[]" - */ -static const char worddelimiters[] = " "; - -/* Size of the window border */ -static const unsigned int border_width = 4; diff --git a/dmenu-5.0/config.h b/dmenu-5.0/config.h deleted file mode 100644 index d1d0761..0000000 --- a/dmenu-5.0/config.h +++ /dev/null @@ -1,29 +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[] = { - "Roboto:size=13" -}; -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", "#8800aa" }, - [SchemeOut] = { "#000000", "#C000FF" }, -}; -/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ -static unsigned int lines = 10; -/* -h option; minimum height of a menu line */ -static unsigned int lineheight = 0; -static unsigned int min_lineheight = 8; - -/* - * Characters not considered part of a word while deleting words - * for example: " /?\"&[]" - */ -static const char worddelimiters[] = " "; - -/* Size of the window border */ -static const unsigned int border_width = 4; diff --git a/dmenu-5.0/config.mk b/dmenu-5.0/config.mk deleted file mode 100644 index 05d5a3e..0000000 --- a/dmenu-5.0/config.mk +++ /dev/null @@ -1,31 +0,0 @@ -# dmenu version -VERSION = 5.0 - -# paths -PREFIX = /usr/local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = $(X11INC)/freetype2 - -# includes and libs -INCS = -I$(X11INC) -I$(FREETYPEINC) -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) -CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) -LDFLAGS = $(LIBS) - -# compiler and linker -CC = cc diff --git a/dmenu-5.0/dmenu b/dmenu-5.0/dmenu deleted file mode 100755 index 1880e68f526875f8cb0dbff276c7ab210d423d27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43208 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%0A&fiTws%+xdirEh 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 -#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 LENGTH(X) (sizeof X / sizeof X[0]) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -/* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ - -struct item { - char *text; - struct item *left, *right; - int out; -}; - -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 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 char * cistrstr(const char *s, const char *sub); -static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; -static char *(*fstrstr)(const char *, const char *) = cistrstr; - -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 * 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 : MIN(TEXTW(next->text), n)) > n) - break; - for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) - break; -} - -static int -max_textw(void) -{ - int len = 0; - for (struct item *item = items; item && item->text; item++) - len = MAX(TEXTW(item->text), len); - return len; -} - -static void -cleanup(void) -{ - size_t i; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < SchemeLast; i++) - free(scheme[i]); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static char * -cistrstr(const char *s, const char *sub) -{ - size_t len; - - for (len = strlen(sub); *s; s++) - if (!strncasecmp(s, sub, len)) - return (char *)s; - 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, fh = drw->fonts->h, 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]); - if ((curpos += lrpad / 2 - 1) < w) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0); - } - - if (lines > 0) { - /* draw vertical list */ - for (item = curr; item != next; item = item->right) - drawitem(item, x, y += bh, mw - x); - } 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, MIN(TEXTW(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 %u 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 -keypress(XKeyEvent *ev) -{ - char buf[32]; - int len; - KeySym ksym; - Status status; - - len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); - switch (status) { - default: /* XLookupNone, XBufferOverflow */ - return; - case XLookupChars: - goto insert; - case XLookupKeySym: - case XLookupBoth: - break; - } - - 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: - movewordedge(-1); - goto draw; - case XK_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(*buf)) - insert(buf, len); - break; - case XK_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: - 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: - if (sel == matches) { - cursor = 0; - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_Left: - if (cursor > 0 && (!sel || !sel->left || lines > 0)) { - cursor = nextrune(-1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Up: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_Next: - if (!next) - return; - sel = curr = next; - calcoffsets(); - break; - case XK_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 (text[cursor] != '\0') { - cursor = nextrune(+1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Down: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_Tab: - if (!sel) - return; - strncpy(text, sel->text, sizeof text - 1); - text[sizeof text - 1] = '\0'; - cursor = strlen(text); - match(); - break; - } - -draw: - drawmenu(); -} - -static void -buttonpress(XEvent *e) -{ - struct item *item; - XButtonPressedEvent *ev = &e->xbutton; - int x = 0, y = 0, h = bh, w; - - if (ev->window != win) - return; - - /* right-click: exit */ - if (ev->button == Button3) - exit(1); - - if (prompt && *prompt) - x += promptw; - - /* input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - - /* left-click on input: clear input, - * NOTE: if there is no left-arrow the space for < is reserved so - * add that to the input width */ - if (ev->button == Button1 && - ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + - ((!prev || !curr->left) ? TEXTW("<") : 0)) || - (lines > 0 && ev->y >= y && ev->y <= y + h))) { - insert(NULL, -cursor); - drawmenu(); - return; - } - /* middle-mouse click: paste selection */ - if (ev->button == Button2) { - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - drawmenu(); - return; - } - /* scroll up */ - if (ev->button == Button4 && prev) { - sel = curr = prev; - calcoffsets(); - drawmenu(); - return; - } - /* scroll down */ - if (ev->button == Button5 && next) { - sel = curr = next; - calcoffsets(); - drawmenu(); - return; - } - if (ev->button != Button1) - return; - if (ev->state & ~ControlMask) - return; - if (lines > 0) { - /* vertical list: (ctrl)left-click on item */ - w = mw - x; - for (item = curr; item != next; item = item->right) { - y += h; - if (ev->y >= y && ev->y <= (y + h)) { - puts(item->text); - if (!(ev->state & ControlMask)) - exit(0); - sel = item; - if (sel) { - sel->out = 1; - drawmenu(); - } - return; - } - } - } else if (matches) { - /* left-click on left arrow */ - x += inputw; - w = TEXTW("<"); - if (prev && curr->left) { - if (ev->x >= x && ev->x <= x + w) { - sel = curr = prev; - calcoffsets(); - drawmenu(); - return; - } - } - /* horizontal list: (ctrl)left-click on item */ - for (item = curr; item != next; item = item->right) { - x += w; - w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); - if (ev->x >= x && ev->x <= x + w) { - puts(item->text); - if (!(ev->state & ControlMask)) - exit(0); - sel = item; - if (sel) { - sel->out = 1; - drawmenu(); - } - return; - } - } - /* left-click on right arrow */ - w = TEXTW(">"); - x = mw - w; - if (next && ev->x >= x && ev->x <= x + w) { - sel = curr = next; - calcoffsets(); - drawmenu(); - return; - } - } -} - -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); - } - drawmenu(); -} - -static void -readstdin(void) -{ - char buf[sizeof text], *p; - size_t i, imax = 0, size = 0; - unsigned int tmpmax = 0; - - /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { - if (i + 1 >= size / sizeof *items) - if (!(items = realloc(items, (size += BUFSIZ)))) - die("cannot realloc %u bytes:", size); - if ((p = strchr(buf, '\n'))) - *p = '\0'; - if (!(items[i].text = strdup(buf))) - die("cannot strdup %u bytes:", strlen(buf) + 1); - items[i].out = 0; - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); - if (tmpmax > inputw) { - inputw = tmpmax; - imax = i; - } - } - if (items) - items[i].text = NULL; - inputw = items ? TEXTW(items[imax].text) : 0; - 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 ButtonPress: - buttonpress(&ev); - break; - 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; - bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ - lines = MAX(lines, 0); - mh = (lines + 1) * bh; - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; -#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])) - break; - - mw = MIN(MAX(max_textw() + promptw, 600), info[i].width); - x = info[i].x_org + ((info[i].width - mw) / 2); - y = info[i].y_org + ((info[i].height - mh) / 2); - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - mw = MIN(MAX(max_textw() + promptw, 600), wa.width); - x = (wa.width - mw) / 2; - y = (wa.height - mh) / 2; - } - inputw = MIN(inputw, mw/3); - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonPressMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); - 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) { - 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) -{ - fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); - exit(1); -} - -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], "-s")) { /* case-sensitive item matching */ - fstrncmp = strncmp; - fstrstr = strstr; - } else if (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ - lines = atoi(argv[++i]); - else if (!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ - lineheight = atoi(argv[++i]); - lineheight = MAX(lineheight, min_lineheight); - } - 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/dmenu-5.0/dmenu.c.orig b/dmenu-5.0/dmenu.c.orig deleted file mode 100644 index d7608cc..0000000 --- a/dmenu-5.0/dmenu.c.orig +++ /dev/null @@ -1,903 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#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 LENGTH(X) (sizeof X / sizeof X[0]) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -/* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ - -struct item { - char *text; - struct item *left, *right; - int out; -}; - -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 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 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 * 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 : MIN(TEXTW(next->text), n)) > n) - break; - for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) - break; -} - -static int -max_textw(void) -{ - int len = 0; - for (struct item *item = items; item && item->text; item++) - len = MAX(TEXTW(item->text), len); - return len; -} - -static void -cleanup(void) -{ - size_t i; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < SchemeLast; i++) - free(scheme[i]); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static char * -cistrstr(const char *s, const char *sub) -{ - size_t len; - - for (len = strlen(sub); *s; s++) - if (!strncasecmp(s, sub, len)) - return (char *)s; - 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, fh = drw->fonts->h, 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]); - if ((curpos += lrpad / 2 - 1) < w) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0); - } - - if (lines > 0) { - /* draw vertical list */ - for (item = curr; item != next; item = item->right) - drawitem(item, x, y += bh, mw - x); - } 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, MIN(TEXTW(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 %u 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 -keypress(XKeyEvent *ev) -{ - char buf[32]; - int len; - KeySym ksym; - Status status; - - len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); - switch (status) { - default: /* XLookupNone, XBufferOverflow */ - return; - case XLookupChars: - goto insert; - case XLookupKeySym: - case XLookupBoth: - break; - } - - 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: - movewordedge(-1); - goto draw; - case XK_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(*buf)) - insert(buf, len); - break; - case XK_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: - 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: - if (sel == matches) { - cursor = 0; - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_Left: - if (cursor > 0 && (!sel || !sel->left || lines > 0)) { - cursor = nextrune(-1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Up: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_Next: - if (!next) - return; - sel = curr = next; - calcoffsets(); - break; - case XK_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 (text[cursor] != '\0') { - cursor = nextrune(+1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Down: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_Tab: - if (!sel) - return; - strncpy(text, sel->text, sizeof text - 1); - text[sizeof text - 1] = '\0'; - cursor = strlen(text); - match(); - break; - } - -draw: - drawmenu(); -} - -static void -buttonpress(XEvent *e) -{ - struct item *item; - XButtonPressedEvent *ev = &e->xbutton; - int x = 0, y = 0, h = bh, w; - - if (ev->window != win) - return; - - /* right-click: exit */ - if (ev->button == Button3) - exit(1); - - if (prompt && *prompt) - x += promptw; - - /* input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - - /* left-click on input: clear input, - * NOTE: if there is no left-arrow the space for < is reserved so - * add that to the input width */ - if (ev->button == Button1 && - ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + - ((!prev || !curr->left) ? TEXTW("<") : 0)) || - (lines > 0 && ev->y >= y && ev->y <= y + h))) { - insert(NULL, -cursor); - drawmenu(); - return; - } - /* middle-mouse click: paste selection */ - if (ev->button == Button2) { - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - drawmenu(); - return; - } - /* scroll up */ - if (ev->button == Button4 && prev) { - sel = curr = prev; - calcoffsets(); - drawmenu(); - return; - } - /* scroll down */ - if (ev->button == Button5 && next) { - sel = curr = next; - calcoffsets(); - drawmenu(); - return; - } - if (ev->button != Button1) - return; - if (ev->state & ~ControlMask) - return; - if (lines > 0) { - /* vertical list: (ctrl)left-click on item */ - w = mw - x; - for (item = curr; item != next; item = item->right) { - y += h; - if (ev->y >= y && ev->y <= (y + h)) { - puts(item->text); - if (!(ev->state & ControlMask)) - exit(0); - sel = item; - if (sel) { - sel->out = 1; - drawmenu(); - } - return; - } - } - } else if (matches) { - /* left-click on left arrow */ - x += inputw; - w = TEXTW("<"); - if (prev && curr->left) { - if (ev->x >= x && ev->x <= x + w) { - sel = curr = prev; - calcoffsets(); - drawmenu(); - return; - } - } - /* horizontal list: (ctrl)left-click on item */ - for (item = curr; item != next; item = item->right) { - x += w; - w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); - if (ev->x >= x && ev->x <= x + w) { - puts(item->text); - if (!(ev->state & ControlMask)) - exit(0); - sel = item; - if (sel) { - sel->out = 1; - drawmenu(); - } - return; - } - } - /* left-click on right arrow */ - w = TEXTW(">"); - x = mw - w; - if (next && ev->x >= x && ev->x <= x + w) { - sel = curr = next; - calcoffsets(); - drawmenu(); - return; - } - } -} - -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); - } - drawmenu(); -} - -static void -readstdin(void) -{ - char buf[sizeof text], *p; - size_t i, imax = 0, size = 0; - unsigned int tmpmax = 0; - - /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { - if (i + 1 >= size / sizeof *items) - if (!(items = realloc(items, (size += BUFSIZ)))) - die("cannot realloc %u bytes:", size); - if ((p = strchr(buf, '\n'))) - *p = '\0'; - if (!(items[i].text = strdup(buf))) - die("cannot strdup %u bytes:", strlen(buf) + 1); - items[i].out = 0; - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); - if (tmpmax > inputw) { - inputw = tmpmax; - imax = i; - } - } - if (items) - items[i].text = NULL; - inputw = items ? TEXTW(items[imax].text) : 0; - 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 ButtonPress: - buttonpress(&ev); - break; - 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; - bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ - lines = MAX(lines, 0); - mh = (lines + 1) * bh; - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; -#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])) - break; - - mw = MIN(MAX(max_textw() + promptw, 600), info[i].width); - x = info[i].x_org + ((info[i].width - mw) / 2); - y = info[i].y_org + ((info[i].height - mh) / 2); - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - mw = MIN(MAX(max_textw() + promptw, 600), wa.width); - x = (wa.width - mw) / 2; - y = (wa.height - mh) / 2; - } - inputw = MIN(inputw, mw/3); - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonPressMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); - 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) { - 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) -{ - fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); - exit(1); -} - -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 (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ - lines = atoi(argv[++i]); - else if (!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ - lineheight = atoi(argv[++i]); - lineheight = MAX(lineheight, min_lineheight); - } - 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/dmenu-5.0/dmenu.c.rej b/dmenu-5.0/dmenu.c.rej deleted file mode 100644 index 209c051..0000000 --- a/dmenu-5.0/dmenu.c.rej +++ /dev/null @@ -1,12 +0,0 @@ ---- dmenu.c -+++ dmenu.c -@@ -774,7 +890,8 @@ setup(void) - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; -+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | -+ ButtonPressMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); diff --git a/dmenu-5.0/dmenu.o b/dmenu-5.0/dmenu.o deleted file mode 100644 index 4959b1340caf6a3166692ccd2b1f31686bd7e24e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36400 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 Ar2qf` diff --git a/dmenu-5.0/dmenu_path b/dmenu-5.0/dmenu_path deleted file mode 100755 index 3a7cda7..0000000 --- a/dmenu-5.0/dmenu_path +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" -cache="$cachedir/dmenu_run" - -[ ! -e "$cachedir" ] && mkdir -p "$cachedir" - -IFS=: -if stest -dqr -n "$cache" $PATH; then - stest -flx $PATH | sort -u | tee "$cache" -else - cat "$cache" -fi diff --git a/dmenu-5.0/dmenu_run b/dmenu-5.0/dmenu_run deleted file mode 100755 index 834ede5..0000000 --- a/dmenu-5.0/dmenu_run +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & diff --git a/dmenu-5.0/drw.c b/dmenu-5.0/drw.c deleted file mode 100644 index c1c265c..0000000 --- a/dmenu-5.0/drw.c +++ /dev/null @@ -1,423 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 - -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) -{ - for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) - return (unsigned char)c & ~utfmask[*i]; - return 0; -} - -static size_t -utf8validate(long *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; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) -{ - size_t i, j, len, type; - long 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) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - char buf[1024]; - int ty; - unsigned int ew; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - size_t i, len; - int utf8strlen, utf8charlen, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0; - - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) - return 0; - - if (!render) { - w = ~w; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - while (1) { - utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; - } else { - nextfont = curfont; - } - break; - } - } - - if (!charexists || nextfont) - break; - else - charexists = 0; - } - - if (utf8strlen) { - drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); - /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - - if (len) { - memcpy(buf, utf8str, len); - buf[len] = '\0'; - if (len < utf8strlen) - for (i = len; i && i > len - 3; buf[--i] = '.') - ; /* NOP */ - - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)buf, len); - } - x += ew; - w -= ew; - } - } - - if (!*text) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} diff --git a/dmenu-5.0/drw.h b/dmenu-5.0/drw.h deleted file mode 100644 index 4c67419..0000000 --- a/dmenu-5.0/drw.h +++ /dev/null @@ -1,57 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - -/* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); - -/* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); - -/* Drawing context manipulation */ -void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Clr *scm); - -/* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); - -/* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/dmenu-5.0/drw.o b/dmenu-5.0/drw.o deleted file mode 100644 index 2b22ad343936a116cacf0e7187de55dff0ad9253..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10328 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 G;(q}n!6eZD diff --git a/dmenu-5.0/stest.1 b/dmenu-5.0/stest.1 deleted file mode 100644 index 2667d8a..0000000 --- a/dmenu-5.0/stest.1 +++ /dev/null @@ -1,90 +0,0 @@ -.TH STEST 1 dmenu\-VERSION -.SH NAME -stest \- filter a list of files by properties -.SH SYNOPSIS -.B stest -.RB [ -abcdefghlpqrsuwx ] -.RB [ -n -.IR file ] -.RB [ -o -.IR file ] -.RI [ file ...] -.SH DESCRIPTION -.B stest -takes a list of files and filters by the files' properties, analogous to -.IR test (1). -Files which pass all tests are printed to stdout. If no files are given, stest -reads files from stdin. -.SH OPTIONS -.TP -.B \-a -Test hidden files. -.TP -.B \-b -Test that files are block specials. -.TP -.B \-c -Test that files are character specials. -.TP -.B \-d -Test that files are directories. -.TP -.B \-e -Test that files exist. -.TP -.B \-f -Test that files are regular files. -.TP -.B \-g -Test that files have their set-group-ID flag set. -.TP -.B \-h -Test that files are symbolic links. -.TP -.B \-l -Test the contents of a directory given as an argument. -.TP -.BI \-n " file" -Test that files are newer than -.IR file . -.TP -.BI \-o " file" -Test that files are older than -.IR file . -.TP -.B \-p -Test that files are named pipes. -.TP -.B \-q -No files are printed, only the exit status is returned. -.TP -.B \-r -Test that files are readable. -.TP -.B \-s -Test that files are not empty. -.TP -.B \-u -Test that files have their set-user-ID flag set. -.TP -.B \-v -Invert the sense of tests, only failing files pass. -.TP -.B \-w -Test that files are writable. -.TP -.B \-x -Test that files are executable. -.SH EXIT STATUS -.TP -.B 0 -At least one file passed all tests. -.TP -.B 1 -No files passed all tests. -.TP -.B 2 -An error occurred. -.SH SEE ALSO -.IR dmenu (1), -.IR test (1) diff --git a/dmenu-5.0/stest.c b/dmenu-5.0/stest.c deleted file mode 100644 index 7a7b0bc..0000000 --- a/dmenu-5.0/stest.c +++ /dev/null @@ -1,109 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include - -#include -#include -#include -#include -#include -#include - -#include "arg.h" -char *argv0; - -#define FLAG(x) (flag[(x)-'a']) - -static void test(const char *, const char *); -static void usage(void); - -static int match = 0; -static int flag[26]; -static struct stat old, new; - -static void -test(const char *path, const char *name) -{ - struct stat st, ln; - - if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ - && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ - && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ - && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ - && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ - && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ - && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ - && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ - && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ - && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ - && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ - && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ - && (!FLAG('s') || st.st_size > 0) /* not empty */ - && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ - && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ - && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ - if (FLAG('q')) - exit(0); - match = 1; - puts(name); - } -} - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " - "[-n file] [-o file] [file...]\n", argv0); - exit(2); /* like test(1) return > 1 on error */ -} - -int -main(int argc, char *argv[]) -{ - struct dirent *d; - char path[PATH_MAX], *line = NULL, *file; - size_t linesiz = 0; - ssize_t n; - DIR *dir; - int r; - - ARGBEGIN { - case 'n': /* newer than file */ - case 'o': /* older than file */ - file = EARGF(usage()); - if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) - perror(file); - break; - default: - /* miscellaneous operators */ - if (strchr("abcdefghlpqrsuvwx", ARGC())) - FLAG(ARGC()) = 1; - else - usage(); /* unknown flag */ - } ARGEND; - - if (!argc) { - /* read list from stdin */ - while ((n = getline(&line, &linesiz, stdin)) > 0) { - if (n && line[n - 1] == '\n') - line[n - 1] = '\0'; - test(line, line); - } - free(line); - } else { - for (; argc; argc--, argv++) { - if (FLAG('l') && (dir = opendir(*argv))) { - /* test directory contents */ - while ((d = readdir(dir))) { - r = snprintf(path, sizeof path, "%s/%s", - *argv, d->d_name); - if (r >= 0 && (size_t)r < sizeof path) - test(path, d->d_name); - } - closedir(dir); - } else { - test(*argv, *argv); - } - } - } - return match ? 0 : 1; -} diff --git a/dmenu-5.0/stest.o b/dmenu-5.0/stest.o deleted file mode 100644 index 72f9ebeeb0579223651d08393c2846ea5302263b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5248 zcmbW4eQaCR6~M3UwDFqGFKx3bj8V+`0;wQxakY=Mqf=huz%w|k16rmvA#v=N57n`Q z{oDk^)KswxuIqxfvQKFR!5^KbNoZ^XiK(+_ORH%}6`S~rP5gldmWSF+s7!3&opawk z_RXFB&yMtb@A=(x&OP_u^FDlZEP9vM<6$Ho_6^q5h%&a?-RuwZ?l9|S8ryG`_MvK( zzk*GuVwFCJo%iwQ_g?Cm4@Qa~9gOw?f6~ z3{|R^0I%`jEZ1qS-l-c-Rp?H4DXa(k*fqxXv1!I~S6U4OVc_Lf1H&-zGYZ{B7Q1TO zLf5V0Rm$PL>T?wyqm0|3w<=ky3qAUCb)xCz@P+xc{E;Th^@&x#g5}{1oWrIWOgmlCep`V#@W`9k z`9pO##Mr}^<$RGgt}|5UyL^drj1(=t$B6}dgY}TGZg&gB+2HbH7qD(7&5841-IQE5 zHfQe*_GN>I24XYuggrYqpImw*lg%AjUYP`#3eGMhZS19~hrlq5$xZBkJXl}$OMO{p zJ`^qU$}$j2GXD7XNt;o@h{rZfWkTYm6=bGFto_ zk=nE1OUc#FhAJW=l)hCutz#WP)%NhmTC-}gUJgOonv>?k=G1w1_vq-}VE^6s9oQ8N zg^bqmWjm)5h-fC_unfPBrM!QpXEI$t+1+&2%znHDbdprhOX7xEw~AWypuy9rw46`>Qq zMexfa4xSZ>k8PxGqjmG(cUpsC=MJuIfVb{?2?@S`J!W48y<1_Z;?ru2v_Ei^Tt?xy zmHoYK__y0|%%fGDhuZMTHhiWH&jQ~n?HjK>U@L9xkGA2*+whZZ_~|zM$8Gp?ZTQdI z@L#pzEbG`=$A~lj0%NGK*<@^vrR-&vPA1r5%!$u4BRV>WKOy|t4NeI=lVP#U+>t>x zyOdc-IkU`OS#Ve^9=EeumdrXahb`rtESs8we*ExMeE#s%Y-}M35f@Ty3H;L;2$YG> zW0L?jXFJJ-l+9){w$0K@b}F%uVHrD?z&4&tXKn0cQ(`_?k^8*D79SA-xc-BWdXO%J zAjq*#oSs+6@!lkk_Ze3<5-sJqEc70QKPB{CqQ&^Q zw-oJb z#@{UQ+a-Ivm&x9i>_024&q(oal=ur0$FkU=`QW)cA@sTwCn(u(!Nq`JBd=>m8?M&jc@Z}(>@k12PJ*DLP<&To?8~A< zoW6IaCBBJ_u{E-fE;_LpXq}AP&QmXACu4?VuQ<#|#GDv2X5futWYVahdB}j*P{RmF zEaT*sm=RAeF4`&ZN~Im!fUnm9{^k+-TqWe0AI4PuE5iSeibJsB>2~lt5lwb0ocs?eoWfB%Cj8a?+b$BK?=T8OexwgWr`7(g z;)a1xoui6#sQdQ-FpN0}mn=)-!HDlpS!jN0Ct#5JvfUazSY_D4HVLc~F7>#c6#i;n zls|>diG2_ l>W}}Q)Y=2YR&W61RkvyUs(X#^#8&>-ME<85o^D6=|1aRXVwnH{ diff --git a/dmenu-5.0/util.c b/dmenu-5.0/util.c deleted file mode 100644 index fe044fc..0000000 --- a/dmenu-5.0/util.c +++ /dev/null @@ -1,35 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "util.h" - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - -void -die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } - - exit(1); -} diff --git a/dmenu-5.0/util.h b/dmenu-5.0/util.h deleted file mode 100644 index f633b51..0000000 --- a/dmenu-5.0/util.h +++ /dev/null @@ -1,8 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size); diff --git a/dmenu-5.0/util.o b/dmenu-5.0/util.o deleted file mode 100644 index c0e1b2e540a7db2dd2bbe25ad82a49373d5cbbfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2216 zcmbtVJ!n%=6h5!5Hr6zWZHG!7B3vbb`e+J5NmZha_9;PXRn#t;CNDOaKVNPnRl$mN z2qnHbf`g!=(4d2>qmy+M>QDy{=7Uon>yE} zX&_C5Q?NUeEI?$>uAi{o1O%WTE*p()zCXB`vmM|JAW~3TPHj_f{`f`iM zgV7|r6^y1>B^Z6imQWsyK4+^ozF=!MzGiQ1e8*ZgzGt5iv&Kr#kq9~l7L3GN#>z>Y z;Owi>TxMG$Fl;ohu#nMAvawG|7V;sDI5Z~0;qU0c(j*uw$I0WPMq`5-_Sper1-+$* z-R*d7a6OE1n~k+?*z8;Hlhiuxjm=(i5}&qeexqr3WD|2AGwDL1oQVTWPff+ck?D(9 zqv2RgAJ?fD=)n=jLEDKT=mM=poZNFw%=aNjHskd>ivSJ-$g_6Vf4vJPea-X z;YePd59rm!B2UjFa?8O5=~-qWt#h-^LC>an8ua;U6?Cgi6OzaD80eXDv1pc1QYv#( z$ESC!%F~%UVt%_+(<@dP&y6o)Dit&rZsx3X(UhJ2ABHiVwt~)9wS<@qh<%bV*AzxD zK>L@F0)Z9UY&4%p*pEKB&iiz}6BIuxcp)dswpsT=f_KxS$WzUK&5vO&)f~s6np|J@ zD`Rqfi3tplZ+}Fk2yspb1{IE6nJ4kQ!l}}t6sV+!_6BnF&eXd~DHW0L?#umq?xL2Y z?)){8KSRY7bLST@=5_vcBGKgfbpG_dWj=jh$-LGkp8hY$CIr%(rjqV_s_8y^q#z>5 ZGc-|5l-ptG`|p+iQuO~|N9j23{J$JY3UB}b diff --git a/st-0.8.4/FAQ b/st-0.8.4/FAQ deleted file mode 100644 index 0f9609d..0000000 --- a/st-0.8.4/FAQ +++ /dev/null @@ -1,250 +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 patch 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. diff --git a/st-0.8.4/LEGACY b/st-0.8.4/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/st-0.8.4/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/st-0.8.4/LICENSE b/st-0.8.4/LICENSE deleted file mode 100644 index d80eb47..0000000 --- a/st-0.8.4/LICENSE +++ /dev/null @@ -1,34 +0,0 @@ -MIT/X Consortium License - -© 2014-2020 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/st-0.8.4/Makefile b/st-0.8.4/Makefile deleted file mode 100644 index 5152b8b..0000000 --- a/st-0.8.4/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# st - simple terminal -# See LICENSE file for copyright and license details. -.POSIX: - -include config.mk - -SRC = st.c x.c -OBJ = $(SRC:.c=.o) - -all: options st - -options: - @echo st build options: - @echo "CFLAGS = $(STCFLAGS)" - @echo "LDFLAGS = $(STLDFLAGS)" - @echo "CC = $(CC)" - -config.h: - cp config.def.h config.h - -.c.o: - $(CC) $(STCFLAGS) -c $< - -st.o: config.h st.h win.h -x.o: arg.h config.h st.h win.h - -$(OBJ): config.h config.mk - -st: $(OBJ) - $(CC) -o $@ $(OBJ) $(STLDFLAGS) - -clean: - rm -f st $(OBJ) st-$(VERSION).tar.gz - -dist: clean - mkdir -p st-$(VERSION) - cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ - config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ - st-$(VERSION) - tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz - rm -rf st-$(VERSION) - -install: st - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f st $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/st - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 - tic -sx st.info - @echo Please see the README file regarding the terminfo entry of st. - mkdir -p $(DESTDIR)$(PREFIX)/share/applications - cp -f st.desktop $(DESTDIR)$(PREFIX)/share/applications - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/st - rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 - rm -f $(DESTDIR)$(PREFIX)/share/applications/st.desktop - -.PHONY: all options clean dist install uninstall diff --git a/st-0.8.4/README b/st-0.8.4/README deleted file mode 100644 index 6a846ed..0000000 --- a/st-0.8.4/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/st-0.8.4/TODO b/st-0.8.4/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/st-0.8.4/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/st-0.8.4/arg.h b/st-0.8.4/arg.h deleted file mode 100644 index a22e019..0000000 --- a/st-0.8.4/arg.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - int i_;\ - for (i_ = 1, brk_ = 0, argv_ = argv;\ - argv[0][i_] && !brk_;\ - i_++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][i_];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/st-0.8.4/config.def.h b/st-0.8.4/config.def.h deleted file mode 100644 index e7aad60..0000000 --- a/st-0.8.4/config.def.h +++ /dev/null @@ -1,482 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "JetBrains Mono NL:style=Regular:pixelsize=15:antialias=true:autohint=true"; - -static int borderpx = 0; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 8; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 4; - -/* bg opacity */ -float alpha = 0.85; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "black", - "#FF9F12", -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 15; -unsigned int defaultbg = 258; -static unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 4; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { ShiftMask, Button4, kscrollup, {.i = 1} }, - { ShiftMask, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/st-0.8.4/config.def.h.orig b/st-0.8.4/config.def.h.orig deleted file mode 100644 index 5317c0c..0000000 --- a/st-0.8.4/config.def.h.orig +++ /dev/null @@ -1,485 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "JetBrains Mono:style=Bold:pixelsize=14:antialias=true:autohint=true"; -/* Spare fonts */ - static char *font2[] = { - "Symbols Nerd Font:pixelsize=14","Noto Color Emoji:style=Regular:pixelsize=14" -}; - -static int borderpx = 0; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 0.9; -static float chscale = 0.9; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 8; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "black", -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 15; -unsigned int defaultbg = 258; -static unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 4; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { ShiftMask, Button4, kscrollup, {.i = 1} }, - { ShiftMask, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/st-0.8.4/config.def.h.rej b/st-0.8.4/config.def.h.rej deleted file mode 100644 index a092951..0000000 --- a/st-0.8.4/config.def.h.rej +++ /dev/null @@ -1,15 +0,0 @@ ---- config.def.h -+++ config.def.h -@@ -6,12 +6,6 @@ - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ - static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; --/* Spare fonts */ --static char *font2[] = { --/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ --/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ --}; -- - static int borderpx = 2; - - /* diff --git a/st-0.8.4/config.h b/st-0.8.4/config.h deleted file mode 100644 index e7aad60..0000000 --- a/st-0.8.4/config.h +++ /dev/null @@ -1,482 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "JetBrains Mono NL:style=Regular:pixelsize=15:antialias=true:autohint=true"; - -static int borderpx = 0; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 8; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 4; - -/* bg opacity */ -float alpha = 0.85; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "black", - "#FF9F12", -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 15; -unsigned int defaultbg = 258; -static unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 4; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { ShiftMask, Button4, kscrollup, {.i = 1} }, - { ShiftMask, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/st-0.8.4/config.mk b/st-0.8.4/config.mk deleted file mode 100644 index aaa54ff..0000000 --- a/st-0.8.4/config.mk +++ /dev/null @@ -1,35 +0,0 @@ -# st version -VERSION = 0.8.4 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -PKG_CONFIG = pkg-config - -# includes and libs -INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -# flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) -STLDFLAGS = $(LIBS) $(LDFLAGS) - -# OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `$(PKG_CONFIG) --libs fontconfig` \ -# `$(PKG_CONFIG) --libs freetype2` - -# compiler and linker -# CC = c99 diff --git a/st-0.8.4/st b/st-0.8.4/st deleted file mode 100755 index ff425017ceb3da529e7efc730e0e053a4995476d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106752 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 AdH?_b diff --git a/st-0.8.4/st-font2-20190416-ba72400.diff b/st-0.8.4/st-font2-20190416-ba72400.diff deleted file mode 100644 index c7a2950..0000000 --- a/st-0.8.4/st-font2-20190416-ba72400.diff +++ /dev/null @@ -1,167 +0,0 @@ -From ba724004c6a368e452114f7dc147a9978fe0f3b4 Mon Sep 17 00:00:00 2001 -From: Kirill Bugaev -Date: Tue, 16 Apr 2019 04:31:30 +0800 -Subject: [PATCH] This patch allows to add spare font besides default. Some - glyphs can be not present in default font. For this glyphs st uses - font-config and try to find them in font cache first. This patch append fonts - defined in font2 variable to the beginning of font cache. So they will be - used first for glyphs that absent in default font. - ---- - config.def.h | 6 +++ - x.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 107 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 482901e..676719e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -6,6 +6,12 @@ - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ - static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -+/* Spare fonts */ -+static char *font2[] = { -+/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ -+/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ -+}; -+ - static int borderpx = 2; - - /* -diff --git a/x.c b/x.c -index 5828a3b..d37e59d 100644 ---- a/x.c -+++ b/x.c -@@ -149,6 +149,8 @@ static void xhints(void); - static int xloadcolor(int, const char *, Color *); - static int xloadfont(Font *, FcPattern *); - static void xloadfonts(char *, double); -+static int xloadsparefont(FcPattern *, int); -+static void xloadsparefonts(void); - static void xunloadfont(Font *); - static void xunloadfonts(void); - static void xsetenv(void); -@@ -296,6 +298,7 @@ zoomabs(const Arg *arg) - { - xunloadfonts(); - xloadfonts(usedfont, arg->f); -+ xloadsparefonts(); - cresize(0, 0); - redraw(); - xhints(); -@@ -977,6 +980,101 @@ xloadfonts(char *fontstr, double fontsize) - FcPatternDestroy(pattern); - } - -+int -+xloadsparefont(FcPattern *pattern, int flags) -+{ -+ FcPattern *match; -+ FcResult result; -+ -+ match = FcFontMatch(NULL, pattern, &result); -+ if (!match) { -+ return 1; -+ } -+ -+ if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { -+ FcPatternDestroy(match); -+ return 1; -+ } -+ -+ frc[frclen].flags = flags; -+ /* Believe U+0000 glyph will present in each default font */ -+ frc[frclen].unicodep = 0; -+ frclen++; -+ -+ return 0; -+} -+ -+void -+xloadsparefonts(void) -+{ -+ FcPattern *pattern; -+ double sizeshift, fontval; -+ int fc; -+ char **fp; -+ -+ if (frclen != 0) -+ die("can't embed spare fonts. cache isn't empty"); -+ -+ /* Calculate count of spare fonts */ -+ fc = sizeof(font2) / sizeof(*font2); -+ if (fc == 0) -+ return; -+ -+ /* Allocate memory for cache entries. */ -+ if (frccap < 4 * fc) { -+ frccap += 4 * fc - frccap; -+ frc = xrealloc(frc, frccap * sizeof(Fontcache)); -+ } -+ -+ for (fp = font2; fp - font2 < fc; ++fp) { -+ -+ if (**fp == '-') -+ pattern = XftXlfdParse(*fp, False, False); -+ else -+ pattern = FcNameParse((FcChar8 *)*fp); -+ -+ if (!pattern) -+ die("can't open spare font %s\n", *fp); -+ -+ if (defaultfontsize > 0) { -+ sizeshift = usedfontsize - defaultfontsize; -+ if (sizeshift != 0 && -+ FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == -+ FcResultMatch) { -+ fontval += sizeshift; -+ FcPatternDel(pattern, FC_PIXEL_SIZE); -+ FcPatternDel(pattern, FC_SIZE); -+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); -+ } -+ } -+ -+ FcPatternAddBool(pattern, FC_SCALABLE, 1); -+ -+ FcConfigSubstitute(NULL, pattern, FcMatchPattern); -+ XftDefaultSubstitute(xw.dpy, xw.scr, pattern); -+ -+ if (xloadsparefont(pattern, FRC_NORMAL)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_SLANT); -+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); -+ if (xloadsparefont(pattern, FRC_ITALIC)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_WEIGHT); -+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); -+ if (xloadsparefont(pattern, FRC_ITALICBOLD)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDel(pattern, FC_SLANT); -+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); -+ if (xloadsparefont(pattern, FRC_BOLD)) -+ die("can't open spare font %s\n", *fp); -+ -+ FcPatternDestroy(pattern); -+ } -+} -+ - void - xunloadfont(Font *f) - { -@@ -1057,6 +1155,9 @@ xinit(int cols, int rows) - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - -+ /* spare fonts */ -+ xloadsparefonts(); -+ - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - xloadcols(); --- -2.21.0 - diff --git a/st-0.8.4/st.1 b/st-0.8.4/st.1 deleted file mode 100644 index 39120b4..0000000 --- a/st-0.8.4/st.1 +++ /dev/null @@ -1,177 +0,0 @@ -.TH ST 1 st\-VERSION -.SH NAME -st \- simple terminal -.SH SYNOPSIS -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-l -.IR line ] -.RB [ \-w -.IR windowid ] -.RB [[ \-e ] -.IR command -.RI [ arguments ...]] -.PP -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-w -.IR windowid ] -.RB \-l -.IR line -.RI [ stty_args ...] -.SH DESCRIPTION -.B st -is a simple terminal emulator. -.SH OPTIONS -.TP -.B \-a -disable alternate screens in terminal -.TP -.BI \-c " class" -defines the window class (default $TERM). -.TP -.BI \-f " font" -defines the -.I font -to use when st is run. -.TP -.BI \-g " geometry" -defines the X11 geometry string. -The form is [=][{xX}][{+-}{+-}]. See -.BR XParseGeometry (3) -for further details. -.TP -.B \-i -will fixate the position given with the -g option. -.TP -.BI \-n " name" -defines the window instance name (default $TERM). -.TP -.BI \-o " iofile" -writes all the I/O to -.I iofile. -This feature is useful when recording st sessions. A value of "-" means -standard output. -.TP -.BI \-T " title" -defines the window title (default 'st'). -.TP -.BI \-t " title" -defines the window title (default 'st'). -.TP -.BI \-w " windowid" -embeds st within the window identified by -.I windowid -.TP -.BI \-l " line" -use a tty -.I line -instead of a pseudo terminal. -.I line -should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port -0). -When this flag is given -remaining arguments are used as flags for -.BR stty(1). -By default st initializes the serial line to 8 bits, no parity, 1 stop bit -and a 38400 baud rate. The speed is set by appending it as last argument -(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are -.BR stty(1) -flags. If you want to set odd parity on 115200 baud use for example 'st -l -/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for -example 'st -l /dev/ttyS0 cs7 115200'. See -.BR stty(1) -for more arguments and cases. -.TP -.B \-v -prints version information to stderr, then exits. -.TP -.BI \-e " command " [ " arguments " "... ]" -st executes -.I command -instead of the shell. If this is used it -.B must be the last option -on the command line, as in xterm / rxvt. -This option is only intended for compatibility, -and all the remaining arguments are used as a command -even without it. -.SH SHORTCUTS -.TP -.B Break -Send a break in the serial line. -Break key is obtained in PC keyboards -pressing at the same time control and pause. -.TP -.B Ctrl-Print Screen -Toggle if st should print to the -.I iofile. -.TP -.B Shift-Print Screen -Print the full screen to the -.I iofile. -.TP -.B Print Screen -Print the selection to the -.I iofile. -.TP -.B Ctrl-Shift-Page Up -Increase font size. -.TP -.B Ctrl-Shift-Page Down -Decrease font size. -.TP -.B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). -.TP -.B Ctrl-Shift-c -Copy the selected text to the clipboard selection. -.TP -.B Ctrl-Shift-v -Paste from the clipboard selection. -.SH CUSTOMIZATION -.B st -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH AUTHORS -See the LICENSE file for the authors. -.SH LICENSE -See the LICENSE file for the terms of redistribution. -.SH SEE ALSO -.BR tabbed (1), -.BR utmp (1), -.BR stty (1), -.BR scroll (1) -.SH BUGS -See the TODO file in the distribution. - diff --git a/st-0.8.4/st.c b/st-0.8.4/st.c deleted file mode 100644 index edec064..0000000 --- a/st-0.8.4/st.c +++ /dev/null @@ -1,2668 +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 -#define HISTSIZE 2000 - -/* 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)) -#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ - term.scr + HISTSIZE + 1) % HISTSIZE] : \ - term.line[(y) - term.scr]) - -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 */ - Line hist[HISTSIZE]; /* history buffer */ - int histi; /* history index */ - int scr; /* scroll back */ - 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 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, int); -static void tscrolldown(int, int, int); -static void tsetattr(int *, int); -static void tsetchar(Rune, Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, 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(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 uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static 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(char *s) -{ - if ((s = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return s; -} - -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; -} - -static const char base64_digits[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint(**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - - 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 (TLINE(y)[i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && TLINE(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; - 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 = &TLINE(*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 (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - - gp = &TLINE(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 (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { - if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - 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 = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - last = &TLINE(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(char *line, char *cmd, 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); - 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)); - close(s); - close(m); -#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; - Arg arg = (Arg) { .i = term.scr }; - - kscrolldown(&arg); - - 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() -{ - /* 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 -kscrolldown(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (n > term.scr) - n = term.scr; - - if (term.scr > 0) { - term.scr -= n; - selscroll(0, -n); - tfulldirt(); - } -} - -void -kscrollup(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (term.scr <= HISTSIZE-n) { - term.scr += n; - selscroll(0, n); - tfulldirt(); - } -} - -void -tscrolldown(int orig, int n, int copyhist) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - if (copyhist) { - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[term.bot]; - term.line[term.bot] = temp; - } - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); - - for (i = term.bot; i >= orig+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - - if (term.scr == 0) - selscroll(orig, n); -} - -void -tscrollup(int orig, int n, int copyhist) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - if (copyhist) { - term.histi = (term.histi + 1) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[orig]; - term.line[orig] = temp; - } - - if (term.scr > 0 && term.scr < HISTSIZE) - term.scr = MIN(term.scr + n, HISTSIZE-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; - } - - if (term.scr == 0) - selscroll(orig, -n); -} - -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1) - 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, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - - 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 (*p != ';' || 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, Glyph *attr, int x, int y) -{ - static 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, 0); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n, 0); -} - -int32_t -tdefcolor(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(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, int *args, int narg) -{ - int alt, *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 */ - DEFAULT(csiescseq.arg[0], 1); - 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 > 1) - 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 */ - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0], 0); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0], 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 (cursor position) */ - if (csiescseq.arg[0] == 6) { - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - } - 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) */ - 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 -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - - 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: - case 1: - 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 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset, here p = NULL */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) - 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 - */ - redraw(); - } - 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]; - 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, 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, 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(); - 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) { - 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)); - - if (term.c.x+width > term.col) { - tnewline(1); - 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) { - 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, j; - 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)); - - for (i = 0; i < HISTSIZE; i++) { - term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); - for (j = mincol; j < col; j++) { - term.hist[i][j] = term.c.attr; - term.hist[i][j].u = ' '; - } - } - - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - 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(TLINE(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); - if (term.scr == 0) - 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/st-0.8.4/st.c.orig b/st-0.8.4/st.c.orig deleted file mode 100644 index 76b7e0d..0000000 --- a/st-0.8.4/st.c.orig +++ /dev/null @@ -1,2597 +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 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(int *, int); -static void tsetchar(Rune, Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, 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(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 uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static 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(char *s) -{ - if ((s = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return s; -} - -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; -} - -static const char base64_digits[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint(**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - - 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; - 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; - 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(char *line, char *cmd, 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); - 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)); - close(s); - close(m); -#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() -{ - /* 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) - 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; - - 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 (*p != ';' || 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, Glyph *attr, int x, int y) -{ - static 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(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(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, int *args, int narg) -{ - int alt, *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 */ - DEFAULT(csiescseq.arg[0], 1); - 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 > 1) - 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 */ - 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 (cursor position) */ - if (csiescseq.arg[0] == 6) { - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - } - 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) */ - 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 -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - - 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: - case 1: - 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 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset, here p = NULL */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) - 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 - */ - redraw(); - } - 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]; - 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(); - 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) { - 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)); - - if (term.c.x+width > term.col) { - tnewline(1); - 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) { - 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/st-0.8.4/st.c.rej b/st-0.8.4/st.c.rej deleted file mode 100644 index b2053b8..0000000 --- a/st-0.8.4/st.c.rej +++ /dev/null @@ -1,13 +0,0 @@ ---- st.c -+++ st.c -@@ -191,8 +198,8 @@ 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 tscrollup(int, int, int); -+static void tscrolldown(int, int, int); - static void tsetattr(const int *, int); - static void tsetchar(Rune, const Glyph *, int, int); - static void tsetdirt(int, int); diff --git a/st-0.8.4/st.desktop b/st-0.8.4/st.desktop deleted file mode 100644 index 49029d8..0000000 --- a/st-0.8.4/st.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=st -Comment=st is a simple terminal implementation for X -Exec=st -Icon=utilities-terminal -Terminal=false -Type=Application -Categories=System;TerminalEmulator; diff --git a/st-0.8.4/st.h b/st-0.8.4/st.h deleted file mode 100644 index 7ea2fd3..0000000 --- a/st-0.8.4/st.h +++ /dev/null @@ -1,128 +0,0 @@ -/* See LICENSE for license details. */ - -#include -#include - -/* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ - (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ - (t1.tv_nsec-t2.tv_nsec)/1E6) -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - -#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) - -enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1 << 0, - ATTR_FAINT = 1 << 1, - ATTR_ITALIC = 1 << 2, - ATTR_UNDERLINE = 1 << 3, - ATTR_BLINK = 1 << 4, - ATTR_REVERSE = 1 << 5, - ATTR_INVISIBLE = 1 << 6, - ATTR_STRUCK = 1 << 7, - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, -}; - -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 -}; - -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; - -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; - -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned short ushort; - -typedef uint_least32_t Rune; - -#define Glyph Glyph_ -typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ -} Glyph; - -typedef Glyph *Line; - -typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; -} Arg; - -void die(const char *, ...); -void redraw(void); -void draw(void); - -void kscrolldown(const Arg *); -void kscrollup(const Arg *); -void printscreen(const Arg *); -void printsel(const Arg *); -void sendbreak(const Arg *); -void toggleprinter(const Arg *); - -int tattrset(int); -void tnew(int, int); -void tresize(int, int); -void tsetdirtattr(int); -void ttyhangup(void); -int ttynew(char *, char *, char *, char **); -size_t ttyread(void); -void ttyresize(int, int); -void ttywrite(const char *, size_t, int); - -void resettitle(void); - -void selclear(void); -void selinit(void); -void selstart(int, int, int); -void selextend(int, int, int, int); -int selected(int, int); -char *getsel(void); - -size_t utf8encode(Rune, char *); - -void *xmalloc(size_t); -void *xrealloc(void *, size_t); -char *xstrdup(char *); - -/* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; -extern unsigned int tabspaces; -extern unsigned int defaultfg; -extern unsigned int defaultbg; -extern float alpha; diff --git a/st-0.8.4/st.h.orig b/st-0.8.4/st.h.orig deleted file mode 100644 index 3d351b6..0000000 --- a/st-0.8.4/st.h.orig +++ /dev/null @@ -1,125 +0,0 @@ -/* See LICENSE for license details. */ - -#include -#include - -/* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ - (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ - (t1.tv_nsec-t2.tv_nsec)/1E6) -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - -#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) - -enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1 << 0, - ATTR_FAINT = 1 << 1, - ATTR_ITALIC = 1 << 2, - ATTR_UNDERLINE = 1 << 3, - ATTR_BLINK = 1 << 4, - ATTR_REVERSE = 1 << 5, - ATTR_INVISIBLE = 1 << 6, - ATTR_STRUCK = 1 << 7, - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, -}; - -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 -}; - -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; - -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; - -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned short ushort; - -typedef uint_least32_t Rune; - -#define Glyph Glyph_ -typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ -} Glyph; - -typedef Glyph *Line; - -typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; -} Arg; - -void die(const char *, ...); -void redraw(void); -void draw(void); - -void printscreen(const Arg *); -void printsel(const Arg *); -void sendbreak(const Arg *); -void toggleprinter(const Arg *); - -int tattrset(int); -void tnew(int, int); -void tresize(int, int); -void tsetdirtattr(int); -void ttyhangup(void); -int ttynew(char *, char *, char *, char **); -size_t ttyread(void); -void ttyresize(int, int); -void ttywrite(const char *, size_t, int); - -void resettitle(void); - -void selclear(void); -void selinit(void); -void selstart(int, int, int); -void selextend(int, int, int, int); -int selected(int, int); -char *getsel(void); - -size_t utf8encode(Rune, char *); - -void *xmalloc(size_t); -void *xrealloc(void *, size_t); -char *xstrdup(char *); - -/* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; -extern unsigned int tabspaces; -extern unsigned int defaultfg; -extern unsigned int defaultbg; diff --git a/st-0.8.4/st.info b/st-0.8.4/st.info deleted file mode 100644 index 8201ad6..0000000 --- a/st-0.8.4/st.info +++ /dev/null @@ -1,239 +0,0 @@ -st-mono| simpleterm monocolor, - acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, - am, - bce, - bel=^G, - blink=\E[5m, - bold=\E[1m, - cbt=\E[Z, - cvvis=\E[?25h, - civis=\E[?25l, - clear=\E[H\E[2J, - cnorm=\E[?12l\E[?25h, - colors#2, - cols#80, - cr=^M, - csr=\E[%i%p1%d;%p2%dr, - cub=\E[%p1%dD, - cub1=^H, - cud1=^J, - cud=\E[%p1%dB, - cuf1=\E[C, - cuf=\E[%p1%dC, - cup=\E[%i%p1%d;%p2%dH, - cuu1=\E[A, - cuu=\E[%p1%dA, - dch=\E[%p1%dP, - dch1=\E[P, - dim=\E[2m, - dl=\E[%p1%dM, - dl1=\E[M, - ech=\E[%p1%dX, - ed=\E[J, - el=\E[K, - el1=\E[1K, - enacs=\E)0, - flash=\E[?5h$<80/>\E[?5l, - fsl=^G, - home=\E[H, - hpa=\E[%i%p1%dG, - hs, - ht=^I, - hts=\EH, - ich=\E[%p1%d@, - il1=\E[L, - il=\E[%p1%dL, - ind=^J, - indn=\E[%p1%dS, - invis=\E[8m, - is2=\E[4l\E>\E[?1034l, - it#8, - kel=\E[1;2F, - ked=\E[1;5F, - ka1=\E[1~, - ka3=\E[5~, - kc1=\E[4~, - kc3=\E[6~, - kbs=\177, - kcbt=\E[Z, - kb2=\EOu, - kcub1=\EOD, - kcud1=\EOB, - kcuf1=\EOC, - kcuu1=\EOA, - kDC=\E[3;2~, - kent=\EOM, - kEND=\E[1;2F, - kIC=\E[2;2~, - kNXT=\E[6;2~, - kPRV=\E[5;2~, - kHOM=\E[1;2H, - kLFT=\E[1;2D, - kRIT=\E[1;2C, - kind=\E[1;2B, - kri=\E[1;2A, - kclr=\E[3;5~, - kdl1=\E[3;2~, - kdch1=\E[3~, - kich1=\E[2~, - kend=\E[4~, - kf1=\EOP, - kf2=\EOQ, - kf3=\EOR, - kf4=\EOS, - kf5=\E[15~, - kf6=\E[17~, - kf7=\E[18~, - kf8=\E[19~, - kf9=\E[20~, - kf10=\E[21~, - kf11=\E[23~, - kf12=\E[24~, - kf13=\E[1;2P, - kf14=\E[1;2Q, - kf15=\E[1;2R, - kf16=\E[1;2S, - kf17=\E[15;2~, - kf18=\E[17;2~, - kf19=\E[18;2~, - kf20=\E[19;2~, - kf21=\E[20;2~, - kf22=\E[21;2~, - kf23=\E[23;2~, - kf24=\E[24;2~, - kf25=\E[1;5P, - kf26=\E[1;5Q, - kf27=\E[1;5R, - kf28=\E[1;5S, - kf29=\E[15;5~, - kf30=\E[17;5~, - kf31=\E[18;5~, - kf32=\E[19;5~, - kf33=\E[20;5~, - kf34=\E[21;5~, - kf35=\E[23;5~, - kf36=\E[24;5~, - kf37=\E[1;6P, - kf38=\E[1;6Q, - kf39=\E[1;6R, - kf40=\E[1;6S, - kf41=\E[15;6~, - kf42=\E[17;6~, - kf43=\E[18;6~, - kf44=\E[19;6~, - kf45=\E[20;6~, - kf46=\E[21;6~, - kf47=\E[23;6~, - kf48=\E[24;6~, - kf49=\E[1;3P, - kf50=\E[1;3Q, - kf51=\E[1;3R, - kf52=\E[1;3S, - kf53=\E[15;3~, - kf54=\E[17;3~, - kf55=\E[18;3~, - kf56=\E[19;3~, - kf57=\E[20;3~, - kf58=\E[21;3~, - kf59=\E[23;3~, - kf60=\E[24;3~, - kf61=\E[1;4P, - kf62=\E[1;4Q, - kf63=\E[1;4R, - khome=\E[1~, - kil1=\E[2;5~, - krmir=\E[2;2~, - knp=\E[6~, - kmous=\E[M, - kpp=\E[5~, - lines#24, - mir, - msgr, - npc, - op=\E[39;49m, - pairs#64, - mc0=\E[i, - mc4=\E[4i, - mc5=\E[5i, - rc=\E8, - rev=\E[7m, - ri=\EM, - rin=\E[%p1%dT, - ritm=\E[23m, - rmacs=\E(B, - rmcup=\E[?1049l, - rmir=\E[4l, - rmkx=\E[?1l\E>, - rmso=\E[27m, - rmul=\E[24m, - rs1=\Ec, - rs2=\E[4l\E>\E[?1034l, - sc=\E7, - sitm=\E[3m, - sgr0=\E[0m, - smacs=\E(0, - smcup=\E[?1049h, - smir=\E[4h, - smkx=\E[?1h\E=, - smso=\E[7m, - smul=\E[4m, - tbc=\E[3g, - tsl=\E]0;, - xenl, - vpa=\E[%i%p1%dd, -# XTerm extensions - rmxx=\E[29m, - smxx=\E[9m, -# disabled rep for now: causes some issues with older ncurses versions. -# rep=%p1%c\E[%p2%{1}%-%db, -# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) - Tc, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, - -st| simpleterm, - use=st-mono, - colors#8, - setab=\E[4%p1%dm, - setaf=\E[3%p1%dm, - setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, - -st-256color| simpleterm with 256 colors, - use=st, - ccc, - colors#256, - oc=\E]104\007, - pairs#32767, -# Nicked from xterm-256color - initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, - setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, - setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, - -st-meta| simpleterm with meta key, - use=st, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-meta-256color| simpleterm with meta key and 256 colors, - use=st-256color, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-bs| simpleterm with backspace as backspace, - use=st, - kbs=\010, - kdch1=\177, - -st-bs-256color| simpleterm with backspace as backspace and 256colors, - use=st-256color, - kbs=\010, - kdch1=\177, diff --git a/st-0.8.4/st.o b/st-0.8.4/st.o deleted file mode 100644 index 133c6203f93849f98506fc8d92854dfbcf11344a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77064 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 diff --git a/st-0.8.4/win.h b/st-0.8.4/win.h deleted file mode 100644 index a6ef1b9..0000000 --- a/st-0.8.4/win.h +++ /dev/null @@ -1,39 +0,0 @@ -/* See LICENSE for license details. */ - -enum win_mode { - MODE_VISIBLE = 1 << 0, - MODE_FOCUSED = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_MOUSEBTN = 1 << 3, - MODE_MOUSEMOTION = 1 << 4, - MODE_REVERSE = 1 << 5, - MODE_KBDLOCK = 1 << 6, - MODE_HIDE = 1 << 7, - MODE_APPCURSOR = 1 << 8, - MODE_MOUSESGR = 1 << 9, - MODE_8BIT = 1 << 10, - MODE_BLINK = 1 << 11, - MODE_FBLINK = 1 << 12, - MODE_FOCUS = 1 << 13, - MODE_MOUSEX10 = 1 << 14, - MODE_MOUSEMANY = 1 << 15, - MODE_BRCKTPASTE = 1 << 16, - MODE_NUMLOCK = 1 << 17, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ - |MODE_MOUSEMANY, -}; - -void xbell(void); -void xclipcopy(void); -void xdrawcursor(int, int, Glyph, int, int, Glyph); -void xdrawline(Line, int, int, int); -void xfinishdraw(void); -void xloadcols(void); -int xsetcolorname(int, const char *); -void xsettitle(char *); -int xsetcursor(int); -void xsetmode(int, unsigned int); -void xsetpointermotion(int); -void xsetsel(char *); -int xstartdraw(void); -void xximspot(int, int); diff --git a/st-0.8.4/x.c b/st-0.8.4/x.c deleted file mode 100644 index 8c478f9..0000000 --- a/st-0.8.4/x.c +++ /dev/null @@ -1,2070 +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) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(char *, double); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static 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_alpha = NULL; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static int oldbutton = 3; /* button event on startup: 3 = release */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, x = evcol(e), y = evrow(e), - button = e->xbutton.button, state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - /* from urxvt */ - if (e->xbutton.type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MOUSE_MOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) - return; - - button = oldbutton + 32; - ox = x; - oy = y; - } else { - if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { - button = 3; - } else { - button -= Button1; - if (button >= 3) - button += 64 - 3; - } - if (e->xbutton.type == ButtonPress) { - oldbutton = button; - ox = x; - oy = y; - } else if (e->xbutton.type == ButtonRelease) { - oldbutton = 3; - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - if (button == 64 || button == 65) - return; - } - } - - if (!IS_SET(MODE_MOUSEX10)) { - button += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - button, x+1, y+1, - e->xbutton.type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+button, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -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) -{ - struct timespec now; - int snap; - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (e->xbutton.button == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); - clipcopy(NULL); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (e->xbutton.button == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); - 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); - } - - /* set alpha value of bg color */ - if (opt_alpha) - alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - XWindowAttributes attr; - XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - 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; - - 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); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, numspecs = 0; - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; - - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -{ - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, - width, 1); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec spec; - - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - 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 -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop); - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'A': - opt_alpha = EARGF(usage()); - 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/st-0.8.4/x.c.orig b/st-0.8.4/x.c.orig deleted file mode 100644 index c87e48e..0000000 --- a/st-0.8.4/x.c.orig +++ /dev/null @@ -1,2171 +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) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(char *, double); -static int xloadsparefont(FcPattern *, int); -static void xloadsparefonts(void); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_alpha = NULL; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static int oldbutton = 3; /* button event on startup: 3 = release */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - xloadsparefonts(); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, x = evcol(e), y = evrow(e), - button = e->xbutton.button, state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - /* from urxvt */ - if (e->xbutton.type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MOUSE_MOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) - return; - - button = oldbutton + 32; - ox = x; - oy = y; - } else { - if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { - button = 3; - } else { - button -= Button1; - if (button >= 3) - button += 64 - 3; - } - if (e->xbutton.type == ButtonPress) { - oldbutton = button; - ox = x; - oy = y; - } else if (e->xbutton.type == ButtonRelease) { - oldbutton = 3; - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - if (button == 64 || button == 65) - return; - } - } - - if (!IS_SET(MODE_MOUSEX10)) { - button += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - button, x+1, y+1, - e->xbutton.type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+button, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -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) -{ - struct timespec now; - int snap; - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (e->xbutton.button == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); - clipcopy(NULL); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (e->xbutton.button == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); - 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); - } - - /* set alpha value of bg color */ - if (opt_alpha) - alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -int -xloadsparefont(FcPattern *pattern, int flags) -{ - FcPattern *match; - FcResult result; - - match = FcFontMatch(NULL, pattern, &result); - if (!match) { - return 1; - } - - if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(match); - return 1; - } - - frc[frclen].flags = flags; - /* Believe U+0000 glyph will present in each default font */ - frc[frclen].unicodep = 0; - frclen++; - - return 0; -} - -void -xloadsparefonts(void) -{ - FcPattern *pattern; - double sizeshift, fontval; - int fc; - char **fp; - - if (frclen != 0) - die("can't embed spare fonts. cache isn't empty"); - - /* Calculate count of spare fonts */ - fc = sizeof(font2) / sizeof(*font2); - if (fc == 0) - return; - - /* Allocate memory for cache entries. */ - if (frccap < 4 * fc) { - frccap += 4 * fc - frccap; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - for (fp = font2; fp - font2 < fc; ++fp) { - - if (**fp == '-') - pattern = XftXlfdParse(*fp, False, False); - else - pattern = FcNameParse((FcChar8 *)*fp); - - if (!pattern) - die("can't open spare font %s\n", *fp); - - if (defaultfontsize > 0) { - sizeshift = usedfontsize - defaultfontsize; - if (sizeshift != 0 && - FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - fontval += sizeshift; - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); - } - } - - FcPatternAddBool(pattern, FC_SCALABLE, 1); - - FcConfigSubstitute(NULL, pattern, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, pattern); - - if (xloadsparefont(pattern, FRC_NORMAL)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadsparefont(pattern, FRC_ITALIC)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadsparefont(pattern, FRC_ITALICBOLD)) - die("can't open spare font %s\n", *fp); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadsparefont(pattern, FRC_BOLD)) - die("can't open spare font %s\n", *fp); - - FcPatternDestroy(pattern); - } -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - XWindowAttributes attr; - XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* spare fonts */ - xloadsparefonts(); - - /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - 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; - - 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); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, numspecs = 0; - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; - - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -{ - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, - width, 1); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec spec; - - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - 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 -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop); - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'A': - opt_alpha = EARGF(usage()); - 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/st-0.8.4/x.o b/st-0.8.4/x.o deleted file mode 100644 index 3f917815cfa429955bd9517ad074be4ac35d379a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74800 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

^2~2}L61MN2Cq1r<(3#2H=@Odgv$HU-|I99~@M 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