From 700f2012f0eba694d6d6ed2c35d050942745e1fb Mon Sep 17 00:00:00 2001 From: Hektor Misplon Date: Thu, 7 May 2020 00:26:42 +0000 Subject: [PATCH] Add suckless config --- .suckless/dmenu/.gitignore | 1 + .suckless/dmenu/LICENSE | 30 + .suckless/dmenu/Makefile | 64 + .suckless/dmenu/README | 24 + .suckless/dmenu/arg.h | 49 + .suckless/dmenu/config.def.h | 23 + .suckless/dmenu/config.h | 23 + .suckless/dmenu/config.mk | 31 + .suckless/dmenu/dmenu | Bin 0 -> 43840 bytes .suckless/dmenu/dmenu.1 | 194 ++ .suckless/dmenu/dmenu.c | 771 ++++++ .suckless/dmenu/dmenu.o | Bin 0 -> 32504 bytes .suckless/dmenu/dmenu_path | 13 + .suckless/dmenu/dmenu_run | 2 + .suckless/dmenu/drw.c | 435 +++ .suckless/dmenu/drw.h | 57 + .suckless/dmenu/drw.o | Bin 0 -> 10472 bytes .suckless/dmenu/stest | Bin 0 -> 17688 bytes .suckless/dmenu/stest.1 | 90 + .suckless/dmenu/stest.c | 109 + .suckless/dmenu/stest.o | Bin 0 -> 5296 bytes .suckless/dmenu/util.c | 35 + .suckless/dmenu/util.h | 8 + .suckless/dmenu/util.o | Bin 0 -> 2224 bytes .suckless/dwm | 1 + .suckless/sselp/.gitignore | 1 + .suckless/sselp/.hgtags | 2 + .suckless/sselp/LICENSE | 21 + .suckless/sselp/Makefile | 48 + .suckless/sselp/README | 24 + .suckless/sselp/config.mk | 21 + .suckless/sselp/sselp | Bin 0 -> 14480 bytes .suckless/sselp/sselp.c | 44 + .suckless/sselp/sselp.o | Bin 0 -> 3256 bytes .suckless/st/.gitignore | 1 + .suckless/st/FAQ | 195 ++ .suckless/st/LEGACY | 17 + .suckless/st/LICENSE | 34 + .suckless/st/Makefile | 57 + .suckless/st/README | 34 + .suckless/st/TODO | 28 + .suckless/st/arg.h | 50 + .suckless/st/config.def.h | 459 ++++ .suckless/st/config.h | 460 ++++ .suckless/st/config.mk | 35 + .suckless/st/patches/st-anysize-0.8.1.diff | 152 + .suckless/st/patches/st-nordtheme-0.8.2.diff | 100 + .suckless/st/st | Bin 0 -> 102208 bytes .suckless/st/st.1 | 176 ++ .suckless/st/st.c | 2599 ++++++++++++++++++ .suckless/st/st.h | 123 + .suckless/st/st.info | 222 ++ .suckless/st/st.o | Bin 0 -> 73184 bytes .suckless/st/win.h | 39 + .suckless/st/x.c | 2045 ++++++++++++++ .suckless/st/x.o | Bin 0 -> 73896 bytes 56 files changed, 8947 insertions(+) create mode 100644 .suckless/dmenu/.gitignore create mode 100644 .suckless/dmenu/LICENSE create mode 100644 .suckless/dmenu/Makefile create mode 100644 .suckless/dmenu/README create mode 100644 .suckless/dmenu/arg.h create mode 100644 .suckless/dmenu/config.def.h create mode 100644 .suckless/dmenu/config.h create mode 100644 .suckless/dmenu/config.mk create mode 100755 .suckless/dmenu/dmenu create mode 100644 .suckless/dmenu/dmenu.1 create mode 100644 .suckless/dmenu/dmenu.c create mode 100644 .suckless/dmenu/dmenu.o create mode 100755 .suckless/dmenu/dmenu_path create mode 100755 .suckless/dmenu/dmenu_run create mode 100644 .suckless/dmenu/drw.c create mode 100644 .suckless/dmenu/drw.h create mode 100644 .suckless/dmenu/drw.o create mode 100755 .suckless/dmenu/stest create mode 100644 .suckless/dmenu/stest.1 create mode 100644 .suckless/dmenu/stest.c create mode 100644 .suckless/dmenu/stest.o create mode 100644 .suckless/dmenu/util.c create mode 100644 .suckless/dmenu/util.h create mode 100644 .suckless/dmenu/util.o create mode 160000 .suckless/dwm create mode 100644 .suckless/sselp/.gitignore create mode 100644 .suckless/sselp/.hgtags create mode 100644 .suckless/sselp/LICENSE create mode 100644 .suckless/sselp/Makefile create mode 100644 .suckless/sselp/README create mode 100644 .suckless/sselp/config.mk create mode 100755 .suckless/sselp/sselp create mode 100644 .suckless/sselp/sselp.c create mode 100644 .suckless/sselp/sselp.o create mode 100644 .suckless/st/.gitignore create mode 100644 .suckless/st/FAQ create mode 100644 .suckless/st/LEGACY create mode 100644 .suckless/st/LICENSE create mode 100644 .suckless/st/Makefile create mode 100644 .suckless/st/README create mode 100644 .suckless/st/TODO create mode 100644 .suckless/st/arg.h create mode 100644 .suckless/st/config.def.h create mode 100644 .suckless/st/config.h create mode 100644 .suckless/st/config.mk create mode 100644 .suckless/st/patches/st-anysize-0.8.1.diff create mode 100644 .suckless/st/patches/st-nordtheme-0.8.2.diff create mode 100755 .suckless/st/st create mode 100644 .suckless/st/st.1 create mode 100644 .suckless/st/st.c create mode 100644 .suckless/st/st.h create mode 100644 .suckless/st/st.info create mode 100644 .suckless/st/st.o create mode 100644 .suckless/st/win.h create mode 100644 .suckless/st/x.c create mode 100644 .suckless/st/x.o diff --git a/.suckless/dmenu/.gitignore b/.suckless/dmenu/.gitignore new file mode 100644 index 0000000..c190512 --- /dev/null +++ b/.suckless/dmenu/.gitignore @@ -0,0 +1 @@ +*.backup diff --git a/.suckless/dmenu/LICENSE b/.suckless/dmenu/LICENSE new file mode 100644 index 0000000..9762166 --- /dev/null +++ b/.suckless/dmenu/LICENSE @@ -0,0 +1,30 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 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-2019 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/.suckless/dmenu/Makefile b/.suckless/dmenu/Makefile new file mode 100644 index 0000000..a03a95c --- /dev/null +++ b/.suckless/dmenu/Makefile @@ -0,0 +1,64 @@ +# 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/.suckless/dmenu/README b/.suckless/dmenu/README new file mode 100644 index 0000000..a8fcdfe --- /dev/null +++ b/.suckless/dmenu/README @@ -0,0 +1,24 @@ +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/.suckless/dmenu/arg.h b/.suckless/dmenu/arg.h new file mode 100644 index 0000000..e94e02b --- /dev/null +++ b/.suckless/dmenu/arg.h @@ -0,0 +1,49 @@ +/* + * 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/.suckless/dmenu/config.def.h b/.suckless/dmenu/config.def.h new file mode 100644 index 0000000..1edb647 --- /dev/null +++ b/.suckless/dmenu/config.def.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/.suckless/dmenu/config.h b/.suckless/dmenu/config.h new file mode 100644 index 0000000..5543f2a --- /dev/null +++ b/.suckless/dmenu/config.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 0; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "Iosevka:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/.suckless/dmenu/config.mk b/.suckless/dmenu/config.mk new file mode 100644 index 0000000..0929b4a --- /dev/null +++ b/.suckless/dmenu/config.mk @@ -0,0 +1,31 @@ +# dmenu version +VERSION = 4.9 + +# 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/.suckless/dmenu/dmenu b/.suckless/dmenu/dmenu new file mode 100755 index 0000000000000000000000000000000000000000..cf40be43136370e70b71244803582c9b22a3f71a GIT binary patch literal 43840 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 literal 0 HcmV?d00001 diff --git a/.suckless/dmenu/dmenu.1 b/.suckless/dmenu/dmenu.1 new file mode 100644 index 0000000..323f93c --- /dev/null +++ b/.suckless/dmenu/dmenu.1 @@ -0,0 +1,194 @@ +.TH DMENU 1 dmenu\-VERSION +.SH NAME +dmenu \- dynamic menu +.SH SYNOPSIS +.B dmenu +.RB [ \-bfiv ] +.RB [ \-l +.IR lines ] +.RB [ \-m +.IR monitor ] +.RB [ \-p +.IR prompt ] +.RB [ \-fn +.IR font ] +.RB [ \-nb +.IR color ] +.RB [ \-nf +.IR color ] +.RB [ \-sb +.IR color ] +.RB [ \-sf +.IR color ] +.RB [ \-w +.IR windowid ] +.P +.BR dmenu_run " ..." +.SH DESCRIPTION +.B dmenu +is a dynamic menu for X, which reads a list of newline\-separated items from +stdin. When the user selects an item and presses Return, their choice is printed +to stdout and dmenu terminates. Entering text will narrow the items to those +matching the tokens in the input. +.P +.B dmenu_run +is a script used by +.IR dwm (1) +which lists programs in the user's $PATH and runs the result in their $SHELL. +.SH OPTIONS +.TP +.B \-b +dmenu appears at the bottom of the screen. +.TP +.B \-f +dmenu grabs the keyboard before reading stdin if not reading from a tty. This +is faster, but will lock up X until stdin reaches end\-of\-file. +.TP +.B \-i +dmenu matches menu items case insensitively. +.TP +.BI \-l " lines" +dmenu lists items vertically, with the given number of lines. +.TP +.BI \-m " monitor" +dmenu is displayed on the monitor number supplied. Monitor numbers are starting +from 0. +.TP +.BI \-p " prompt" +defines the prompt to be displayed to the left of the input field. +.TP +.BI \-fn " font" +defines the font or font set used. +.TP +.BI \-nb " color" +defines the normal background color. +.IR #RGB , +.IR #RRGGBB , +and X color names are supported. +.TP +.BI \-nf " color" +defines the normal foreground color. +.TP +.BI \-sb " color" +defines the selected background color. +.TP +.BI \-sf " color" +defines the selected foreground color. +.TP +.B \-v +prints version information to stdout, then exits. +.TP +.BI \-w " windowid" +embed into windowid. +.SH USAGE +dmenu is completely controlled by the keyboard. Items are selected using the +arrow keys, page up, page down, home, and end. +.TP +.B Tab +Copy the selected item to the input field. +.TP +.B Return +Confirm selection. Prints the selected item to stdout and exits, returning +success. +.TP +.B Ctrl-Return +Confirm selection. Prints the selected item to stdout and continues. +.TP +.B Shift\-Return +Confirm input. Prints the input text to stdout and exits, returning success. +.TP +.B Escape +Exit without selecting an item, returning failure. +.TP +.B Ctrl-Left +Move cursor to the start of the current word +.TP +.B Ctrl-Right +Move cursor to the end of the current word +.TP +.B C\-a +Home +.TP +.B C\-b +Left +.TP +.B C\-c +Escape +.TP +.B C\-d +Delete +.TP +.B C\-e +End +.TP +.B C\-f +Right +.TP +.B C\-g +Escape +.TP +.B C\-h +Backspace +.TP +.B C\-i +Tab +.TP +.B C\-j +Return +.TP +.B C\-J +Shift-Return +.TP +.B C\-k +Delete line right +.TP +.B C\-m +Return +.TP +.B C\-M +Shift-Return +.TP +.B C\-n +Down +.TP +.B C\-p +Up +.TP +.B C\-u +Delete line left +.TP +.B C\-w +Delete word left +.TP +.B C\-y +Paste from primary X selection +.TP +.B C\-Y +Paste from X clipboard +.TP +.B M\-b +Move cursor to the start of the current word +.TP +.B M\-f +Move cursor to the end of the current word +.TP +.B M\-g +Home +.TP +.B M\-G +End +.TP +.B M\-h +Up +.TP +.B M\-j +Page down +.TP +.B M\-k +Page up +.TP +.B M\-l +Down +.SH SEE ALSO +.IR dwm (1), +.IR stest (1) diff --git a/.suckless/dmenu/dmenu.c b/.suckless/dmenu/dmenu.c new file mode 100644 index 0000000..65f25ce --- /dev/null +++ b/.suckless/dmenu/dmenu.c @@ -0,0 +1,771 @@ +/* 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 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, 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, 2, bh - 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 +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 Expose: + if (ev.xexpose.count == 0) + drw_map(drw, win, 0, 0, mw, mh); + break; + case FocusIn: + /* regrab focus from parent window */ + if (ev.xfocus.window != win) + grabfocus(); + break; + case KeyPress: + keypress(&ev.xkey); + break; + case SelectionNotify: + if (ev.xselection.property == utf8) + paste(); + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) + XRaiseWindow(dpy, win); + break; + } + } +} + +static void +setup(void) +{ + int x, y, i, j; + unsigned int du; + XSetWindowAttributes swa; + XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; +#ifdef XINERAMA + XineramaScreenInfo *info; + Window pw; + int a, di, n, area = 0; +#endif + /* init appearance */ + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], 2); + + clip = XInternAtom(dpy, "CLIPBOARD", False); + utf8 = XInternAtom(dpy, "UTF8_STRING", False); + + /* calculate menu geometry */ + bh = drw->fonts->h + 2; + lines = MAX(lines, 0); + mh = (lines + 1) * bh; +#ifdef XINERAMA + i = 0; + if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { + XGetInputFocus(dpy, &w, &di); + if (mon >= 0 && mon < n) + i = mon; + else if (w != root && w != PointerRoot && w != None) { + /* find top-level window containing current input focus */ + do { + if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while (w != root && w != pw); + /* find xinerama screen with which the window intersects most */ + if (XGetWindowAttributes(dpy, pw, &wa)) + for (j = 0; j < n; j++) + if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + /* no focused window is on screen, so use pointer location instead */ + if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, info[i])) + break; + + x = info[i].x_org; + y = info[i].y_org + (topbar ? 0 : info[i].height - mh); + mw = info[i].width; + XFree(info); + } else +#endif + { + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + x = 0; + y = topbar ? 0 : wa.height - mh; + mw = wa.width; + } + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + inputw = 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; + win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + XSetClassHint(dpy, win, &ch); + + + /* input methods */ + if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed: could not open input device"); + + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + + XMapRaised(dpy, win); + if (embed) { + 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] [-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], "-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/.suckless/dmenu/dmenu.o b/.suckless/dmenu/dmenu.o new file mode 100644 index 0000000000000000000000000000000000000000..826665fc6d7d965a02f92f81fec6468882d3fcd3 GIT binary patch literal 32504 zcmeI5dwf*Y)%Q;>U_hJ+h%HrYr!v|^A!Yy};bJo|ffF4hkbsekkjn%DxivF^P_cqZ z(9b<*c1@pvXC3r<`pW?tL-CPC32)olZEk{>(b~jlCOoI(HS@@#|p6vOA{Y z>IDA0gypKOV5!}@zo*FgEYLa6c23#OKT7`Rm-eYY*d4d@1lLXRTd^ONi=0Q1KdE)Fi*6}&k(KRB;2@L{kN=)97^VSD`tSw73Evg7GjWps4jDUpVCx z+X?wI$bnLShV7(+2hEp3b_@{2M2F9IUbRoXK{_^580drup>EpVQ0@pQ6)Fl@sGN99 zo{H!kXt=O{xXK)dFickYR}IoND02Q3cFrXdpZE0G?LDz<+c{LU<1Yj39mfXPd($sK zqc_CIUrXUpM$(i4ot?_cKV*An9C9v4xgFO*ud>JKR)`JIj<4^+#=)iwE)L!rT(T=T zFIYOSWNut#Yd;(t@MZj=umw~3qtWL(R?UPttb|{(X=cSAAlO|Q+uK8 z?ojrhv%9l*QCtEa+SGQ`vD**E=C&$3maa|nR69OaR#*#zPN#Dyl(IAbt?0;PjCJ|( zToIU*-TB?O4>L>ao|(*3kVzgS*7QKs^_|VeFhuBqUW^H9}Cg>X~?o6PYbahYv zSDrr0a_Zjkf(*Nlx82_>(=D=VUWwiML6$goLjDoZ!^kZg&Y%noFK%QOO!HdJOP)WG zrq3v_sRB_L*dN@6C;7AZ^Bn%zm3JM()sABq*lBlRnCy6CrV1CF8Y2TI`Aq3~x%pY@ z?SW2p+=kvd;=Eqe+Lg6%F*y5t720b3Ag_Q38;zQ6&bw=QZZ{33rL9x_VVt$DK z`&5D+qw;~p0;CA+e=ZeFD*?FIvDQCAZG(f)pYI?9%;@H=U3uUj^lj(&!P21f`aBri zZ0B6Doqsu)P5PmS$Jp@J+eQFWel%Y|8>&3r8CO`&N6(@^J>x=}e4qS0btdE_LeBA^ zvqM*=wQB@5C6B$j$~a2mi557lbisLKC~$B^O8g@9DX7{DDyuVSbGo$PtqWj8ij}O( zvtl>(wcE$bz)9_;s>pes>S6*1*;g0?oL$tjnul^9qcgmDFl_|0kMu1u_yR`4?oelT zpW;K#J6tX2C`TxG>Yu$ua{D_UQT24wQ;3{Bc8Wd_To7Ccr#i(NOawb>2lj-rcL(!7 zSOw=Bo$)HSa6yN#WBfHYlSG9>^`sS6sH5OBr45z^Z=q_(@@+j{!L`fIS2fa6^0qw# zCk_pBaCT(B=^TY-KJklx;$Tsi+5HEOm$&V1P_j#U5KL2@Och4s^llykT3a%#SW(}I ziW)#qJF1+f)+4*$KXu0LxCDENlbG8Z&RcE`Yxh(B6z)(Xa#&Y_vU%IqLzbd=vp$jZ z5RO+$9YF0{(AksStz5W9o*UV_g84_I7bi1QMRs&wnlz&_Wp_JoUZXm2_70pXd>lA< zqV2Puo>>qjXLn*HjIOiVKa5q|Iy5Rz-|Dj)T_O%D1}iLmN}kt~DHfsZ_n^y(c$6&& z>E>G)*dI8U4592~bm2>2EMa=29DmMQ2Ul(5#8X|2y#2Sg11DvU1*(*JbgGoha z0lhDdPb+9U8S_)o$s#Y-6T|z^w7$so7Ou}j&g$c<1Z=-7*HkSYY*m)m*Ehs`O_B22+J;KsmCe42HL*x^5+8`hnyQ)`1)l;p#FS}SQ+b7N zWn@i7LwQqGA6VT`*&Kzyj#*`?nvNNtlW&cwu*OtdV`{81wbqzAYfK~T)?45{EWo3% zj>391G){R_eNFwcNxu39A9z(>8}UV(8yg#%Vo8S^8YA_-s+wqHZTT9jvZ1-Q3dAwr zvPjGqsjG-oRY88Lr>{H~YpSVe#%lR;Tdu5avA{0IH44GPoD~r$ro1Xrm80FYriY7) zr_Bz|4O#O_XXGs@DV26+K4r(LM3a|Se2|%5tXb_xw+R}H*q4aG2yxzl2z0YjjUQ( zJ}FxB&B)Y1t`)qQ2DIRO7{6fF`U1>vEF8PB|F8dGA58z8wf-Su%HQVS1~AYWnhdjk zZ^v24P*k~_&J{a8dKa7qyRpyml>t~=kEzJl<-5?phhz}vnXo>KHFW?=9|2oMG~ zaSo=(a52>}pur6y%JV((7^-`aIt*8!V~!* zv)l19xMHZQ7Cb`fodsPIILMQ-r2W|Oq(cw*_hIJVE_ZSAkm@27ysZ5nqcGD1OV_WXI92aEYWC98>HXEt zzPfy6-P>Ld14*)mG5=`os2~`|Z}#DXXsuoD3XJ`~zDjzSduWPu^%ukQuHm%HJKk zIvlSB8y%(oydvk#u=6)^G29XI7li3<7W(q;?yX7ZAMh7L;o{&X>@&zhai|zR)tHqY zia+2l0~F{99EPc52)a|LQas{c1na_-orNhchw@L|KF9mgQ145@^pN+ZHK{2FLiq=R z-q|}t`8$K&@PX_D-k0VK40`R|p_H?s{I}rHYlZp$RpheL4)ej(g}b<9W!b<9oyr@smwrrXXw*sMtnc$aJL}_6_6cx#XDH>ks@`mmjA0`73&48L~W^%hKGb!=5J&!&S7-FJH* zdYn3wy$c_8c4`yP!c#sAJAIixk>H7d9+mPBKtIqL-6Hz<-ZuZ!kON$R?xyZ?lefe0 z=##1pqRl9Rizrtgd|w(YU7iZp;}!J3c-UVIcMf4~zO^ftv|)J02gA)C8t1~v=Xq-6 z#5?fh$cv|Mvxi1?da@YSj;^qt%Yga^I>Q~xO`BHE$HC%07m~isBx_8~UADm6)(+L- z+UW>CXIWW#c*ZC2`W)`7z%K1qXEHT*=p}+w$N^f4F12{}2F< zvGX}OwbKG zJ$1I)p0BnCsoY25y!CFt!O5PgbC=;!-D}`v#w$Yma1be%Ps05icm=n>Uu4Ad3d)h+ z=C?rMZT~(@U{oIU#H0JI*6sdGH~>fPfFpg+7VO1+dyC4MmWR@e$ZonQZTi52%>iaqDDyajLid&)}+E8S@VbJEs!wfevC=RA z_1^V9?$Jq6nZDjm+1GQ-o;pX_#<(Z;qhM->0zZa=6Wb8Lxs6dqUBW?k2waAsMF6~` zOe_Pi?sx`t8$8l_dZxF14Ym0reZ#_`~%`n(|SNA!Hf`0aESEk*KGqkghD| zLgPP&57Lw<*&p_(AXuVX^s)7bvULgkT6X>eYB2Y<|N3-KPjDV}ML6r=tth|IhS#GR z_(TI|wPi5LX!AFM%f)k5p*Bo#pg-IghAFL$k2r(sTLKuN^{X2CqSI;tYp9K2O9{F!9+bz8wugx`%9apskH*L62`kI%H@a02$NPrFgP{1beeue#moL<+QA) za19=ANCib}TF6t7x<$Dh^kksUhqfU-ia))&B2RJZ{j8e;hiuZ_jyiC%Bef8H38633 z(HE#!izlzhQ&4%HKW&f&U&Ug23@)Kou_yB$tV;*RWh2&Q1J1!!K3k99#c><0;J#Y>j zO`Qz~7r?;=SO-x)ECaS~0x}zn%m5=rAP<7P2<1QWL(tO4V1#USe5a zf*rKacGWlo46dw-&m*xKYhXKz_`}52xB}Z_VZm~rCeHrgxPctkn3&@^jC`M>7(<<= z6Yr#b=0(JZ7<@MDqyG!3PpYvA*h13dlUGb^=T_Lpat|ol%gc#(8N7!0CgSXWJ@LB@ z9wq*e!CPP-{Y+5Pt8oxmJLwM@`Z)2W2EP~f(awWZp-1WX3g~KBFWb<6pY#){>D71w z>@iqSzYf-zxLyOP|M(QOtP!++9M)LwR^*6PhV&&uKo{-dd z3G2b2Lp#q9SK}k_Oo}I$$MwSbEBeEUkNb&lrUT5!C{D)V81w6h^FFVy2af*SrXF!w zmKtNpW|}pSwt82ER4%s@dlpulIvdED7b`v_Ij`Vy=M!hkxwNsE?6=T9+o>X6Oq}i1 z6K^zll=yOkw-7HdIPRt;qeTa4m1gzEQyxjPcyy2y?Rfiwq#f>^y@&B8(&}fNTu*#c zuT*VqApUcM$BFMSIL`IZ{w{-mm-udjKTP~Bga4TL2L|6l{3C<^oH(8bGX0YHISFBV zEAh__{v7cXweCIGNj%-)dx&3P@K=cA`6tss;&^K)(;?zR4StmPB?f<&_?HZh_tO}E zeAX$`C&a&M@RP*-2LFusl?G2$1I_>|Xz&c;^9=4GuKQ81N5hG4HuRSgf85|c;!hj= zD&pG>KAQLmgO4TtsloGzr>J$WpSYD~dHMp_yB>7spIz{t%7x?gyFY!o3$J$JqoM5n z>@>OPabDb?ew_<%bK!9pexD2fi3{K6!tuJ)pP&Ej!ryV>pSbWI7k&|3Li#KB3oiUC zF8pgQe1Z!f>%u3y@SqEy?ZWZ>L4WmH?7}0!hl%U2x?h35w!%ff$R(cNaM7=F;p<%Z zCKvug7rw=X#d51|wWU8^T#aU%R3Shjt1SFhF!`yV`a;jDYFwkR{#dZ8seCmS zWkn;kP+IwF{6f;ITTTY8y7E}%@<tgO$;pDonq$>@R!dE# zl@p$xi$4MU8H+#T@Mk>!T!%js@Mj|a~{=j#B_^a{+RHlH+6;Rm%Dqlcl45*v| zl{KL9j#YWb>he_Hu`2Iam3OSlJ67c#tMZOjdB>`}<5b>pD(^V$>^KX0Laa&b2ZFZ8Ls0$lSVIl;=@?WVzGDR= z`a{-enD+6TQeiFDfK`jo*P_AXm#fMR=w9V9?Y8Q75FkP|QTWJJ`x>pRV_H^J59dIA zFxF6KmBIJLP33jvbDASfYf4l{jap?hRK*l4?cFSHsKJa-S5+W=xr(8jURxfG+HjOV zhGk9BbgOJudE?yjnrNg7Y8k18aH@8o;NnNCR@qGu?ZQ=Xc0kcJwNM7_)K!EV8df$p zmcW;~^~<2OD`RUKBTFilV4o?Q-cY{^&O2?i2F^N&Z9T@lH&VrLQiBALa)DgNxv@?# z9Z>h+TWOze@8Mow^CQG3(;9gNEbvZMrD=kHUGSO2VR*Kx1fL^#MDRNW$7d{TAHO!m zgyk-Sh54TmLPGm^@6P;vgpg2=$DYI;NWH&rL9)ofWXK zok@bP6da#-U^4Aj34JXbXFK|SUh9K`Zxni2?)@(I^?h=0x#Q6ZNc)AII@srOUo-4< zDYa!CcHx7tLXfy#Y+v6u>iFQZNVc!<8+-Nq&PLxi_Hr)QXV~ZGIAdHm-oIhOc4>fx z%dK+JHyHc?W`@M?Bk(ZV;(Fa7^wWT|{dU1o{|YRaHX5Akb-%$omD;i%B91m>+*vwge|#AMnZW9ZrbB!hE&rW^bLZPp4Koc+1k zg|9R?$F0fW9Jlob=W;i?aQtQs6UTw|ct0jN$LHt7&G`Jv&~tot8l3I#H#pn>ql^8+ zhMw)Gq9c&l|JU@cm1Xcn#OD*oRU<5XzElbR4Z$0Posi(GgkFxralz&I^Rlpmo9xda zp>GoQ-!}9iIELv%gR`A8!VbRU;d%|A_aS&#)+>`Z#;s83@tZ?TsF(E`Ex4>#SlGcl zYcVsV5`%O5E-<)X%dKSwA5FZ`;3J7Q6UQ=RuyB2EGxXa@um6ofZ$IJl<-3NS{rsu0 z-z@C^&d{?zFB+Wf{9f3Re!gMo_mQ8+49?e)j}6ZDKNa>@2|v#n`XOZBORs47eBt6F1|z+0b)5pE5Yd?RN&}a=V0m8K0M3^sfoMoNv5k z=(m#p?--oR{lLY}8AH$Y8cGes{gCa9FgVBga^hy(Mj3jJ&v=8g{UTvUo-ZYao_4Lp z2H!|=SZ44x;&le+{_{XlgGXP6dYsJMgIJjI5OG3+YLRp z%Wi{neP1&;x64}wXFuO2j^)N+VL$QHe@xu&T<$*%&hh!o;B0>&-3Xu^8HbCBW4W^b zj}&@5#`U^V@ae$W&(VUTz6};k;|$LJOe2n38E4zjbAOm?aJExsaE?!fi~Z#;`UZou z{X1Ojv>SRZ_g;gu|KD@5^QfU`J9`9|aempw&OxEan2yBYLweKTT(7qc&gK49*pESe zZr=}G^k)su^-ZDgIJn<({~Tm+_Gg&jvc98;W1VFG94+*CY#%I`@(j-YeBIz7Ew^SE zoc&o~@KVw*H~1prb;QvZ{I-JQ7BlqRE^CAyzg=PdIz#U#`|U3JjfQ?S>A&Nmf5^~t zeSawQ-xU6AG4x#D{}B4yg#H;9eW$^Xke~Yv{%hig1)l_rze6}d9OEpX7kw)9cx)@# z`KQ6T-1Na(!2OfU{es}K+)>2Ma<3J7S?=`)=W=Hloc)|HxGZ-eakJcS2)!)#n}SO_ z>jjtk`&{fl;iCVY!MR>L1uuZma)16n*vD_WnEzeqX9#{y=)Wbn=R(+l#O;N3z~nPH z+y9!uSwDd|?$^M=`l*JV`7EJdA@rp#`h|kadesO!vR-!zJ^IAuZZoX0`_AfO!>qi@$?T<4!>n9nU^+AKLrMTG! z-$*<{9AhA#Gi)^UM@ava!Fl|7Q`or!v>g9WT=a9rI1GPbC8^&gIQq_Z==NHjzZh$N zpAm*_Ovq-!!uqAKjS1_u9v0>+5kf+}4GZ%|gpg2wCoIf4eyA@JybZQ7nfC9|I62N_ z(*BPGzX7({{^P_=JHHY78-@M_7d_8ku7=~)LjPZ+NB`ydDBthM^WuG>$2{X`|8Ih0 z%-R1l#7+PC`#$8YLeJmvp=~@y(?3hT51J+P{QaG2|61`rMcT*jXfdJvG+5YA{{9a6 zO@bE*JF=hLBJ5zLKVp+`Hce^v0gg1_Nn=RKiEJHuhY^s(S2u+R2Sx!Ab?8w3)r&<@9${~ZkS zQdro|2-2JVL4Uuf?clN3VZp@jr!d<*SlG@D!cLpu^NHiCLh!|c&lkLcIF?x@c#Yug zg2x2kAoy*jNSWCyi(!NPtXHte(Bd_Tqfl(2KRu#<`>GbFRzL4udTaW2Fm9 zLNDuenZY>@R~Ve*iQg$=LK_Y&T<$cX$NoGT7EI=QsPP(GbA+9517kb*-61Bd?=7$} zuMm3K?lnS>KCylLjt~>aZM)vJ?i6<7z}S9V=rPYMFwYovWcTV-+_hWu-njIj7A|H zG&r~KUkv_=mRs)&`!a5SH}u@@XARDNUO>;i(N7tNVaD@tw(}*y<#p%F!j2rDuM&DJ zgX?>}!MVP(4bJtQZ}1@$hZ=*ACtgn+%aqT_*BJWkq`%XJ-)Hbn(m!T!_EWw$!LqwZ z&+kXL|1f`E*ui7J9IP|!6ddi0Bs;Ggoa1)b;Ox(P1`m^+GY04WaA}4XV43&9!u?jh zzrbUxA5VI&S4d~KrU*Ot3p>*dJ=?iS=pPXJ#X`SW@G7B~{cWYtqo3^0ZGzt_?A$5% z62b2ge5v5~6Gz+M75rhLm*tx8DY(8*82Tw-3)54=KF&2b{#yU<_|2-Ew=KBk_^O>+C$6J2yz~yrM&G!y$XM%X{A^n*uxE$Z65l8#D+=s!2 zWDAaHpQ3QjYj8d<<{A75=@%KC$CGm6Xd9mqa=TOuJ^J%BT|XSbF%Q>QzF+vhu(R3F zhu|2dCq%gq!#lO){!toNxLwwgp8vfs`go_%?-qK@!_Tc=A&&Zp z(7z`1c#QpjPjG1`)p(A|?KQ~Y++M>C&h{@eIJXx+-$q~LbGFfjp6z^HaP*V=)jZ;8 z=Mh*q{@)XNd|$wP(-7E!gf=kGR@{N~u;6%%$N9$vm-?p#NBwGgp7?^nx!f+n<@<|2 z5J%f9VPXBBgnJo7r;%2#{gkF|=wcxVc>kS@)axmRs@G6b1 z5`)(gUtn-PAD0uyGJgmQ*Q-hB(NBIpyVl^>QU88WaE!xtSTH3FenMmG3Xk4E+p@kB z1;=CT&-H>!eW44VFSxW*X>jgW4T4Mi4;s9c{NHSFJU1}?%;0M^wtj7J)<0+Pjii4` zaP(2&fJ0H35&kVjrc>~X2y?O)7MEe|v zOoKm7dY{36P5f$uvz;jhr|FzE%Y`pAINND);ddCE%jN6Qvw~w8RcHj#0fUD$wvHNn5%F`x z(Z-KqVLvY&ss+g9^(aJ~+l$Agn}q&eVW-5<^SrB0a4duUj2WE$TqEpn7WN+$yg_i- zR0;jeg{63i-p8^qF~5`MVKhxn@(si(Taqs#Kw(Srdq_WAn@{rlh>tM%gTzM~{9)og zga3%Q-{6lC&ocPq#77(a7sN3pm^co8Akm3XPa4-&^`Aegw^H;8lpV%|gkFIDPZ{Z-WNRR*6-e7V87 zzttMNh4hUE=kEYw2EUQ?Ee7ZL=vsq6Px^HRKR~?A;6tgtcN=^l&6hSB{0Q0EWbkvu zA29eZvh$F^hf}$a82nPwZ#MXsiElCZ6~vz~_*KN8H27>P_i2OYkbbMde?at-1MV!C0 zW8OydLNcSWJ<2<<&Y*2H_n6?ki5xXU&>$qK$8G-ijpVMfk9;KQM_?vMY{yUBr)V$d z_s3ZVA5Z#RgHJK+;4UGh98Y@Y6KUTzIKGp{6w@nZ1M@sg`<({Izl(!OwhN*JKBR}_ z$BIJYa`Ep&V3PkH7LW1Yf8&4O%6k5LZX8$U^Xa_cI5FqHw^oV(5_A5$YHJP7&sp%# z(Mmo4eY4?I4?N5sc*QxT0?IZX|? zgYrNQ{MCS@2nhUP2Ka~m8fh8rs2rd)c5~D}mbY>$8|vV%K*X#Z_-`yla%SE%Z;bjQ z0HlsAUs4VKq8*F1+{dWfSmi{&4SpvAf@*ir{dj5A`SU#3*mXEy<%QxfSI0_&n3WMH(U(U~9DQxst z{=QXO!RIEHkC$rB&-KUgtiSTtQTch=O!C*4+|nBjuhTEKv`D4V)_CH4Xx23UCui1a5_zbSU`ftXE zxR91pfmnZROU}>n$HQjXfUJkUhQIKhfUegU!*&HMW_}#*4Htn}*0Bj{WqpLsiDcFv UZyWo|pRq<~dQ#-YO*8-h2G|?Ab^rhX literal 0 HcmV?d00001 diff --git a/.suckless/dmenu/dmenu_path b/.suckless/dmenu/dmenu_path new file mode 100755 index 0000000..3a7cda7 --- /dev/null +++ b/.suckless/dmenu/dmenu_path @@ -0,0 +1,13 @@ +#!/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/.suckless/dmenu/dmenu_run b/.suckless/dmenu/dmenu_run new file mode 100755 index 0000000..834ede5 --- /dev/null +++ b/.suckless/dmenu/dmenu_run @@ -0,0 +1,2 @@ +#!/bin/sh +dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & diff --git a/.suckless/dmenu/drw.c b/.suckless/dmenu/drw.c new file mode 100644 index 0000000..8fd1ca4 --- /dev/null +++ b/.suckless/dmenu/drw.c @@ -0,0 +1,435 @@ +/* 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); + 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."); + } + + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + + 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/.suckless/dmenu/drw.h b/.suckless/dmenu/drw.h new file mode 100644 index 0000000..4c67419 --- /dev/null +++ b/.suckless/dmenu/drw.h @@ -0,0 +1,57 @@ +/* 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/.suckless/dmenu/drw.o b/.suckless/dmenu/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..db93e5e92a628b3c0d2ed4735a7dbec3d34f07f0 GIT binary patch literal 10472 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 G+y4(;tavd1 literal 0 HcmV?d00001 diff --git a/.suckless/dmenu/stest b/.suckless/dmenu/stest new file mode 100755 index 0000000000000000000000000000000000000000..60c69a1991d444747aeebf013d5a8cf003844789 GIT binary patch literal 17688 zcmeHPeQ;aVmA{hW*d(#!Bo26i5|Jvcy~RqLueA#*l4B=Ntem95PO~&YQS@P}$dZws z5+{?L8sso2Mp-YD?a(f?o|ZCn>FgNF0OgNh^2v6}5NOL}O1n)dA5t9}mqJL>khkaD zdyoC}EbVlrGyO}~qj&E4-E+>p@7%9<-@Dge@APdjn@o&?g?))3H?&wFZkce_B_lxG ztd-4&>u1=FY%cI~I408Ff8{b_)?ms#os-A zV14H=&PRFzb!YG0eq-B*Bh);FfbO~&3@y^}6m5ctofsYc0mMtmKU4l zGlm<>$hU%^-6#zFN%)nre{&f-lOVsWgq?pcW9R2(@c%A@|E>()RHi&*W#liH!M|As zf2$1M3HjEs2KGoh2kUWEau)U=P z8~!@x_jY&rL*Zn&H=0tz$?mT8u|z!F9oQWUGrzyLKN0t*)Id`8`-NypK{ObRhm(Q+ z09tLq93qLh8cf6^(cWojdqfqz4U&T*`|w~?Wyx?L6pALSV|2=<18@{j-w24pamou>`Su9Kr$LvBdj;9LLbLF2o47Pk!U;+ zi|!AzKrk3ip-C)&ys!QMSWCsFVk8+xtwG3BML8J>hXQH<_}!_LP-A|`o^AAb+t>S7 zIoC|bRyo&#v(5ZxmK1sVvrNYjF~J{RQ69$)GrJ!sjdS(UD0D>&yMxy+W9jRoFf*B1 zH}Du}9-w+1zyS=xxE${Zw@dsHH&14S6My!0f#aAZN+S4kI-JjY0%my~t{=arbU5XK zDwlNld}#y8m|HMto5n{(Cfs-xbL~HfD8Dwi1%uP9bO8tKIvmGi3XN_NLwTBW5LxNQ zD`SYuDVy`HZcaER9|1Vv*5UJn2)`;ie1Q(%qQh}4rLf&CVwk6uK%l$afp@{P9pj$8~uOD}ZbhvyZtzAT0kS z@;Idz&T#$>%K2xI$48UG5a<63d7Kst z1DyXZ^7x2S*v0v8A&*mjVGHLUMjog7f}8V)kjF=t!b;BHk33HK1v}^WBac&kp^o!O zTnWUH37fYgWuJZu~OGiVI8HrozPLFCXD)9@R%;dc?c+?-xGG-zh& z`AX(^jrMBcHMFfwc(cFiY`LgpEnOqGI6Rq)CeNWxHaubbk7J(UH*Ld@ft0uHSGI#k zAYwZ@mD~1kM{dt|GM7zzcY22Y)x^@au929drt9Db>3RA4pmx04$;r9et6r$++u}-Y z?a!Tz`LY+ff)|xsRWGpl`9gdp9UqBAZP^|!0H+i!!r#c!YV@j^0 zS{rJem$sZjA02SiDA}ud6BJV!S#r4sQr!F!1gdgn=6ET*S7tV@4m#H{^N@bXj_JkCJg614(G@ z@2a)Rh-(|*+LCdA@cyH>wn?s;n-z6d2cVnl}i_Zs5&oxpYj z-4D8iXn%Z6f9i8MrhBt*dV0Lsk3HR#W^wmn@gbo@~0McY0F!( zKl!pB`m%rM$iDB<>VE@cib-kvb^7->U+R1KOq<94qw5Z%e7?h$YMr1 zGAsQSxCO3*b2Q{~9F!`d;(>|>DjukKpyGjw2Pz);TRec@Ez+q#Z}^M$U+PFE(&*GL_!5cW@_waeE{h3u7!nF$A1W=gxU-mIhm%TCqF@g)-e>xpfOrT%4b{ zplP`1IWeVa=Ycx@q-imrpZQ4Beh9P!=mgLs7d7oRcru#v3CIJj2l^<`H9((59%L|> z_HSjT!8+3o3#w~IC5|6s$3N6GT#>PkYIvlDeBieReyxx{e_piKZLl`nVVl3VW{BN> z{jLAF+OZ7fPa;p1t$weBHvhqd7W%N^D;W=pHt+5lqh zR#@x%Ao)@Foq>Grl(PS3_F5YbTiUJm+?;l6<3m**>&ge_c34|8)&FcgXSXz&t*rog ztc@VjZfyYb+!mPO-|5c--SV-fg%Q|bt&{dT(OxIo>p*)7+S_P#$4eSRf2{%k41yhe z$wC2fAK(LklTR@X{ScD!dK}X#q2hsx2Pz(@c%b5eiU%qlsCb~_frWlKvLSQR4e(%<>oHh%SHRvZjkBxGbhBamptuXqm8kY{_#~U zfg&~VNect5MaE?WKloyB%XIvJi(!|%!TExP9h4&AzFd8fYG6R1xCFz%zf1$AwG4hp z#z1@4_?Kkh2_KXZD)$tZ7He3HQvUFzhu;rCTok@la9)x6@KuKMR6nrn<$Rq?hu8X? zpDwq|=kHBuU%4^gb+{0OutCyol13!mBk2Q@enZkHBz;cOQ3fo1lyt7#1b3}| zGaTgmh#PZeikS2njaiHHy?bG5*NpUxHNMQ|S{?T;_U zEi6wBN0(rM9f;I!bujGiteS4G#rRxC?YbDRW>o*hcnza=Q;c83s67_r^TZAaJqU3N zoXVj7t534911YezG!;?tKOQ0 zEuP;0T8!7TQti~jmN44?S}cF<^f*wAU<>dPKx6x_#ODR12d~ZwAHwJcs>Jn?Xbj z2Z2&Jy4}ob**-Y{eO@X;2{}F{asGY@FdSD+P#$}`5bP6#yB+a!ZUKx+9N%vtKIAFJ z8zugrw1Z!8F~ByDlI3gz9LqVb-((8dtr9Na^*kCQ|yoj7R1Y{rVcf?J$cO+p{&%2Ddbs$7vFC+g!8N3GkTYfEw&$!K9i} z)37xv$Yzf3_|<+t9G{7Y@sLX>;qQ$lb_ZhqkeW!Q{DJf!3nuypVqrBLa{klmw$-JD z@VrdaA4nzx`{0y|n%u`CaIz=t52gG2_koIz^J9^VME(8^TRmN!{?1Jucx1>A2j%>o ziUgI8t<1mCx4GTp^Kag;;m*!(f48UI*NK8fmO{kO!f6zb_CE z@snWF9>;oOfn@KVmGaP)(S+`d6yAjH=+=zn8akmh1Ia4m2d;`yIuBNiii2Opm^j~6 zjEO^K#h725=aQ$ziqrUcFy>6{>sJH2fvQPC`zQtn%)-e5=8PxQu(LOwcJ59`;Y?{X zBq2|`w^@bm%G3G+sXpcm?TdpwLDi&4*%MBtqKSAB$nQG9OI2b!M=TL%%nKCR1$+DTASqkaeA z@F^LmQ66ahMikGzVxZ?Enm+`}7(U1C^iTh~5Kf_)da&T3-@f$+g806i1qcpI+ZC z^@#FBor1wUJ7UzA>ttFl4^J0N7$JQ!iR&7D{TE`Q`=X!mh`Xg)tB3AgxZZo}(qjUd8dE$xw6m;R~ zeOjO1D~{uyYzQPLxEY@CvygyQMETRYivF*HT{?!Uk@Tn@e+#;Ji=3ZkGVz4nAE?7#&yB2 zi(~XM{7^)SBg6yg+a*tg%;_n$J(58>Aq_q#Zxs76p1P*{rtuT^3{lx3Ivo^zQ2}AZ YkVyH8R9qXB*8kaULc(HDFtF_Z0EGRqDF6Tf literal 0 HcmV?d00001 diff --git a/.suckless/dmenu/stest.1 b/.suckless/dmenu/stest.1 new file mode 100644 index 0000000..2667d8a --- /dev/null +++ b/.suckless/dmenu/stest.1 @@ -0,0 +1,90 @@ +.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/.suckless/dmenu/stest.c b/.suckless/dmenu/stest.c new file mode 100644 index 0000000..7a7b0bc --- /dev/null +++ b/.suckless/dmenu/stest.c @@ -0,0 +1,109 @@ +/* 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/.suckless/dmenu/stest.o b/.suckless/dmenu/stest.o new file mode 100644 index 0000000000000000000000000000000000000000..f3d919245e6349c6d04b5a070963273e6939475b GIT binary patch literal 5296 zcmbW5Z){sv6~M3Uv@uEXOV`q+6qwV!utZu++`*J~E#&1-`@A`{khBw8GS{`A6Kjs0 z+0RYJhMEz3lHLBbIyJD z#5b>gUpUpvz2|q&IrrRq&->$^7!B`tyIhRK#Xip(8d1hpI~x5#-W_BL^RYvEc^|5J z<#X5st9tok*tv;+UUgGXn+TQOJFJ)ft3Ug<0f-;h%PrkKFshddY7YQ#teC2oyA`Wu zYp}X<74Q-d&ho9=;$Agit_a=iD37TAZnnzUK6aF`{Pku7ei*pWY+w)uUZT+LWYJsO z61=6C-lZJgUYW1g>(WGvj48z!F!E@>HKKO4D20O!mR}1uS_|rxpR3?Xjq%X)bOaHj7bQI9I8KDgbO>aKM|l|M;CTcs4?l$2t%G1y2)t!=y5 zg0a_fG2dGGCRplA&!_`TIknvIGWo*1O5u2e<-5hIU%~P)`z~VB2&SB=D!;749C+jn zZ2o3t7sS}jmu2pxjcX0o`7U4O93zEGZ*!u<-e5h%^#`m1F*jKJ*~?frQ`+Puux>~` z7o9ft_`7rd$NHkjVsRreJ(HSyGMmdEpI?{)nD!@LCaO0#j}54iDCy`%HI^ zX^)00yz;ao+F@r0os_19N^i_Z0GsPyJ2mZWE_e7~wK z-EwKmqpVO>UVKd}{81@<53EAF-&Bfcprc$|tsHq_q;mZGOCP%Cr?kbdxmaEqE2mWN zSn-{F8{frH{Yq_P{q@k&W$)g!xMjnocgJG4^oo_LGP=qwgKt2_XI>jFZM~rJqc(fN zkPp@F(XGwl8m!Db2LXn!wp_r2goH!&7Ih^A1r0M*CROjszo7&mhgKc5j#^h3?)1)D zO0SHx))xob@}6JAYRk{4UcGeNifKJV^a^Kx77UeQ^~5zRiKq1PL%bI%UBMhCDLqi~ zJJuAwpJtc}@4?!&aOLP0z1)ru9R8#lE8V!r;JCu2_j$a1b%n9{pN30+B~tq#%tg7? zUJh18G^lyKd{V^%fO6f$pJ$D7#X@-u>Q$T49@iq5*n#2UJ^mgo8=LWmlj;0|e|O-4 zK!0Db*XqF5p=`Ap=KAWFnQNiLwPRDO_cZJ)1Y@5NWA|aJ`8s-_=@%@F_uY`Mx|J=qA-@sDq zBfcAcPp{iI07&!ofXR@r6TI1Nu+*G6Hz zzVR^3_D=DzwmYDe_nqs#pIdH#xAl4n3Vvuk=9-5=A=uvS@e?;&rHhxg>KM0Pw;2J6a_igs$ z!oFR!l;@*D-)iF-q4$aw<9}R=|0SFKgqZJ`jpu}(vhnwXJ$$`zp?v0r{v8`XA@p-L zz9jTth}OOj*KPJ?p}%G0-w^scHvTQrF+mV}{Ou0BM{rsfzS~jyZTxA$_egQ%Ivljw zpB47>e#3lrz(waCm*U`e1aW$^;4u2^6>%PhJ_>UAexbTTju*wb34IibL;Rl>UgP-O zM7eD>d`|g3+AikDTs{RC#n~x1#>e*$@%tqEdn8W#M|sly{BSc{oG+-JFCJV%) zW|Rev!8;|8&7gwj!2rCT){KBevu1vd1!9@mStAWz>5ORv4t()&AAk111!+Get3-1vWJagp2 z3=x-~+2$oK%7s*h-;Eg4?q3!DFWVgaYo1mIzc0~bmyMJE5gVs))Q$>&`~Gbc3DNf$ zg&{xE2cgq!|KPu(xX|+z_Ydc=@838ujM)#DEJ^Vo?2;k$X?|)aB_^9L3xAnmpZtj9 z_W&~cah(?a=gCmClt1AVbegRne{G`ZR>N@pSW@Iq_0w!_bQur_a$cOnM}gsYmE9kI ix!7w55W69M() +#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/.suckless/dmenu/util.h b/.suckless/dmenu/util.h new file mode 100644 index 0000000..f633b51 --- /dev/null +++ b/.suckless/dmenu/util.h @@ -0,0 +1,8 @@ +/* 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/.suckless/dmenu/util.o b/.suckless/dmenu/util.o new file mode 100644 index 0000000000000000000000000000000000000000..59a07457a785bae0ce4bed63b5ac76e960595509 GIT binary patch literal 2224 zcmbVM&rcIU6n>>u3Iav+fWbpeM$;y;X*C8UYFa3;kd1(r7(G}^yM)G;HruVKMk7Wv zX$T2_fCm#j8sfpD2~9kpC-q`H5>6x%e{k`l;CtJdbh2(Qyk`2n`QG>5%)Z&#hr`-P zlgkCdTyP2MGr>W7ug2R);-K?kul~~mt)Mo9%G&mXF9jgfrST{v~-SKGoU{Hu!p58KXz8t z-=7!mx9<*=j;#4HW@*EF7JO@6YZcTQwZvkltbg@MwbZ6ATYIsH8}CxdY&M@702mz_ z8t@0AMrzKlW#&s||9R!C66y^HYYrA7J6Z#9-Ma#=a;K}Ot=YSRt8^oOoX36=Mmsv6 zHjQ^|@K`^O9pkZU9bV2j18v*`zxJG>ZpV`baO2O(+*rxU+#tOilE4kk(yZ>f;r~6? zm_~ID)|0u{j@Tvb-|7`|hjDarjSSRRCthj5_ch?@$errM8t`Mt(>}%itaC$dyn!A{ zW+tnoK+%Rmkk05(G}F3aKw?yz7>sI(iII`3!|_BsI;agN;LdEp$jqCwFk2{@DJY;a zZ-8FTn4s5QNL1hbNz#YMha{;AzH)kei5KW_obHX$9 zY*I1xvI$B$X(mCLDHcI7@-!iNSP6rY%I9+WJWA&Crml=$p6)H0$<%GsQMNvpm^G3) zU2J3D=*LWYWc!VXAV=21`%#;E-*LUwP3F>LryDHY4GALcdBAj&4z7yA`4vA)0v2FMQy0mmsWIAP;OokG?9X!@V@~Jyl}I%4Ty%bvEAqwp(K7b6k%ISpeS!3i5H%<+@>|fi epB=?lI5|ZV$?R>R@3T|Bmw)=_q+D|C`TqcZ6$B~( literal 0 HcmV?d00001 diff --git a/.suckless/dwm b/.suckless/dwm new file mode 160000 index 0000000..1bc9d16 --- /dev/null +++ b/.suckless/dwm @@ -0,0 +1 @@ +Subproject commit 1bc9d164add89795ee46a2eb729aab7663d8fcc1 diff --git a/.suckless/sselp/.gitignore b/.suckless/sselp/.gitignore new file mode 100644 index 0000000..c190512 --- /dev/null +++ b/.suckless/sselp/.gitignore @@ -0,0 +1 @@ +*.backup diff --git a/.suckless/sselp/.hgtags b/.suckless/sselp/.hgtags new file mode 100644 index 0000000..07c9150 --- /dev/null +++ b/.suckless/sselp/.hgtags @@ -0,0 +1,2 @@ +effa85f232313bdd7855a83941d42e28ccaf8808 0.1 +5293716fdc7c4c31e2936ec52d684b403356e747 0.2 diff --git a/.suckless/sselp/LICENSE b/.suckless/sselp/LICENSE new file mode 100644 index 0000000..faf1c09 --- /dev/null +++ b/.suckless/sselp/LICENSE @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2006-2008 Anselm R Garbe + +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/.suckless/sselp/Makefile b/.suckless/sselp/Makefile new file mode 100644 index 0000000..bc23d57 --- /dev/null +++ b/.suckless/sselp/Makefile @@ -0,0 +1,48 @@ +# sselp - simple print selection + +include config.mk + +SRC = sselp.c +OBJ = ${SRC:.c=.o} + +all: options sselp + +options: + @echo sselp build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + @echo CC $< + @${CC} -c ${CFLAGS} $< + +${OBJ}: config.mk + +sselp: ${OBJ} + @echo CC -o $@ + @${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + @echo cleaning + @rm -f sselp ${OBJ} sselp-${VERSION}.tar.gz + +dist: clean + @echo creating dist tarball + @mkdir -p sselp-${VERSION} + @cp -R LICENSE Makefile README config.mk ${SRC} sselp-${VERSION} + @tar -cf sselp-${VERSION}.tar sselp-${VERSION} + @gzip sselp-${VERSION}.tar + @rm -rf sselp-${VERSION} + +install: all + @echo installing executable file to ${DESTDIR}${PREFIX}/bin + @mkdir -p ${DESTDIR}${PREFIX}/bin + @cp -f sselp ${DESTDIR}${PREFIX}/bin + @chmod 755 ${DESTDIR}${PREFIX}/bin/sselp + +uninstall: + @echo removing executable file from ${DESTDIR}${PREFIX}/bin + @rm -f ${DESTDIR}${PREFIX}/bin/sselp + +.PHONY: all options clean dist install uninstall diff --git a/.suckless/sselp/README b/.suckless/sselp/README new file mode 100644 index 0000000..f76ab9f --- /dev/null +++ b/.suckless/sselp/README @@ -0,0 +1,24 @@ +sselp - simple print selection +============================== +Prints X selection to standard out. + + +Requirements +------------ +In order to build sselp you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (sselp is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install sselp +(if necessary as root): + + make clean install + + +Running sselp +------------- +Simply invoke the 'sselp' command. diff --git a/.suckless/sselp/config.mk b/.suckless/sselp/config.mk new file mode 100644 index 0000000..0731c35 --- /dev/null +++ b/.suckless/sselp/config.mk @@ -0,0 +1,21 @@ +# sselp version +VERSION = 0.2 + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# includes and libs +INCS = -I. -I/usr/include -I${X11INC} +LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 + +# flags +CPPFLAGS = -DVERSION=\"${VERSION}\" +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -s ${LIBS} + +# compiler and linker +CC = cc diff --git a/.suckless/sselp/sselp b/.suckless/sselp/sselp new file mode 100755 index 0000000000000000000000000000000000000000..cfae47920ef085ea43bda977af2be3d1b6e0c94c GIT binary patch literal 14480 zcmeHOZ)_aJ6(67N#1L{mXj0rHkZt5tmx3>MPHZ_)mtDty_R!(Fu^mhyTrR$KeC2$1 zy;}zdpm86I(%tg%EAAbe%KfSdSaL2npZW3GtBKm^>|zdRHclS`KplnGHh7DZ%E4x!65NsyGw7$GbHxRU+r3-C8Bz;`adcPzj^y8wRxcm+0RDTf4I zDbAx{cqQJufIUtpSF-;R@Ct0s@*)sdvVU^{z6tm>&PG7~`vUg0z+cO1*rW;-C^W9t zK>R*-eTf%Z#u_+Z!w#v$2wW$5YNw=y>$e{-*G3kN=FC|CebN5G`=SG}M3QBO&Hlky zmgUTNde~$GAm`Y?{n>p@$~&&*>uLpnxJma8V2iwZgNJ+Wpg^U3$)!v(&#r6=@jehG)By} zT}H|T)2tCQjqb!yCTWPqSk#Ee%oqf?BbO8L0hNlgj!3v=bF@CNu~e%MG(cK$kqOK0p00OC*+}|1JD{F*dv+0e21$Yegd{G+)zoFpU!dlvz0+ z6Q7a%0hOyu*A2;MZWBDtDHItpvo_v7kLGQ>yp{0==4`x|Gh+9Njlb5$)AfhcC9#XV!l^ZP277;92R1$o@4sH&(TN4Y~rS8*?F zuNGCl?^1<;_Bc0E=~G1w`D=&-+^z}%c{s79GN_6w^3^4lv5bwUdlRZhZ2WadxW&zY zn*lciZU)>8{2ylEV)c#x)W^Eo5Ju7}(4zG>4_Jf)AFsG8wNTWmNBbaCxlu&-XN zLJj3X)D>onP}aVNGCoQaPI38Vl<`rgFwNx`QN~A#!eK5SM;RX_3WvD-8geYw1@=s94N2Nj+mmfzNA0-MZmmftLA0Y}sEkhQH^uh!Gstv`Hz4!F2JUa{5>72Vofn+FU{7yr0ty*|FDN}p)>6Fhn4Z$U5X z#J=g_8hyMW0hU0e-f{`6;P*jihoAIp2fWzS&<3LCb5hvzN-Bx$KJzwm#B&H0xiz`b6D%pt~dMKEpAeFMbMHJoZ_+xjOV0=^wE^h*UObQ&PZnJf`R&*mE%8C>Vv_?y82)!sAwrr3@KZbj#zewaW(7h zX>W>l_iPDwcCcu7cUz>3BsiwBmF2ev0r6%2l?%mU9PpQO#o|H0y&n{d5yXqdVg8xEXLW;AX(hz(N_I^=h;}4PSwQy11267H>TaR)UK{>*Hu~Ea^YGR7|5qm0Vm#?=<|&FYvSmPL+CE z3)UqArZr$Sq8qkcB7t;cOce}%fX31!{pDel)}&o8)NBsFEJKmNYGj4tJ|ol&KQLpV z{^83RKOUgCDST4oa$X(?e39ca!4lYR*3@= zcS+nY@rM$hlK3l$CncVi__oB4B~rf!R8i~Ly!jTz4=c3SDVqZIfe`!_0l!9sHUyc_ zXxaWjC4x)9h5jbe*VTW{g9UPfuwd4V?O=ffE?~{DKq_q-ft{)0z>eVrEGAFHC8f25 z>&)0r#&v_S+#n0Ycc*f@hXk5gp@9{xIb6%i&7=?oUDim(&_UKRNfWzFz}|#KuPguy zcoU#Y^ChkUV=y|9jSU&m!8rJmBs`+AY!+7Bau2FQ!?B@6KlGZ0wqO_F9f-zYxhxCx zr-z1cVeNlhaGc>aOXKHhSs|oxO&!toO){=E#UVug&i_Ne-*4=t!Y)AlYp~h<^RgjA z#bNLC-w67TVQf+VG~W=S9t+JsG|mOf;J;tQdQo zX+EU>oyU)tAfA&J*&xlYgft(cKmK2Z(|-?em=lbT7n&y|(tU^2&hx(;6n1|_`Vr2O zqeMsZY_G!~{wY8diEWMvoBX8}d(`1i_fNv5WGK-Y|D^P%{4+%wN(@Vp!0G=aDDe2n zKcWarLc0D1d-MtaWc+k}ksqDMm%tZI$e-5lpIHwi6u*Gd zp8N?_~kJjoANHHh9ra+Wd(AH%6GgL;wH) literal 0 HcmV?d00001 diff --git a/.suckless/sselp/sselp.c b/.suckless/sselp/sselp.c new file mode 100644 index 0000000..217c39a --- /dev/null +++ b/.suckless/sselp/sselp.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +int +main(int argc, char *argv[]) { + Atom clip, utf8, type; + Display *dpy; + Window win; + XEvent ev; + int fmt; + long off = 0; + unsigned char *data; + unsigned long len, more; + + if(argc > 1 && !strcmp(argv[1], "-v")) { + fputs("sselp-"VERSION", © 2006-2010 Anselm R Garbe\n", stdout); + return 0; + } + if(!(dpy = XOpenDisplay(NULL))) + return 1; + + utf8 = XInternAtom(dpy, "UTF8_STRING", False); + clip = XInternAtom(dpy, "_SSELP_STRING", False); + win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent); + XConvertSelection(dpy, XA_PRIMARY, utf8, clip, win, CurrentTime); + + XNextEvent(dpy, &ev); + if(ev.type == SelectionNotify && ev.xselection.property != None) { + do { + XGetWindowProperty(dpy, win, ev.xselection.property, off, BUFSIZ, + False, utf8, &type, &fmt, &len, &more, &data); + fwrite(data, 1, len, stdout); + XFree(data); + off += len/4; + } + while(more > 0); + putchar('\n'); + } + XCloseDisplay(dpy); + return 0; +} diff --git a/.suckless/sselp/sselp.o b/.suckless/sselp/sselp.o new file mode 100644 index 0000000000000000000000000000000000000000..8a5efbbe5c83611918732bef8a31940eea16e5ed GIT binary patch literal 3256 zcmbuBO>7%Q6o8-Yq$#D{gz^_?5eqWHsLf(KDijdlO=5eEOcK>jYXqs;IvZl@Kdm=u z0##9!q+(@KawuHk*xt$of`p1oQ?->4R6Qag<$xfSKm~~-Qh0B7#@TMX7kJUky!qbG z%&gze=7V@T;rID~iw|Cb%^9Zv2k+U`W0o2N0d_&(4Akpdsn!>kqWi_~E{M@^__@Al zI1(1+3L47dAu*}y$FviF*!SyQBMEdyBwkt~qXmNrdo2!e>>0YH_A!X_1mgV*^9wD+Je?up+d=>Mm zve@iiI6#J5EQ?}Zvy2XKM=`J1>_+64{58d=Fto6^hMK%WbH%))Twd!^0*mCRG-^Gg z?*jeV3(c>J@yLy|c{^n`74xS{EF@*F+V&+Q7{V0RWd39@^mzB;CzJ>Ex1oE%L_Hq) zBaLo7@?p#*uYd@E`O@aEwDi(YFf_W^?`3*MX`Bl#W3atSV;8Epxol8T=2yc?<7BYM z+6pt{lxai3Ugh$-KjphhTM%K|{B}nxjd>>?`Gq;!KgER7Z~rz%r_E2V(oZ&IuDv-f zza@{$N3TF~aPUPjB;+e0B!1y_N;w2YQwRLeE+MfY7@X7!bsdI%FYqrc)Ne^V^cb=YIbe!g(}a z#I}O1=}!@S4Pg#p0$~DSLb&dig`56yGO9v&NC?S-h&eI$fUupd)_$NZbiiL5?W}>e zZw^2J{O#P42RwL(2k-RY?e`o2$4kp1ZL&4LVA(si?C5^R_qkT?W&C*;r)dDXw$R6r z?1s(#TfZf;C$aTx@y7ecgTLy*6COP6!Qb%Ung^fr;0+J{sRzH{!7qC7FFp7r5B|Le zw{K~w08)A|OkIS!D0Tf%R*MzLC(|PXaymbfNMz#Kd{!Pv$MaA(^g_9Y!$fu3fXUjl zQHR_}O{)wQ>$Q?P2f0+m(DaIIRLhVX)HT)6GR1POq#Y?%CaNcpRVy=^Ze+BQRxpay z3gm{hStCB9RSd`_HN*BB)vGo1nuEy`deP7zm(Vp0aJj;is$-H;wXX3c^ZB}=7LMl& zQ^)g@YO#bzhCb?0=uM*<|7XLNC_xmec&anbW2lpm|9#jvPZC5SPWK?^R7WI~XE!#^ zj}k;7PVWlmb%H3A=U!}_zfTZ_{OQi)e1RYe`R~NW`NsrN-2T^WZ1D$C=l;Jr_(Kl< zw}U_I;IGq#hC=!2o#uJ6jJuyt$>INq!+*xXA9e6^4!+01KXY)p-}$;ndX*;R8IiF5b*-dIg(+34h9)J4$NH>NW4_u{eo|M, 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 (in programs such as w3m)? + +This is a terrible hack that overdraws an image on top of the terminal emulator +window. It also relies on a very specific way the terminal draws it's contents. + +A more proper (but limited way) would be using sixels. Which st doesn't +support. + +## 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/.suckless/st/LEGACY b/.suckless/st/LEGACY new file mode 100644 index 0000000..bf28b1e --- /dev/null +++ b/.suckless/st/LEGACY @@ -0,0 +1,17 @@ +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/.suckless/st/LICENSE b/.suckless/st/LICENSE new file mode 100644 index 0000000..c356c39 --- /dev/null +++ b/.suckless/st/LICENSE @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2018 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/.suckless/st/Makefile b/.suckless/st/Makefile new file mode 100644 index 0000000..470ac86 --- /dev/null +++ b/.suckless/st/Makefile @@ -0,0 +1,57 @@ +# 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. + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + +.PHONY: all options clean dist install uninstall diff --git a/.suckless/st/README b/.suckless/st/README new file mode 100644 index 0000000..6a846ed --- /dev/null +++ b/.suckless/st/README @@ -0,0 +1,34 @@ +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/.suckless/st/TODO b/.suckless/st/TODO new file mode 100644 index 0000000..5f74cd5 --- /dev/null +++ b/.suckless/st/TODO @@ -0,0 +1,28 @@ +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/.suckless/st/arg.h b/.suckless/st/arg.h new file mode 100644 index 0000000..a22e019 --- /dev/null +++ b/.suckless/st/arg.h @@ -0,0 +1,50 @@ +/* + * 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/.suckless/st/config.def.h b/.suckless/st/config.def.h new file mode 100644 index 0000000..013b9a6 --- /dev/null +++ b/.suckless/st/config.def.h @@ -0,0 +1,459 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static int borderpx = 2; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: utmp option + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* frames per second st should at maximum draw to the screen */ +static unsigned int xfps = 120; +static unsigned int actionfps = 30; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "#3b4252", /* black */ + "#bf616a", /* red */ + "#a3be8c", /* green */ + "#ebcb8b", /* yellow */ + "#81a1c1", /* blue */ + "#b48ead", /* magenta */ + "#88c0d0", /* cyan */ + "#e5e9f0", /* white */ + + /* 8 bright colors */ + "#4c566a", /* black */ + "#bf616a", /* red */ + "#a3be8c", /* green */ + "#ebcb8b", /* yellow */ + "#81a1c1", /* blue */ + "#b48ead", /* magenta */ + "#8fbcbb", /* cyan */ + "#eceff4", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#2e3440", /* background */ + "#d8dee9", /* foreground */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 257; +unsigned int defaultbg = 256; +static unsigned int defaultcs = 257; +static unsigned int defaultrcs = 256; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/.suckless/st/config.h b/.suckless/st/config.h new file mode 100644 index 0000000..053be8b --- /dev/null +++ b/.suckless/st/config.h @@ -0,0 +1,460 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Iosevka:pixelsize=20:antialias=true:autohint:true"; +static int borderpx = 8; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: utmp option + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* frames per second st should at maximum draw to the screen */ +static unsigned int xfps = 120; +static unsigned int actionfps = 30; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "#000000", /* black */ + "#bf616a", /* red */ + "#a3be8c", /* green */ + "#ebcb8b", /* yellow */ + "#81a1c1", /* blue */ + "#b48ead", /* magenta */ + "#88c0d0", /* cyan */ + "#ffffff", /* white */ + + /* 8 bright colors */ + "#111111", /* black */ + "#bf616a", /* red */ + "#a3be8c", /* green */ + "#ebcb8b", /* yellow */ + "#81a1c1", /* blue */ + "#b48ead", /* magenta */ + "#8fbcbb", /* cyan */ + "#eeeeee", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#000000", /* background */ + "#d8dee9", /* foreground */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 257; +unsigned int defaultbg = 256; +static unsigned int defaultcs = 257; +static unsigned int defaultrcs = 256; + + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/.suckless/st/config.mk b/.suckless/st/config.mk new file mode 100644 index 0000000..0cbb002 --- /dev/null +++ b/.suckless/st/config.mk @@ -0,0 +1,35 @@ +# st version +VERSION = 0.8.2 + +# 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 \ + `$(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/.suckless/st/patches/st-anysize-0.8.1.diff b/.suckless/st/patches/st-anysize-0.8.1.diff new file mode 100644 index 0000000..1eaf2ba --- /dev/null +++ b/.suckless/st/patches/st-anysize-0.8.1.diff @@ -0,0 +1,152 @@ +diff --git a/x.c b/x.c +index 00cb6b1..8f87c0f 100644 +--- a/x.c ++++ b/x.c +@@ -78,6 +78,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; + typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ ++ int hborderpx, vborderpx; + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ +@@ -311,7 +312,7 @@ zoomreset(const Arg *arg) + int + evcol(XEvent *e) + { +- int x = e->xbutton.x - borderpx; ++ int x = e->xbutton.x - win.hborderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; + } +@@ -319,7 +320,7 @@ evcol(XEvent *e) + int + evrow(XEvent *e) + { +- int y = e->xbutton.y - borderpx; ++ int y = e->xbutton.y - win.vborderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; + } +@@ -675,6 +676,9 @@ cresize(int width, int height) + col = MAX(1, col); + row = MAX(1, row); + ++ win.hborderpx = (win.w - col * win.cw) / 2; ++ win.vborderpx = (win.h - row * win.ch) / 2; ++ + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +@@ -793,8 +797,8 @@ xhints(void) + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; +- sizeh->height_inc = win.ch; +- sizeh->width_inc = win.cw; ++ sizeh->height_inc = 1; ++ sizeh->width_inc = 1; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; +@@ -1022,8 +1026,8 @@ xinit(int cols, int rows) + xloadcols(); + + /* adjust fixed window geometry */ +- win.w = 2 * borderpx + cols * win.cw; +- win.h = 2 * borderpx + rows * win.ch; ++ win.w = 2 * win.hborderpx + cols * win.cw; ++ win.h = 2 * win.vborderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) +@@ -1123,7 +1127,7 @@ xinit(int cols, int rows) + int + xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) + { +- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; ++ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; +@@ -1259,7 +1263,7 @@ void + xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) + { + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); +- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, ++ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; +@@ -1349,17 +1353,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i + + /* Intelligent cleaning up of the borders. */ + if (x == 0) { +- xclear(0, (y == 0)? 0 : winy, borderpx, ++ xclear(0, (y == 0)? 0 : winy, win.vborderpx, + winy + win.ch + +- ((winy + win.ch >= borderpx + win.th)? win.h : 0)); ++ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + } +- if (winx + width >= borderpx + win.tw) { ++ if (winx + width >= win.hborderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, +- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); ++ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) +- xclear(winx, 0, winx + width, borderpx); +- if (winy + win.ch >= borderpx + win.th) ++ xclear(winx, 0, winx + width, win.hborderpx); ++ if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ +@@ -1452,35 +1456,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - \ ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + (cx + 1) * win.cw - 1, +- borderpx + cy * win.ch, ++ win.hborderpx + (cx + 1) * win.cw - 1, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - 1, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } + } diff --git a/.suckless/st/patches/st-nordtheme-0.8.2.diff b/.suckless/st/patches/st-nordtheme-0.8.2.diff new file mode 100644 index 0000000..01e9231 --- /dev/null +++ b/.suckless/st/patches/st-nordtheme-0.8.2.diff @@ -0,0 +1,100 @@ +From 3e8f83d40c6fdd89653ef547aa16cffe1f3c1793 Mon Sep 17 00:00:00 2001 +From: aleks +Date: Sun, 4 Aug 2019 13:23:10 +0200 +Subject: [PATCH] Apply nord-theme + +*"Inspired by the beauty of the arctic, the colors reflect the cold, yet +harmonious world of ice and the colorfulness of the Aurora Borealis."* - [Nord +Theme](https://www.nordtheme.com/) + +There are also many [ports](https://www.nordtheme.com/ports) for other programs +like [vim](https://www.nordtheme.com/ports/vim) and +[tmux](https://www.nordtheme.com/ports/tmux) to make the overall appearance +coherent. I would recommend to use it in combination with the arc-theme for gtk +(fits perfectly). + +The default behaviour of st is to reverse the fore- and background colors of +each selected cell. If you want that the selection-colors are not reveresed but +instead have fixed fore- and background colors apply on top of this patch the +[selectioncolors](../selectioncolors/)-patch. Then set the following settings +in your config.h: + +static unsigned int defaultcs = 257; +static unsigned int defaultrcs = 257; +unsigned int selectionfg = 257; +unsigned int selectionbg = 0; +--- + config.def.h | 44 ++++++++++++++++++++++---------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 0e01717..fb504d4 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -85,30 +85,30 @@ unsigned int tabspaces = 8; + /* Terminal colors (16 first used in escape sequence) */ + static const char *colorname[] = { + /* 8 normal colors */ +- "black", +- "red3", +- "green3", +- "yellow3", +- "blue2", +- "magenta3", +- "cyan3", +- "gray90", ++ "#3b4252", /* black */ ++ "#bf616a", /* red */ ++ "#a3be8c", /* green */ ++ "#ebcb8b", /* yellow */ ++ "#81a1c1", /* blue */ ++ "#b48ead", /* magenta */ ++ "#88c0d0", /* cyan */ ++ "#e5e9f0", /* white */ + + /* 8 bright colors */ +- "gray50", +- "red", +- "green", +- "yellow", +- "#5c5cff", +- "magenta", +- "cyan", +- "white", ++ "#4c566a", /* black */ ++ "#bf616a", /* red */ ++ "#a3be8c", /* green */ ++ "#ebcb8b", /* yellow */ ++ "#81a1c1", /* blue */ ++ "#b48ead", /* magenta */ ++ "#8fbcbb", /* cyan */ ++ "#eceff4", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ +- "#cccccc", +- "#555555", ++ "#2e3440", /* background */ ++ "#d8dee9", /* foreground */ + }; + + +@@ -116,10 +116,10 @@ static const char *colorname[] = { + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +-unsigned int defaultfg = 7; +-unsigned int defaultbg = 0; +-static unsigned int defaultcs = 256; +-static unsigned int defaultrcs = 257; ++unsigned int defaultfg = 257; ++unsigned int defaultbg = 256; ++static unsigned int defaultcs = 257; ++static unsigned int defaultrcs = 256; + + /* + * Default shape of cursor +-- +2.22.0 + diff --git a/.suckless/st/st b/.suckless/st/st new file mode 100755 index 0000000000000000000000000000000000000000..b05e62681b7d62e6635392257b59a227be37697b GIT binary patch literal 102208 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 literal 0 HcmV?d00001 diff --git a/.suckless/st/st.1 b/.suckless/st/st.1 new file mode 100644 index 0000000..e8d6059 --- /dev/null +++ b/.suckless/st/st.1 @@ -0,0 +1,176 @@ +.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) +.SH BUGS +See the TODO file in the distribution. + diff --git a/.suckless/st/st.c b/.suckless/st/st.c new file mode 100644 index 0000000..3e48410 --- /dev/null +++ b/.suckless/st/st.c @@ -0,0 +1,2599 @@ +/* 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) == '\177') +#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, + MODE_SIXEL = 1 << 7, +}; + +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, /* 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, + ESC_DCS =128, +}; + +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; +} 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)) + *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; + 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]; + else if (utmp) + prog = utmp; + else + prog = sh; + DEFAULT(args, ((char *[]) {prog, 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 written; + int ret; + + /* append read bytes to unprocessed bytes */ + if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) + die("couldn't read from shell: %s\n", strerror(errno)); + buflen += ret; + + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any uncomplete utf8 char 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.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) { + if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) { + selclear(); + return; + } + if (sel.type == SEL_RECTANGULAR) { + if (sel.ob.y < term.top) + sel.ob.y = term.top; + if (sel.oe.y > term.bot) + sel.oe.y = term.bot; + } else { + if (sel.ob.y < term.top) { + sel.ob.y = term.top; + sel.ob.x = 0; + } + if (sel.oe.y > term.bot) { + sel.oe.y = term.bot; + sel.oe.x = term.col; + } + } + 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 '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) { + 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 */ + term.mode |= ESC_DCS; + 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) +{ + strreset(); + + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + term.esc |= ESC_DCS; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + 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); + 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 (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) { + memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ + 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|ESC_DCS); + if (IS_SET(MODE_SIXEL)) { + /* TODO: render sixel */; + term.mode &= ~MODE_SIXEL; + return; + } + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (IS_SET(MODE_SIXEL)) { + /* TODO: implement sixel mode */ + return; + } + if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') + term.mode |= MODE_SIXEL; + + 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 + */ + 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 (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.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); + + 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) && !IS_SET(MODE_SIXEL)) { + /* 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; + + 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(); + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/.suckless/st/st.h b/.suckless/st/st.h new file mode 100644 index 0000000..a1928ca --- /dev/null +++ b/.suckless/st/st.h @@ -0,0 +1,123 @@ +/* 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 *stty_args; +extern char *vtiden; +extern wchar_t *worddelimiters; +extern int allowaltscreen; +extern char *termname; +extern unsigned int tabspaces; +extern unsigned int defaultfg; +extern unsigned int defaultbg; diff --git a/.suckless/st/st.info b/.suckless/st/st.info new file mode 100644 index 0000000..78ffd30 --- /dev/null +++ b/.suckless/st/st.info @@ -0,0 +1,222 @@ +st| simpleterm, + 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#8, + 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, + 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, + 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, + sgr0=\E[0m, + 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, + sitm=\E[3m, + 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, +# 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-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, diff --git a/.suckless/st/st.o b/.suckless/st/st.o new file mode 100644 index 0000000000000000000000000000000000000000..90f6a064ac8ec9a2646bf031abf48e33cbf054be GIT binary patch literal 73184 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≈y6pWvCxBs4Mh!P*FH3D|uMH+$OQ#-)k4 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 literal 0 HcmV?d00001 diff --git a/.suckless/st/win.h b/.suckless/st/win.h new file mode 100644 index 0000000..a6ef1b9 --- /dev/null +++ b/.suckless/st/win.h @@ -0,0 +1,39 @@ +/* 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/.suckless/st/x.c b/.suckless/st/x.c new file mode 100644 index 0000000..78a4044 --- /dev/null +++ b/.suckless/st/x.c @@ -0,0 +1,2045 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *argv0; +#include "arg.h" +#include "st.h" +#include "win.h" + +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +typedef struct { + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ +} Key; + +/* X modifiers */ +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 +#define XK_SWITCH_MOD (1<<13) + +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void numlock(const Arg *); +static void selpaste(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); +static void ttysend(const Arg *); + +/* config.h for applying patches and the configuration. */ +#include "config.h" + +/* XEMBED messages */ +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 + +/* macros */ +#define IS_SET(flag) ((win.mode & (flag)) != 0) +#define TRUERED(x) (((x) & 0xff0000) >> 8) +#define TRUEGREEN(x) (((x) & 0xff00)) +#define TRUEBLUE(x) (((x) & 0xff) << 8) + +typedef XftDraw *Draw; +typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; + +/* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int hborderpx, vborderpx; + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ +} TermWindow; + +typedef struct { + Display *dpy; + Colormap cmap; + Window win; + Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + Atom xembed, wmdeletewin, netwmname, netwmpid; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; + Draw draw; + Visual *vis; + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ +} XWindow; + +typedef struct { + Atom xtarget; + char *primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; +} XSelection; + +/* Font structure */ +#define Font Font_ +typedef struct { + int height; + int width; + int ascent; + int descent; + int badslant; + int badweight; + short lbearing; + short rbearing; + XftFont *match; + FcFontSet *set; + FcPattern *pattern; +} Font; + +/* Drawing Context */ +typedef struct { + Color *col; + size_t collen; + Font font, bfont, ifont, ibfont; + GC gc; +} DC; + +static inline ushort sixd_to_16bit(int); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyph(Glyph, int, int); +static void xclear(int, int, int, int); +static int xgeommasktogravity(int); +static int ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); +static void xinit(int, int); +static void cresize(int, int); +static void xresize(int, int); +static void xhints(void); +static int xloadcolor(int, const char *, Color *); +static int xloadfont(Font *, FcPattern *); +static void xloadfonts(char *, double); +static void xunloadfont(Font *); +static void xunloadfonts(void); +static void xsetenv(void); +static void xseturgency(int); +static int evcol(XEvent *); +static int evrow(XEvent *); + +static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); +static void kpress(XEvent *); +static void cmessage(XEvent *); +static void resize(XEvent *); +static void focus(XEvent *); +static int mouseaction(XEvent *, uint); +static void brelease(XEvent *); +static void bpress(XEvent *); +static void bmotion(XEvent *); +static void propnotify(XEvent *); +static void selnotify(XEvent *); +static void selclear_(XEvent *); +static void selrequest(XEvent *); +static void setsel(char *, Time); +static void mousesel(XEvent *, int); +static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); + +static void run(void); +static void usage(void); + +static void (*handler[LASTEvent])(XEvent *) = { + [KeyPress] = kpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = resize, + [VisibilityNotify] = visibility, + [UnmapNotify] = unmap, + [Expose] = expose, + [FocusIn] = focus, + [FocusOut] = focus, + [MotionNotify] = bmotion, + [ButtonPress] = bpress, + [ButtonRelease] = brelease, +/* + * Uncomment if you want the selection to disappear when you select something + * different in another window. + */ +/* [SelectionClear] = selclear_, */ + [SelectionNotify] = selnotify, +/* + * PropertyNotify is only turned on when there is some INCR transfer happening + * for the selection retrieval. + */ + [PropertyNotify] = propnotify, + [SelectionRequest] = selrequest, +}; + +/* Globals */ +static DC dc; +static XWindow xw; +static XSelection xsel; +static TermWindow win; + +/* Font Ring Cache */ +enum { + FRC_NORMAL, + FRC_ITALIC, + FRC_BOLD, + FRC_ITALICBOLD +}; + +typedef struct { + XftFont *font; + int flags; + Rune unicodep; +} Fontcache; + +/* Fontcache is an array now. A new font will be appended to the array. */ +static Fontcache *frc = NULL; +static int frclen = 0; +static int frccap = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; + +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + +static int oldbutton = 3; /* button event on startup: 3 = release */ + +void +clipcopy(const Arg *dummy) +{ + Atom clipboard; + + free(xsel.clipboard); + xsel.clipboard = NULL; + + if (xsel.primary != NULL) { + xsel.clipboard = xstrdup(xsel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } +} + +void +clippaste(const Arg *dummy) +{ + Atom clipboard; + + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, + xw.win, CurrentTime); +} + +void +selpaste(const Arg *dummy) +{ + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, + xw.win, CurrentTime); +} + +void +numlock(const Arg *dummy) +{ + win.mode ^= MODE_NUMLOCK; +} + +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + +int +evcol(XEvent *e) +{ + int x = e->xbutton.x - win.hborderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; +} + +int +evrow(XEvent *e) +{ + int y = e->xbutton.y - win.vborderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; +} + +void +mousesel(XEvent *e, int done) +{ + int type, seltype = SEL_REGULAR; + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + + for (type = 1; type < LEN(selmasks); ++type) { + if (match(selmasks[type], state)) { + seltype = type; + break; + } + } + selextend(evcol(e), evrow(e), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); +} + +void +mousereport(XEvent *e) +{ + int len, x = evcol(e), y = evrow(e), + button = e->xbutton.button, state = e->xbutton.state; + char buf[40]; + static int ox, oy; + + /* from urxvt */ + if (e->xbutton.type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MOUSE_MOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + return; + + button = oldbutton + 32; + ox = x; + oy = y; + } else { + if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { + button = 3; + } else { + button -= Button1; + if (button >= 3) + button += 64 - 3; + } + if (e->xbutton.type == ButtonPress) { + oldbutton = button; + ox = x; + oy = y; + } else if (e->xbutton.type == ButtonRelease) { + oldbutton = 3; + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + if (button == 64 || button == 65) + return; + } + } + + if (!IS_SET(MODE_MOUSEX10)) { + button += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + button, x+1, y+1, + e->xbutton.type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+button, 32+x+1, 32+y+1); + } else { + return; + } + + ttywrite(buf, len, 0); +} + +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (match(ms->mod, e->xbutton.state) || /* exact or forced */ + match(ms->mod, e->xbutton.state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + +void +bpress(XEvent *e) +{ + struct timespec now; + int snap; + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 0)) + return; + + if (e->xbutton.button == Button1) { + /* + * If the user clicks below predefined timeouts specific + * snapping behaviour is exposed. + */ + clock_gettime(CLOCK_MONOTONIC, &now); + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { + snap = SNAP_LINE; + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { + snap = SNAP_WORD; + } else { + snap = 0; + } + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; + + selstart(evcol(e), evrow(e), snap); + } +} + +void +propnotify(XEvent *e) +{ + XPropertyEvent *xpev; + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + + xpev = &e->xproperty; + if (xpev->state == PropertyNewValue && + (xpev->atom == XA_PRIMARY || + xpev->atom == clipboard)) { + selnotify(e); + } +} + +void +selnotify(XEvent *e) +{ + ulong nitems, ofs, rem; + int format; + uchar *data, *last, *repl; + Atom type, incratom, property = None; + + incratom = XInternAtom(xw.dpy, "INCR", 0); + + ofs = 0; + if (e->type == SelectionNotify) + property = e->xselection.property; + else if (e->type == PropertyNotify) + property = e->xproperty.atom; + + if (property == None) + return; + + do { + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, + BUFSIZ/4, False, AnyPropertyType, + &type, &format, &nitems, &rem, + &data)) { + fprintf(stderr, "Clipboard allocation failed\n"); + return; + } + + if (e->type == PropertyNotify && nitems == 0 && rem == 0) { + /* + * If there is some PropertyNotify with no data, then + * this is the signal of the selection owner that all + * data has been transferred. We won't need to receive + * PropertyNotify events anymore. + */ + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + } + + if (type == incratom) { + /* + * Activate the PropertyNotify events so we receive + * when the selection owner does send us the next + * chunk of data. + */ + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + + /* + * Deleting the property is the transfer start signal. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); + continue; + } + + /* + * As seen in getsel: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while ((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) + ttywrite("\033[201~", 6, 0); + XFree(data); + /* number of 32-bit chunks returned */ + ofs += nitems * format / 32; + } while (rem > 0); + + /* + * Deleting the property again tells the selection owner to send the + * next data chunk in the property. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); +} + +void +xclipcopy(void) +{ + clipcopy(NULL); +} + +void +selclear_(XEvent *e) +{ + selclear(); +} + +void +selrequest(XEvent *e) +{ + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + Atom xa_targets, string, clipboard; + char *seltext; + + xsre = (XSelectionRequestEvent *) e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + if (xsre->property == None) + xsre->property = xsre->target; + + /* reject */ + xev.property = None; + + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); + if (xsre->target == xa_targets) { + /* respond with the supported type */ + string = xsel.xtarget; + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + XA_ATOM, 32, PropModeReplace, + (uchar *) &string, 1); + xev.property = xsre->property; + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if (xsre->selection == XA_PRIMARY) { + seltext = xsel.primary; + } else if (xsre->selection == clipboard) { + seltext = xsel.clipboard; + } else { + fprintf(stderr, + "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if (seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, + xsre->property, xsre->target, + 8, PropModeReplace, + (uchar *)seltext, strlen(seltext)); + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) + fprintf(stderr, "Error sending SelectionNotify event\n"); +} + +void +setsel(char *str, Time t) +{ + if (!str) + return; + + free(xsel.primary); + xsel.primary = str; + + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + selclear(); +} + +void +xsetsel(char *str) +{ + setsel(str, CurrentTime); +} + +void +brelease(XEvent *e) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 1)) + return; + if (e->xbutton.button == Button1) + mousesel(e, 1); +} + +void +bmotion(XEvent *e) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + mousesel(e, 0); +} + +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + col = MAX(1, col); + row = MAX(1, row); + + win.hborderpx = (win.w - col * win.cw) / 2; + win.vborderpx = (win.h - row * win.ch) / 2; + + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +} + +void +xresize(int col, int row) +{ + win.tw = col * win.cw; + win.th = row * win.ch; + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); +} + +ushort +sixd_to_16bit(int x) +{ + return x == 0 ? 0 : 0x3737 + 0x2828 * x; +} + +int +xloadcolor(int i, const char *name, Color *ncolor) +{ + XRenderColor color = { .alpha = 0xffff }; + + if (!name) { + if (BETWEEN(i, 16, 255)) { /* 256 color */ + if (i < 6*6*6+16) { /* same colors as xterm */ + color.red = sixd_to_16bit( ((i-16)/36)%6 ); + color.green = sixd_to_16bit( ((i-16)/6) %6 ); + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); + } else { /* greyscale */ + color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); + color.green = color.blue = color.red; + } + return XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, ncolor); + } else + name = colorname[i]; + } + + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); +} + +void +xloadcols(void) +{ + int i; + static int loaded; + Color *cp; + + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); + } + + for (i = 0; i < dc.collen; i++) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } + loaded = 1; +} + +int +xsetcolorname(int x, const char *name) +{ + Color ncolor; + + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + if (!xloadcolor(x, name, &ncolor)) + return 1; + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + + return 0; +} + +/* + * Absolute coordinates. + */ +void +xclear(int x1, int y1, int x2, int y2) +{ + XftDrawRect(xw.draw, + &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], + x1, y1, x2-x1, y2-y1); +} + +void +xhints(void) +{ + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints *sizeh; + + sizeh = XAllocSizeHints(); + + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; + sizeh->height_inc = 1; + sizeh->width_inc = 1; + 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, + XNFocusWindow, xw.win, + XNDestroyCallback, &icdestroy, + NULL); + } + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); + + return 1; +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.ime.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + XFree(xw.ime.spotlist); +} + +int +xicdestroy(XIC xim, XPointer client, XPointer call) +{ + xw.ime.xic = NULL; + return 1; +} + +void +xinit(int cols, int rows) +{ + XGCValues gcvalues; + Cursor cursor; + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); + xw.vis = XDefaultVisual(xw.dpy, xw.scr); + + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); + + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + + /* colors */ + xw.cmap = XDefaultColormap(xw.dpy, xw.scr); + xloadcols(); + + /* adjust fixed window geometry */ + win.w = 2 * win.hborderpx + cols * win.cw; + win.h = 2 * win.vborderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; + + /* Events */ + xw.attrs.background_pixel = dc.col[defaultbg].pixel; + xw.attrs.border_pixel = dc.col[defaultbg].pixel; + xw.attrs.bit_gravity = NorthWestGravity; + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; + + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, + win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, + &gcvalues); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + + /* font spec buffer */ + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + + /* Xft rendering context */ + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + + /* input methods */ + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } + + /* white cursor, black outline */ + cursor = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, cursor); + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { + xmousefg.red = 0xffff; + xmousefg.green = 0xffff; + xmousefg.blue = 0xffff; + } + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { + xmousebg.red = 0x0000; + xmousebg.green = 0x0000; + xmousebg.blue = 0x0000; + } + + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); + + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&thispid, 1); + + win.mode = MODE_NUMLOCK; + resettitle(); + xhints(); + XMapWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); + + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); + if (xsel.xtarget == None) + xsel.xtarget = XA_STRING; +} + +int +xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +{ + float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; + 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 = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; + 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, win.vborderpx, + winy + win.ch + + ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + } + if (winx + width >= win.hborderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, win.hborderpx); + if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + + /* Set the clip region because Xft is sometimes dirty. */ + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, + width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, + width, 1); + } + + /* Reset clip to none. */ + XftDrawSetClip(xw.draw, 0); +} + +void +xdrawglyph(Glyph g, int x, int y) +{ + int numspecs; + XftGlyphFontSpec spec; + + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y); +} + +void +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +{ + Color drawcol; + + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + xdrawglyph(og, ox, oy); + + if (IS_SET(MODE_HIDE)) + return; + + /* + * Select the right color for the right mode. + */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; + + if (IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.bg = defaultfg; + if (selected(cx, cy)) { + drawcol = dc.col[defaultcs]; + g.fg = defaultrcs; + } else { + drawcol = dc.col[defaultrcs]; + g.fg = defaultcs; + } + } else { + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; + } else { + g.fg = defaultbg; + g.bg = defaultcs; + } + drawcol = dc.col[g.bg]; + } + + /* draw the new one */ + if (IS_SET(MODE_FOCUSED)) { + switch (win.cursor) { + case 7: /* st extension: snowman (U+2603) */ + g.u = 0x2603; + case 0: /* Blinking Block */ + case 1: /* Blinking Block (Default) */ + case 2: /* Steady Block */ + xdrawglyph(g, cx, cy); + break; + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + cx * win.cw, + win.vborderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + (cx + 1) * win.cw - 1, + win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + win.hborderpx + cx * win.cw, + win.vborderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } +} + +void +xsetenv(void) +{ + char buf[sizeof(long) * 8 + 1]; + + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); +} + +void +xsettitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop); + XSetWMName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); + XFree(prop.value); +} + +int +xstartdraw(void) +{ + return IS_SET(MODE_VISIBLE); +} + +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, x, ox, numspecs; + Glyph base, new; + XftGlyphFontSpec *specs = xw.specbuf; + + numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1); +} + +void +xfinishdraw(void) +{ + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, + win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); +} + +void +xximspot(int x, int y) +{ + if (xw.ime.xic == NULL) + return; + + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; + + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); +} + +void +expose(XEvent *ev) +{ + redraw(); +} + +void +visibility(XEvent *ev) +{ + XVisibilityEvent *e = &ev->xvisibility; + + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); +} + +void +unmap(XEvent *ev) +{ + win.mode &= ~MODE_VISIBLE; +} + +void +xsetpointermotion(int set) +{ + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); +} + +void +xsetmode(int set, unsigned int flags) +{ + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); +} + +int +xsetcursor(int cursor) +{ + DEFAULT(cursor, 1); + if (!BETWEEN(cursor, 0, 6)) + return 1; + win.cursor = cursor; + return 0; +} + +void +xseturgency(int add) +{ + XWMHints *h = XGetWMHints(xw.dpy, xw.win); + + MODBIT(h->flags, add, XUrgencyHint); + XSetWMHints(xw.dpy, xw.win, h); + XFree(h); +} + +void +xbell(void) +{ + if (!(IS_SET(MODE_FOCUSED))) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); +} + +void +focus(XEvent *ev) +{ + XFocusChangeEvent *e = &ev->xfocus; + + if (e->mode == NotifyGrab) + return; + + if (ev->type == FocusIn) { + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); + } +} + +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + return kp->s; + } + + return NULL; +} + +void +kpress(XEvent *ev) +{ + XKeyEvent *e = &ev->xkey; + KeySym ksym; + char buf[64], *customkey; + int len; + Rune c; + Status status; + Shortcut *bp; + + if (IS_SET(MODE_KBDLOCK)) + return; + + if (xw.ime.xic) + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + else + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + /* 1. shortcuts */ + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state)) { + bp->func(&(bp->arg)); + return; + } + } + + /* 2. custom keys from config.h */ + if ((customkey = kmap(ksym, e->state))) { + ttywrite(customkey, strlen(customkey), 1); + return; + } + + /* 3. composed string from input method */ + if (len == 0) + return; + if (len == 1 && e->state & Mod1Mask) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, len, 1); +} + +void +cmessage(XEvent *e) +{ + /* + * See xembed specs + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html + */ + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { + win.mode |= MODE_FOCUSED; + xseturgency(0); + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { + win.mode &= ~MODE_FOCUSED; + } + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { + ttyhangup(); + exit(0); + } +} + +void +resize(XEvent *e) +{ + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) + return; + + cresize(e->xconfigure.width, e->xconfigure.height); +} + +void +run(void) +{ + XEvent ev; + int w = win.w, h = win.h; + fd_set rfd; + int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0; + int ttyfd; + struct timespec drawtimeout, *tv = NULL, now, last, lastblink; + long deltatime; + + /* Waiting for window mapping */ + do { + XNextEvent(xw.dpy, &ev); + /* + * This XFilterEvent call is required because of XOpenIM. It + * does filter out the key event and some client message for + * the input method too. + */ + if (XFilterEvent(&ev, None)) + continue; + if (ev.type == ConfigureNotify) { + w = ev.xconfigure.width; + h = ev.xconfigure.height; + } + } while (ev.type != MapNotify); + + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); + cresize(w, h); + + clock_gettime(CLOCK_MONOTONIC, &last); + lastblink = last; + + for (xev = actionfps;;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(ttyfd, &rfd)) { + ttyread(); + if (blinktimeout) { + blinkset = tattrset(ATTR_BLINK); + if (!blinkset) + MODBIT(win.mode, 0, MODE_BLINK); + } + } + + if (FD_ISSET(xfd, &rfd)) + xev = actionfps; + + clock_gettime(CLOCK_MONOTONIC, &now); + drawtimeout.tv_sec = 0; + drawtimeout.tv_nsec = (1000 * 1E6)/ xfps; + tv = &drawtimeout; + + dodraw = 0; + if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { + tsetdirtattr(ATTR_BLINK); + win.mode ^= MODE_BLINK; + lastblink = now; + dodraw = 1; + } + deltatime = TIMEDIFF(now, last); + if (deltatime > 1000 / (xev ? xfps : actionfps)) { + dodraw = 1; + last = now; + } + + if (dodraw) { + while (XPending(xw.dpy)) { + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + draw(); + XFlush(xw.dpy); + + if (xev && !FD_ISSET(xfd, &rfd)) + xev--; + if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) { + if (blinkset) { + if (TIMEDIFF(now, lastblink) \ + > blinktimeout) { + drawtimeout.tv_nsec = 1000; + } else { + drawtimeout.tv_nsec = (1E6 * \ + (blinktimeout - \ + TIMEDIFF(now, + lastblink))); + } + drawtimeout.tv_sec = \ + drawtimeout.tv_nsec / 1E9; + drawtimeout.tv_nsec %= (long)1E9; + } else { + tv = NULL; + } + } + } + } +} + +void +usage(void) +{ + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + +int +main(int argc, char *argv[]) +{ + xw.l = xw.t = 0; + xw.isfixed = False; + win.cursor = cursorshape; + + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + if (argc > 0) + --argc, ++argv; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + xw.gm = XParseGeometry(EARGF(usage()), + &xw.l, &xw.t, &cols, &rows); + break; + case 'i': + xw.isfixed = 1; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 'l': + opt_line = EARGF(usage()); + break; + case 'n': + opt_name = EARGF(usage()); + break; + case 't': + case 'T': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + die("%s " VERSION "\n", argv0); + break; + default: + usage(); + } ARGEND; + +run: + if (argc > 0) /* eat all remaining arguments */ + opt_cmd = argv; + + if (!opt_title) + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; + + setlocale(LC_CTYPE, ""); + XSetLocaleModifiers(""); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); + + return 0; +} diff --git a/.suckless/st/x.o b/.suckless/st/x.o new file mode 100644 index 0000000000000000000000000000000000000000..ce343e4f75995097b5318af633a960f1171f2050 GIT binary patch literal 73896 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�;S_7O^4`NFa?p=YW?C-EHrTYV_$_^sVk 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 literal 0 HcmV?d00001