From 90315ab61ebcbe9091f68cfc17366aea825d739a Mon Sep 17 00:00:00 2001 From: Hektor Misplon Date: Sun, 16 Feb 2020 09:27:34 +0000 Subject: [PATCH] Convert submodules to directories --- .suckless/dmenu | 1 - .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 -> 43888 bytes .suckless/dmenu/dmenu.1 | 194 ++ .suckless/dmenu/dmenu.c | 771 ++++++++ .suckless/dmenu/dmenu.o | Bin 0 -> 32520 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 -> 10488 bytes .suckless/dmenu/stest | Bin 0 -> 17736 bytes .suckless/dmenu/stest.1 | 90 + .suckless/dmenu/stest.c | 109 ++ .suckless/dmenu/stest.o | Bin 0 -> 5312 bytes .suckless/dmenu/util.c | 35 + .suckless/dmenu/util.h | 8 + .suckless/dmenu/util.o | Bin 0 -> 2240 bytes .suckless/dwm | 1 - .suckless/dwm/.gitignore | 1 + .suckless/dwm/LICENSE | 37 + .suckless/dwm/Makefile | 51 + .suckless/dwm/README | 48 + .suckless/dwm/config.def.h | 115 ++ .suckless/dwm/config.h | 114 ++ .suckless/dwm/config.mk | 38 + .suckless/dwm/drw.c | 435 +++++ .suckless/dwm/drw.h | 57 + .suckless/dwm/drw.o | Bin 0 -> 10488 bytes .suckless/dwm/dwm | Bin 0 -> 62304 bytes .suckless/dwm/dwm.1 | 176 ++ .suckless/dwm/dwm.c | 2149 +++++++++++++++++++++ .suckless/dwm/dwm.o | Bin 0 -> 57536 bytes .suckless/dwm/dwm.png | Bin 0 -> 373 bytes .suckless/dwm/transient.c | 42 + .suckless/dwm/util.c | 35 + .suckless/dwm/util.h | 8 + .suckless/dwm/util.o | Bin 0 -> 2240 bytes .suckless/sselp | 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 | 23 + .suckless/sselp/sselp | Bin 0 -> 14480 bytes .suckless/sselp/sselp.c | 45 + .suckless/sselp/sselp.o | Bin 0 -> 3256 bytes .suckless/st | 1 - .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/st | Bin 0 -> 102256 bytes .suckless/st/st-anysize-0.8.1.diff | 152 ++ .suckless/st/st-nordtheme-0.8.2.diff | 100 + .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 -> 73200 bytes .suckless/st/win.h | 39 + .suckless/st/x.c | 2045 ++++++++++++++++++++ .suckless/st/x.o | Bin 0 -> 73912 bytes 78 files changed, 12255 insertions(+), 4 deletions(-) delete mode 160000 .suckless/dmenu 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 delete mode 160000 .suckless/dwm create mode 100644 .suckless/dwm/.gitignore create mode 100644 .suckless/dwm/LICENSE create mode 100644 .suckless/dwm/Makefile create mode 100644 .suckless/dwm/README create mode 100644 .suckless/dwm/config.def.h create mode 100644 .suckless/dwm/config.h create mode 100644 .suckless/dwm/config.mk create mode 100644 .suckless/dwm/drw.c create mode 100644 .suckless/dwm/drw.h create mode 100644 .suckless/dwm/drw.o create mode 100755 .suckless/dwm/dwm create mode 100644 .suckless/dwm/dwm.1 create mode 100644 .suckless/dwm/dwm.c create mode 100644 .suckless/dwm/dwm.o create mode 100644 .suckless/dwm/dwm.png create mode 100644 .suckless/dwm/transient.c create mode 100644 .suckless/dwm/util.c create mode 100644 .suckless/dwm/util.h create mode 100644 .suckless/dwm/util.o delete mode 160000 .suckless/sselp 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 delete mode 160000 .suckless/st 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 100755 .suckless/st/st create mode 100644 .suckless/st/st-anysize-0.8.1.diff create mode 100644 .suckless/st/st-nordtheme-0.8.2.diff 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 b/.suckless/dmenu deleted file mode 160000 index db6093f..0000000 --- a/.suckless/dmenu +++ /dev/null @@ -1 +0,0 @@ -Subproject commit db6093f6ec1bb884f7540f2512935b5254750b30 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..1edb647 --- /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 = 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.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..e85b0b5010e0a5f84f6948361dc00d8a4d5aea4c GIT binary patch literal 43888 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 YhgPqKU4+DN +#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..e0b153e57bf837fcef82d8d541ce076bffb9b5b1 GIT binary patch literal 32520 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 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..622000761139598e51783f5f8042982d8ad43752 GIT binary patch literal 10488 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 T5rwsPEn**K!2V3Vi`)MX)B1ZN literal 0 HcmV?d00001 diff --git a/.suckless/dmenu/stest b/.suckless/dmenu/stest new file mode 100755 index 0000000000000000000000000000000000000000..3ec07e4b602f583e119822059795c08c42791114 GIT binary patch literal 17736 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 p(x&sK@e|h=QQh_SgZQEX(uhGw