diff --git a/.zprofile b/.zprofile index 331502e..25c6539 100644 --- a/.zprofile +++ b/.zprofile @@ -26,10 +26,18 @@ alias \ cleae="clear" \ clera="clear" \ hotp="htop" \ - copykey='cat ~/.local/key/vault1.key | xclip -sel clipboard' + copykey='cat ~/.local/key/vault1.key | xclip -sel clipboard' \ grep --color=auto < /dev/null &>/dev/null && alias grep='grep --color=auto' +#utilize sbase coreutils when in shell +export GNU_PATH_BACKUP="$PATH" +export PATH="/bin/sbaseutils/bin:$PATH" +export COREUTILSMODE="POSIX" +alias gnumode='export PATH="/usr/bin:/bin:$GNU_PATH_BACKUP"; export COREUTILSMODE="GNU"' +alias posixmode='export PATH="/home/coast/.local/sbase/bin:$HOME/.local/bin:$GNU_PATH_BACKUP"; export COREUTILSMODE="POSIX"' + + export PATH="$HOME/.local/bin:$PATH" export PATH="/usr/pkg/sbin:/usr/pkg/bin:$PATH" export PATH="$PATH:/home/coast/.spicetify" diff --git a/suckless/dmenu/LICENSE b/suckless/dmenu/LICENSE deleted file mode 100644 index 2a64b28..0000000 --- a/suckless/dmenu/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -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-2022 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 deleted file mode 100644 index 458c524..0000000 --- a/suckless/dmenu/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# dmenu - dynamic menu -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = drw.c dmenu.c stest.c util.c -OBJ = $(SRC:.c=.o) - -all: dmenu stest - -.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 clean dist install uninstall diff --git a/suckless/dmenu/README b/suckless/dmenu/README deleted file mode 100644 index a8fcdfe..0000000 --- a/suckless/dmenu/README +++ /dev/null @@ -1,24 +0,0 @@ -dmenu - dynamic menu -==================== -dmenu is an efficient dynamic menu for X. - - -Requirements ------------- -In order to build dmenu you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dmenu is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dmenu -(if necessary as root): - - make clean install - - -Running dmenu -------------- -See the man page for details. diff --git a/suckless/dmenu/arg.h b/suckless/dmenu/arg.h deleted file mode 100644 index e94e02b..0000000 --- a/suckless/dmenu/arg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - for (brk_ = 0, argv[0]++, argv_ = argv;\ - argv[0][0] && !brk_;\ - argv[0]++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][0];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/suckless/dmenu/config.def.h b/suckless/dmenu/config.def.h deleted file mode 100644 index 1edb647..0000000 --- a/suckless/dmenu/config.def.h +++ /dev/null @@ -1,23 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -/* Default settings; can be overriden by command line. */ - -static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -/* -fn option overrides fonts[0]; default X11 font or font set */ -static const char *fonts[] = { - "monospace:size=10" -}; -static const char *prompt = NULL; /* -p option; prompt to the left of input field */ -static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, -}; -/* -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 deleted file mode 100644 index 1edb647..0000000 --- a/suckless/dmenu/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -/* Default settings; can be overriden by command line. */ - -static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -/* -fn option overrides fonts[0]; default X11 font or font set */ -static const char *fonts[] = { - "monospace:size=10" -}; -static const char *prompt = NULL; /* -p option; prompt to the left of input field */ -static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, -}; -/* -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 deleted file mode 100644 index 137f7c8..0000000 --- a/suckless/dmenu/config.mk +++ /dev/null @@ -1,32 +0,0 @@ -# dmenu version -VERSION = 5.3 - -# 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 -#MANPREFIX = ${PREFIX}/man - -# 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 deleted file mode 100755 index 28c9d8a..0000000 Binary files a/suckless/dmenu/dmenu and /dev/null differ diff --git a/suckless/dmenu/dmenu.1 b/suckless/dmenu/dmenu.1 deleted file mode 100644 index 323f93c..0000000 --- a/suckless/dmenu/dmenu.1 +++ /dev/null @@ -1,194 +0,0 @@ -.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 deleted file mode 100644 index fd49549..0000000 --- a/suckless/dmenu/dmenu.c +++ /dev/null @@ -1,795 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef XINERAMA -#include -#endif -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ - * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) -#define 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 unsigned int -textw_clamp(const char *str, unsigned int n) -{ - unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; - return MIN(w, n); -} - -static void -appenditem(struct item *item, struct item **list, struct item **last) -{ - if (*last) - (*last)->right = item; - else - *list = item; - - item->left = *last; - item->right = NULL; - *last = item; -} - -static void -calcoffsets(void) -{ - int i, n; - - if (lines > 0) - n = lines * bh; - else - n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); - /* calculate which items will begin the next page and previous page */ - for (i = 0, next = curr; next; next = next->right) - if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) - break; - for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) - break; -} - -static void -cleanup(void) -{ - size_t i; - - XUngrabKeyboard(dpy, CurrentTime); - for (i = 0; i < SchemeLast; i++) - free(scheme[i]); - for (i = 0; items && items[i].text; ++i) - free(items[i].text); - free(items); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static char * -cistrstr(const char *h, const char *n) -{ - size_t i; - - if (!n[0]) - return (char *)h; - - for (; *h; ++h) { - for (i = 0; n[i] && tolower((unsigned char)n[i]) == - tolower((unsigned char)h[i]); ++i) - ; - if (n[i] == '\0') - return (char *)h; - } - return NULL; -} - -static int -drawitem(struct item *item, int x, int y, int w) -{ - if (item == sel) - drw_setscheme(drw, scheme[SchemeSel]); - else if (item->out) - drw_setscheme(drw, scheme[SchemeOut]); - else - drw_setscheme(drw, scheme[SchemeNorm]); - - return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -} - -static void -drawmenu(void) -{ - unsigned int curpos; - struct item *item; - int x = 0, y = 0, w; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); - - if (prompt && *prompt) { - drw_setscheme(drw, scheme[SchemeSel]); - x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); - } - /* draw input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); - - curpos = TEXTW(text) - TEXTW(&text[cursor]); - 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, textw_clamp(item->text, mw - x - TEXTW(">"))); - if (next) { - w = TEXTW(">"); - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); - } - } - drw_map(drw, win, 0, 0, mw, mh); -} - -static void -grabfocus(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; - Window focuswin; - int i, revertwin; - - for (i = 0; i < 100; ++i) { - XGetInputFocus(dpy, &focuswin, &revertwin); - if (focuswin == win) - return; - XSetInputFocus(dpy, win, RevertToParent, CurrentTime); - nanosleep(&ts, NULL); - } - die("cannot grab focus"); -} - -static void -grabkeyboard(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; - int i; - - if (embed) - return; - /* try to grab keyboard, we may have to wait for another process to ungrab */ - for (i = 0; i < 1000; i++) { - if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, - GrabModeAsync, CurrentTime) == GrabSuccess) - return; - nanosleep(&ts, NULL); - } - die("cannot grab keyboard"); -} - -static void -match(void) -{ - static char **tokv = NULL; - static int tokn = 0; - - char buf[sizeof text], *s; - int i, tokc = 0; - size_t len, textsize; - struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; - - strcpy(buf, text); - /* separate input text into tokens to be matched individually */ - for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) - if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) - die("cannot realloc %zu bytes:", tokn * sizeof *tokv); - len = tokc ? strlen(tokv[0]) : 0; - - matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - textsize = strlen(text) + 1; - for (item = items; item && item->text; item++) { - for (i = 0; i < tokc; i++) - if (!fstrstr(item->text, tokv[i])) - break; - if (i != tokc) /* not all tokens match */ - continue; - /* exact matches go first, then prefixes, then substrings */ - if (!tokc || !fstrncmp(text, item->text, textsize)) - appenditem(item, &matches, &matchend); - else if (!fstrncmp(tokv[0], item->text, len)) - appenditem(item, &lprefix, &prefixend); - else - appenditem(item, &lsubstr, &substrend); - } - if (lprefix) { - if (matches) { - matchend->right = lprefix; - lprefix->left = matchend; - } else - matches = lprefix; - matchend = prefixend; - } - if (lsubstr) { - if (matches) { - matchend->right = lsubstr; - lsubstr->left = matchend; - } else - matches = lsubstr; - matchend = substrend; - } - curr = sel = matches; - calcoffsets(); -} - -static void -insert(const char *str, ssize_t n) -{ - if (strlen(text) + n > sizeof text - 1) - return; - /* move existing text out of the way, insert new text, and update cursor */ - memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); - if (n > 0) - memcpy(&text[cursor], str, n); - cursor += n; - match(); -} - -static size_t -nextrune(int inc) -{ - ssize_t n; - - /* return location of next utf8 rune in the given direction (+1 or -1) */ - for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) - ; - return n; -} - -static void -movewordedge(int dir) -{ - if (dir < 0) { /* move cursor to the start of the word*/ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - } else { /* move cursor to the end of the word */ - while (text[cursor] && strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - while (text[cursor] && !strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - } -} - -static void -keypress(XKeyEvent *ev) -{ - char buf[64]; - int len; - KeySym ksym = NoSymbol; - Status status; - - len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); - switch (status) { - default: /* XLookupNone, XBufferOverflow */ - return; - case XLookupChars: /* composed string from input method */ - goto insert; - case XLookupKeySym: - case XLookupBoth: /* a KeySym and a string are returned: use keysym */ - break; - } - - if (ev->state & ControlMask) { - switch(ksym) { - case XK_a: ksym = XK_Home; break; - case XK_b: ksym = XK_Left; break; - case XK_c: ksym = XK_Escape; break; - case XK_d: ksym = XK_Delete; break; - case XK_e: ksym = XK_End; break; - case XK_f: ksym = XK_Right; break; - case XK_g: ksym = XK_Escape; break; - case XK_h: ksym = XK_BackSpace; break; - case XK_i: ksym = XK_Tab; break; - case XK_j: /* fallthrough */ - case XK_J: /* fallthrough */ - case XK_m: /* fallthrough */ - case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; - case XK_n: ksym = XK_Down; break; - case XK_p: ksym = XK_Up; break; - - case XK_k: /* delete right */ - text[cursor] = '\0'; - match(); - break; - case XK_u: /* delete left */ - insert(NULL, 0 - cursor); - break; - case XK_w: /* delete word */ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - break; - case XK_y: /* paste selection */ - case XK_Y: - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return; - case XK_Left: - case XK_KP_Left: - movewordedge(-1); - goto draw; - case XK_Right: - case XK_KP_Right: - movewordedge(+1); - goto draw; - case XK_Return: - case XK_KP_Enter: - break; - case XK_bracketleft: - cleanup(); - exit(1); - default: - return; - } - } else if (ev->state & Mod1Mask) { - switch(ksym) { - case XK_b: - movewordedge(-1); - goto draw; - case XK_f: - movewordedge(+1); - goto draw; - case XK_g: ksym = XK_Home; break; - case XK_G: ksym = XK_End; break; - case XK_h: ksym = XK_Up; break; - case XK_j: ksym = XK_Next; break; - case XK_k: ksym = XK_Prior; break; - case XK_l: ksym = XK_Down; break; - default: - return; - } - } - - switch(ksym) { - default: -insert: - if (!iscntrl((unsigned char)*buf)) - insert(buf, len); - break; - case XK_Delete: - case XK_KP_Delete: - if (text[cursor] == '\0') - return; - cursor = nextrune(+1); - /* fallthrough */ - case XK_BackSpace: - if (cursor == 0) - return; - insert(NULL, nextrune(-1) - cursor); - break; - case XK_End: - case XK_KP_End: - if (text[cursor] != '\0') { - cursor = strlen(text); - break; - } - if (next) { - /* jump to end of list and position items in reverse */ - curr = matchend; - calcoffsets(); - curr = prev; - calcoffsets(); - while (next && (curr = curr->right)) - calcoffsets(); - } - sel = matchend; - break; - case XK_Escape: - cleanup(); - exit(1); - case XK_Home: - case XK_KP_Home: - if (sel == matches) { - cursor = 0; - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_Left: - case XK_KP_Left: - if (cursor > 0 && (!sel || !sel->left || lines > 0)) { - cursor = nextrune(-1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Up: - case XK_KP_Up: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_Next: - case XK_KP_Next: - if (!next) - return; - sel = curr = next; - calcoffsets(); - break; - case XK_Prior: - case XK_KP_Prior: - if (!prev) - return; - sel = curr = prev; - calcoffsets(); - break; - case XK_Return: - case XK_KP_Enter: - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); - if (!(ev->state & ControlMask)) { - cleanup(); - exit(0); - } - if (sel) - sel->out = 1; - break; - case XK_Right: - case XK_KP_Right: - if (text[cursor] != '\0') { - cursor = nextrune(+1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Down: - case XK_KP_Down: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_Tab: - if (!sel) - return; - cursor = strnlen(sel->text, sizeof text - 1); - memcpy(text, sel->text, cursor); - text[cursor] = '\0'; - match(); - break; - } - -draw: - drawmenu(); -} - -static void -paste(void) -{ - char *p, *q; - int di; - unsigned long dl; - Atom da; - - /* we have been given the current selection, now insert it into input */ - if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, - utf8, &da, &di, &dl, &dl, (unsigned char **)&p) - == Success && p) { - insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); - XFree(p); - } - drawmenu(); -} - -static void -readstdin(void) -{ - char *line = NULL; - size_t i, itemsiz = 0, linesiz = 0; - ssize_t len; - - /* read each line from stdin and add it to the item list */ - for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) { - if (i + 1 >= itemsiz) { - itemsiz += 256; - if (!(items = realloc(items, itemsiz * sizeof(*items)))) - die("cannot realloc %zu bytes:", itemsiz * sizeof(*items)); - } - if (line[len - 1] == '\n') - line[len - 1] = '\0'; - if (!(items[i].text = strdup(line))) - die("strdup:"); - - items[i].out = 0; - } - free(line); - if (items) - items[i].text = NULL; - lines = MIN(lines, i); -} - -static void -run(void) -{ - XEvent ev; - - while (!XNextEvent(dpy, &ev)) { - if (XFilterEvent(&ev, win)) - continue; - switch(ev.type) { - case DestroyNotify: - if (ev.xdestroywindow.window != win) - break; - cleanup(); - exit(1); - case Expose: - if (ev.xexpose.count == 0) - drw_map(drw, win, 0, 0, mw, mh); - break; - case FocusIn: - /* regrab focus from parent window */ - if (ev.xfocus.window != win) - grabfocus(); - break; - case KeyPress: - keypress(&ev.xkey); - break; - case SelectionNotify: - if (ev.xselection.property == utf8) - paste(); - break; - case VisibilityNotify: - if (ev.xvisibility.state != VisibilityUnobscured) - XRaiseWindow(dpy, win); - break; - } - } -} - -static void -setup(void) -{ - int x, y, i, j; - unsigned int du; - XSetWindowAttributes swa; - XIM xim; - Window w, dw, *dws; - XWindowAttributes wa; - XClassHint ch = {"dmenu", "dmenu"}; -#ifdef XINERAMA - XineramaScreenInfo *info; - Window pw; - int a, di, n, area = 0; -#endif - /* init appearance */ - for (j = 0; j < SchemeLast; j++) - scheme[j] = drw_scm_create(drw, colors[j], 2); - - clip = XInternAtom(dpy, "CLIPBOARD", False); - utf8 = XInternAtom(dpy, "UTF8_STRING", False); - - /* calculate menu geometry */ - bh = drw->fonts->h + 2; - lines = MAX(lines, 0); - mh = (lines + 1) * bh; -#ifdef XINERAMA - i = 0; - if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { - XGetInputFocus(dpy, &w, &di); - if (mon >= 0 && mon < n) - i = mon; - else if (w != root && w != PointerRoot && w != None) { - /* find top-level window containing current input focus */ - do { - if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) - XFree(dws); - } while (w != root && w != pw); - /* find xinerama screen with which the window intersects most */ - if (XGetWindowAttributes(dpy, pw, &wa)) - for (j = 0; j < n; j++) - if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { - area = a; - i = j; - } - } - /* no focused window is on screen, so use pointer location instead */ - if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) - for (i = 0; i < n; i++) - if (INTERSECT(x, y, 1, 1, info[i]) != 0) - break; - - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; - } - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = mw / 3; /* input width: ~33% of monitor width */ - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, root, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - XSetClassHint(dpy, win, &ch); - - /* input methods */ - if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) - die("XOpenIM failed: could not open input device"); - - xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, win, XNFocusWindow, win, NULL); - - XMapRaised(dpy, win); - if (embed) { - XReparentWindow(dpy, win, parentwin, x, y); - XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); - if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { - for (i = 0; i < du && dws[i] != win; ++i) - XSelectInput(dpy, dws[i], FocusChangeMask); - XFree(dws); - } - grabfocus(); - } - drw_resize(drw, mw, mh); - drawmenu(); -} - -static void -usage(void) -{ - die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); -} - -int -main(int argc, char *argv[]) -{ - XWindowAttributes wa; - int i, fast = 0; - - for (i = 1; i < argc; i++) - /* these options take no arguments */ - if (!strcmp(argv[i], "-v")) { /* prints version information */ - puts("dmenu-"VERSION); - exit(0); - } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ - topbar = 0; - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; - } else if (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 deleted file mode 100644 index 7028ae2..0000000 Binary files a/suckless/dmenu/dmenu.o and /dev/null differ diff --git a/suckless/dmenu/dmenu_path b/suckless/dmenu/dmenu_path deleted file mode 100644 index 3a7cda7..0000000 --- a/suckless/dmenu/dmenu_path +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" -cache="$cachedir/dmenu_run" - -[ ! -e "$cachedir" ] && mkdir -p "$cachedir" - -IFS=: -if stest -dqr -n "$cache" $PATH; then - stest -flx $PATH | sort -u | tee "$cache" -else - cat "$cache" -fi diff --git a/suckless/dmenu/dmenu_run b/suckless/dmenu/dmenu_run deleted file mode 100644 index 834ede5..0000000 --- a/suckless/dmenu/dmenu_run +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & diff --git a/suckless/dmenu/drw.c b/suckless/dmenu/drw.c deleted file mode 100644 index c41e6af..0000000 --- a/suckless/dmenu/drw.c +++ /dev/null @@ -1,448 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD - -static int -utf8decode(const char *s_in, long *u, int *err) -{ - static const unsigned char lens[] = { - /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ - /* 110XX */ 2, 2, 2, 2, - /* 1110X */ 3, 3, - /* 11110 */ 4, - /* 11111 */ 0, /* invalid */ - }; - static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; - static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; - - const unsigned char *s = (const unsigned char *)s_in; - int len = lens[*s >> 3]; - *u = UTF_INVALID; - *err = 1; - if (len == 0) - return 1; - - long cp = s[0] & leading_mask[len - 1]; - for (int i = 1; i < len; ++i) { - if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) - return i; - cp = (cp << 6) | (s[i] & 0x3F); - } - /* out of range, surrogate, overlong encoding */ - if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) - return len; - - *err = 0; - *u = cp; - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - int ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0, overflow = 0; - /* keep track of a couple codepoints for which we have no match. */ - static unsigned int nomatches[128], ellipsis_width, invalid_width; - static const char invalid[] = "�"; - - if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) - return 0; - - if (!render) { - w = invert ? invert : ~invert; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - if (w < lpad) - return x + w; - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); - if (!invalid_width && render) - invalid_width = drw_fontset_getwidth(drw, invalid); - while (1) { - ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); - if (ew + ellipsis_width <= w) { - /* keep track where the ellipsis still fits */ - ellipsis_x = x + ew; - ellipsis_w = w - ew; - ellipsis_len = utf8strlen; - } - - if (ew + tmpw > w) { - overflow = 1; - /* called from drw_fontset_getwidth_clamp(): - * it wants the width AFTER the overflow - */ - if (!render) - x += tmpw; - else - utf8strlen = ellipsis_len; - } else if (curfont == usedfont) { - text += utf8charlen; - utf8strlen += utf8err ? 0 : utf8charlen; - ew += utf8err ? 0 : tmpw; - } else { - nextfont = curfont; - } - break; - } - } - - if (overflow || !charexists || nextfont || utf8err) - break; - else - charexists = 0; - } - - if (utf8strlen) { - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); - } - x += ew; - w -= ew; - } - if (utf8err && (!render || invalid_width < w)) { - if (render) - drw_text(drw, x, y, w, h, 0, invalid, invert); - x += invalid_width; - w -= invalid_width; - } - if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - - if (!*text || overflow) { - 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; - - hash = (unsigned int)utf8codepoint; - hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; - hash = ((hash >> 15) ^ hash) * 0xD35A2D97; - h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); - h1 = (hash >> 17) % LENGTH(nomatches); - /* avoid expensive XftFontMatch call when we know we won't find a match */ - if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) - goto no_match; - - 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); - - 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); - nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; -no_match: - 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); -} - -unsigned int -drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) -{ - unsigned int tmp = 0; - if (drw && drw->fonts && text && n) - tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); - return MIN(n, tmp); -} - -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 deleted file mode 100644 index fd7631b..0000000 --- a/suckless/dmenu/drw.h +++ /dev/null @@ -1,58 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); -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 deleted file mode 100644 index 69dbfa9..0000000 Binary files a/suckless/dmenu/drw.o and /dev/null differ diff --git a/suckless/dmenu/stest b/suckless/dmenu/stest deleted file mode 100755 index 344348c..0000000 Binary files a/suckless/dmenu/stest and /dev/null differ diff --git a/suckless/dmenu/stest.1 b/suckless/dmenu/stest.1 deleted file mode 100644 index 2667d8a..0000000 --- a/suckless/dmenu/stest.1 +++ /dev/null @@ -1,90 +0,0 @@ -.TH STEST 1 dmenu\-VERSION -.SH NAME -stest \- filter a list of files by properties -.SH SYNOPSIS -.B stest -.RB [ -abcdefghlpqrsuwx ] -.RB [ -n -.IR file ] -.RB [ -o -.IR file ] -.RI [ file ...] -.SH DESCRIPTION -.B stest -takes a list of files and filters by the files' properties, analogous to -.IR test (1). -Files which pass all tests are printed to stdout. If no files are given, stest -reads files from stdin. -.SH OPTIONS -.TP -.B \-a -Test hidden files. -.TP -.B \-b -Test that files are block specials. -.TP -.B \-c -Test that files are character specials. -.TP -.B \-d -Test that files are directories. -.TP -.B \-e -Test that files exist. -.TP -.B \-f -Test that files are regular files. -.TP -.B \-g -Test that files have their set-group-ID flag set. -.TP -.B \-h -Test that files are symbolic links. -.TP -.B \-l -Test the contents of a directory given as an argument. -.TP -.BI \-n " file" -Test that files are newer than -.IR file . -.TP -.BI \-o " file" -Test that files are older than -.IR file . -.TP -.B \-p -Test that files are named pipes. -.TP -.B \-q -No files are printed, only the exit status is returned. -.TP -.B \-r -Test that files are readable. -.TP -.B \-s -Test that files are not empty. -.TP -.B \-u -Test that files have their set-user-ID flag set. -.TP -.B \-v -Invert the sense of tests, only failing files pass. -.TP -.B \-w -Test that files are writable. -.TP -.B \-x -Test that files are executable. -.SH EXIT STATUS -.TP -.B 0 -At least one file passed all tests. -.TP -.B 1 -No files passed all tests. -.TP -.B 2 -An error occurred. -.SH SEE ALSO -.IR dmenu (1), -.IR test (1) diff --git a/suckless/dmenu/stest.c b/suckless/dmenu/stest.c deleted file mode 100644 index e27d3a5..0000000 --- a/suckless/dmenu/stest.c +++ /dev/null @@ -1,109 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include - -#include -#include -#include -#include -#include -#include - -#include "arg.h" -char *argv0; - -#define FLAG(x) (flag[(x)-'a']) - -static void test(const char *, const char *); -static void usage(void); - -static int match = 0; -static int flag[26]; -static struct stat old, new; - -static void -test(const char *path, const char *name) -{ - struct stat st, ln; - - if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ - && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ - && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ - && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ - && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ - && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ - && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ - && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ - && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ - && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ - && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ - && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ - && (!FLAG('s') || st.st_size > 0) /* not empty */ - && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ - && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ - && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ - if (FLAG('q')) - exit(0); - match = 1; - puts(name); - } -} - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " - "[-n file] [-o file] [file...]\n", argv0); - exit(2); /* like test(1) return > 1 on error */ -} - -int -main(int argc, char *argv[]) -{ - struct dirent *d; - char path[PATH_MAX], *line = NULL, *file; - size_t linesiz = 0; - ssize_t n; - DIR *dir; - int r; - - ARGBEGIN { - case 'n': /* newer than file */ - case 'o': /* older than file */ - file = EARGF(usage()); - if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) - perror(file); - break; - default: - /* miscellaneous operators */ - if (strchr("abcdefghlpqrsuvwx", ARGC())) - FLAG(ARGC()) = 1; - else - usage(); /* unknown flag */ - } ARGEND; - - if (!argc) { - /* read list from stdin */ - while ((n = getline(&line, &linesiz, stdin)) > 0) { - if (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 deleted file mode 100644 index 3d5045e..0000000 Binary files a/suckless/dmenu/stest.o and /dev/null differ diff --git a/suckless/dmenu/util.c b/suckless/dmenu/util.c deleted file mode 100644 index 8e26a51..0000000 --- a/suckless/dmenu/util.c +++ /dev/null @@ -1,37 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "util.h" - -void -die(const char *fmt, ...) -{ - va_list ap; - int saved_errno; - - saved_errno = errno; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(saved_errno)); - fputc('\n', stderr); - - exit(1); -} - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} diff --git a/suckless/dmenu/util.h b/suckless/dmenu/util.h deleted file mode 100644 index c0a50d4..0000000 --- a/suckless/dmenu/util.h +++ /dev/null @@ -1,9 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) -#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) - -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 deleted file mode 100644 index 5dd48bf..0000000 Binary files a/suckless/dmenu/util.o and /dev/null differ diff --git a/suckless/dwm/#dwm.c# b/suckless/dwm/#dwm.c# deleted file mode 100644 index 3c2c1b6..0000000 --- a/suckless/dwm/#dwm.c# +++ /dev/null @@ -1,2302 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ - if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ - int i = 1; \ - for (; i <= 6; i++) { \ - if (value.addr[i] < 48) break; \ - if (value.addr[i] > 57 && value.addr[i] < 65) break; \ - if (value.addr[i] > 70 && value.addr[i] < 97) break; \ - if (value.addr[i] > 102) break; \ - } \ - if (i == 7) { \ - strncpy(V, value.addr, 7); \ - V[7] = '\0'; \ - } \ - } \ - } - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, - ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachaside(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Atom getatomprop(Client *c, Atom prop); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void loadxrdb(void); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttagged(Client *c); -static Client *nexttiled(Client *c); -static void pop(Client *c); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void run(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setgaps(const Arg *arg); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void updatewindowtype(Client *c); -static void updatewmhints(Client *c); -static void view(const Arg *arg); -static void warp(const Client *c); -static Client *wintoclient(Window w); -static Monitor *wintomon(Window w); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xrdb(const Arg *arg); -static void zoom(const Arg *arg); -static void sighup(int unused); -static void sigterm(int unused); - - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh; /* bar height */ -static int lrpad; /* sum of left and right padding for text */ -static int vp; /* vertical padding for bar */ -static int sp; /* side padding for bar */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int restart = 0; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - if (!c->hintsvalid) - updatesizehints(c); - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachaside(Client *c) { - Client *at = nexttagged(c); - if(!at) { - attach(c); - return; - } - c->next = at->next; - at->next = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; - else - click = ClkStatusText; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, tw = 0; - unsigned int i, occ = 0, urg = 0; - Client *c; - - if (!m->showbar) - return; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon || 1) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j, k; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - int start, end, skip; - KeySym *syms; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XDisplayKeycodes(dpy, &start, &end); - syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); - if (!syms) - return; - for (k = start; k <= end; k++) - for (i = 0; i < LENGTH(keys); i++) - /* skip modifier codes, we do that ourselves */ - if (keys[i].keysym == syms[(k - start) * skip]) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, k, - keys[i].mod | modifiers[j], - root, True, - GrabModeAsync, GrabModeAsync); - XFree(syms); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -loadxrdb() -{ - Display *display; - char * resm; - XrmDatabase xrdb; - char *type; - XrmValue value; - - display = XOpenDisplay(NULL); - - if (display != NULL) { - resm = XResourceManagerString(display); - - if (resm != NULL) { - xrdb = XrmGetStringDatabase(resm); - - if (xrdb != NULL) { - XRDB_LOAD_COLOR("dwm.color2", normbordercolor); - XRDB_LOAD_COLOR("dwm.background", normbgcolor); - XRDB_LOAD_COLOR("dwm.color7", normfgcolor); - XRDB_LOAD_COLOR("dwm.color6", selbordercolor); - XRDB_LOAD_COLOR("dwm.color11", selbgcolor); - XRDB_LOAD_COLOR("dwm.color15", selfgcolor); - } - } - } - - XCloseDisplay(display); -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) - c->x = c->mon->wx + c->mon->ww - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) - c->y = c->mon->wy + c->mon->wh - HEIGHT(c); - c->x = MAX(c->x, c->mon->wx); - c->y = MAX(c->y, c->mon->wy); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, ""); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttagged(Client *c) { - Client *walked = c->mon->clients; - for(; - walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); - walked = walked->next - ); - return walked; -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - c->hintsvalid = 0; - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) - updatetitle(c); - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - if(arg->i) restart = 1; - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int x, y, ocw, och, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocw = c->w; - och = c->h; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - if(!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ocw + (ev.xmotion.x - x), 1); - nh = MAX(och + (ev.xmotion.y - y), 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) - warp(m->sel); - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - struct sigaction sa; - - /* do not transform children into zombies when they terminate */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - - /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); - - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + user_bh; - - sp = sidepad; - vp = (topbar == 1) ? vertpad : - vertpad; - updategeom(); - - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - -void -spawn(const Arg *arg) -{ - struct sigaction sa; - - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww - m->gappx; - for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; - resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); - if (my + HEIGHT(c) + m->gappx < m->wh) - my += HEIGHT(c) + m->gappx; - } else { - h = (m->wh - ty) / (n - i) - m->gappx; - resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); - if (ty + HEIGHT(c) + m->gappx < m->wh) - ty += HEIGHT(c) + m->gappx; - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixmap = ParentRelative, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh = m->wh - vertpad - bh; - m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; - m->wy = m->topbar ? m->wy + bh + vp : m->wy; - } else - m->by = -bh - vp; -} - -void -updateclientlist(void) -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - - /* new monitors if nn > n */ - for (i = n; i < nn; i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - /* removed monitors if n > nn */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attachaside(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - c->hintsvalid = 1; -} - -void -updatestatus(void) -{ - Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - for(m = mons; m; m = m->next) - drawbar(m); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -void -warp(const Client *c) -{ - int x, y; - - if (!c) { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); - return; - } - - if (!getrootptr(&x, &y) || - (x > c->x - c->bw && - y > c->y - c->bw && - x < c->x + c->w + c->bw*2 && - y < c->y + c->h + c->bw*2) || - (y > c->mon->by && y < c->mon->by + bh) || - (c->mon->topbar && !y)) - return; - - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xrdb(const Arg *arg) -{ - loadxrdb(); - int i; - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - focus(NULL); - arrange(NULL); -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - XrmInitialize(); - loadxrdb(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/suckless/dwm/LICENSE b/suckless/dwm/LICENSE deleted file mode 100644 index 995172f..0000000 --- a/suckless/dwm/LICENSE +++ /dev/null @@ -1,38 +0,0 @@ -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe -© 2006-2009 Jukka Salmi -© 2006-2007 Sander van Dijk -© 2007-2011 Peter Hartlich -© 2007-2009 Szabolcs Nagy -© 2007-2009 Christof Musik -© 2007-2009 Premysl Hruby -© 2007-2008 Enno Gottox Boland -© 2008 Martin Hurton -© 2008 Neale Pickett -© 2009 Mate Nagy -© 2010-2016 Hiltjo Posthuma -© 2010-2012 Connor Lane Smith -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau -© 2015-2016 Eric Pruitt -© 2016-2017 Markus Teich -© 2020-2022 Chris Down - -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/dwm/Makefile b/suckless/dwm/Makefile deleted file mode 100644 index ffa69b4..0000000 --- a/suckless/dwm/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# dwm - dynamic window manager -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = drw.c dwm.c util.c -OBJ = ${SRC:.c=.o} - -all: dwm - -.c.o: - ${CC} -c ${CFLAGS} $< - -${OBJ}: config.h config.mk - -config.h: - cp config.def.h $@ - -dwm: ${OBJ} - ${CC} -o $@ ${OBJ} ${LDFLAGS} - -clean: - rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz - -dist: clean - mkdir -p dwm-${VERSION} - cp -R LICENSE Makefile README config.def.h config.mk\ - dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} - tar -cf dwm-${VERSION}.tar dwm-${VERSION} - gzip dwm-${VERSION}.tar - rm -rf dwm-${VERSION} - -install: all - mkdir -p ${DESTDIR}${PREFIX}/bin - cp -f dwm ${DESTDIR}${PREFIX}/bin - chmod 755 ${DESTDIR}${PREFIX}/bin/dwm - mkdir -p ${DESTDIR}${MANPREFIX}/man1 - sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 - chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -uninstall: - rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -.PHONY: all clean dist install uninstall diff --git a/suckless/dwm/README b/suckless/dwm/README deleted file mode 100644 index 95d4fd0..0000000 --- a/suckless/dwm/README +++ /dev/null @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dwm is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -Running dwm ------------ -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -Configuration -------------- -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/suckless/dwm/README.md b/suckless/dwm/README.md deleted file mode 100644 index 70e3d98..0000000 --- a/suckless/dwm/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## DWM -This is one of my favorite window managers, it's great - very customizable. -Credits to Swindles McCoop on Github and YouTube, I've cloned their dwm build and made my own configurations to it. - -## Compiling -### Dependencies -X11, Xinerama, xcb, freetype, rofi, slock, Alacritty -### Instructions -Run `./configure` to properly set up `config.mk`. -#### Linux -`make && sudo make install` -#### BSD -`gmake && doas gmake install` - -## Keybinds: -- `MODKEY + Enter` - Spawn Alacritty (MUST BE INSTALLED) -- `MODKEY + Shift + Enter`, `F12` - Toggle scratchpad terminal -- `MODKEY + r` - Rofi (MUST BE INSTALLED) -- `MODKEY + s` - Kill window -- `MODKEY + m` - Toggle status bar -- `MODKEY + f` - Toggle fullscreen -- `MODKEY + o/O` - Increase/decrease number of masters -- `MODKEY + j/k` - Move focus down/up -- `MODKEY + J/K` - Move window in stack down/up -- `MODKEY + SHIFTMASK + q` - Kill DWM -- `MODKEY + Space` - Set all windows to Floating mode -- `MODKEY + K/J` - Change focused window in on the direction of K/J on a qwerty keyboard -- `MODKEY + SHIFTMASK + K/J` - Move window in on the direction of K/J on a qwerty keyboard -- `MODKEY + H/L` - Expand/shrink master window in direction of H/L on a qwerty keyboard -- `MODKEY + SHIFTMASK + L` - Lock using slock (MUST BE INSTALLED) \ No newline at end of file diff --git a/suckless/dwm/attachaside.diff b/suckless/dwm/attachaside.diff deleted file mode 100644 index 2f34ac2..0000000 --- a/suckless/dwm/attachaside.diff +++ /dev/null @@ -1,93 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index f1d86b2..8b04e0b 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -49,7 +49,8 @@ - #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) --#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -+#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -+#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) -@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac - static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); -+static void attachaside(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -184,6 +186,7 @@ static void maprequest(XEvent *e); - static void monocle(Monitor *m); - static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); -+static Client *nexttagged(Client *c); - static Client *nexttiled(Client *c); - static void pop(Client *c); - static void propertynotify(XEvent *e); -@@ -408,6 +411,17 @@ attach(Client *c) - c->mon->clients = c; - } - -+void -+attachaside(Client *c) { -+ Client *at = nexttagged(c); -+ if(!at) { -+ attach(c); -+ return; -+ } -+ c->next = at->next; -+ at->next = c; -+} -+ - void - attachstack(Client *c) - { -@@ -1074,7 +1088,7 @@ manage(Window w, XWindowAttributes *wa) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1202,6 +1216,16 @@ movemouse(const Arg *arg) - } - } - -+Client * -+nexttagged(Client *c) { -+ Client *walked = c->mon->clients; -+ for(; -+ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); -+ walked = walked->next -+ ); -+ return walked; -+} -+ - Client * - nexttiled(Client *c) - { -@@ -1427,7 +1451,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1915,7 +1939,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachaside(c); - attachstack(c); - } - if (m == selmon) - diff --git a/suckless/dwm/config.def.h b/suckless/dwm/config.def.h deleted file mode 100644 index ac4674b..0000000 --- a/suckless/dwm/config.def.h +++ /dev/null @@ -1,129 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx = 2; /* border pixel of windows */ -static const unsigned int gappx = 14; /* gaps between windows */ -static const unsigned int snap = 3; /* snap pixel */ -static const int user_bh = 12; /* 2 is the default spacing around the bar's font */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int vertpad = 10; /* vertical padding of bar */ -static const int sidepad = 16; /* horizontal padding of bar */ -static const char *fonts[] = {"CaskaydiaMonoNerdFont-Bold:size=9.2"}; -static const char dmenufont[] = "CaskaydiaMonoNerdFont-Bold:size=10.6"; -static char normbgcolor[] = "#222222"; -static char normbordercolor[] = "#444444"; -static char normfgcolor[] = "#bbbbbb"; -static char selfgcolor[] = "#eeeeee"; -static char selbordercolor[] = "#005577"; -static char selbgcolor[] = "#005577"; -static char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, - [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, -}; - -/* tagging */ -static const char *tags[] = { "","","","","", }; - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { NULL, NULL, NULL, 0, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { - /* symbol arrange function */ - {"", tile}, /* first entry is default */ - {"󰭩", NULL}, /* no layout function means floating behavior */ - {"", monocle}, -}; - - - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = {"bash", "-c", "st -e bash & walrs -R -q ",NULL}; - -#include "movestack.c" -static const Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_n, xrdb, {.v = NULL } }, - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - { MODKEY, XK_minus, setgaps, {.i = -1 } }, - { MODKEY, XK_equal, setgaps, {.i = +1 } }, - { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static const Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; - diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h deleted file mode 100644 index 3878b2b..0000000 --- a/suckless/dwm/config.h +++ /dev/null @@ -1,164 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx = 2.5; /* border pixel of windows */ -static const unsigned int gappx = 14; /* gaps between windows */ -static const unsigned int snap = 3; /* snap pixel */ -static const int user_bh = 12; /* 2 is the default spacing around the bar's font */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 0; /* 0 means bottom bar */ -static const int vertpad = 10; /* vertical padding of bar */ -static const int sidepad = 400; /* horizontal padding of bar */ -static const char *fonts[] = {"CaskaydiaMonoNerdFont-Bold:size=9.2"}; -static const char dmenufont[] = "CaskaydiaMonoNerdFont-Bold:size=10.6"; -static char normbgcolor[] = "#222222"; -static char normbordercolor[] = "#444444"; -static char normfgcolor[] = "#bbbbbb"; -static char selfgcolor[] = "#222222"; -static char selbordercolor[] = "#555555"; -static char selbgcolor[] = "#DB940A"; -static char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, - [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, -}; - -/* tagging */ -static const char *tags[] = { "[one]", "[two]", "[three]", "[four]", "[five]", "[six]", "[seven]", "[eight]", "[nine]" }; - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { NULL, NULL, NULL, 0, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { - /* symbol arrange function */ - {"[]=", tile}, /* first entry is default */ - {"<#>", NULL}, /* no layout function means floating behavior */ - {"<@>", monocle}, -}; - -static const char *ranger[] = { "st", "-e", "ranger", NULL }; -static const char *firemenu[] = { "firemenu", NULL }; - -#include -//different commands per OS -#ifdef __linux__ - #define VOL_UP "pamixer --allow-boost -i 10; kill -44 $(pidof dwmblocks)" - #define XK_UP "pamixer --allow-boost -i 5; kill -44 $(pidof dwmblocks)" - #define VOL_DOWN "pamixer --allow-boost -d 10; kill -44 $(pidof dwmblocks)" - #define XK_DOWN "pamixer --allow-boost -d 5; kill -44 $(pidof dwmblocks)" - #define VOL_MUTE "pamixer -t; kill -44 $(pidof dwmblocks)" - #define VOL_KILL "kill -44 $(pidof dwmblocks)" -#elif __OpenBSD__ - #define VOL_UP "sndioctl output.level=+0.10; pkill -SIGUSR1 dwmblocks" - #define XK_UP "sndioctl output.level=+0.05; pkill -SIGUSR1 dwmblocks" - #define VOL_DOWN "sndioctl output.level=-0.10; pkill -SIGUSR1 dwmblocks" - #define XK_DOWN "sndioctl output.level=-0.05; pkill -SIGUSR1 dwmblocks" - #define VOL_MUTE "sndioctl output.mute=!; pkill -SIGUSR1 dwmblocks" - #define VOL_KILL "pkill -SIGUSR1 dwmblocks" -#elif __FreeBSD__ - #define VOL_UP "sndioctl output.level=+0.10" - #define XK_UP "sndioctl output.level=+0.05" - #define VOL_DOWN "sndioctl output.level=-0.10" - #define XK_DOWN "sndioctl output.level=-0.05" - #define VOL_MUTE "sndioctl output.level=-1" - #define VOL_KILL "pkill -SIGUSR2 dwmblocks" -#endif - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", "#222222", "-nf", "#bbbbbb", "-sb", "#DB940A", "-sf", "#222222", NULL }; -static const char *termcmd[] = {"zsh", "-c", "st -e zsh & walrs -R -q ",NULL}; - -#include "movestack.c" -static Key keys[] = { - /*modifierkey function argument */ - { Mod4Mask|ShiftMask, XK_r, spawn, {.v = firemenu } }, - { MODKEY, XK_f, spawn, {.v = ranger } }, - { MODKEY, XK_r, spawn, {.v = dmenucmd } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY|ControlMask, XK_n, focusstack, {.i = +1 } }, - { MODKEY|ControlMask, XK_p, focusstack, {.i = -1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_F5, xrdb, {.v = NULL } }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_space, setlayout, {0} }, - - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY, XK_b, spawn, SHCMD("floorp") }, - { MODKEY, XK_m, togglebar, {0} }, - { MODKEY, XK_o, incnmaster, {.i = +1 } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_KP_Enter, spawn, {.v = termcmd } }, - { MODKEY, XK_grave, spawn, {.v = termcmd } }, -// { MODKEY|ShiftMask, XK_o, incnmaster {.i = -1 } }, - { MODKEY, XK_s, killclient, {0} }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY|ControlMask|ShiftMask, XK_n, movestack, {.i = +1 } }, - { MODKEY|ControlMask|ShiftMask, XK_p, movestack, {.i = -1 } }, - - //volume control - { Mod1Mask, XK_equal, spawn, SHCMD(VOL_UP) }, - { Mod1Mask, XK_minus, spawn, SHCMD(VOL_DOWN) }, - { Mod1Mask, XK_minus, spawn, SHCMD(VOL_DOWN) }, - { 0, XF86XK_AudioMute, spawn, SHCMD(VOL_MUTE) }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD(XK_UP) }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD(XK_DOWN) }, - //lock - { MODKEY|ShiftMask, XK_l, spawn, SHCMD("slock") }, - { 0, XK_Print, spawn, SHCMD("flameshot gui -r | xclip -selection clipboard -t image/png && notify-send 'Screenshot taken!'") }, -}; - - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static const Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; - diff --git a/suckless/dwm/config.h~ b/suckless/dwm/config.h~ deleted file mode 100644 index 6af2dd0..0000000 --- a/suckless/dwm/config.h~ +++ /dev/null @@ -1,165 +0,0 @@ - -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx = 2.5; /* border pixel of windows */ -static const unsigned int gappx = 14; /* gaps between windows */ -static const unsigned int snap = 3; /* snap pixel */ -static const int user_bh = 12; /* 2 is the default spacing around the bar's font */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int vertpad = 10; /* vertical padding of bar */ -static const int sidepad = 400; /* horizontal padding of bar */ -static const char *fonts[] = {"CaskaydiaMonoNerdFont-Bold:size=9.2"}; -static const char dmenufont[] = "CaskaydiaMonoNerdFont-Bold:size=10.6"; -static char normbgcolor[] = "#222222"; -static char normbordercolor[] = "#444444"; -static char normfgcolor[] = "#bbbbbb"; -static char selfgcolor[] = "#222222"; -static char selbordercolor[] = "#555555"; -static char selbgcolor[] = "#DB940A"; -static char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, - [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, -}; - -/* tagging */ -static const char *tags[] = { "[one]", "[two]", "[three]", "[four]", "[five]", "[six]", "[seven]", "[eight]", "[nine]" }; - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { NULL, NULL, NULL, 0, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { - /* symbol arrange function */ - {"[]=", tile}, /* first entry is default */ - {"<#>", NULL}, /* no layout function means floating behavior */ - {"<@>", monocle}, -}; - -static const char *ranger[] = { "st", "-e", "ranger", NULL }; -static const char *firemenu[] = { "firemenu", NULL }; - -#include -//different commands per OS -#ifdef __linux__ - #define VOL_UP "pamixer --allow-boost -i 10; kill -44 $(pidof dwmblocks)" - #define XK_UP "pamixer --allow-boost -i 5; kill -44 $(pidof dwmblocks)" - #define VOL_DOWN "pamixer --allow-boost -d 10; kill -44 $(pidof dwmblocks)" - #define XK_DOWN "pamixer --allow-boost -d 5; kill -44 $(pidof dwmblocks)" - #define VOL_MUTE "pamixer -t; kill -44 $(pidof dwmblocks)" - #define VOL_KILL "kill -44 $(pidof dwmblocks)" -#elif __OpenBSD__ - #define VOL_UP "sndioctl output.level=+0.10; pkill -SIGUSR1 dwmblocks" - #define XK_UP "sndioctl output.level=+0.05; pkill -SIGUSR1 dwmblocks" - #define VOL_DOWN "sndioctl output.level=-0.10; pkill -SIGUSR1 dwmblocks" - #define XK_DOWN "sndioctl output.level=-0.05; pkill -SIGUSR1 dwmblocks" - #define VOL_MUTE "sndioctl output.mute=!; pkill -SIGUSR1 dwmblocks" - #define VOL_KILL "pkill -SIGUSR1 dwmblocks" -#elif __FreeBSD__ - #define VOL_UP "sndioctl output.level=+0.10" - #define XK_UP "sndioctl output.level=+0.05" - #define VOL_DOWN "sndioctl output.level=-0.10" - #define XK_DOWN "sndioctl output.level=-0.05" - #define VOL_MUTE "sndioctl output.level=-1" - #define VOL_KILL "pkill -SIGUSR2 dwmblocks" -#endif - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = {"zsh", "-c", "st -e zsh & walrs -R -q ",NULL}; - -#include "movestack.c" -static Key keys[] = { - /*modifierkey function argument */ - { Mod4Mask|ShiftMask, XK_r, spawn, {.v = firemenu } }, - { MODKEY, XK_f, spawn, {.v = ranger } }, - { MODKEY, XK_r, spawn, {.v = dmenucmd } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY|ControlMask, XK_n, focusstack, {.i = +1 } }, - { MODKEY|ControlMask, XK_p, focusstack, {.i = -1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_F5, xrdb, {.v = NULL } }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_space, setlayout, {0} }, - - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY, XK_b, spawn, SHCMD("mullvad-browser") }, - { MODKEY, XK_m, togglebar, {0} }, - { MODKEY, XK_o, incnmaster, {.i = +1 } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_KP_Enter, spawn, {.v = termcmd } }, - { MODKEY, XK_grave, spawn, {.v = termcmd } }, -// { MODKEY|ShiftMask, XK_o, incnmaster {.i = -1 } }, - { MODKEY, XK_s, killclient, {0} }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY|ControlMask|ShiftMask, XK_n, movestack, {.i = +1 } }, - { MODKEY|ControlMask|ShiftMask, XK_p, movestack, {.i = -1 } }, - - //volume control - { Mod1Mask, XK_equal, spawn, SHCMD(VOL_UP) }, - { Mod1Mask, XK_minus, spawn, SHCMD(VOL_DOWN) }, - { Mod1Mask, XK_minus, spawn, SHCMD(VOL_DOWN) }, - { 0, XF86XK_AudioMute, spawn, SHCMD(VOL_MUTE) }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD(XK_UP) }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD(XK_DOWN) }, - //lock - { MODKEY|ShiftMask, XK_l, spawn, SHCMD("slock") }, - { 0, XK_Print, spawn, SHCMD("flameshot gui -r | xclip -selection clipboard -t image/png && notify-send 'Screenshot taken!'") }, -}; - - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static const Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; - diff --git a/suckless/dwm/config.mk b/suckless/dwm/config.mk deleted file mode 100644 index 8efca9a..0000000 --- a/suckless/dwm/config.mk +++ /dev/null @@ -1,39 +0,0 @@ -# dwm version -VERSION = 6.5 - -# Customize below to fit your system - -# 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 -#MANPREFIX = ${PREFIX}/man - -# 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=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# Solaris -#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/suckless/dwm/configure b/suckless/dwm/configure deleted file mode 100644 index 69e51e6..0000000 --- a/suckless/dwm/configure +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -#OS=$(printf 'Linux\nOpenBSD\nFreeBSD\nSolaris' | fzf --layout=reverse --height 40%) -OS=$(uname) - -case $OS in - Linux) cp -f mkconfig/config.mk.linux config.mk ;; - OpenBSD) cp -f mkconfig/config.mk.openbsd config.mk ;; - FreeBSD) cp -f mkconfig/config.mk.freebsd config.mk ;; - Solaris) cp -f mkconfig/config.mk.solaris config.mk ;; -esac - -#sed -i 's/##/#/g' config.mk -#sed -i '14 s/^/#/' config.mk -#sed -i '15 s/^/#/' config.mk -#sed -i '25 s/^/#/' config.mk -#sed -i '27 s/^/#/' config.mk -#sed -i '29 s/^/#/' config.mk -#sed -i '65 s/^/#/' config.mk -#sed -i '66 s/^/#/' config.mk -#sed -i 's/##/#/g' config.mk -# -#if [ "$OS" = "Linux" ]; then -# true -#else if [ "$OS" = "OpenBSD" ]; then -# sed -i '27 s/.//' config.mk -# sed -i '29 s/.//' config.mk -#else if [ "$OS" = "FreeBSD" ]; then -# sed -i '14 s/.//' config.mk -# sed -i '15 s/.//' config.mk -# sed -i '25 s/.//' config.mk -#else if [ "$OS" = "Solaris" ]; then -# sed -i '65 s/.//' config.mk -# sed -i '66 s/.//' config.mk -#fi -#fi -#fi -#fi -# -#sed -i 's/##/#/g' config.mk diff --git a/suckless/dwm/drw.c b/suckless/dwm/drw.c deleted file mode 100644 index 6be5dee..0000000 --- a/suckless/dwm/drw.c +++ /dev/null @@ -1,448 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD - -static int -utf8decode(const char *s_in, long *u, int *err) -{ - static const unsigned char lens[] = { - /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ - /* 110XX */ 2, 2, 2, 2, - /* 1110X */ 3, 3, - /* 11110 */ 4, - /* 11111 */ 0, /* invalid */ - }; - static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; - static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; - - const unsigned char *s = (const unsigned char *)s_in; - int len = lens[*s >> 3]; - *u = UTF_INVALID; - *err = 1; - if (len == 0) - return 1; - - long cp = s[0] & leading_mask[len - 1]; - for (int i = 1; i < len; ++i) { - if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) - return i; - cp = (cp << 6) | (s[i] & 0x3F); - } - /* out of range, surrogate, overlong encoding */ - if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) - return len; - - *err = 0; - *u = cp; - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, 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) -{ - int ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0, overflow = 0; - /* keep track of a couple codepoints for which we have no match. */ - static unsigned int nomatches[128], ellipsis_width, invalid_width; - static const char invalid[] = "�"; - - if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) - return 0; - - if (!render) { - w = invert ? invert : ~invert; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - if (w < lpad) - return x + w; - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); - if (!invalid_width && render) - invalid_width = drw_fontset_getwidth(drw, invalid); - while (1) { - ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); - if (ew + ellipsis_width <= w) { - /* keep track where the ellipsis still fits */ - ellipsis_x = x + ew; - ellipsis_w = w - ew; - ellipsis_len = utf8strlen; - } - - if (ew + tmpw > w) { - overflow = 1; - /* called from drw_fontset_getwidth_clamp(): - * it wants the width AFTER the overflow - */ - if (!render) - x += tmpw; - else - utf8strlen = ellipsis_len; - } else if (curfont == usedfont) { - text += utf8charlen; - utf8strlen += utf8err ? 0 : utf8charlen; - ew += utf8err ? 0 : tmpw; - } else { - nextfont = curfont; - } - break; - } - } - - if (overflow || !charexists || nextfont || utf8err) - break; - else - charexists = 0; - } - - if (utf8strlen) { - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); - } - x += ew; - w -= ew; - } - if (utf8err && (!render || invalid_width < w)) { - if (render) - drw_text(drw, x, y, w, h, 0, invalid, invert); - x += invalid_width; - w -= invalid_width; - } - if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - - if (!*text || overflow) { - 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; - - hash = (unsigned int)utf8codepoint; - hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; - hash = ((hash >> 15) ^ hash) * 0xD35A2D97; - h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); - h1 = (hash >> 17) % LENGTH(nomatches); - /* avoid expensive XftFontMatch call when we know we won't find a match */ - if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) - goto no_match; - - 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); - - 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); - nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; -no_match: - 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); -} - -unsigned int -drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) -{ - unsigned int tmp = 0; - if (drw && drw->fonts && text && n) - tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); - return MIN(n, tmp); -} - -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/dwm/drw.h b/suckless/dwm/drw.h deleted file mode 100644 index bdbf950..0000000 --- a/suckless/dwm/drw.h +++ /dev/null @@ -1,58 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg, ColBorder }; /* 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); -unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); -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, 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/dwm/drw.o b/suckless/dwm/drw.o deleted file mode 100644 index 69dbfa9..0000000 Binary files a/suckless/dwm/drw.o and /dev/null differ diff --git a/suckless/dwm/dwm b/suckless/dwm/dwm deleted file mode 100755 index ee9c011..0000000 Binary files a/suckless/dwm/dwm and /dev/null differ diff --git a/suckless/dwm/dwm.1 b/suckless/dwm/dwm.1 deleted file mode 100644 index 7b6cadb..0000000 --- a/suckless/dwm/dwm.1 +++ /dev/null @@ -1,186 +0,0 @@ -.TH DWM 1 dwm\-VERSION -.SH NAME -dwm \- dynamic window manager -.SH SYNOPSIS -.B dwm -.RB [ \-v ] -.SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. -.P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. -.P -Windows are grouped by tags. Each window can be tagged with one or multiple -tags. Selecting certain tags displays all windows with these tags. -.P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. -.P -dwm draws a small border around windows to indicate the focus state. -.SH OPTIONS -.TP -.B \-v -prints version information to stderr, then exits. -.SH USAGE -.SS Status bar -.TP -.B X root window name -is read and displayed in the status text area. It can be set with the -.BR xsetroot (1) -command. -.TP -.B Button1 -click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. -.TP -.B Button3 -click on a tag label adds/removes all windows with that tag to/from the view. -.TP -.B Mod1\-Button1 -click on a tag label applies that tag to the focused window. -.TP -.B Mod1\-Button3 -click on a tag label adds/removes that tag to/from the focused window. -.SS Keyboard commands -.TP -.B Mod1\-Shift\-Return -Start -.BR st(1). -.TP -.B Mod1\-p -Spawn -.BR dmenu(1) -for launching other programs. -.TP -.B Mod1\-, -Focus previous screen, if any. -.TP -.B Mod1\-. -Focus next screen, if any. -.TP -.B Mod1\-Shift\-, -Send focused window to previous screen, if any. -.TP -.B Mod1\-Shift\-. -Send focused window to next screen, if any. -.TP -.B Mod1\-b -Toggles bar on and off. -.TP -.B Mod1\-t -Sets tiled layout. -.TP -.B Mod1\-f -Sets floating layout. -.TP -.B Mod1\-m -Sets monocle layout. -.TP -.B Mod1\-space -Toggles between current and previous layout. -.TP -.B Mod1\-j -Focus next window. -.TP -.B Mod1\-k -Focus previous window. -.TP -.B Mod1\-i -Increase number of windows in master area. -.TP -.B Mod1\-d -Decrease number of windows in master area. -.TP -.B Mod1\-l -Increase master area size. -.TP -.B Mod1\-h -Decrease master area size. -.TP -.B Mod1\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod1\-Shift\-c -Close focused window. -.TP -.B Mod1\-Shift\-space -Toggle focused window between tiled and floating state. -.TP -.B Mod1\-Tab -Toggles to the previously selected tags. -.TP -.B Mod1\-Shift\-[1..n] -Apply nth tag to focused window. -.TP -.B Mod1\-Shift\-0 -Apply all tags to focused window. -.TP -.B Mod1\-Control\-Shift\-[1..n] -Add/remove nth tag to/from focused window. -.TP -.B Mod1\-[1..n] -View all windows with nth tag. -.TP -.B Mod1\-0 -View all windows with any tag. -.TP -.B Mod1\-Control\-[1..n] -Add/remove all windows with nth tag to/from the view. -.TP -.B Mod1\-Shift\-q -Quit dwm. -.TP -.B Mod1\-Control\-Shift\-q -Restart dwm. -.SS Mouse commands -.TP -.B Mod1\-Button1 -Move focused window while dragging. Tiled windows will be toggled to the floating state. -.TP -.B Mod1\-Button2 -Toggles focused window between floating and tiled state. -.TP -.B Mod1\-Button3 -Resize focused window while dragging. Tiled windows will be toggled to the floating state. -.SH CUSTOMIZATION -dwm is customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH SIGNALS -.TP -.B SIGHUP - 1 -Restart the dwm process. -.TP -.B SIGTERM - 15 -Cleanly terminate the dwm process. -.SH SEE ALSO -.BR dmenu (1), -.BR st (1) -.SH ISSUES -Java applications which use the XToolkit/XAWT backend may draw grey windows -only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early -JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds -are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the -environment variable -.BR AWT_TOOLKIT=MToolkit -(to use the older Motif backend instead) or running -.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D -or -.B wmname LG3D -(to pretend that a non-reparenting window manager is running that the -XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable -.BR _JAVA_AWT_WM_NONREPARENTING=1 . -.SH BUGS -Send all bug reports with a patch to hackers@suckless.org. diff --git a/suckless/dwm/dwm.c b/suckless/dwm/dwm.c deleted file mode 100644 index 3c2c1b6..0000000 --- a/suckless/dwm/dwm.c +++ /dev/null @@ -1,2302 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ - if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ - int i = 1; \ - for (; i <= 6; i++) { \ - if (value.addr[i] < 48) break; \ - if (value.addr[i] > 57 && value.addr[i] < 65) break; \ - if (value.addr[i] > 70 && value.addr[i] < 97) break; \ - if (value.addr[i] > 102) break; \ - } \ - if (i == 7) { \ - strncpy(V, value.addr, 7); \ - V[7] = '\0'; \ - } \ - } \ - } - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, - ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachaside(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Atom getatomprop(Client *c, Atom prop); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void loadxrdb(void); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttagged(Client *c); -static Client *nexttiled(Client *c); -static void pop(Client *c); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void run(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setgaps(const Arg *arg); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void updatewindowtype(Client *c); -static void updatewmhints(Client *c); -static void view(const Arg *arg); -static void warp(const Client *c); -static Client *wintoclient(Window w); -static Monitor *wintomon(Window w); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xrdb(const Arg *arg); -static void zoom(const Arg *arg); -static void sighup(int unused); -static void sigterm(int unused); - - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh; /* bar height */ -static int lrpad; /* sum of left and right padding for text */ -static int vp; /* vertical padding for bar */ -static int sp; /* side padding for bar */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int restart = 0; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - if (!c->hintsvalid) - updatesizehints(c); - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachaside(Client *c) { - Client *at = nexttagged(c); - if(!at) { - attach(c); - return; - } - c->next = at->next; - at->next = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; - else - click = ClkStatusText; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, tw = 0; - unsigned int i, occ = 0, urg = 0; - Client *c; - - if (!m->showbar) - return; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon || 1) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j, k; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - int start, end, skip; - KeySym *syms; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XDisplayKeycodes(dpy, &start, &end); - syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); - if (!syms) - return; - for (k = start; k <= end; k++) - for (i = 0; i < LENGTH(keys); i++) - /* skip modifier codes, we do that ourselves */ - if (keys[i].keysym == syms[(k - start) * skip]) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, k, - keys[i].mod | modifiers[j], - root, True, - GrabModeAsync, GrabModeAsync); - XFree(syms); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -loadxrdb() -{ - Display *display; - char * resm; - XrmDatabase xrdb; - char *type; - XrmValue value; - - display = XOpenDisplay(NULL); - - if (display != NULL) { - resm = XResourceManagerString(display); - - if (resm != NULL) { - xrdb = XrmGetStringDatabase(resm); - - if (xrdb != NULL) { - XRDB_LOAD_COLOR("dwm.color2", normbordercolor); - XRDB_LOAD_COLOR("dwm.background", normbgcolor); - XRDB_LOAD_COLOR("dwm.color7", normfgcolor); - XRDB_LOAD_COLOR("dwm.color6", selbordercolor); - XRDB_LOAD_COLOR("dwm.color11", selbgcolor); - XRDB_LOAD_COLOR("dwm.color15", selfgcolor); - } - } - } - - XCloseDisplay(display); -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) - c->x = c->mon->wx + c->mon->ww - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) - c->y = c->mon->wy + c->mon->wh - HEIGHT(c); - c->x = MAX(c->x, c->mon->wx); - c->y = MAX(c->y, c->mon->wy); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, ""); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttagged(Client *c) { - Client *walked = c->mon->clients; - for(; - walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); - walked = walked->next - ); - return walked; -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - c->hintsvalid = 0; - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) - updatetitle(c); - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - if(arg->i) restart = 1; - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int x, y, ocw, och, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocw = c->w; - och = c->h; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - if(!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ocw + (ev.xmotion.x - x), 1); - nh = MAX(och + (ev.xmotion.y - y), 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) - warp(m->sel); - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - struct sigaction sa; - - /* do not transform children into zombies when they terminate */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - - /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); - - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + user_bh; - - sp = sidepad; - vp = (topbar == 1) ? vertpad : - vertpad; - updategeom(); - - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - -void -spawn(const Arg *arg) -{ - struct sigaction sa; - - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww - m->gappx; - for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; - resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); - if (my + HEIGHT(c) + m->gappx < m->wh) - my += HEIGHT(c) + m->gappx; - } else { - h = (m->wh - ty) / (n - i) - m->gappx; - resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); - if (ty + HEIGHT(c) + m->gappx < m->wh) - ty += HEIGHT(c) + m->gappx; - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixmap = ParentRelative, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh = m->wh - vertpad - bh; - m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; - m->wy = m->topbar ? m->wy + bh + vp : m->wy; - } else - m->by = -bh - vp; -} - -void -updateclientlist(void) -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - - /* new monitors if nn > n */ - for (i = n; i < nn; i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - /* removed monitors if n > nn */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attachaside(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - c->hintsvalid = 1; -} - -void -updatestatus(void) -{ - Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - for(m = mons; m; m = m->next) - drawbar(m); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -void -warp(const Client *c) -{ - int x, y; - - if (!c) { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); - return; - } - - if (!getrootptr(&x, &y) || - (x > c->x - c->bw && - y > c->y - c->bw && - x < c->x + c->w + c->bw*2 && - y < c->y + c->h + c->bw*2) || - (y > c->mon->by && y < c->mon->by + bh) || - (c->mon->topbar && !y)) - return; - - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xrdb(const Arg *arg) -{ - loadxrdb(); - int i; - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - focus(NULL); - arrange(NULL); -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - XrmInitialize(); - loadxrdb(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/suckless/dwm/dwm.c.orig b/suckless/dwm/dwm.c.orig deleted file mode 100644 index 7fd5c88..0000000 --- a/suckless/dwm/dwm.c.orig +++ /dev/null @@ -1,2278 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ - if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ - int i = 1; \ - for (; i <= 6; i++) { \ - if (value.addr[i] < 48) break; \ - if (value.addr[i] > 57 && value.addr[i] < 65) break; \ - if (value.addr[i] > 70 && value.addr[i] < 97) break; \ - if (value.addr[i] > 102) break; \ - } \ - if (i == 7) { \ - strncpy(V, value.addr, 7); \ - V[7] = '\0'; \ - } \ - } \ - } - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, - ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Atom getatomprop(Client *c, Atom prop); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void loadxrdb(void); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttiled(Client *c); -static void pop(Client *c); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void run(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setgaps(const Arg *arg); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void updatewindowtype(Client *c); -static void updatewmhints(Client *c); -static void view(const Arg *arg); -static void warp(const Client *c); -static Client *wintoclient(Window w); -static Monitor *wintomon(Window w); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xrdb(const Arg *arg); -static void zoom(const Arg *arg); -static void sighup(int unused); -static void sigterm(int unused); - - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh; /* bar height */ -static int lrpad; /* sum of left and right padding for text */ -static int vp; /* vertical padding for bar */ -static int sp; /* side padding for bar */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int restart = 0; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - if (!c->hintsvalid) - updatesizehints(c); - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; - else - click = ClkStatusText; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, tw = 0; - unsigned int i, occ = 0, urg = 0; - Client *c; - - if (!m->showbar) - return; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon || 1) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j, k; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - int start, end, skip; - KeySym *syms; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XDisplayKeycodes(dpy, &start, &end); - syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); - if (!syms) - return; - for (k = start; k <= end; k++) - for (i = 0; i < LENGTH(keys); i++) - /* skip modifier codes, we do that ourselves */ - if (keys[i].keysym == syms[(k - start) * skip]) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, k, - keys[i].mod | modifiers[j], - root, True, - GrabModeAsync, GrabModeAsync); - XFree(syms); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -loadxrdb() -{ - Display *display; - char * resm; - XrmDatabase xrdb; - char *type; - XrmValue value; - - display = XOpenDisplay(NULL); - - if (display != NULL) { - resm = XResourceManagerString(display); - - if (resm != NULL) { - xrdb = XrmGetStringDatabase(resm); - - if (xrdb != NULL) { - XRDB_LOAD_COLOR("dwm.color2", normbordercolor); - XRDB_LOAD_COLOR("dwm.background", normbgcolor); - XRDB_LOAD_COLOR("dwm.color7", normfgcolor); - XRDB_LOAD_COLOR("dwm.color6", selbordercolor); - XRDB_LOAD_COLOR("dwm.color11", selbgcolor); - XRDB_LOAD_COLOR("dwm.color15", selfgcolor); - } - } - } - - XCloseDisplay(display); -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) - c->x = c->mon->wx + c->mon->ww - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) - c->y = c->mon->wy + c->mon->wh - HEIGHT(c); - c->x = MAX(c->x, c->mon->wx); - c->y = MAX(c->y, c->mon->wy); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attach(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, ""); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - c->hintsvalid = 0; - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) - updatetitle(c); - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - if(arg->i) restart = 1; - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int x, y, ocw, och, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocw = c->w; - och = c->h; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - if(!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ocw + (ev.xmotion.x - x), 1); - nh = MAX(och + (ev.xmotion.y - y), 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) - warp(m->sel); - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attach(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - struct sigaction sa; - - /* do not transform children into zombies when they terminate */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - - /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); - - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + user_bh; - - sp = sidepad; - vp = (topbar == 1) ? vertpad : - vertpad; - updategeom(); - - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - -void -spawn(const Arg *arg) -{ - struct sigaction sa; - - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww - m->gappx; - for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; - resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); - if (my + HEIGHT(c) + m->gappx < m->wh) - my += HEIGHT(c) + m->gappx; - } else { - h = (m->wh - ty) / (n - i) - m->gappx; - resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); - if (ty + HEIGHT(c) + m->gappx < m->wh) - ty += HEIGHT(c) + m->gappx; - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixmap = ParentRelative, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh = m->wh - vertpad - bh; - m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; - m->wy = m->topbar ? m->wy + bh + vp : m->wy; - } else - m->by = -bh - vp; -} - -void -updateclientlist(void) -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - - /* new monitors if nn > n */ - for (i = n; i < nn; i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - /* removed monitors if n > nn */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - c->hintsvalid = 1; -} - -void -updatestatus(void) -{ - Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - for(m = mons; m; m = m->next) - drawbar(m); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -void -warp(const Client *c) -{ - int x, y; - - if (!c) { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); - return; - } - - if (!getrootptr(&x, &y) || - (x > c->x - c->bw && - y > c->y - c->bw && - x < c->x + c->w + c->bw*2 && - y < c->y + c->h + c->bw*2) || - (y > c->mon->by && y < c->mon->by + bh) || - (c->mon->topbar && !y)) - return; - - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xrdb(const Arg *arg) -{ - loadxrdb(); - int i; - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - focus(NULL); - arrange(NULL); -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - XrmInitialize(); - loadxrdb(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/suckless/dwm/dwm.c.rej b/suckless/dwm/dwm.c.rej deleted file mode 100644 index a9d5891..0000000 --- a/suckless/dwm/dwm.c.rej +++ /dev/null @@ -1,20 +0,0 @@ ---- dwm.c -+++ dwm.c -@@ -1461,7 +1485,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1914,7 +1938,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachaside(c); - attachstack(c); - } - if (m == selmon) diff --git a/suckless/dwm/dwm.o b/suckless/dwm/dwm.o deleted file mode 100644 index 796d8ce..0000000 Binary files a/suckless/dwm/dwm.o and /dev/null differ diff --git a/suckless/dwm/dwm.png b/suckless/dwm/dwm.png deleted file mode 100644 index b1f9ba7..0000000 Binary files a/suckless/dwm/dwm.png and /dev/null differ diff --git a/suckless/dwm/mkconfig/config.mk.freebsd b/suckless/dwm/mkconfig/config.mk.freebsd deleted file mode 100644 index e3fb9ab..0000000 --- a/suckless/dwm/mkconfig/config.mk.freebsd +++ /dev/null @@ -1,59 +0,0 @@ -# dwm version -VERSION = 6.3 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -X11INC = /usr/local/include -X11LIB = /usr/local/lib - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -FREETYPEINC = /usr/local/include/freetype2 - -# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -XRENDER = -lXrender - -# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH -#MPDCLIENT = -lmpdclient - -# Uncomment for the pango patch / BAR_PANGO_PATCH -#PANGOINC = `pkg-config --cflags xft pango pangoxft` -#PANGOLIB = `pkg-config --libs xft pango pangoxft` - -# Uncomment for the ipc patch / IPC_PATCH -#YAJLLIBS = -lyajl -#YAJLINC = -I/usr/include/yajl - -# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH -#XEXTLIB = -lXext - -# Uncomment this for the swallow patch / SWALLOW_PATCH -XCBLIBS = -lX11-xcb -lxcb -lxcb-res - -# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH -#IMLIB2LIBS = -lImlib2 - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/suckless/dwm/mkconfig/config.mk.linux b/suckless/dwm/mkconfig/config.mk.linux deleted file mode 100644 index 7b3b027..0000000 --- a/suckless/dwm/mkconfig/config.mk.linux +++ /dev/null @@ -1,55 +0,0 @@ -# dwm version -VERSION = 6.3 - -# Customize below to fit your system - -# 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 - -# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -XRENDER = -lXrender - -# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH -#MPDCLIENT = -lmpdclient - -# Uncomment for the pango patch / BAR_PANGO_PATCH -#PANGOINC = `pkg-config --cflags xft pango pangoxft` -#PANGOLIB = `pkg-config --libs xft pango pangoxft` - -# Uncomment for the ipc patch / IPC_PATCH -#YAJLLIBS = -lyajl -#YAJLINC = -I/usr/include/yajl - -# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH -#XEXTLIB = -lXext - -# Uncomment this for the swallow patch / SWALLOW_PATCH -XCBLIBS = -lX11-xcb -lxcb -lxcb-res - -# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH -#IMLIB2LIBS = -lImlib2 - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/suckless/dwm/mkconfig/config.mk.openbsd b/suckless/dwm/mkconfig/config.mk.openbsd deleted file mode 100644 index 6651dbb..0000000 --- a/suckless/dwm/mkconfig/config.mk.openbsd +++ /dev/null @@ -1,57 +0,0 @@ -# dwm version -VERSION = 6.3 - -# Customize below to fit your system - -# 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 -FREETYPEINC = ${X11INC}/freetype2 -KVMLIB = -lkvm - -# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -XRENDER = -lXrender - -# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH -#MPDCLIENT = -lmpdclient - -# Uncomment for the pango patch / BAR_PANGO_PATCH -#PANGOINC = `pkg-config --cflags xft pango pangoxft` -#PANGOLIB = `pkg-config --libs xft pango pangoxft` - -# Uncomment for the ipc patch / IPC_PATCH -#YAJLLIBS = -lyajl -#YAJLINC = -I/usr/include/yajl - -# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH -#XEXTLIB = -lXext - -# Uncomment this for the swallow patch / SWALLOW_PATCH -XCBLIBS = -lX11-xcb -lxcb -lxcb-res - -# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH -#IMLIB2LIBS = -lImlib2 - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/suckless/dwm/mkconfig/config.mk.solaris b/suckless/dwm/mkconfig/config.mk.solaris deleted file mode 100644 index 7a6d93f..0000000 --- a/suckless/dwm/mkconfig/config.mk.solaris +++ /dev/null @@ -1,58 +0,0 @@ -# dwm version -VERSION = 6.3 - -# Customize below to fit your system - -# 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 - -# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -XRENDER = -lXrender - -# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH -#MPDCLIENT = -lmpdclient - -# Uncomment for the pango patch / BAR_PANGO_PATCH -#PANGOINC = `pkg-config --cflags xft pango pangoxft` -#PANGOLIB = `pkg-config --libs xft pango pangoxft` - -# Uncomment for the ipc patch / IPC_PATCH -#YAJLLIBS = -lyajl -#YAJLINC = -I/usr/include/yajl - -# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH -#XEXTLIB = -lXext - -# Uncomment this for the swallow patch / SWALLOW_PATCH -XCBLIBS = -lX11-xcb -lxcb -lxcb-res - -# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH -#IMLIB2LIBS = -lImlib2 - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/suckless/dwm/movestack.c b/suckless/dwm/movestack.c deleted file mode 100644 index 520f4ae..0000000 --- a/suckless/dwm/movestack.c +++ /dev/null @@ -1,48 +0,0 @@ -void -movestack(const Arg *arg) { - Client *c = NULL, *p = NULL, *pc = NULL, *i; - - if(arg->i > 0) { - /* find the client after selmon->sel */ - for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - if(!c) - for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - - } - else { - /* find the client before selmon->sel */ - for(i = selmon->clients; i != selmon->sel; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - if(!c) - for(; i; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - } - /* find the client before selmon->sel and c */ - for(i = selmon->clients; i && (!p || !pc); i = i->next) { - if(i->next == selmon->sel) - p = i; - if(i->next == c) - pc = i; - } - - /* swap c and selmon->sel selmon->clients in the selmon->clients list */ - if(c && c != selmon->sel) { - Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; - selmon->sel->next = c->next==selmon->sel?c:c->next; - c->next = temp; - - if(p && p != c) - p->next = c; - if(pc && pc != selmon->sel) - pc->next = selmon->sel; - - if(selmon->sel == selmon->clients) - selmon->clients = c; - else if(c == selmon->clients) - selmon->clients = selmon->sel; - - arrange(selmon); - } -} \ No newline at end of file diff --git a/suckless/dwm/patch/attachx.c b/suckless/dwm/patch/attachx.c deleted file mode 100644 index c683dce..0000000 --- a/suckless/dwm/patch/attachx.c +++ /dev/null @@ -1,20 +0,0 @@ -void -attachx(Client *c) -{ - Client *at; - - - unsigned int n; - for (at = c->mon->clients, n = 0; at; at = at->next) - if (!at->isfloating && ISVISIBLEONTAG(at, c->tags)) - if (++n >= c->mon->nmaster) - break; - - if (at && c->mon->nmaster) { - c->next = at->next; - at->next = c; - return; - } - attach(c); // master (default) -} - diff --git a/suckless/dwm/patch/attachx.h b/suckless/dwm/patch/attachx.h deleted file mode 100644 index e522d27..0000000 --- a/suckless/dwm/patch/attachx.h +++ /dev/null @@ -1,2 +0,0 @@ -static void attachx(Client *c); - diff --git a/suckless/dwm/patch/bar.c b/suckless/dwm/patch/bar.c deleted file mode 100644 index 65e1a69..0000000 --- a/suckless/dwm/patch/bar.c +++ /dev/null @@ -1,39 +0,0 @@ -void -barhover(XEvent *e, Bar *bar) -{ - const BarRule *br; - Monitor *m = bar->mon; - XMotionEvent *ev = &e->xmotion; - BarArg barg = { 0, 0, 0, 0 }; - int r; - - for (r = 0; r < LENGTH(barrules); r++) { - br = &barrules[r]; - if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL) - continue; - if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) - continue; - if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r]) - continue; - - barg.x = ev->x - bar->x[r]; - barg.y = ev->y - bar->borderpx; - barg.w = bar->w[r]; - barg.h = bar->bh - 2 * bar->borderpx; - - br->hoverfunc(bar, &barg, ev); - break; - } -} - -Bar * -wintobar(Window win) -{ - Monitor *m; - Bar *bar; - for (m = mons; m; m = m->next) - for (bar = m->bar; bar; bar = bar->next) - if (bar->win == win) - return bar; - return NULL; -} diff --git a/suckless/dwm/patch/bar.h b/suckless/dwm/patch/bar.h deleted file mode 100644 index 3e006dc..0000000 --- a/suckless/dwm/patch/bar.h +++ /dev/null @@ -1,2 +0,0 @@ -static void barhover(XEvent *e, Bar *bar); -static Bar *wintobar(Window win); diff --git a/suckless/dwm/patch/bar_alpha.c b/suckless/dwm/patch/bar_alpha.c deleted file mode 100644 index 465f6f2..0000000 --- a/suckless/dwm/patch/bar_alpha.c +++ /dev/null @@ -1,43 +0,0 @@ - -static int useargb = 0; -static Visual *visual; -static int depth; -static Colormap cmap; - -void -xinitvisual() -{ - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - for (i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - if (!visual) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } -} - diff --git a/suckless/dwm/patch/bar_alpha.h b/suckless/dwm/patch/bar_alpha.h deleted file mode 100644 index 1c2a012..0000000 --- a/suckless/dwm/patch/bar_alpha.h +++ /dev/null @@ -1,4 +0,0 @@ -#define OPAQUE 0xffU - -static void xinitvisual(); - diff --git a/suckless/dwm/patch/bar_indicators.c b/suckless/dwm/patch/bar_indicators.c deleted file mode 100644 index b003fc8..0000000 --- a/suckless/dwm/patch/bar_indicators.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Indicator properties, you can override these in your config.h if you want. */ -#ifndef TAGSINDICATOR -#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on -#endif -#ifndef TAGSPX -#define TAGSPX 5 // # pixels for tag grid boxes -#endif -#ifndef TAGSROWS -#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3) -#endif - -void -drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type) -{ - int i, boxw, boxs, indn = 0; - if (!(occ & 1 << tag) || type == INDICATOR_NONE) - return; - - boxs = drw->fonts->h / 9; - boxw = drw->fonts->h / 6 + 2; - if (filled == -1) - filled = m == selmon && m->sel && m->sel->tags & 1 << tag; - - switch (type) { - default: - case INDICATOR_TOP_LEFT_SQUARE: - drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert); - break; - case INDICATOR_TOP_LEFT_LARGER_SQUARE: - drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert); - break; - case INDICATOR_TOP_BAR: - drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert); - break; - case INDICATOR_TOP_BAR_SLIM: - drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert); - break; - case INDICATOR_BOTTOM_BAR: - drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert); - break; - case INDICATOR_BOTTOM_BAR_SLIM: - drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert); - break; - case INDICATOR_BOX: - drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert); - break; - case INDICATOR_BOX_WIDER: - drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert); - break; - case INDICATOR_BOX_FULL: - drw_rect(drw, x, y, w - 2, h, 0, invert); - break; - case INDICATOR_CLIENT_DOTS: - for (c = m->clients; c; c = c->next) { - if (c->tags & (1 << tag)) { - drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert); - indn++; - } - if (h <= 1 + (indn * 2)) { - indn = 0; - x += 2; - } - } - break; - case INDICATOR_RIGHT_TAGS: - if (!c) - break; - for (i = 0; i < NUMTAGS; i++) { - drw_rect(drw, - ( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX) - - (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX) - ), - ( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX) - - ((i / (NUMTAGS/TAGSROWS))) - ), - TAGSPX, TAGSPX, (c->tags >> i) & 1, 0 - ); - } - break; - case INDICATOR_PLUS_AND_LARGER_SQUARE: - boxs += 2; - boxw += 2; - /* falls through */ - case INDICATOR_PLUS_AND_SQUARE: - drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert); - /* falls through */ - case INDICATOR_PLUS: - if (!(boxw % 2)) - boxw += 1; - drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // | - drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒ - break; - } -} - -void -drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert) -{ - if (c->isfloating) - drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype); - else - drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype); -} - diff --git a/suckless/dwm/patch/bar_indicators.h b/suckless/dwm/patch/bar_indicators.h deleted file mode 100644 index c66e4f0..0000000 --- a/suckless/dwm/patch/bar_indicators.h +++ /dev/null @@ -1,21 +0,0 @@ -enum { - INDICATOR_NONE, - INDICATOR_TOP_LEFT_SQUARE, - INDICATOR_TOP_LEFT_LARGER_SQUARE, - INDICATOR_TOP_BAR, - INDICATOR_TOP_BAR_SLIM, - INDICATOR_BOTTOM_BAR, - INDICATOR_BOTTOM_BAR_SLIM, - INDICATOR_BOX, - INDICATOR_BOX_WIDER, - INDICATOR_BOX_FULL, - INDICATOR_CLIENT_DOTS, - INDICATOR_RIGHT_TAGS, - INDICATOR_PLUS, - INDICATOR_PLUS_AND_SQUARE, - INDICATOR_PLUS_AND_LARGER_SQUARE, -}; - -static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type); -static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert); - diff --git a/suckless/dwm/patch/bar_ltsymbol.c b/suckless/dwm/patch/bar_ltsymbol.c deleted file mode 100644 index 1fbd1b8..0000000 --- a/suckless/dwm/patch/bar_ltsymbol.c +++ /dev/null @@ -1,18 +0,0 @@ -int -width_ltsymbol(Bar *bar, BarArg *a) -{ - return TEXTW(bar->mon->ltsymbol); -} - -int -draw_ltsymbol(Bar *bar, BarArg *a) -{ - return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False); -} - -int -click_ltsymbol(Bar *bar, Arg *arg, BarArg *a) -{ - return ClkLtSymbol; -} - diff --git a/suckless/dwm/patch/bar_ltsymbol.h b/suckless/dwm/patch/bar_ltsymbol.h deleted file mode 100644 index 4de5720..0000000 --- a/suckless/dwm/patch/bar_ltsymbol.h +++ /dev/null @@ -1,4 +0,0 @@ -static int width_ltsymbol(Bar *bar, BarArg *a); -static int draw_ltsymbol(Bar *bar, BarArg *a); -static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a); - diff --git a/suckless/dwm/patch/bar_status.c b/suckless/dwm/patch/bar_status.c deleted file mode 100644 index 65595e0..0000000 --- a/suckless/dwm/patch/bar_status.c +++ /dev/null @@ -1,20 +0,0 @@ -int -width_status(Bar *bar, BarArg *a) -{ - return TEXTWM(stext); -} - - -int -draw_status(Bar *bar, BarArg *a) -{ - return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True); -} - - -int -click_status(Bar *bar, Arg *arg, BarArg *a) -{ - return ClkStatusText; -} - diff --git a/suckless/dwm/patch/bar_status.h b/suckless/dwm/patch/bar_status.h deleted file mode 100644 index c580597..0000000 --- a/suckless/dwm/patch/bar_status.h +++ /dev/null @@ -1,4 +0,0 @@ -static int width_status(Bar *bar, BarArg *a); -static int draw_status(Bar *bar, BarArg *a); -static int click_status(Bar *bar, Arg *arg, BarArg *a); - diff --git a/suckless/dwm/patch/bar_tagicons.c b/suckless/dwm/patch/bar_tagicons.c deleted file mode 100644 index 57d1629..0000000 --- a/suckless/dwm/patch/bar_tagicons.c +++ /dev/null @@ -1,9 +0,0 @@ -char * -tagicon(Monitor *m, int tag) -{ - int tagindex = tag + NUMTAGS * m->num; - if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) - tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); - return tagicons[DEFAULT_TAGS][tagindex]; -} - diff --git a/suckless/dwm/patch/bar_tagicons.h b/suckless/dwm/patch/bar_tagicons.h deleted file mode 100644 index 16fad2a..0000000 --- a/suckless/dwm/patch/bar_tagicons.h +++ /dev/null @@ -1,8 +0,0 @@ -enum { - DEFAULT_TAGS, - ALTERNATIVE_TAGS, - ALT_TAGS_DECORATION, -}; - -static char * tagicon(Monitor *m, int tag); - diff --git a/suckless/dwm/patch/bar_tags.c b/suckless/dwm/patch/bar_tags.c deleted file mode 100644 index 8aa37b2..0000000 --- a/suckless/dwm/patch/bar_tags.c +++ /dev/null @@ -1,81 +0,0 @@ -int -width_tags(Bar *bar, BarArg *a) -{ - int w, i; - Client *c; - unsigned int occ = 0; - for (c = bar->mon->clients; c; c = c->next) - occ |= c->tags == 255 ? 0 : c->tags; - - for (w = 0, i = 0; i < NUMTAGS; i++) { - if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) - continue; - w += TEXTW(tagicon(bar->mon, i)); - } - return w; -} - -int -draw_tags(Bar *bar, BarArg *a) -{ - int invert; - int w, x = a->x; - unsigned int i, occ = 0, urg = 0; - char *icon; - Client *c; - Monitor *m = bar->mon; - - for (c = m->clients; c; c = c->next) { - occ |= c->tags == 255 ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - for (i = 0; i < NUMTAGS; i++) { - /* do not draw vacant tags */ - if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) - continue; - - icon = tagicon(bar->mon, i); - invert = 0; - w = TEXTW(icon); - drw_setscheme(drw, scheme[ - m->tagset[m->seltags] & 1 << i - ? SchemeTagsSel - : urg & 1 << i - ? SchemeUrg - : SchemeTagsNorm - ]); - drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); - drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); - x += w; - } - - return 1; -} - -int -click_tags(Bar *bar, Arg *arg, BarArg *a) -{ - int i = 0, x = 0; - Client *c; - unsigned int occ = 0; - for (c = bar->mon->clients; c; c = c->next) - occ |= c->tags == 255 ? 0 : c->tags; - - do { - if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) - continue; - x += TEXTW(tagicon(bar->mon, i)); - } while (a->x >= x && ++i < NUMTAGS); - if (i < NUMTAGS) { - arg->ui = 1 << i; - } - return ClkTagBar; -} - -int -hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev) -{ - - return 1; -} diff --git a/suckless/dwm/patch/bar_tags.h b/suckless/dwm/patch/bar_tags.h deleted file mode 100644 index 70040d2..0000000 --- a/suckless/dwm/patch/bar_tags.h +++ /dev/null @@ -1,4 +0,0 @@ -static int width_tags(Bar *bar, BarArg *a); -static int draw_tags(Bar *bar, BarArg *a); -static int click_tags(Bar *bar, Arg *arg, BarArg *a); -static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/suckless/dwm/patch/bar_wintitle.c b/suckless/dwm/patch/bar_wintitle.c deleted file mode 100644 index d086736..0000000 --- a/suckless/dwm/patch/bar_wintitle.c +++ /dev/null @@ -1,48 +0,0 @@ -int -width_wintitle(Bar *bar, BarArg *a) -{ - return a->w; -} - -int -draw_wintitle(Bar *bar, BarArg *a) -{ - int x = a->x + lrpad / 2, w = a->w - lrpad / 2; - Monitor *m = bar->mon; - Client *c = m->sel; - - if (!c) { - drw_setscheme(drw, scheme[SchemeTitleNorm]); - drw_rect(drw, x, a->y, w, a->h, 1, 1); - return 0; - } - - int tpad = lrpad / 2; - int tx = x; - int tw = w; - - drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]); - - if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small - tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); - - XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); - - - tx += tpad; - tw -= lrpad; - - - drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); - - drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); - return 1; -} - -int -click_wintitle(Bar *bar, Arg *arg, BarArg *a) -{ - return ClkWinTitle; -} - diff --git a/suckless/dwm/patch/bar_wintitle.h b/suckless/dwm/patch/bar_wintitle.h deleted file mode 100644 index 7e8cce5..0000000 --- a/suckless/dwm/patch/bar_wintitle.h +++ /dev/null @@ -1,4 +0,0 @@ -static int width_wintitle(Bar *bar, BarArg *a); -static int draw_wintitle(Bar *bar, BarArg *a); -static int click_wintitle(Bar *bar, Arg *arg, BarArg *a); - diff --git a/suckless/dwm/patch/cool_autostart.c b/suckless/dwm/patch/cool_autostart.c deleted file mode 100644 index ffd4ba3..0000000 --- a/suckless/dwm/patch/cool_autostart.c +++ /dev/null @@ -1,29 +0,0 @@ -/* dwm will keep pid's of processes from autostart array and kill them at quit */ -static pid_t *autostart_pids; -static size_t autostart_len; - -/* execute command from autostart array */ -static void -autostart_exec() -{ - const char *const *p; - size_t i = 0; - - /* count entries */ - for (p = autostart; *p; autostart_len++, p++) - while (*++p); - - autostart_pids = malloc(autostart_len * sizeof(pid_t)); - for (p = autostart; *p; i++, p++) { - if ((autostart_pids[i] = fork()) == 0) { - setsid(); - execvp(*p, (char *const *)p); - fprintf(stderr, "dwm: execvp %s\n", *p); - perror(" failed"); - _exit(EXIT_FAILURE); - } - /* skip arguments */ - while (*++p); - } -} - diff --git a/suckless/dwm/patch/cool_autostart.h b/suckless/dwm/patch/cool_autostart.h deleted file mode 100644 index 5534d99..0000000 --- a/suckless/dwm/patch/cool_autostart.h +++ /dev/null @@ -1,2 +0,0 @@ -static void autostart_exec(void); - diff --git a/suckless/dwm/patch/dwm-alpha-20230401-348f655.diff b/suckless/dwm/patch/dwm-alpha-20230401-348f655.diff deleted file mode 100644 index 06d7405..0000000 Binary files a/suckless/dwm/patch/dwm-alpha-20230401-348f655.diff and /dev/null differ diff --git a/suckless/dwm/patch/dwmc b/suckless/dwm/patch/dwmc deleted file mode 100644 index 3880428..0000000 --- a/suckless/dwm/patch/dwmc +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bash - -signal() { - xsetroot -name "fsignal:$*" -} - -case $# in -1) - case $1 in - focusurgent) ;& - mirrorlayout) ;& - mpdcontrol) ;& - pushdown) ;& - pushup) ;& - self_restart) ;& - setlayout) ;& - setcfact) ;& - switchcol) ;& - view) ;& - viewall) ;& - viewtoleft) ;& - viewtoright) ;& - tagtoleft) ;& - tagtoright) ;& - tagandviewtoleft) ;& - tagandviewtoright) ;& - transfer) ;& - transferall) ;& - togglealttag) ;& - togglebar) ;& - togglefloating) ;& - togglefullscreen) ;& - fullscreen) ;& - togglefakefullscreen) ;& - togglesticky) ;& - togglehorizontalmax) ;& - toggleverticalmax) ;& - togglemax) ;& - togglegaps) ;& - defaultgaps) ;& - unfloatvisible) ;& - winview) ;& - xrdb) ;& - zoom) ;& - killclient) ;& - quit) - signal $1 - ;; - *) - echo "Unknown command ($1) or missing one argument." - exit 1 - ;; - esac - ;; -2) - case $1 in - cyclelayout) ;& - explace) ;& - moveplace) ;& - mpdchange) ;& - setkeymode) ;& - switchtag) ;& - togglescratch) ;& - view) - signal $1 ui $2 - ;; - viewex) ;& - toggleviewex) ;& - tagallmon) ;& - tagswapmon) ;& - tagex) ;& - toggletagex) ;& - setborderpx) ;& - setgaps) ;& - setlayoutex) ;& - setlayoutaxisex) ;& - swapfocus) ;& - focusstack) ;& - pushstack) ;& - inplacerotate) ;& - rotatestack) ;& - rotatelayoutaxis) ;& - incnmaster) ;& - incnstack) ;& - incrgaps) ;& - incrigaps) ;& - incrogaps) ;& - incrihgaps) ;& - incrivgaps) ;& - incrohgaps) ;& - incrovgaps) ;& - movestack) ;& - shiftview) ;& - shiftviewclients) ;& - focusmon) ;& - tagmon) - signal $1 i $2 - ;; - setcfact) ;& - setmfact) - signal $1 f $2 - ;; - *) - echo "Unknown command ($1) or too many arguments" - exit 1 - ;; - esac - ;; -5) - case $1 in - setgaps) - # Expects "setgaps oh ov ih iv" where -1 means to keep existing values - [ $2 = -1 ] && oh=128 || oh=$2 - [ $3 = -1 ] && ov=128 || ov=$3 - [ $4 = -1 ] && ih=128 || ih=$4 - [ $5 = -1 ] && iv=128 || iv=$5 - signal $1 i $(((oh << 24) + (ov << 16) + (ih << 8) + iv)) - ;; - *) - echo "Unknown command ($1) or too many arguments" - exit 1 - ;; - esac - ;; -*) - echo "Unknown command ($1) or too many arguments" - exit 1 - ;; -esac - diff --git a/suckless/dwm/patch/dwmc.c b/suckless/dwm/patch/dwmc.c deleted file mode 100644 index a892ff7..0000000 --- a/suckless/dwm/patch/dwmc.c +++ /dev/null @@ -1,85 +0,0 @@ -void -setlayoutex(const Arg *arg) -{ - setlayout(&((Arg) { .v = &layouts[arg->i] })); -} - -void -viewex(const Arg *arg) -{ - view(&((Arg) { .ui = 1 << arg->ui })); -} - -void -viewallex(const Arg *arg) -{ - view(&((Arg){.ui = ~SPTAGMASK})); -} - -void -toggleviewex(const Arg *arg) -{ - toggleview(&((Arg) { .ui = 1 << arg->ui })); -} - -void -tagex(const Arg *arg) -{ - tag(&((Arg) { .ui = 1 << arg->ui })); -} - -void -toggletagex(const Arg *arg) -{ - toggletag(&((Arg) { .ui = 1 << arg->ui })); -} - -void -tagallex(const Arg *arg) -{ - tag(&((Arg){.ui = ~SPTAGMASK})); -} - -int -fake_signal(void) -{ - char fsignal[256]; - char indicator[9] = "fsignal:"; - char str_sig[50]; - char param[16]; - int i, len_str_sig, n, paramn; - size_t len_fsignal, len_indicator = strlen(indicator); - Arg arg; - - // Get root name property - if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { - len_fsignal = strlen(fsignal); - - // Check if this is indeed a fake signal - if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { - paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); - - if (paramn == 1) arg = (Arg) {0}; - else if (paramn > 2) return 1; - else if (strncmp(param, "i", n - len_str_sig) == 0) - sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); - else if (strncmp(param, "ui", n - len_str_sig) == 0) - sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); - else if (strncmp(param, "f", n - len_str_sig) == 0) - sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); - else return 1; - - // Check if a signal was found, and if so handle it - for (i = 0; i < LENGTH(signals); i++) - if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) - signals[i].func(&(arg)); - - // A fake signal was sent - return 1; - } - } - - // No fake signal was sent, so proceed with update - return 0; -} - diff --git a/suckless/dwm/patch/dwmc.h b/suckless/dwm/patch/dwmc.h deleted file mode 100644 index 66e23a9..0000000 --- a/suckless/dwm/patch/dwmc.h +++ /dev/null @@ -1,14 +0,0 @@ -typedef struct { - const char * sig; - void (*func)(const Arg *); -} Signal; - -static void setlayoutex(const Arg *arg); -static void viewex(const Arg *arg); -static void viewallex(const Arg *arg); -static void toggleviewex(const Arg *arg); -static void tagex(const Arg *arg); -static void toggletagex(const Arg *arg); -static void tagallex(const Arg *arg); -static int fake_signal(void); - diff --git a/suckless/dwm/patch/fullscreen.c b/suckless/dwm/patch/fullscreen.c deleted file mode 100644 index 5fb682a..0000000 --- a/suckless/dwm/patch/fullscreen.c +++ /dev/null @@ -1,15 +0,0 @@ -Layout *last_layout; - -void -fullscreen(const Arg *arg) -{ - int monocle_pos = 0; - if (selmon->showbar || last_layout == NULL) { - for (last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); - setlayout(&((Arg) { .v = &layouts[monocle_pos] })); - } else { - setlayout(&((Arg) { .v = last_layout })); - } - togglebar(arg); -} - diff --git a/suckless/dwm/patch/fullscreen.h b/suckless/dwm/patch/fullscreen.h deleted file mode 100644 index 72983e1..0000000 --- a/suckless/dwm/patch/fullscreen.h +++ /dev/null @@ -1,2 +0,0 @@ -static void fullscreen(const Arg *arg); - diff --git a/suckless/dwm/patch/hidevacanttags.diff b/suckless/dwm/patch/hidevacanttags.diff deleted file mode 100644 index 0b02555..0000000 --- a/suckless/dwm/patch/hidevacanttags.diff +++ /dev/null @@ -1,49 +0,0 @@ -:100644 100644 f1d86b2 0000000 M dwm.c - -diff --git a/dwm.c b/dwm.c -index f1d86b2..d41cc14 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -433,9 +433,15 @@ buttonpress(XEvent *e) - } - if (ev->window == selmon->barwin) { - i = x = 0; -- do -+ unsigned int occ = 0; -+ for(c = m->clients; c; c=c->next) -+ occ |= c->tags == TAGMASK ? 0 : c->tags; -+ do { -+ /* Do not reserve space for vacant tags */ -+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - x += TEXTW(tags[i]); -- while (ev->x >= x && ++i < LENGTH(tags)); -+ } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -@@ -715,19 +721,18 @@ drawbar(Monitor *m) - } - - for (c = m->clients; c; c = c->next) { -- occ |= c->tags; -+ occ |= c->tags == TAGMASK ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -+ /* Do not draw vacant tags */ -+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -- if (occ & 1 << i) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, -- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - diff --git a/suckless/dwm/patch/hidevacanttags.diff.orig b/suckless/dwm/patch/hidevacanttags.diff.orig deleted file mode 100644 index 0b02555..0000000 --- a/suckless/dwm/patch/hidevacanttags.diff.orig +++ /dev/null @@ -1,49 +0,0 @@ -:100644 100644 f1d86b2 0000000 M dwm.c - -diff --git a/dwm.c b/dwm.c -index f1d86b2..d41cc14 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -433,9 +433,15 @@ buttonpress(XEvent *e) - } - if (ev->window == selmon->barwin) { - i = x = 0; -- do -+ unsigned int occ = 0; -+ for(c = m->clients; c; c=c->next) -+ occ |= c->tags == TAGMASK ? 0 : c->tags; -+ do { -+ /* Do not reserve space for vacant tags */ -+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - x += TEXTW(tags[i]); -- while (ev->x >= x && ++i < LENGTH(tags)); -+ } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -@@ -715,19 +721,18 @@ drawbar(Monitor *m) - } - - for (c = m->clients; c; c = c->next) { -- occ |= c->tags; -+ occ |= c->tags == TAGMASK ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -+ /* Do not draw vacant tags */ -+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -- if (occ & 1 << i) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, -- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - diff --git a/suckless/dwm/patch/hidevacanttags.diff.rej b/suckless/dwm/patch/hidevacanttags.diff.rej deleted file mode 100644 index a6fdf1d..0000000 --- a/suckless/dwm/patch/hidevacanttags.diff.rej +++ /dev/null @@ -1,44 +0,0 @@ ---- dwm.c -+++ dwm.c -@@ -433,9 +433,15 @@ buttonpress(XEvent *e) - } - if (ev->window == selmon->barwin) { - i = x = 0; -- do -+ unsigned int occ = 0; -+ for(c = m->clients; c; c=c->next) -+ occ |= c->tags == TAGMASK ? 0 : c->tags; -+ do { -+ /* Do not reserve space for vacant tags */ -+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - x += TEXTW(tags[i]); -- while (ev->x >= x && ++i < LENGTH(tags)); -+ } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -@@ -715,19 +721,18 @@ drawbar(Monitor *m) - } - - for (c = m->clients; c; c = c->next) { -- occ |= c->tags; -+ occ |= c->tags == TAGMASK ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -+ /* Do not draw vacant tags */ -+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -- if (occ & 1 << i) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, -- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); diff --git a/suckless/dwm/patch/include.c b/suckless/dwm/patch/include.c deleted file mode 100644 index 7130889..0000000 --- a/suckless/dwm/patch/include.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Bar functionality */ -#include "bar_indicators.c" -#include "bar_tagicons.c" -#include "bar.c" - -#include "bar_alpha.c" -#include "bar_ltsymbol.c" -#include "bar_status.c" -#include "bar_tags.c" -#include "bar_wintitle.c" - -/* Other patches */ -#include "attachx.c" -#include "cool_autostart.c" -#include "dwmc.c" -#include "fullscreen.c" -#include "moveresize.c" -#include "movestack.c" -#include "scratchpad.c" -#include "swallow.c" -#include "togglefullscreen.c" -#include "vanitygaps.c" -#include "xrdb.c" -/* Layouts */ -#include "layout_facts.c" -#include "layout_tile.c" - diff --git a/suckless/dwm/patch/include.h b/suckless/dwm/patch/include.h deleted file mode 100644 index de7c6ec..0000000 --- a/suckless/dwm/patch/include.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Bar functionality */ -#include "bar_indicators.h" -#include "bar_tagicons.h" -#include "bar.h" - -#include "bar_alpha.h" -#include "bar_ltsymbol.h" -#include "bar_status.h" -#include "bar_tags.h" -#include "bar_wintitle.h" - -/* Other patches */ -#include "attachx.h" -#include "cool_autostart.h" -#include "dwmc.h" -#include "fullscreen.h" -#include "moveresize.h" -#include "movestack.h" -#include "scratchpad.h" -#include "swallow.h" -#include "togglefullscreen.h" -#include "vanitygaps.h" -#include "xrdb.h" -/* Layouts */ -#include "layout_tile.h" - diff --git a/suckless/dwm/patch/ipc/IPCClient.h b/suckless/dwm/patch/ipc/IPCClient.h deleted file mode 100644 index ee93030..0000000 --- a/suckless/dwm/patch/ipc/IPCClient.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef IPC_CLIENT_H_ -#define IPC_CLIENT_H_ - -#include -#include -#include - -typedef struct IPCClient IPCClient; -/** - * This structure contains the details of an IPC Client and pointers for a - * linked list - */ -struct IPCClient { - int fd; - int subscriptions; - - char *buffer; - uint32_t buffer_size; - - struct epoll_event event; - IPCClient *next; - IPCClient *prev; -}; - -typedef IPCClient *IPCClientList; - -/** - * Allocate memory for new IPCClient with the specified file descriptor and - * initialize struct. - * - * @param fd File descriptor of IPC client - * - * @return Address to allocated IPCClient struct - */ -IPCClient *ipc_client_new(int fd); - -/** - * Add an IPC Client to the specified list - * - * @param list Address of the list to add the client to - * @param nc Address of the IPCClient - */ -void ipc_list_add_client(IPCClientList *list, IPCClient *nc); - -/** - * Remove an IPCClient from the specified list - * - * @param list Address of the list to remove the client from - * @param c Address of the IPCClient - */ -void ipc_list_remove_client(IPCClientList *list, IPCClient *c); - -/** - * Get an IPCClient from the specified IPCClient list - * - * @param list List to remove the client from - * @param fd File descriptor of the IPCClient - */ -IPCClient *ipc_list_get_client(IPCClientList list, int fd); - -#endif // IPC_CLIENT_H_ - diff --git a/suckless/dwm/patch/ipc/dwm-msg.c b/suckless/dwm/patch/ipc/dwm-msg.c deleted file mode 100644 index ca1e1a4..0000000 --- a/suckless/dwm/patch/ipc/dwm-msg.c +++ /dev/null @@ -1,549 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IPC_MAGIC "DWM-IPC" -// clang-format off -#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' } -// clang-format on -#define IPC_MAGIC_LEN 7 // Not including null char - -#define IPC_EVENT_TAG_CHANGE "tag_change_event" -#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event" -#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event" -#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event" -#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event" -#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event" - -#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) -#define YINT(num) yajl_gen_integer(gen, num) -#define YDOUBLE(num) yajl_gen_double(gen, num) -#define YBOOL(v) yajl_gen_bool(gen, v) -#define YNULL() yajl_gen_null(gen) -#define YARR(body) \ - { \ - yajl_gen_array_open(gen); \ - body; \ - yajl_gen_array_close(gen); \ - } -#define YMAP(body) \ - { \ - yajl_gen_map_open(gen); \ - body; \ - yajl_gen_map_close(gen); \ - } - -typedef unsigned long Window; - -const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock"; -static int sock_fd = -1; -static unsigned int ignore_reply = 0; - -typedef enum IPCMessageType { - IPC_TYPE_RUN_COMMAND = 0, - IPC_TYPE_GET_MONITORS = 1, - IPC_TYPE_GET_TAGS = 2, - IPC_TYPE_GET_LAYOUTS = 3, - IPC_TYPE_GET_DWM_CLIENT = 4, - IPC_TYPE_SUBSCRIBE = 5, - IPC_TYPE_EVENT = 6 -} IPCMessageType; - -// Every IPC message must begin with this -typedef struct dwm_ipc_header { - uint8_t magic[IPC_MAGIC_LEN]; - uint32_t size; - uint8_t type; -} __attribute((packed)) dwm_ipc_header_t; - -static int -recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply) -{ - uint32_t read_bytes = 0; - const int32_t to_read = sizeof(dwm_ipc_header_t); - char header[to_read]; - char *walk = header; - - // Try to read header - while (read_bytes < to_read) { - ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes); - - if (n == 0) { - if (read_bytes == 0) { - fprintf(stderr, "Unexpectedly reached EOF while reading header."); - fprintf(stderr, - "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", - read_bytes, to_read); - return -2; - } else { - fprintf(stderr, "Unexpectedly reached EOF while reading header."); - fprintf(stderr, - "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", - read_bytes, to_read); - return -3; - } - } else if (n == -1) { - return -1; - } - - read_bytes += n; - } - - // Check if magic string in header matches - if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) { - fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n", - IPC_MAGIC_LEN, walk, IPC_MAGIC); - return -3; - } - - walk += IPC_MAGIC_LEN; - - // Extract reply size - memcpy(reply_size, walk, sizeof(uint32_t)); - walk += sizeof(uint32_t); - - // Extract message type - memcpy(msg_type, walk, sizeof(uint8_t)); - walk += sizeof(uint8_t); - - (*reply) = malloc(*reply_size); - - // Extract payload - read_bytes = 0; - while (read_bytes < *reply_size) { - ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); - - if (n == 0) { - fprintf(stderr, "Unexpectedly reached EOF while reading payload."); - fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", - read_bytes, *reply_size); - free(*reply); - return -2; - } else if (n == -1) { - if (errno == EINTR || errno == EAGAIN) continue; - free(*reply); - return -1; - } - - read_bytes += n; - } - - return 0; -} - -static int -read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg) -{ - int ret = -1; - - while (ret != 0) { - ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg); - - if (ret < 0) { - // Try again (non-fatal error) - if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; - - fprintf(stderr, "Error receiving response from socket. "); - fprintf(stderr, "The connection might have been lost.\n"); - exit(2); - } - } - - return 0; -} - -static ssize_t -write_socket(const void *buf, size_t count) -{ - size_t written = 0; - - while (written < count) { - const ssize_t n = - write(sock_fd, ((uint8_t *)buf) + written, count - written); - - if (n == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - continue; - else - return n; - } - written += n; - } - return written; -} - -static void -connect_to_socket() -{ - struct sockaddr_un addr; - - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - - // Initialize struct to 0 - memset(&addr, 0, sizeof(struct sockaddr_un)); - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, DEFAULT_SOCKET_PATH); - - connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); - - sock_fd = sock; -} - -static int -send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg) -{ - dwm_ipc_header_t header = { - .magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type}; - - size_t header_size = sizeof(dwm_ipc_header_t); - size_t total_size = header_size + msg_size; - - uint8_t buffer[total_size]; - - // Copy header to buffer - memcpy(buffer, &header, header_size); - // Copy message to buffer - memcpy(buffer + header_size, msg, header.size); - - write_socket(buffer, total_size); - - return 0; -} - -static int -is_float(const char *s) -{ - size_t len = strlen(s); - int is_dot_used = 0; - int is_minus_used = 0; - - // Floats can only have one decimal point in between or digits - // Optionally, floats can also be below zero (negative) - for (int i = 0; i < len; i++) { - if (isdigit(s[i])) - continue; - else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) { - is_dot_used = 1; - continue; - } else if (!is_minus_used && s[i] == '-' && i == 0) { - is_minus_used = 1; - continue; - } else - return 0; - } - - return 1; -} - -static int -is_unsigned_int(const char *s) -{ - size_t len = strlen(s); - - // Unsigned int can only have digits - for (int i = 0; i < len; i++) { - if (isdigit(s[i])) - continue; - else - return 0; - } - - return 1; -} - -static int -is_signed_int(const char *s) -{ - size_t len = strlen(s); - - // Signed int can only have digits and a negative sign at the start - for (int i = 0; i < len; i++) { - if (isdigit(s[i])) - continue; - else if (i == 0 && s[i] == '-') { - continue; - } else - return 0; - } - - return 1; -} - -static void -flush_socket_reply() -{ - IPCMessageType reply_type; - uint32_t reply_size; - char *reply; - - read_socket(&reply_type, &reply_size, &reply); - - free(reply); -} - -static void -print_socket_reply() -{ - IPCMessageType reply_type; - uint32_t reply_size; - char *reply; - - read_socket(&reply_type, &reply_size, &reply); - - printf("%.*s\n", reply_size, reply); - fflush(stdout); - free(reply); -} - -static int -run_command(const char *name, char *args[], int argc) -{ - const unsigned char *msg; - size_t msg_size; - - yajl_gen gen = yajl_gen_alloc(NULL); - - // Message format: - // { - // "command": "", - // "args": [ ... ] - // } - // clang-format off - YMAP( - YSTR("command"); YSTR(name); - YSTR("args"); YARR( - for (int i = 0; i < argc; i++) { - if (is_signed_int(args[i])) { - long long num = atoll(args[i]); - YINT(num); - } else if (is_float(args[i])) { - float num = atof(args[i]); - YDOUBLE(num); - } else { - YSTR(args[i]); - } - } - ) - ) - // clang-format on - - yajl_gen_get_buf(gen, &msg, &msg_size); - - send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg); - - if (!ignore_reply) - print_socket_reply(); - else - flush_socket_reply(); - - yajl_gen_free(gen); - - return 0; -} - -static int -get_monitors() -{ - send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)""); - print_socket_reply(); - return 0; -} - -static int -get_tags() -{ - send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)""); - print_socket_reply(); - - return 0; -} - -static int -get_layouts() -{ - send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)""); - print_socket_reply(); - - return 0; -} - -static int -get_dwm_client(Window win) -{ - const unsigned char *msg; - size_t msg_size; - - yajl_gen gen = yajl_gen_alloc(NULL); - - // Message format: - // { - // "client_window_id": "" - // } - // clang-format off - YMAP( - YSTR("client_window_id"); YINT(win); - ) - // clang-format on - - yajl_gen_get_buf(gen, &msg, &msg_size); - - send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg); - - print_socket_reply(); - - yajl_gen_free(gen); - - return 0; -} - -static int -subscribe(const char *event) -{ - const unsigned char *msg; - size_t msg_size; - - yajl_gen gen = yajl_gen_alloc(NULL); - - // Message format: - // { - // "event": "", - // "action": "subscribe" - // } - // clang-format off - YMAP( - YSTR("event"); YSTR(event); - YSTR("action"); YSTR("subscribe"); - ) - // clang-format on - - yajl_gen_get_buf(gen, &msg, &msg_size); - - send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg); - - if (!ignore_reply) - print_socket_reply(); - else - flush_socket_reply(); - - yajl_gen_free(gen); - - return 0; -} - -static void -usage_error(const char *prog_name, const char *format, ...) -{ - va_list args; - va_start(args, format); - - fprintf(stderr, "Error: "); - vfprintf(stderr, format, args); - fprintf(stderr, "\nusage: %s [...]\n", prog_name); - fprintf(stderr, "Try '%s help'\n", prog_name); - - va_end(args); - exit(1); -} - -static void -print_usage(const char *name) -{ - printf("usage: %s [options] [...]\n", name); - puts(""); - puts("Commands:"); - puts(" run_command [args...] Run an IPC command"); - puts(""); - puts(" get_monitors Get monitor properties"); - puts(""); - puts(" get_tags Get list of tags"); - puts(""); - puts(" get_layouts Get list of layouts"); - puts(""); - puts(" get_dwm_client Get dwm client proprties"); - puts(""); - puts(" subscribe [events...] Subscribe to specified events"); - puts(" Options: " IPC_EVENT_TAG_CHANGE ","); - puts(" " IPC_EVENT_LAYOUT_CHANGE ","); - puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ","); - puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ","); - puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ","); - puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); - puts(""); - puts(" help Display this message"); - puts(""); - puts("Options:"); - puts(" --ignore-reply Don't print reply messages from"); - puts(" run_command and subscribe."); - puts(""); -} - -int -main(int argc, char *argv[]) -{ - const char *prog_name = argv[0]; - - connect_to_socket(); - if (sock_fd == -1) { - fprintf(stderr, "Failed to connect to socket\n"); - return 1; - } - - int i = 1; - if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) { - ignore_reply = 1; - i++; - } - - if (i >= argc) usage_error(prog_name, "Expected an argument, got none"); - - if (!argc || strcmp(argv[i], "help") == 0) - print_usage(prog_name); - else if (strcmp(argv[i], "run_command") == 0) { - if (++i >= argc) usage_error(prog_name, "No command specified"); - // Command name - char *command = argv[i]; - // Command arguments are everything after command name - char **command_args = argv + ++i; - // Number of command arguments - int command_argc = argc - i; - run_command(command, command_args, command_argc); - } else if (strcmp(argv[i], "get_monitors") == 0) { - get_monitors(); - } else if (strcmp(argv[i], "get_tags") == 0) { - get_tags(); - } else if (strcmp(argv[i], "get_layouts") == 0) { - get_layouts(); - } else if (strcmp(argv[i], "get_dwm_client") == 0) { - if (++i < argc) { - if (is_unsigned_int(argv[i])) { - Window win = atol(argv[i]); - get_dwm_client(win); - } else - usage_error(prog_name, "Expected unsigned integer argument"); - } else - usage_error(prog_name, "Expected the window id"); - } else if (strcmp(argv[i], "subscribe") == 0) { - if (++i < argc) { - for (int j = i; j < argc; j++) subscribe(argv[j]); - } else - usage_error(prog_name, "Expected event name"); - // Keep listening for events forever - while (1) { - print_socket_reply(); - } - } else - usage_error(prog_name, "Invalid argument '%s'", argv[i]); - - return 0; -} - diff --git a/suckless/dwm/patch/ipc/yajl_dumps.h b/suckless/dwm/patch/ipc/yajl_dumps.h deleted file mode 100644 index bb57a17..0000000 --- a/suckless/dwm/patch/ipc/yajl_dumps.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef YAJL_DUMPS_H_ -#define YAJL_DUMPS_H_ - -#include -#include - -#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) -#define YINT(num) yajl_gen_integer(gen, num) -#define YDOUBLE(num) yajl_gen_double(gen, num) -#define YBOOL(v) yajl_gen_bool(gen, v) -#define YNULL() yajl_gen_null(gen) -#define YARR(body) \ - { \ - yajl_gen_array_open(gen); \ - body; \ - yajl_gen_array_close(gen); \ - } -#define YMAP(body) \ - { \ - yajl_gen_map_open(gen); \ - body; \ - yajl_gen_map_close(gen); \ - } - -int dump_tag(yajl_gen gen, const char *name, const int tag_mask); - -int dump_tags(yajl_gen gen, int tags_len); - -int dump_client(yajl_gen gen, Client *c); - -int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected); - -int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon); - -int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len); - -int dump_tag_state(yajl_gen gen, TagState state); - -int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state, - TagState new_state); - -int dump_client_focus_change_event(yajl_gen gen, Client *old_client, - Client *new_client, int mon_num); - -int dump_layout_change_event(yajl_gen gen, const int mon_num, - const char *old_symbol, const Layout *old_layout, - const char *new_symbol, const Layout *new_layout); - -int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num, - const int new_mon_num); - -int dump_focused_title_change_event(yajl_gen gen, const int mon_num, - const Window client_id, - const char *old_name, const char *new_name); - -int dump_client_state(yajl_gen gen, const ClientState *state); - -int dump_focused_state_change_event(yajl_gen gen, const int mon_num, - const Window client_id, - const ClientState *old_state, - const ClientState *new_state); - -int dump_error_message(yajl_gen gen, const char *reason); - -#endif // YAJL_DUMPS_H_ - diff --git a/suckless/dwm/patch/layout_facts.c b/suckless/dwm/patch/layout_facts.c deleted file mode 100644 index 241d344..0000000 --- a/suckless/dwm/patch/layout_facts.c +++ /dev/null @@ -1,24 +0,0 @@ -void -getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) -{ - unsigned int n; - float mfacts, sfacts; - int mtotal = 0, stotal = 0; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - mfacts = MIN(n, m->nmaster); - sfacts = n - m->nmaster; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) - if (n < m->nmaster) - mtotal += msize / mfacts; - else - stotal += ssize / sfacts; - - *mf = mfacts; // total factor of master area - *sf = sfacts; // total factor of stack area - *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split - *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split -} - diff --git a/suckless/dwm/patch/layout_tile.c b/suckless/dwm/patch/layout_tile.c deleted file mode 100644 index 8d41d2a..0000000 --- a/suckless/dwm/patch/layout_tile.c +++ /dev/null @@ -1,41 +0,0 @@ -static void -tile(Monitor *m) -{ - unsigned int i, n; - int mx = 0, my = 0, mh = 0, mw = 0; - int sx = 0, sy = 0, sh = 0, sw = 0; - float mfacts, sfacts; - int mrest, srest; - Client *c; - - - int oh, ov, ih, iv; - getgaps(m, &oh, &ov, &ih, &iv, &n); - - if (n == 0) - return; - - sx = mx = m->wx + ov; - sy = my = m->wy + oh; - mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); - sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); - sw = mw = m->ww - 2*ov; - - if (m->nmaster && n > m->nmaster) { - sw = (mw - iv) * (1 - m->mfact); - mw = (mw - iv) * m->mfact; - sx = mx + mw + iv; - } - - getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); - - for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); - my += HEIGHT(c) + ih; - } else { - resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); - sy += HEIGHT(c) + ih; - } -} - diff --git a/suckless/dwm/patch/layout_tile.h b/suckless/dwm/patch/layout_tile.h deleted file mode 100644 index 78cafc8..0000000 --- a/suckless/dwm/patch/layout_tile.h +++ /dev/null @@ -1,2 +0,0 @@ -static void tile(Monitor *); - diff --git a/suckless/dwm/patch/moveresize.c b/suckless/dwm/patch/moveresize.c deleted file mode 100644 index 75d58e2..0000000 --- a/suckless/dwm/patch/moveresize.c +++ /dev/null @@ -1,65 +0,0 @@ -void -moveresize(const Arg *arg) { - /* only floating windows can be moved */ - Client *c; - c = selmon->sel; - int x, y, w, h, nx, ny, nw, nh, ox, oy, ow, oh; - char xAbs, yAbs, wAbs, hAbs; - int msx, msy, dx, dy, nmx, nmy; - unsigned int dui; - Window dummy; - - if (!c || !arg) - return; - if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) - return; - if (sscanf((char *)arg->v, "%d%c %d%c %d%c %d%c", &x, &xAbs, &y, &yAbs, &w, &wAbs, &h, &hAbs) != 8) - return; - - /* compute new window position; prevent window from be positioned outside the current monitor */ - nw = c->w + w; - if (wAbs == 'W') - nw = w < selmon->mw - 2 * c->bw ? w : selmon->mw - 2 * c->bw; - - nh = c->h + h; - if (hAbs == 'H') - nh = h < selmon->mh - 2 * c->bw ? h : selmon->mh - 2 * c->bw; - - nx = c->x + x; - if (xAbs == 'X') { - if (x < selmon->mx) - nx = selmon->mx; - else if (x > selmon->mx + selmon->mw) - nx = selmon->mx + selmon->mw - nw - 2 * c->bw; - else - nx = x; - } - - ny = c->y + y; - if (yAbs == 'Y') { - if (y < selmon->my) - ny = selmon->my; - else if (y > selmon->my + selmon->mh) - ny = selmon->my + selmon->mh - nh - 2 * c->bw; - else - ny = y; - } - - ox = c->x; - oy = c->y; - ow = c->w; - oh = c->h; - - XRaiseWindow(dpy, c->win); - Bool xqp = XQueryPointer(dpy, root, &dummy, &dummy, &msx, &msy, &dx, &dy, &dui); - resize(c, nx, ny, nw, nh, True); - - /* move cursor along with the window to avoid problems caused by the sloppy focus */ - if (xqp && ox <= msx && (ox + ow) >= msx && oy <= msy && (oy + oh) >= msy) - { - nmx = c->x - ox + c->w - ow; - nmy = c->y - oy + c->h - oh; - XWarpPointer(dpy, None, None, 0, 0, 0, 0, nmx, nmy); - } -} - diff --git a/suckless/dwm/patch/moveresize.h b/suckless/dwm/patch/moveresize.h deleted file mode 100644 index 919ebad..0000000 --- a/suckless/dwm/patch/moveresize.h +++ /dev/null @@ -1,2 +0,0 @@ -static void moveresize(const Arg *arg); - diff --git a/suckless/dwm/patch/movestack.c b/suckless/dwm/patch/movestack.c deleted file mode 100644 index fe97f1d..0000000 --- a/suckless/dwm/patch/movestack.c +++ /dev/null @@ -1,51 +0,0 @@ -void -movestack(const Arg *arg) -{ - Client *c = NULL, *p = NULL, *pc = NULL, *i; - if (arg->i > 0) { - if (!selmon->sel) - return; - /* find the client after selmon->sel */ - for (c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - if (!c) - for (c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - } - else { - /* find the client before selmon->sel */ - for (i = selmon->clients; i != selmon->sel; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i) && !i->isfloating) - c = i; - } - - /* find the client before selmon->sel and c */ - for (i = selmon->clients; i && (!p || !pc); i = i->next) { - if (i->next == selmon->sel) - p = i; - if (i->next == c) - pc = i; - } - - /* swap c and selmon->sel selmon->clients in the selmon->clients list */ - if (c && c != selmon->sel) { - Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; - selmon->sel->next = c->next==selmon->sel?c:c->next; - c->next = temp; - - if (p && p != c) - p->next = c; - if (pc && pc != selmon->sel) - pc->next = selmon->sel; - - if (selmon->sel == selmon->clients) - selmon->clients = c; - else if (c == selmon->clients) - selmon->clients = selmon->sel; - - arrange(selmon); - } -} - diff --git a/suckless/dwm/patch/movestack.h b/suckless/dwm/patch/movestack.h deleted file mode 100644 index 25f198f..0000000 --- a/suckless/dwm/patch/movestack.h +++ /dev/null @@ -1,2 +0,0 @@ -static void movestack(const Arg *arg); - diff --git a/suckless/dwm/patch/scratchpad.c b/suckless/dwm/patch/scratchpad.c deleted file mode 100644 index 9e24ff6..0000000 --- a/suckless/dwm/patch/scratchpad.c +++ /dev/null @@ -1,77 +0,0 @@ -void -removescratch(const Arg *arg) -{ - Client *c = selmon->sel; - if (!c) - return; - unsigned int scratchtag = SPTAG(arg->ui); - c->tags = c->mon->tagset[c->mon->seltags] ^ scratchtag; - arrange(c->mon); -} - -void -setscratch(const Arg *arg) -{ - Client *c = selmon->sel; - if (!c) - return; - unsigned int scratchtag = SPTAG(arg->ui); - c->tags = scratchtag; - arrange(c->mon); -} - -void -togglescratch(const Arg *arg) -{ - Client *c = NULL, *next = NULL, *found = NULL; - Monitor *mon; - unsigned int scratchtag = SPTAG(arg->ui); - unsigned int newtagset = 0; - int nh = 0, nw = 0; - Arg sparg = {.v = scratchpads[arg->ui].cmd}; - - for (mon = mons; mon; mon = mon->next) { - for (c = mon->clients; c; c = next) { - next = c->next; - if (!(c->tags & scratchtag)) - continue; - - found = c; - - if (HIDDEN(c)) { - XMapWindow(dpy, c->win); - setclientstate(c, NormalState); - newtagset = 0; - } else - newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; - - if (c->mon != selmon) { - if (c->mon->tagset[c->mon->seltags] & SPTAGMASK) - c->mon->tagset[c->mon->seltags] ^= scratchtag; - if (c->w > selmon->ww) - nw = selmon->ww - c->bw * 2; - if (c->h > selmon->wh) - nh = selmon->wh - c->bw * 2; - if (nw > 0 || nh > 0) - resizeclient(c, c->x, c->y, nw ? nw : c->w, nh ? nh : c->h); - sendmon(c, selmon); - } - } - } - - if (found) { - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } - if (ISVISIBLE(found)) { - focus(found); - restack(selmon); - } - } else { - selmon->tagset[selmon->seltags] |= scratchtag; - spawn(&sparg); - } -} - diff --git a/suckless/dwm/patch/scratchpad.h b/suckless/dwm/patch/scratchpad.h deleted file mode 100644 index 6230266..0000000 --- a/suckless/dwm/patch/scratchpad.h +++ /dev/null @@ -1,9 +0,0 @@ -typedef struct { - const char *name; - const void *cmd; -} Sp; - -static void removescratch(const Arg *arg); -static void setscratch(const Arg *arg); -static void togglescratch(const Arg *arg); - diff --git a/suckless/dwm/patch/swallow.c b/suckless/dwm/patch/swallow.c deleted file mode 100644 index 0d65353..0000000 --- a/suckless/dwm/patch/swallow.c +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#ifdef __OpenBSD__ -#include -#include -#endif /* __OpenBSD__ */ - -static int scanner; -static xcb_connection_t *xcon; - -int -swallow(Client *p, Client *c) -{ - Client *s; - XWindowChanges wc; - - if (c->noswallow > 0 || c->isterminal) - return 0; - if (c->noswallow < 0 && !swallowfloating && c->isfloating) - return 0; - - XMapWindow(dpy, c->win); - - detach(c); - detachstack(c); - - setclientstate(c, WithdrawnState); - XUnmapWindow(dpy, p->win); - - p->swallowing = c; - c->mon = p->mon; - - Window w = p->win; - p->win = c->win; - c->win = w; - - XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(p->win), 1); - - updatetitle(p); - s = scanner ? c : p; - - wc.border_width = p->bw; - XConfigureWindow(dpy, p->win, CWBorderWidth, &wc); - XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); - XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel); - - arrange(p->mon); - configure(p); - updateclientlist(); - - return 1; -} - -void -unswallow(Client *c) -{ - XWindowChanges wc; - c->win = c->swallowing->win; - - free(c->swallowing); - c->swallowing = NULL; - - XDeleteProperty(dpy, c->win, netatom[NetClientList]); - - /* unfullscreen the client */ - setfullscreen(c, 0); - updatetitle(c); - arrange(c->mon); - XMapWindow(dpy, c->win); - - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - - setclientstate(c, NormalState); - focus(NULL); - arrange(c->mon); -} - -pid_t -winpid(Window w) -{ - pid_t result = 0; - - #ifdef __linux__ - xcb_res_client_id_spec_t spec = {0}; - spec.client = w; - spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; - - xcb_generic_error_t *e = NULL; - xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); - xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); - - if (!r) - return (pid_t)0; - - xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); - for (; i.rem; xcb_res_client_id_value_next(&i)) { - spec = i.data->spec; - if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { - uint32_t *t = xcb_res_client_id_value_value(i.data); - result = *t; - break; - } - } - - free(r); - - if (result == (pid_t)-1) - result = 0; - - #endif /* __linux__ */ - #ifdef __OpenBSD__ - Atom type; - int format; - unsigned long len, bytes; - unsigned char *prop; - pid_t ret; - - if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) - return 0; - - ret = *(pid_t*)prop; - XFree(prop); - result = ret; - #endif /* __OpenBSD__ */ - - return result; -} - -pid_t -getparentprocess(pid_t p) -{ - unsigned int v = 0; - -#ifdef __linux__ - FILE *f; - char buf[256]; - snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); - - if (!(f = fopen(buf, "r"))) - return (pid_t)0; - - if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) - v = (pid_t)0; - fclose(f); -#endif /* __linux__ */ -#ifdef __OpenBSD__ - int n; - kvm_t *kd; - struct kinfo_proc *kp; - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); - if (!kd) - return 0; - - kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); - v = kp->p_ppid; -#endif /* __OpenBSD__ */ - return (pid_t)v; -} - -int -isdescprocess(pid_t p, pid_t c) -{ - while (p != c && c != 0) - c = getparentprocess(c); - - return (int)c; -} - -Client * -termforwin(const Client *w) -{ - Client *c; - Monitor *m; - - if (!w->pid || w->isterminal) - return NULL; - - c = selmon->sel; - if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) - return c; - - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) { - if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) - return c; - } - } - - return NULL; -} - -Client * -swallowingclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) { - if (c->swallowing && c->swallowing->win == w) - return c; - } - } - - return NULL; -} - diff --git a/suckless/dwm/patch/swallow.h b/suckless/dwm/patch/swallow.h deleted file mode 100644 index 529fea9..0000000 --- a/suckless/dwm/patch/swallow.h +++ /dev/null @@ -1,8 +0,0 @@ -static pid_t getparentprocess(pid_t p); -static int isdescprocess(pid_t p, pid_t c); -static int swallow(Client *p, Client *c); -static Client *swallowingclient(Window w); -static Client *termforwin(const Client *c); -static void unswallow(Client *c); -static pid_t winpid(Window w); - diff --git a/suckless/dwm/patch/togglefullscreen.c b/suckless/dwm/patch/togglefullscreen.c deleted file mode 100644 index a62edef..0000000 --- a/suckless/dwm/patch/togglefullscreen.c +++ /dev/null @@ -1,10 +0,0 @@ -void -togglefullscreen(const Arg *arg) -{ - Client *c = selmon->sel; - if (!c) - return; - - setfullscreen(c, !c->isfullscreen); -} - diff --git a/suckless/dwm/patch/togglefullscreen.h b/suckless/dwm/patch/togglefullscreen.h deleted file mode 100644 index 96a6770..0000000 --- a/suckless/dwm/patch/togglefullscreen.h +++ /dev/null @@ -1,2 +0,0 @@ -static void togglefullscreen(const Arg *arg); - diff --git a/suckless/dwm/patch/vanitygaps.c b/suckless/dwm/patch/vanitygaps.c deleted file mode 100644 index d8d5e6e..0000000 --- a/suckless/dwm/patch/vanitygaps.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Settings */ -static int enablegaps = 1; - -static void -setgaps(int oh, int ov, int ih, int iv) -{ - if (oh < 0) oh = 0; - if (ov < 0) ov = 0; - if (ih < 0) ih = 0; - if (iv < 0) iv = 0; - - selmon->gappoh = oh; - selmon->gappov = ov; - selmon->gappih = ih; - selmon->gappiv = iv; - - - arrange(selmon); -} - -/* External function that takes one integer and splits it - * into four gap values: - * - outer horizontal (oh) - * - outer vertical (ov) - * - inner horizontal (ih) - * - inner vertical (iv) - * - * Each value is represented as one byte with the uppermost - * bit of each byte indicating whether or not to keep the - * current value. - * - * Example: - * - * 10000000 10000000 00001111 00001111 - * | | | | - * + keep oh + keep ov + ih 15px + iv 15px - * - * This gives an int of: - * 10000000100000000000111100001111 = 2155876111 - * - * Thus this command should set inner gaps to 15: - * xsetroot -name "fsignal:setgaps i 2155876111" - */ -static void -setgapsex(const Arg *arg) -{ - int oh = selmon->gappoh; - int ov = selmon->gappov; - int ih = selmon->gappih; - int iv = selmon->gappiv; - - if (!(arg->i & (1 << 31))) - oh = (arg->i & 0x7f000000) >> 24; - if (!(arg->i & (1 << 23))) - ov = (arg->i & 0x7f0000) >> 16; - if (!(arg->i & (1 << 15))) - ih = (arg->i & 0x7f00) >> 8; - if (!(arg->i & (1 << 7))) - iv = (arg->i & 0x7f); - - /* Auto enable gaps if disabled */ - if (!enablegaps) - enablegaps = 1; - - setgaps(oh, ov, ih, iv); -} - -static void -togglegaps(const Arg *arg) -{ - enablegaps = !enablegaps; - - arrange(NULL); -} - -static void -defaultgaps(const Arg *arg) -{ - setgaps(gappoh, gappov, gappih, gappiv); -} - -static void -incrgaps(const Arg *arg) -{ - setgaps( - selmon->gappoh + arg->i, - selmon->gappov + arg->i, - selmon->gappih + arg->i, - selmon->gappiv + arg->i - ); -} - -static void -incrigaps(const Arg *arg) -{ - setgaps( - selmon->gappoh, - selmon->gappov, - selmon->gappih + arg->i, - selmon->gappiv + arg->i - ); -} - -static void -incrogaps(const Arg *arg) -{ - setgaps( - selmon->gappoh + arg->i, - selmon->gappov + arg->i, - selmon->gappih, - selmon->gappiv - ); -} - -static void -incrohgaps(const Arg *arg) -{ - setgaps( - selmon->gappoh + arg->i, - selmon->gappov, - selmon->gappih, - selmon->gappiv - ); -} - -static void -incrovgaps(const Arg *arg) -{ - setgaps( - selmon->gappoh, - selmon->gappov + arg->i, - selmon->gappih, - selmon->gappiv - ); -} - -static void -incrihgaps(const Arg *arg) -{ - setgaps( - selmon->gappoh, - selmon->gappov, - selmon->gappih + arg->i, - selmon->gappiv - ); -} - -static void -incrivgaps(const Arg *arg) -{ - setgaps( - selmon->gappoh, - selmon->gappov, - selmon->gappih, - selmon->gappiv + arg->i - ); -} - -static void -getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) -{ - unsigned int n, oe, ie; - oe = ie = enablegaps; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 1) { - oe *= smartgaps_fact; // outer gaps disabled or multiplied when only one client - } - - *oh = m->gappoh*oe; // outer horizontal gap - *ov = m->gappov*oe; // outer vertical gap - *ih = m->gappih*ie; // inner horizontal gap - *iv = m->gappiv*ie; // inner vertical gap - *nc = n; // number of clients -} - diff --git a/suckless/dwm/patch/vanitygaps.h b/suckless/dwm/patch/vanitygaps.h deleted file mode 100644 index 8a3ed0b..0000000 --- a/suckless/dwm/patch/vanitygaps.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Key binding functions */ -static void defaultgaps(const Arg *arg); -static void incrgaps(const Arg *arg); -static void incrigaps(const Arg *arg); -static void incrogaps(const Arg *arg); -static void incrohgaps(const Arg *arg); -static void incrovgaps(const Arg *arg); -static void incrihgaps(const Arg *arg); -static void incrivgaps(const Arg *arg); -static void togglegaps(const Arg *arg); - -/* Internals */ -static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); -static void setgaps(int oh, int ov, int ih, int iv); -static void setgapsex(const Arg *arg); - diff --git a/suckless/dwm/patch/xrdb.c b/suckless/dwm/patch/xrdb.c deleted file mode 100644 index f450023..0000000 --- a/suckless/dwm/patch/xrdb.c +++ /dev/null @@ -1,73 +0,0 @@ -void -loadxrdb() -{ - Display *display; - char * resm; - XrmDatabase xrdb; - char *type; - XrmValue value; - - display = XOpenDisplay(NULL); - - if (display != NULL) { - resm = XResourceManagerString(display); - - if (resm != NULL) { - xrdb = XrmGetStringDatabase(resm); - - if (xrdb != NULL) { - XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); - XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); - XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); - XRDB_LOAD_COLOR("dwm.normfloatcolor", normfloatcolor); - XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); - XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); - XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); - XRDB_LOAD_COLOR("dwm.selfloatcolor", selfloatcolor); - XRDB_LOAD_COLOR("dwm.titlenormfgcolor", titlenormfgcolor); - XRDB_LOAD_COLOR("dwm.titlenormbgcolor", titlenormbgcolor); - XRDB_LOAD_COLOR("dwm.titlenormbordercolor", titlenormbordercolor); - XRDB_LOAD_COLOR("dwm.titlenormfloatcolor", titlenormfloatcolor); - XRDB_LOAD_COLOR("dwm.titleselfgcolor", titleselfgcolor); - XRDB_LOAD_COLOR("dwm.titleselbgcolor", titleselbgcolor); - XRDB_LOAD_COLOR("dwm.titleselbordercolor", titleselbordercolor); - XRDB_LOAD_COLOR("dwm.titleselfloatcolor", titleselfloatcolor); - XRDB_LOAD_COLOR("dwm.tagsnormfgcolor", tagsnormfgcolor); - XRDB_LOAD_COLOR("dwm.tagsnormbgcolor", tagsnormbgcolor); - XRDB_LOAD_COLOR("dwm.tagsnormbordercolor", tagsnormbordercolor); - XRDB_LOAD_COLOR("dwm.tagsnormfloatcolor", tagsnormfloatcolor); - XRDB_LOAD_COLOR("dwm.tagsselfgcolor", tagsselfgcolor); - XRDB_LOAD_COLOR("dwm.tagsselbgcolor", tagsselbgcolor); - XRDB_LOAD_COLOR("dwm.tagsselbordercolor", tagsselbordercolor); - XRDB_LOAD_COLOR("dwm.tagsselfloatcolor", tagsselfloatcolor); - XRDB_LOAD_COLOR("dwm.hidnormfgcolor", hidnormfgcolor); - XRDB_LOAD_COLOR("dwm.hidnormbgcolor", hidnormbgcolor); - XRDB_LOAD_COLOR("dwm.hidselfgcolor", hidselfgcolor); - XRDB_LOAD_COLOR("dwm.hidselbgcolor", hidselbgcolor); - XRDB_LOAD_COLOR("dwm.urgfgcolor", urgfgcolor); - XRDB_LOAD_COLOR("dwm.urgbgcolor", urgbgcolor); - XRDB_LOAD_COLOR("dwm.urgbordercolor", urgbordercolor); - XRDB_LOAD_COLOR("dwm.urgfloatcolor", urgfloatcolor); - - XrmDestroyDatabase(xrdb); - } - } - } - - XCloseDisplay(display); -} - -void -xrdb(const Arg *arg) -{ - loadxrdb(); - int i; - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], - alphas[i], - ColCount - ); - focus(NULL); - arrange(NULL); -} - diff --git a/suckless/dwm/patch/xrdb.h b/suckless/dwm/patch/xrdb.h deleted file mode 100644 index 3787bec..0000000 --- a/suckless/dwm/patch/xrdb.h +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ - if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ - int i = 1; \ - for (; i <= 6; i++) { \ - if (value.addr[i] < 48) break; \ - if (value.addr[i] > 57 && value.addr[i] < 65) break; \ - if (value.addr[i] > 70 && value.addr[i] < 97) break; \ - if (value.addr[i] > 102) break; \ - } \ - if (i == 7) { \ - strncpy(V, value.addr, 7); \ - V[7] = '\0'; \ - } \ - } \ - } - -static void loadxrdb(void); -static void xrdb(const Arg *arg); - - diff --git a/suckless/dwm/patches/dwm-attachaside-20160718-56a31dc.diff b/suckless/dwm/patches/dwm-attachaside-20160718-56a31dc.diff deleted file mode 100644 index b8471af..0000000 --- a/suckless/dwm/patches/dwm-attachaside-20160718-56a31dc.diff +++ /dev/null @@ -1,92 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index b2bc9bd..58a86fa 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -49,7 +49,8 @@ - #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) --#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -+#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -+#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) -@@ -148,6 +149,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac - static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); -+static void attachaside(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -185,6 +187,7 @@ static void maprequest(XEvent *e); - static void monocle(Monitor *m); - static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); -+static Client *nexttagged(Client *c); - static Client *nexttiled(Client *c); - static void pop(Client *); - static void propertynotify(XEvent *e); -@@ -408,6 +411,17 @@ attach(Client *c) - } - - void -+attachaside(Client *c) { -+ Client *at = nexttagged(c); -+ if(!at) { -+ attach(c); -+ return; -+ } -+ c->next = at->next; -+ at->next = c; -+} -+ -+void - attachstack(Client *c) - { - c->snext = c->mon->stack; -@@ -1079,7 +1093,7 @@ manage(Window w, XWindowAttributes *wa) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1213,6 +1227,16 @@ movemouse(const Arg *arg) - } - - Client * -+nexttagged(Client *c) { -+ Client *walked = c->mon->clients; -+ for(; -+ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); -+ walked = walked->next -+ ); -+ return walked; -+} -+ -+Client * - nexttiled(Client *c) - { - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); -@@ -1437,7 +1461,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1890,7 +1914,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachaside(c); - attachstack(c); - } - if (m == selmon) diff --git a/suckless/dwm/patches/dwm-bar-height-spacing-6.3.diff b/suckless/dwm/patches/dwm-bar-height-spacing-6.3.diff deleted file mode 100644 index cbdeb9a..0000000 --- a/suckless/dwm/patches/dwm-bar-height-spacing-6.3.diff +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..9814500 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+static const int user_bh = 2; /* 2 is the default spacing around the bar's font */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -diff --git a/dwm.c b/dwm.c -index 4465af1..2c27cb3 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -1545,7 +1545,7 @@ setup(void) - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; -- bh = drw->fonts->h + 2; -+ bh = drw->fonts->h + user_bh; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/suckless/dwm/patches/dwm-barpadding-20211020-a786211.diff b/suckless/dwm/patches/dwm-barpadding-20211020-a786211.diff deleted file mode 100755 index 7842181..0000000 --- a/suckless/dwm/patches/dwm-barpadding-20211020-a786211.diff +++ /dev/null @@ -1,118 +0,0 @@ -From a3cfb215f7f647d83d67e33df8f33a73e43bd65f Mon Sep 17 00:00:00 2001 -From: Bakkeby -Date: Wed, 20 Oct 2021 09:14:07 +0200 -Subject: [PATCH] barpadding: adds space between the statusbar and the edge of - the screen - ---- - config.def.h | 2 ++ - dwm.c | 25 +++++++++++++++---------- - 2 files changed, 17 insertions(+), 10 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..f0b739f 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+static const int vertpad = 10; /* vertical padding of bar */ -+static const int sidepad = 10; /* horizontal padding of bar */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -diff --git a/dwm.c b/dwm.c -index 5e4d494..df6d0d7 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -242,6 +242,8 @@ static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ - static int lrpad; /* sum of left and right padding for text */ -+static int vp; /* vertical padding for bar */ -+static int sp; /* side padding for bar */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -568,7 +570,7 @@ configurenotify(XEvent *e) - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); -- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); - } - focus(NULL); - arrange(NULL); -@@ -706,7 +708,7 @@ drawbar(Monitor *m) - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); -+ drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { -@@ -732,12 +734,12 @@ drawbar(Monitor *m) - if ((w = m->ww - tw - x) > bh) { - if (m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+ drw_text(drw, x, 0, w - 2 * sp, bh, lrpad / 2, m->sel->name, 0); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { - drw_setscheme(drw, scheme[SchemeNorm]); -- drw_rect(drw, x, 0, w, bh, 1, 1); -+ drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); - } - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -@@ -1547,7 +1549,10 @@ setup(void) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; -+ sp = sidepad; -+ vp = (topbar == 1) ? vertpad : - vertpad; - updategeom(); -+ - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1704,7 +1709,7 @@ togglebar(const Arg *arg) - { - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); -- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); - arrange(selmon); - } - -@@ -1814,7 +1819,7 @@ updatebars(void) - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; -- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -+ m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -@@ -1829,11 +1834,11 @@ updatebarpos(Monitor *m) - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { -- m->wh -= bh; -- m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -+ m->wh = m->wh - vertpad - bh; -+ m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; -+ m->wy = m->topbar ? m->wy + bh + vp : m->wy; - } else -- m->by = -bh; -+ m->by = -bh - vp; - } - - void --- -2.33.0 - diff --git a/suckless/dwm/patches/dwm-fullgaps-6.4.diff b/suckless/dwm/patches/dwm-fullgaps-6.4.diff deleted file mode 100755 index dc52139..0000000 --- a/suckless/dwm/patches/dwm-fullgaps-6.4.diff +++ /dev/null @@ -1,94 +0,0 @@ -diff -up a/config.def.h b/config.def.h ---- a/config.def.h -+++ b/config.def.h -@@ -2,6 +2,7 @@ - - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ -+static const unsigned int gappx = 5; /* gaps between windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -@@ -85,6 +86,9 @@ static const Key keys[] = { - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ { MODKEY, XK_minus, setgaps, {.i = -1 } }, -+ { MODKEY, XK_equal, setgaps, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) -diff -up a/dwm.c b/dwm.c ---- a/dwm.c 2023-04-30 -+++ b/dwm.c 2023-04-30 -@@ -119,6 +119,7 @@ struct Monitor { - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ -+ int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; -@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor * - static void setclientstate(Client *c, long state); - static void setfocus(Client *c); - static void setfullscreen(Client *c, int fullscreen); -+static void setgaps(const Arg *arg); - static void setlayout(const Arg *arg); - static void setmfact(const Arg *arg); - static void setup(void); -@@ -641,6 +643,7 @@ createmon(void) - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; -+ m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen) - } - - void -+setgaps(const Arg *arg) -+{ -+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) -+ selmon->gappx = 0; -+ else -+ selmon->gappx += arg->i; -+ arrange(selmon); -+} -+ -+void - setlayout(const Arg *arg) - { - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -@@ -1697,18 +1710,18 @@ tile(Monitor *m) - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else -- mw = m->ww; -- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -- if (i < m->nmaster) { -- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -- if (my + HEIGHT(c) < m->wh) -- my += HEIGHT(c); -+ mw = m->ww - m->gappx; -+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+ if (i < m->nmaster) { -+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; -+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); -+ if (my + HEIGHT(c) + m->gappx < m->wh) -+ my += HEIGHT(c) + m->gappx; - } else { -- h = (m->wh - ty) / (n - i); -- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -- if (ty + HEIGHT(c) < m->wh) -- ty += HEIGHT(c); -+ h = (m->wh - ty) / (n - i) - m->gappx; -+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); -+ if (ty + HEIGHT(c) + m->gappx < m->wh) -+ ty += HEIGHT(c) + m->gappx; - } - } diff --git a/suckless/dwm/patches/dwm-notitle-20210715-138b405.diff b/suckless/dwm/patches/dwm-notitle-20210715-138b405.diff deleted file mode 100755 index bc8a3e5..0000000 --- a/suckless/dwm/patches/dwm-notitle-20210715-138b405.diff +++ /dev/null @@ -1,81 +0,0 @@ -From a3a7e94f59553689656871a65ea9ce90169a7c91 Mon Sep 17 00:00:00 2001 -From: birdalicous -Date: Thu, 15 Jul 2021 12:28:29 +0100 -Subject: [PATCH] notitle patch applied# - ---- - config.def.h | 1 - - dwm.c | 20 ++++---------------- - 2 files changed, 4 insertions(+), 17 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..eac20b4 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -103,7 +103,6 @@ static Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, -- { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, -diff --git a/dwm.c b/dwm.c -index 5e4d494..6cd9fb7 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,8 +64,8 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -- ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -+enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, -+ ClkRootWin, ClkLast }; /* clicks */ - - typedef union { - int i; -@@ -440,10 +440,8 @@ buttonpress(XEvent *e) - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; -- else if (ev->x > selmon->ww - (int)TEXTW(stext)) -- click = ClkStatusText; - else -- click = ClkWinTitle; -+ click = ClkStatusText; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); -@@ -730,15 +728,8 @@ drawbar(Monitor *m) - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { -- if (m->sel) { -- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -- if (m->sel->isfloating) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); -- } else { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); -- } - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); - } -@@ -1236,11 +1227,8 @@ propertynotify(XEvent *e) - drawbars(); - break; - } -- if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { -+ if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) - updatetitle(c); -- if (c == c->mon->sel) -- drawbar(c->mon); -- } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } --- -2.32.0 - diff --git a/suckless/dwm/patches/dwm-restartsig-20180523-6.2.diff b/suckless/dwm/patches/dwm-restartsig-20180523-6.2.diff deleted file mode 100755 index f1f8680..0000000 --- a/suckless/dwm/patches/dwm-restartsig-20180523-6.2.diff +++ /dev/null @@ -1,139 +0,0 @@ -From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich -Date: Wed, 23 May 2018 22:50:38 -0400 -Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM - handlers. - -Modified quit() to restart if it receives arg .i = 1 -MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. - -Signal handlers were handled for SIGHUP and SIGTERM. -If dwm receives these signals it calls quit() with -arg .i = to 1 or 0, respectively. - -To restart dwm: -MOD+CTRL+SHIFT+Q -or -kill -HUP dwmpid - -To quit dwm cleanly: -MOD+SHIFT+Q -or -kill -TERM dwmpid ---- - config.def.h | 1 + - dwm.1 | 10 ++++++++++ - dwm.c | 22 ++++++++++++++++++++++ - 3 files changed, 33 insertions(+) - -diff --git a/config.def.h b/config.def.h -index a9ac303..e559429 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -94,6 +94,7 @@ static Key keys[] = { - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, -+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, - }; - - /* button definitions */ -diff --git a/dwm.1 b/dwm.1 -index 13b3729..36a331c 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. - .TP - .B Mod1\-Shift\-q - Quit dwm. -+.TP -+.B Mod1\-Control\-Shift\-q -+Restart dwm. - .SS Mouse commands - .TP - .B Mod1\-Button1 -@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float - .SH CUSTOMIZATION - dwm is customized by creating a custom config.h and (re)compiling the source - code. This keeps it fast, secure and simple. -+.SH SIGNALS -+.TP -+.B SIGHUP - 1 -+Restart the dwm process. -+.TP -+.B SIGTERM - 15 -+Cleanly terminate the dwm process. - .SH SEE ALSO - .BR dmenu (1), - .BR st (1) -diff --git a/dwm.c b/dwm.c -index bb95e26..286eecd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -205,6 +205,8 @@ static void setup(void); - static void seturgent(Client *c, int urg); - static void showhide(Client *c); - static void sigchld(int unused); -+static void sighup(int unused); -+static void sigterm(int unused); - static void spawn(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { - [UnmapNotify] = unmapnotify - }; - static Atom wmatom[WMLast], netatom[NetLast]; -+static int restart = 0; - static int running = 1; - static Cur *cursor[CurLast]; - static Clr **scheme; -@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) - void - quit(const Arg *arg) - { -+ if(arg->i) restart = 1; - running = 0; - } - -@@ -1536,6 +1540,9 @@ setup(void) - /* clean up any zombies immediately */ - sigchld(0); - -+ signal(SIGHUP, sighup); -+ signal(SIGTERM, sigterm); -+ - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); -@@ -1637,6 +1644,20 @@ sigchld(int unused) - } - - void -+sighup(int unused) -+{ -+ Arg a = {.i = 1}; -+ quit(&a); -+} -+ -+void -+sigterm(int unused) -+{ -+ Arg a = {.i = 0}; -+ quit(&a); -+} -+ -+void - spawn(const Arg *arg) - { - if (arg->v == dmenucmd) -@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) - setup(); - scan(); - run(); -+ if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; --- -2.7.4 - diff --git a/suckless/dwm/patches/dwm-statusallmons-6.2.diff b/suckless/dwm/patches/dwm-statusallmons-6.2.diff deleted file mode 100755 index 9d9633d..0000000 --- a/suckless/dwm/patches/dwm-statusallmons-6.2.diff +++ /dev/null @@ -1,25 +0,0 @@ -diff -up a/dwm.c b/dwm.c ---- a/dwm.c 2020-07-09 16:49:10.023585649 +0200 -+++ b/dwm.c 2020-07-09 16:49:43.497542191 +0200 -@@ -702,7 +702,7 @@ drawbar(Monitor *m) - Client *c; - - /* draw status first so it can be overdrawn by tags later */ -- if (m == selmon) { /* status is only drawn on selected monitor */ -+ if (m == selmon || 1) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -@@ -1987,9 +1987,11 @@ updatesizehints(Client *c) - void - updatestatus(void) - { -+ Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); -- drawbar(selmon); -+ for(m = mons; m; m = m->next) -+ drawbar(m); - } - - void diff --git a/suckless/dwm/patches/dwm-warp-6.4.diff b/suckless/dwm/patches/dwm-warp-6.4.diff deleted file mode 100755 index 02fcdba..0000000 --- a/suckless/dwm/patches/dwm-warp-6.4.diff +++ /dev/null @@ -1,79 +0,0 @@ -From a229c36f51ad6f8b40109ed53c643f242351962a Mon Sep 17 00:00:00 2001 -From: Jonas Dujava -Date: Fri, 26 May 2023 22:14:48 +0200 -Subject: [PATCH] Warp patch - -Warps the mouse cursor to the center of the currently focused -window or screen when the mouse cursor is - (a) on a different screen, or - (b) on top of a different window. - -This version properly handles warping to windows that have not been -mapped yet (before it resulted in a change of the stack order). -See the discussion in (thanks goes to Bakkeby): - https://github.com/bakkeby/patches/issues/60 ---- - dwm.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/dwm.c b/dwm.c -index e5efb6a..7ea6c14 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -228,6 +228,7 @@ static void updatetitle(Client *c); - static void updatewindowtype(Client *c); - static void updatewmhints(Client *c); - static void view(const Arg *arg); -+static void warp(const Client *c); - static Client *wintoclient(Window w); - static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); -@@ -834,6 +835,7 @@ focusmon(const Arg *arg) - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); -+ warp(selmon->sel); - } - - void -@@ -1366,6 +1368,8 @@ restack(Monitor *m) - wc.sibling = c->win; - } - } -+ if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) -+ warp(m->sel); - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - } -@@ -2044,6 +2048,28 @@ view(const Arg *arg) - arrange(selmon); - } - -+void -+warp(const Client *c) -+{ -+ int x, y; -+ -+ if (!c) { -+ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); -+ return; -+ } -+ -+ if (!getrootptr(&x, &y) || -+ (x > c->x - c->bw && -+ y > c->y - c->bw && -+ x < c->x + c->w + c->bw*2 && -+ y < c->y + c->h + c->bw*2) || -+ (y > c->mon->by && y < c->mon->by + bh) || -+ (c->mon->topbar && !y)) -+ return; -+ -+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -+} -+ - Client * - wintoclient(Window w) - { --- -2.40.1 - diff --git a/suckless/dwm/patches/dwm-xrdb-6.4.diff b/suckless/dwm/patches/dwm-xrdb-6.4.diff deleted file mode 100755 index 929b4e6..0000000 --- a/suckless/dwm/patches/dwm-xrdb-6.4.diff +++ /dev/null @@ -1,203 +0,0 @@ -From e7c65d2ce902a19a20daa751b42f8ba0209fdb61 Mon Sep 17 00:00:00 2001 -From: NekoCWD -Date: Sun, 22 Jan 2023 23:42:57 +0300 -Subject: [PATCH] [dwm] xrdb update 6.4 - ---- - config.def.h | 22 ++++++++++--------- - drw.c | 2 +- - drw.h | 2 +- - dwm.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 76 insertions(+), 12 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 061ad66..686b947 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -7,15 +7,16 @@ static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; --static const char col_gray1[] = "#222222"; --static const char col_gray2[] = "#444444"; --static const char col_gray3[] = "#bbbbbb"; --static const char col_gray4[] = "#eeeeee"; --static const char col_cyan[] = "#005577"; --static const char *colors[][3] = { -- /* fg bg border */ -- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -+static char normbgcolor[] = "#222222"; -+static char normbordercolor[] = "#444444"; -+static char normfgcolor[] = "#bbbbbb"; -+static char selfgcolor[] = "#eeeeee"; -+static char selbordercolor[] = "#005577"; -+static char selbgcolor[] = "#005577"; -+static char *colors[][3] = { -+ /* fg bg border */ -+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, -+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, - }; - - /* tagging */ -@@ -56,7 +57,7 @@ static const Layout layouts[] = { - #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - - /* commands */ --static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; - static const char *termcmd[] = { "st", NULL }; - - static const Key keys[] = { -@@ -84,6 +85,7 @@ static const Key keys[] = { - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ { MODKEY, XK_F5, xrdb, {.v = NULL } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) -diff --git a/drw.c b/drw.c -index a58a2b4..f8a82f5 100644 ---- a/drw.c -+++ b/drw.c -@@ -195,7 +195,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *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) -+drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount) - { - size_t i; - Clr *ret; -diff --git a/drw.h b/drw.h -index 6471431..bdbf950 100644 ---- a/drw.h -+++ b/drw.h -@@ -40,7 +40,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in - - /* 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); -+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); - - /* Cursor abstraction */ - Cur *drw_cur_create(Drw *drw, int shape); -diff --git a/dwm.c b/dwm.c -index e5efb6a..3fe76be 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - #include - #ifdef XINERAMA - #include -@@ -56,6 +57,21 @@ - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) - #define TAGMASK ((1 << LENGTH(tags)) - 1) - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ -+ if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ -+ int i = 1; \ -+ for (; i <= 6; i++) { \ -+ if (value.addr[i] < 48) break; \ -+ if (value.addr[i] > 57 && value.addr[i] < 65) break; \ -+ if (value.addr[i] > 70 && value.addr[i] < 97) break; \ -+ if (value.addr[i] > 102) break; \ -+ } \ -+ if (i == 7) { \ -+ strncpy(V, value.addr, 7); \ -+ V[7] = '\0'; \ -+ } \ -+ } \ -+ } - - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -@@ -178,6 +194,7 @@ static void grabkeys(void); - static void incnmaster(const Arg *arg); - static void keypress(XEvent *e); - static void killclient(const Arg *arg); -+static void loadxrdb(void); - static void manage(Window w, XWindowAttributes *wa); - static void mappingnotify(XEvent *e); - static void maprequest(XEvent *e); -@@ -233,6 +250,7 @@ static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); -+static void xrdb(const Arg *arg); - static void zoom(const Arg *arg); - - /* variables */ -@@ -1019,6 +1037,37 @@ killclient(const Arg *arg) - } - } - -+void -+loadxrdb() -+{ -+ Display *display; -+ char * resm; -+ XrmDatabase xrdb; -+ char *type; -+ XrmValue value; -+ -+ display = XOpenDisplay(NULL); -+ -+ if (display != NULL) { -+ resm = XResourceManagerString(display); -+ -+ if (resm != NULL) { -+ xrdb = XrmGetStringDatabase(resm); -+ -+ if (xrdb != NULL) { -+ XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); -+ XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); -+ XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); -+ XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); -+ XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); -+ XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); -+ } -+ } -+ } -+ -+ XCloseDisplay(display); -+} -+ - void - manage(Window w, XWindowAttributes *wa) - { -@@ -2110,6 +2159,17 @@ xerrorstart(Display *dpy, XErrorEvent *ee) - return -1; - } - -+void -+xrdb(const Arg *arg) -+{ -+ loadxrdb(); -+ int i; -+ for (i = 0; i < LENGTH(colors); i++) -+ scheme[i] = drw_scm_create(drw, colors[i], 3); -+ focus(NULL); -+ arrange(NULL); -+} -+ - void - zoom(const Arg *arg) - { -@@ -2134,6 +2194,8 @@ main(int argc, char *argv[]) - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); -+ XrmInitialize(); -+ loadxrdb(); - setup(); - #ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) --- -2.38.2 - diff --git a/suckless/dwm/patches/hidevacanttags.diff b/suckless/dwm/patches/hidevacanttags.diff deleted file mode 100644 index 42d9c05..0000000 --- a/suckless/dwm/patches/hidevacanttags.diff +++ /dev/null @@ -1,48 +0,0 @@ -:100644 100644 f1d86b2 0000000 M dwm.c - -diff --git a/dwm.c b/dwm.c -index f1d86b2..d41cc14 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -433,9 +433,15 @@ buttonpress(XEvent *e) - } - if (ev->window == selmon->barwin) { - i = x = 0; -- do -+ unsigned int occ = 0; -+ for(c = m->clients; c; c=c->next) -+ occ |= c->tags == TAGMASK ? 0 : c->tags; -+ do { -+ /* Do not reserve space for vacant tags */ -+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - x += TEXTW(tags[i]); -- while (ev->x >= x && ++i < LENGTH(tags)); -+ } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -@@ -715,19 +721,18 @@ drawbar(Monitor *m) - } - - for (c = m->clients; c; c = c->next) { -- occ |= c->tags; -+ occ |= c->tags == TAGMASK ? 0 : c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -+ /* Do not draw vacant tags */ -+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -- if (occ & 1 << i) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, -- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); diff --git a/suckless/dwm/readme.dwm.txt b/suckless/dwm/readme.dwm.txt deleted file mode 100644 index 95d4fd0..0000000 --- a/suckless/dwm/readme.dwm.txt +++ /dev/null @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dwm is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -Running dwm ------------ -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -Configuration -------------- -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/suckless/dwm/transient.c b/suckless/dwm/transient.c deleted file mode 100644 index 040adb5..0000000 --- a/suckless/dwm/transient.c +++ /dev/null @@ -1,42 +0,0 @@ -/* cc transient.c -o transient -lX11 */ - -#include -#include -#include -#include - -int main(void) { - Display *d; - Window r, f, t = None; - XSizeHints h; - XEvent e; - - d = XOpenDisplay(NULL); - if (!d) - exit(1); - r = DefaultRootWindow(d); - - f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); - h.min_width = h.max_width = h.min_height = h.max_height = 400; - h.flags = PMinSize | PMaxSize; - XSetWMNormalHints(d, f, &h); - XStoreName(d, f, "floating"); - XMapWindow(d, f); - - XSelectInput(d, f, ExposureMask); - while (1) { - XNextEvent(d, &e); - - if (t == None) { - sleep(5); - t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); - XSetTransientForHint(d, t, f); - XStoreName(d, t, "transient"); - XMapWindow(d, t); - XSelectInput(d, t, ExposureMask); - } - } - - XCloseDisplay(d); - exit(0); -} diff --git a/suckless/dwm/util.c b/suckless/dwm/util.c deleted file mode 100644 index 8e26a51..0000000 --- a/suckless/dwm/util.c +++ /dev/null @@ -1,37 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "util.h" - -void -die(const char *fmt, ...) -{ - va_list ap; - int saved_errno; - - saved_errno = errno; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(saved_errno)); - fputc('\n', stderr); - - exit(1); -} - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} diff --git a/suckless/dwm/util.h b/suckless/dwm/util.h deleted file mode 100644 index c0a50d4..0000000 --- a/suckless/dwm/util.h +++ /dev/null @@ -1,9 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) -#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size); diff --git a/suckless/dwm/util.o b/suckless/dwm/util.o deleted file mode 100644 index 5dd48bf..0000000 Binary files a/suckless/dwm/util.o and /dev/null differ diff --git a/suckless/dwmblocks b/suckless/dwmblocks deleted file mode 160000 index 8cedd22..0000000 --- a/suckless/dwmblocks +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8cedd220684064f1433749ed2a19a6184c22cf07 diff --git a/suckless/slstatus/LICENSE b/suckless/slstatus/LICENSE deleted file mode 100644 index 8bee9c8..0000000 --- a/suckless/slstatus/LICENSE +++ /dev/null @@ -1,43 +0,0 @@ -ISC License - -Copyright 2016-2022 Aaron Marcher - -Copyright 2016 Roy Freytag -Copyright 2016 Vincent Loupmon -Copyright 2016 Daniel Walter -Copyright 2016-2018 Ali H. Fardan -Copyright 2016 Jody Leonard -Copyright 2016-2018 Quentin Rameau -Copyright 2016 Mike Coddington -Copyright 2016-2018 Ivan J. -Copyright 2017 Tobias Stoeckmann -Copyright 2017-2018 Laslo Hunhold -Copyright 2018 Darron Anderson -Copyright 2018 Josuah Demangeon -Copyright 2018 Tobias Tschinkowitz -Copyright 2018 David Demelier -Copyright 2018-2012 Michael Buch -Copyright 2018 Ian Remmler -Copyright 2016-2019 Joerg Jung -Copyright 2019 Ryan Kes -Copyright 2019 Cem Keylan -Copyright 2019 Dimitris Papastamos -Copyright 2019-2022 Ingo Feinerer -Copyright 2020 Alexandre Ratchov -Copyright 2020 Mart Lubbers -Copyright 2020 Daniel Moch -Copyright 2022 Nickolas Raymond Kaczynski -Copyright 2022 Patrick Iacob -Copyright 2021-2022 Steven Ward - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/suckless/slstatus/Makefile b/suckless/slstatus/Makefile deleted file mode 100644 index 7a18274..0000000 --- a/suckless/slstatus/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# See LICENSE file for copyright and license details -# slstatus - suckless status monitor -.POSIX: - -include config.mk - -REQ = util -COM =\ - components/battery\ - components/cat\ - components/cpu\ - components/datetime\ - components/disk\ - components/entropy\ - components/hostname\ - components/ip\ - components/kernel_release\ - components/keyboard_indicators\ - components/keymap\ - components/load_avg\ - components/netspeeds\ - components/num_files\ - components/ram\ - components/run_command\ - components/swap\ - components/temperature\ - components/uptime\ - components/user\ - components/volume\ - components/wifi - -all: slstatus - -$(COM:=.o): config.mk $(REQ:=.h) slstatus.h -slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) - -.c.o: - $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< - -config.h: - cp config.def.h $@ - -slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) - $(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) - -clean: - rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz - -dist: - rm -rf "slstatus-$(VERSION)" - mkdir -p "slstatus-$(VERSION)/components" - cp -R LICENSE Makefile README config.mk config.def.h \ - arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ - slstatus.1 "slstatus-$(VERSION)" - cp -R $(COM:=.c) "slstatus-$(VERSION)/components" - tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" - rm -rf "slstatus-$(VERSION)" - -install: all - mkdir -p "$(DESTDIR)$(PREFIX)/bin" - cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" - chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" - mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" - cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" - chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" - -uninstall: - rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" - rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" diff --git a/suckless/slstatus/arg.h b/suckless/slstatus/arg.h deleted file mode 100644 index 5f1f408..0000000 --- a/suckless/slstatus/arg.h +++ /dev/null @@ -1,33 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef ARG_H -#define ARG_H - -extern char *argv0; - -/* int main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \ - *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ - int i_, argused_; \ - if ((*argv)[1] == '-' && !(*argv)[2]) { \ - argc--, argv++; \ - break; \ - } \ - for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \ - switch ((*argv)[i_]) -#define ARGEND if (argused_) { \ - if ((*argv)[i_ + 1]) { \ - break; \ - } else { \ - argc--, argv++; \ - break; \ - } \ - } \ - } \ - } -#define ARGC() ((*argv)[i_]) -#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \ - (*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x)) -#define EARGF(x) ARGF_(((x), exit(1), (char *)0)) -#define ARGF() ARGF_((char *)0) - -#endif diff --git a/suckless/slstatus/components/battery.c b/suckless/slstatus/components/battery.c deleted file mode 100644 index d5ef9ea..0000000 --- a/suckless/slstatus/components/battery.c +++ /dev/null @@ -1,247 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) -/* - * https://www.kernel.org/doc/html/latest/power/power_supply_class.html - */ - #include - #include - #include - - #define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" - #define POWER_SUPPLY_STATUS "/sys/class/power_supply/%s/status" - #define POWER_SUPPLY_CHARGE "/sys/class/power_supply/%s/charge_now" - #define POWER_SUPPLY_ENERGY "/sys/class/power_supply/%s/energy_now" - #define POWER_SUPPLY_CURRENT "/sys/class/power_supply/%s/current_now" - #define POWER_SUPPLY_POWER "/sys/class/power_supply/%s/power_now" - - static const char * - pick(const char *bat, const char *f1, const char *f2, char *path, - size_t length) - { - if (esnprintf(path, length, f1, bat) > 0 && - access(path, R_OK) == 0) - return f1; - - if (esnprintf(path, length, f2, bat) > 0 && - access(path, R_OK) == 0) - return f2; - - return NULL; - } - - const char * - battery_perc(const char *bat) - { - int cap_perc; - char path[PATH_MAX]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) - return NULL; - if (pscanf(path, "%d", &cap_perc) != 1) - return NULL; - - return bprintf("%d", cap_perc); - } - - const char * - battery_state(const char *bat) - { - static struct { - char *state; - char *symbol; - } map[] = { - { "Charging", "󰚥" }, - { "Discharging", "󰚦" }, - { "Full", "󰚥" }, - { "Not charging", "󰚥"}, - }; - size_t i; - char path[PATH_MAX], state[12]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) - return NULL; - if (pscanf(path, "%12[a-zA-Z ]", state) != 1) - return NULL; - - for (i = 0; i < LEN(map); i++) - if (!strcmp(map[i].state, state)) - break; - - return (i == LEN(map)) ? "?" : map[i].symbol; - } - - const char * - battery_remaining(const char *bat) - { - uintmax_t charge_now, current_now, m, h; - double timeleft; - char path[PATH_MAX], state[12]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) - return NULL; - if (pscanf(path, "%12[a-zA-Z ]", state) != 1) - return NULL; - - if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, - sizeof(path)) || - pscanf(path, "%ju", &charge_now) < 0) - return NULL; - - if (!strcmp(state, "Discharging")) { - if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, - sizeof(path)) || - pscanf(path, "%ju", ¤t_now) < 0) - return NULL; - - if (current_now == 0) - return NULL; - - timeleft = (double)charge_now / (double)current_now; - h = timeleft; - m = (timeleft - (double)h) * 60; - - return bprintf("%juh %jum", h, m); - } - - return ""; - } -#elif defined(__OpenBSD__) - #include - #include - #include - #include - - static int - load_apm_power_info(struct apm_power_info *apm_info) - { - int fd; - - fd = open("/dev/apm", O_RDONLY); - if (fd < 0) { - warn("open '/dev/apm':"); - return 0; - } - - memset(apm_info, 0, sizeof(struct apm_power_info)); - if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { - warn("ioctl 'APM_IOC_GETPOWER':"); - close(fd); - return 0; - } - return close(fd), 1; - } - - const char * - battery_perc(const char *unused) - { - struct apm_power_info apm_info; - - if (load_apm_power_info(&apm_info)) - return bprintf("%d", apm_info.battery_life); - - return NULL; - } - - const char * - battery_state(const char *unused) - { - struct { - unsigned int state; - char *symbol; - } map[] = { - { APM_AC_ON, "+" }, - { APM_AC_OFF, "-" }, - }; - struct apm_power_info apm_info; - size_t i; - - if (load_apm_power_info(&apm_info)) { - for (i = 0; i < LEN(map); i++) - if (map[i].state == apm_info.ac_state) - break; - - return (i == LEN(map)) ? "?" : map[i].symbol; - } - - return NULL; - } - - const char * - battery_remaining(const char *unused) - { - struct apm_power_info apm_info; - unsigned int h, m; - - if (load_apm_power_info(&apm_info)) { - if (apm_info.ac_state != APM_AC_ON) { - h = apm_info.minutes_left / 60; - m = apm_info.minutes_left % 60; - return bprintf("%uh %02um", h, m); - } else { - return ""; - } - } - - return NULL; - } -#elif defined(__FreeBSD__) - #include - - #define BATTERY_LIFE "hw.acpi.battery.life" - #define BATTERY_STATE "hw.acpi.battery.state" - #define BATTERY_TIME "hw.acpi.battery.time" - - const char * - battery_perc(const char *unused) - { - int cap_perc; - size_t len; - - len = sizeof(cap_perc); - if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) - return NULL; - - return bprintf("%d", cap_perc); - } - - const char * - battery_state(const char *unused) - { - int state; - size_t len; - - len = sizeof(state); - if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) - return NULL; - - switch (state) { - case 0: /* FALLTHROUGH */ - case 2: - return "+"; - case 1: - return "-"; - default: - return "?"; - } - } - - const char * - battery_remaining(const char *unused) - { - int rem; - size_t len; - - len = sizeof(rem); - if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len - || rem < 0) - return NULL; - - return bprintf("%uh %02um", rem / 60, rem % 60); - } -#endif diff --git a/suckless/slstatus/components/battery.o b/suckless/slstatus/components/battery.o deleted file mode 100644 index 28b2ca7..0000000 Binary files a/suckless/slstatus/components/battery.o and /dev/null differ diff --git a/suckless/slstatus/components/cat.c b/suckless/slstatus/components/cat.c deleted file mode 100644 index 07944cc..0000000 --- a/suckless/slstatus/components/cat.c +++ /dev/null @@ -1,32 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -cat(const char *path) -{ - char *f; - FILE *fp; - - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); - return NULL; - } - - f = fgets(buf, sizeof(buf) - 1, fp); - if (fclose(fp) < 0) { - warn("fclose '%s':", path); - return NULL; - } - if (!f) - return NULL; - - if ((f = strrchr(buf, '\n'))) - f[0] = '\0'; - - return buf[0] ? buf : NULL; -} - diff --git a/suckless/slstatus/components/cat.o b/suckless/slstatus/components/cat.o deleted file mode 100644 index b861349..0000000 Binary files a/suckless/slstatus/components/cat.o and /dev/null differ diff --git a/suckless/slstatus/components/cpu.c b/suckless/slstatus/components/cpu.c deleted file mode 100644 index d0d03c7..0000000 --- a/suckless/slstatus/components/cpu.c +++ /dev/null @@ -1,157 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" - - const char * - cpu_freq(const char *unused) - { - uintmax_t freq; - - /* in kHz */ - if (pscanf(CPU_FREQ, "%ju", &freq) != 1) - return NULL; - - return fmt_human(freq * 1000, 1000); - } - - const char * - cpu_perc(const char *unused) - { - static long double a[7]; - long double b[7], sum; - - memcpy(b, a, sizeof(b)); - /* cpu user nice system idle iowait irq softirq */ - if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", - &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) - != 7) - return NULL; - - if (b[0] == 0) - return NULL; - - sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - - (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); - - if (sum == 0) - return NULL; - - return bprintf("%d", (int)(100 * - ((b[0] + b[1] + b[2] + b[5] + b[6]) - - (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); - } -#elif defined(__OpenBSD__) - #include - #include - #include - - const char * - cpu_freq(const char *unused) - { - int freq, mib[2]; - size_t size; - - mib[0] = CTL_HW; - mib[1] = HW_CPUSPEED; - - size = sizeof(freq); - - /* in MHz */ - if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { - warn("sysctl 'HW_CPUSPEED':"); - return NULL; - } - - return fmt_human(freq * 1E6, 1000); - } - - const char * - cpu_perc(const char *unused) - { - int mib[2]; - static uintmax_t a[CPUSTATES]; - uintmax_t b[CPUSTATES], sum; - size_t size; - - mib[0] = CTL_KERN; - mib[1] = KERN_CPTIME; - - size = sizeof(a); - - memcpy(b, a, sizeof(b)); - if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { - warn("sysctl 'KERN_CPTIME':"); - return NULL; - } - if (b[0] == 0) - return NULL; - - sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); - - if (sum == 0) - return NULL; - - return bprintf("%d", 100 * - ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + - a[CP_INTR]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + - b[CP_INTR])) / sum); - } -#elif defined(__FreeBSD__) - #include - #include - #include - - const char * - cpu_freq(const char *unused) - { - int freq; - size_t size; - - size = sizeof(freq); - /* in MHz */ - if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { - warn("sysctlbyname 'hw.clockrate':"); - return NULL; - } - - return fmt_human(freq * 1E6, 1000); - } - - const char * - cpu_perc(const char *unused) - { - size_t size; - static long a[CPUSTATES]; - long b[CPUSTATES], sum; - - size = sizeof(a); - memcpy(b, a, sizeof(b)); - if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { - warn("sysctlbyname 'kern.cp_time':"); - return NULL; - } - if (b[0] == 0) - return NULL; - - sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); - - if (sum == 0) - return NULL; - - return bprintf("%d", 100 * - ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + - a[CP_INTR]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + - b[CP_INTR])) / sum); - } -#endif diff --git a/suckless/slstatus/components/cpu.o b/suckless/slstatus/components/cpu.o deleted file mode 100644 index 8b3d1b1..0000000 Binary files a/suckless/slstatus/components/cpu.o and /dev/null differ diff --git a/suckless/slstatus/components/datetime.c b/suckless/slstatus/components/datetime.c deleted file mode 100644 index 5b10daf..0000000 --- a/suckless/slstatus/components/datetime.c +++ /dev/null @@ -1,20 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -datetime(const char *fmt) -{ - time_t t; - - t = time(NULL); - if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { - warn("strftime: Result string exceeds buffer size"); - return NULL; - } - - return buf; -} diff --git a/suckless/slstatus/components/datetime.o b/suckless/slstatus/components/datetime.o deleted file mode 100644 index 9181ae6..0000000 Binary files a/suckless/slstatus/components/datetime.o and /dev/null differ diff --git a/suckless/slstatus/components/disk.c b/suckless/slstatus/components/disk.c deleted file mode 100644 index e19a693..0000000 --- a/suckless/slstatus/components/disk.c +++ /dev/null @@ -1,59 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -disk_free(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * fs.f_bavail, 1024); -} - -const char * -disk_perc(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return bprintf("%d", (int)(100 * - (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); -} - -const char * -disk_total(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * fs.f_blocks, 1024); -} - -const char * -disk_used(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); -} diff --git a/suckless/slstatus/components/disk.o b/suckless/slstatus/components/disk.o deleted file mode 100644 index edb3cfb..0000000 Binary files a/suckless/slstatus/components/disk.o and /dev/null differ diff --git a/suckless/slstatus/components/entropy.c b/suckless/slstatus/components/entropy.c deleted file mode 100644 index 65010b0..0000000 --- a/suckless/slstatus/components/entropy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "../slstatus.h" -#if defined(__linux__) - #include - #include - - #include "../util.h" - - #define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" - - const char * - entropy(const char *unused) - { - uintmax_t num; - - if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) - return NULL; - - return bprintf("%ju", num); - } -#elif defined(__OpenBSD__) | defined(__FreeBSD__) - const char * - entropy(const char *unused) - { - // https://www.unicode.org/charts/PDF/U2200.pdf - /* Unicode Character 'INFINITY' (U+221E) */ - return "\u221E"; - } -#endif diff --git a/suckless/slstatus/components/entropy.o b/suckless/slstatus/components/entropy.o deleted file mode 100644 index 8547174..0000000 Binary files a/suckless/slstatus/components/entropy.o and /dev/null differ diff --git a/suckless/slstatus/components/hostname.c b/suckless/slstatus/components/hostname.c deleted file mode 100644 index dab8b63..0000000 --- a/suckless/slstatus/components/hostname.c +++ /dev/null @@ -1,17 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -hostname(const char *unused) -{ - if (gethostname(buf, sizeof(buf)) < 0) { - warn("gethostbyname:"); - return NULL; - } - - return buf; -} diff --git a/suckless/slstatus/components/hostname.o b/suckless/slstatus/components/hostname.o deleted file mode 100644 index 20e1d33..0000000 Binary files a/suckless/slstatus/components/hostname.o and /dev/null differ diff --git a/suckless/slstatus/components/ip.c b/suckless/slstatus/components/ip.c deleted file mode 100644 index 9476549..0000000 --- a/suckless/slstatus/components/ip.c +++ /dev/null @@ -1,61 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#if defined(__OpenBSD__) - #include - #include -#elif defined(__FreeBSD__) - #include - #include -#endif - -#include "../slstatus.h" -#include "../util.h" - -static const char * -ip(const char *interface, unsigned short sa_family) -{ - struct ifaddrs *ifaddr, *ifa; - int s; - char host[NI_MAXHOST]; - - if (getifaddrs(&ifaddr) < 0) { - warn("getifaddrs:"); - return NULL; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - - s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (!strcmp(ifa->ifa_name, interface) && - (ifa->ifa_addr->sa_family == sa_family)) { - freeifaddrs(ifaddr); - if (s != 0) { - warn("getnameinfo: %s", gai_strerror(s)); - return NULL; - } - return bprintf("%s", host); - } - } - - freeifaddrs(ifaddr); - - return NULL; -} - -const char * -ipv4(const char *interface) -{ - return ip(interface, AF_INET); -} - -const char * -ipv6(const char *interface) -{ - return ip(interface, AF_INET6); -} diff --git a/suckless/slstatus/components/ip.o b/suckless/slstatus/components/ip.o deleted file mode 100644 index e1543a5..0000000 Binary files a/suckless/slstatus/components/ip.o and /dev/null differ diff --git a/suckless/slstatus/components/kernel_release.c b/suckless/slstatus/components/kernel_release.c deleted file mode 100644 index 36a6a44..0000000 --- a/suckless/slstatus/components/kernel_release.c +++ /dev/null @@ -1,19 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -kernel_release(const char *unused) -{ - struct utsname udata; - - if (uname(&udata) < 0) { - warn("uname:"); - return NULL; - } - - return bprintf("%s", udata.release); -} diff --git a/suckless/slstatus/components/kernel_release.o b/suckless/slstatus/components/kernel_release.o deleted file mode 100644 index 978d5f9..0000000 Binary files a/suckless/slstatus/components/kernel_release.o and /dev/null differ diff --git a/suckless/slstatus/components/keyboard_indicators.c b/suckless/slstatus/components/keyboard_indicators.c deleted file mode 100644 index 5f62bb7..0000000 --- a/suckless/slstatus/components/keyboard_indicators.c +++ /dev/null @@ -1,50 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -/* - * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num - * lock, each optionally followed by '?', in the order of indicators desired. - * If followed by '?', the letter with case preserved is included in the output - * if the corresponding indicator is on. Otherwise, the letter is always - * included, lowercase when off and uppercase when on. - */ -const char * -keyboard_indicators(const char *fmt) -{ - Display *dpy; - XKeyboardState state; - size_t fmtlen, i, n; - int togglecase, isset; - char key; - - if (!(dpy = XOpenDisplay(NULL))) { - warn("XOpenDisplay: Failed to open display"); - return NULL; - } - XGetKeyboardControl(dpy, &state); - XCloseDisplay(dpy); - - fmtlen = strnlen(fmt, 4); - for (i = n = 0; i < fmtlen; i++) { - key = tolower(fmt[i]); - if (key != 'c' && key != 'n') - continue; - - togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); - isset = (state.led_mask & (1 << (key == 'n'))); - - if (togglecase) - buf[n++] = isset ? toupper(key) : key; - else if (isset) - buf[n++] = fmt[i]; - } - - buf[n] = 0; - return buf; -} diff --git a/suckless/slstatus/components/keyboard_indicators.o b/suckless/slstatus/components/keyboard_indicators.o deleted file mode 100644 index 7df304b..0000000 Binary files a/suckless/slstatus/components/keyboard_indicators.o and /dev/null differ diff --git a/suckless/slstatus/components/keymap.c b/suckless/slstatus/components/keymap.c deleted file mode 100644 index f8a2a47..0000000 --- a/suckless/slstatus/components/keymap.c +++ /dev/null @@ -1,86 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -static int -valid_layout_or_variant(char *sym) -{ - size_t i; - /* invalid symbols from xkb rules config */ - static const char *invalid[] = { "evdev", "inet", "pc", "base" }; - - for (i = 0; i < LEN(invalid); i++) - if (!strncmp(sym, invalid[i], strlen(invalid[i]))) - return 0; - - return 1; -} - -static char * -get_layout(char *syms, int grp_num) -{ - char *tok, *layout; - int grp; - - layout = NULL; - tok = strtok(syms, "+:"); - for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) { - if (!valid_layout_or_variant(tok)) { - continue; - } else if (strlen(tok) == 1 && isdigit(tok[0])) { - /* ignore :2, :3, :4 (additional layout groups) */ - continue; - } - layout = tok; - grp++; - } - - return layout; -} - -const char * -keymap(const char *unused) -{ - Display *dpy; - XkbDescRec *desc; - XkbStateRec state; - char *symbols; - const char *layout; - - layout = NULL; - - if (!(dpy = XOpenDisplay(NULL))) { - warn("XOpenDisplay: Failed to open display"); - return NULL; - } - if (!(desc = XkbAllocKeyboard())) { - warn("XkbAllocKeyboard: Failed to allocate keyboard"); - goto end; - } - if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { - warn("XkbGetNames: Failed to retrieve key symbols"); - goto end; - } - if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { - warn("XkbGetState: Failed to retrieve keyboard state"); - goto end; - } - if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { - warn("XGetAtomName: Failed to get atom name"); - goto end; - } - layout = bprintf("%s", get_layout(symbols, state.group)); - XFree(symbols); -end: - XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); - if (XCloseDisplay(dpy)) - warn("XCloseDisplay: Failed to close display"); - - return layout; -} diff --git a/suckless/slstatus/components/keymap.o b/suckless/slstatus/components/keymap.o deleted file mode 100644 index 5a582c4..0000000 Binary files a/suckless/slstatus/components/keymap.o and /dev/null differ diff --git a/suckless/slstatus/components/load_avg.c b/suckless/slstatus/components/load_avg.c deleted file mode 100644 index f278a40..0000000 --- a/suckless/slstatus/components/load_avg.c +++ /dev/null @@ -1,19 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -load_avg(const char *unused) -{ - double avgs[3]; - - if (getloadavg(avgs, 3) < 0) { - warn("getloadavg: Failed to obtain load average"); - return NULL; - } - - return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); -} diff --git a/suckless/slstatus/components/load_avg.o b/suckless/slstatus/components/load_avg.o deleted file mode 100644 index 735d51d..0000000 Binary files a/suckless/slstatus/components/load_avg.o and /dev/null differ diff --git a/suckless/slstatus/components/netspeeds.c b/suckless/slstatus/components/netspeeds.c deleted file mode 100644 index cde6fa9..0000000 --- a/suckless/slstatus/components/netspeeds.c +++ /dev/null @@ -1,129 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #include - - #define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" - #define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" - - const char * - netspeed_rx(const char *interface) - { - uintmax_t oldrxbytes; - static uintmax_t rxbytes; - extern const unsigned int interval; - char path[PATH_MAX]; - - oldrxbytes = rxbytes; - - if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) - return NULL; - if (pscanf(path, "%ju", &rxbytes) != 1) - return NULL; - if (oldrxbytes == 0) - return NULL; - - return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, - 1024); - } - - const char * - netspeed_tx(const char *interface) - { - uintmax_t oldtxbytes; - static uintmax_t txbytes; - extern const unsigned int interval; - char path[PATH_MAX]; - - oldtxbytes = txbytes; - - if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) - return NULL; - if (pscanf(path, "%ju", &txbytes) != 1) - return NULL; - if (oldtxbytes == 0) - return NULL; - - return fmt_human((txbytes - oldtxbytes) * 1000 / interval, - 1024); - } -#elif defined(__OpenBSD__) | defined(__FreeBSD__) - #include - #include - #include - #include - #include - - const char * - netspeed_rx(const char *interface) - { - struct ifaddrs *ifal, *ifa; - struct if_data *ifd; - uintmax_t oldrxbytes; - static uintmax_t rxbytes; - extern const unsigned int interval; - int if_ok = 0; - - oldrxbytes = rxbytes; - - if (getifaddrs(&ifal) < 0) { - warn("getifaddrs failed"); - return NULL; - } - rxbytes = 0; - for (ifa = ifal; ifa; ifa = ifa->ifa_next) - if (!strcmp(ifa->ifa_name, interface) && - (ifd = (struct if_data *)ifa->ifa_data)) - rxbytes += ifd->ifi_ibytes, if_ok = 1; - - freeifaddrs(ifal); - if (!if_ok) { - warn("reading 'if_data' failed"); - return NULL; - } - if (oldrxbytes == 0) - return NULL; - - return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, - 1024); - } - - const char * - netspeed_tx(const char *interface) - { - struct ifaddrs *ifal, *ifa; - struct if_data *ifd; - uintmax_t oldtxbytes; - static uintmax_t txbytes; - extern const unsigned int interval; - int if_ok = 0; - - oldtxbytes = txbytes; - - if (getifaddrs(&ifal) < 0) { - warn("getifaddrs failed"); - return NULL; - } - txbytes = 0; - for (ifa = ifal; ifa; ifa = ifa->ifa_next) - if (!strcmp(ifa->ifa_name, interface) && - (ifd = (struct if_data *)ifa->ifa_data)) - txbytes += ifd->ifi_obytes, if_ok = 1; - - freeifaddrs(ifal); - if (!if_ok) { - warn("reading 'if_data' failed"); - return NULL; - } - if (oldtxbytes == 0) - return NULL; - - return fmt_human((txbytes - oldtxbytes) * 1000 / interval, - 1024); - } -#endif diff --git a/suckless/slstatus/components/netspeeds.o b/suckless/slstatus/components/netspeeds.o deleted file mode 100644 index 4afd7ae..0000000 Binary files a/suckless/slstatus/components/netspeeds.o and /dev/null differ diff --git a/suckless/slstatus/components/num_files.c b/suckless/slstatus/components/num_files.c deleted file mode 100644 index df0acd1..0000000 --- a/suckless/slstatus/components/num_files.c +++ /dev/null @@ -1,32 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -num_files(const char *path) -{ - struct dirent *dp; - DIR *dir; - int num; - - if (!(dir = opendir(path))) { - warn("opendir '%s':", path); - return NULL; - } - - num = 0; - while ((dp = readdir(dir))) { - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; /* skip self and parent */ - - num++; - } - - closedir(dir); - - return bprintf("%d", num); -} diff --git a/suckless/slstatus/components/num_files.o b/suckless/slstatus/components/num_files.o deleted file mode 100644 index a347143..0000000 Binary files a/suckless/slstatus/components/num_files.o and /dev/null differ diff --git a/suckless/slstatus/components/pixVol.sh b/suckless/slstatus/components/pixVol.sh deleted file mode 100644 index 8f59505..0000000 --- a/suckless/slstatus/components/pixVol.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -volume=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -n 1 | tr -d '%') -muted=$(pactl get-sink-mute @DEFAULT_SINK@ | awk '{print $2}') - -if [ "$muted" = "yes" ]; then - echo "Muted" -else - echo "${volume}" -fi diff --git a/suckless/slstatus/components/ram.c b/suckless/slstatus/components/ram.c deleted file mode 100644 index 15c4b74..0000000 --- a/suckless/slstatus/components/ram.c +++ /dev/null @@ -1,212 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #include - - const char * - ram_free(const char *unused) - { - uintmax_t free; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n", - &free, &free, &free) != 3) - return NULL; - - return fmt_human(free * 1024, 1024); - } - - const char * - ram_perc(const char *unused) - { - uintmax_t total, free, buffers, cached; - int percent; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n" - "Buffers: %ju kB\n" - "Cached: %ju kB\n", - &total, &free, &buffers, &buffers, &cached) != 5) - return NULL; - - if (total == 0) - return NULL; - - percent = 100 * ((total - free) - (buffers + cached)) / total; - return bprintf("%d", percent); - } - - const char * - ram_total(const char *unused) - { - uintmax_t total; - - if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) - != 1) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - ram_used(const char *unused) - { - uintmax_t total, free, buffers, cached, used; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n" - "Buffers: %ju kB\n" - "Cached: %ju kB\n", - &total, &free, &buffers, &buffers, &cached) != 5) - return NULL; - - used = (total - free - buffers - cached); - return fmt_human(used * 1024, 1024); - } -#elif defined(__OpenBSD__) - #include - #include - #include - #include - - #define LOG1024 10 - #define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024)) - - inline int - load_uvmexp(struct uvmexp *uvmexp) - { - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - size_t size; - - size = sizeof(*uvmexp); - - if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0) - return 1; - - return 0; - } - - const char * - ram_free(const char *unused) - { - struct uvmexp uvmexp; - int free_pages; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - free_pages = uvmexp.npages - uvmexp.active; - return fmt_human(pagetok(free_pages, uvmexp.pageshift) * - 1024, 1024); - } - - const char * - ram_perc(const char *unused) - { - struct uvmexp uvmexp; - int percent; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - percent = uvmexp.active * 100 / uvmexp.npages; - return bprintf("%d", percent); - } - - const char * - ram_total(const char *unused) - { - struct uvmexp uvmexp; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - return fmt_human(pagetok(uvmexp.npages, - uvmexp.pageshift) * 1024, 1024); - } - - const char * - ram_used(const char *unused) - { - struct uvmexp uvmexp; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - return fmt_human(pagetok(uvmexp.active, - uvmexp.pageshift) * 1024, 1024); - } -#elif defined(__FreeBSD__) - #include - #include - #include - #include - - const char * - ram_free(const char *unused) { - struct vmtotal vm_stats; - int mib[] = {CTL_VM, VM_TOTAL}; - size_t len; - - len = sizeof(struct vmtotal); - if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 - || !len) - return NULL; - - return fmt_human(vm_stats.t_free * getpagesize(), 1024); - } - - const char * - ram_total(const char *unused) { - unsigned int npages; - size_t len; - - len = sizeof(npages); - if (sysctlbyname("vm.stats.vm.v_page_count", - &npages, &len, NULL, 0) < 0 || !len) - return NULL; - - return fmt_human(npages * getpagesize(), 1024); - } - - const char * - ram_perc(const char *unused) { - unsigned int npages; - unsigned int active; - size_t len; - - len = sizeof(npages); - if (sysctlbyname("vm.stats.vm.v_page_count", - &npages, &len, NULL, 0) < 0 || !len) - return NULL; - - if (sysctlbyname("vm.stats.vm.v_active_count", - &active, &len, NULL, 0) < 0 || !len) - return NULL; - - return bprintf("%d", active * 100 / npages); - } - - const char * - ram_used(const char *unused) { - unsigned int active; - size_t len; - - len = sizeof(active); - if (sysctlbyname("vm.stats.vm.v_active_count", - &active, &len, NULL, 0) < 0 || !len) - return NULL; - - return fmt_human(active * getpagesize(), 1024); - } -#endif diff --git a/suckless/slstatus/components/ram.o b/suckless/slstatus/components/ram.o deleted file mode 100644 index 7e34de6..0000000 Binary files a/suckless/slstatus/components/ram.o and /dev/null differ diff --git a/suckless/slstatus/components/run_command.c b/suckless/slstatus/components/run_command.c deleted file mode 100644 index 93bf6da..0000000 --- a/suckless/slstatus/components/run_command.c +++ /dev/null @@ -1,31 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -run_command(const char *cmd) -{ - char *p; - FILE *fp; - - if (!(fp = popen(cmd, "r"))) { - warn("popen '%s':", cmd); - return NULL; - } - - p = fgets(buf, sizeof(buf) - 1, fp); - if (pclose(fp) < 0) { - warn("pclose '%s':", cmd); - return NULL; - } - if (!p) - return NULL; - - if ((p = strrchr(buf, '\n'))) - p[0] = '\0'; - - return buf[0] ? buf : NULL; -} diff --git a/suckless/slstatus/components/run_command.o b/suckless/slstatus/components/run_command.o deleted file mode 100644 index 2a88b65..0000000 Binary files a/suckless/slstatus/components/run_command.o and /dev/null differ diff --git a/suckless/slstatus/components/swap.c b/suckless/slstatus/components/swap.c deleted file mode 100644 index f270d93..0000000 --- a/suckless/slstatus/components/swap.c +++ /dev/null @@ -1,274 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - static int - get_swap_info(long *s_total, long *s_free, long *s_cached) - { - FILE *fp; - struct { - const char *name; - const size_t len; - long *var; - } ent[] = { - { "SwapTotal", sizeof("SwapTotal") - 1, s_total }, - { "SwapFree", sizeof("SwapFree") - 1, s_free }, - { "SwapCached", sizeof("SwapCached") - 1, s_cached }, - }; - size_t line_len = 0, i, left; - char *line = NULL; - - /* get number of fields we want to extract */ - for (i = 0, left = 0; i < LEN(ent); i++) - if (ent[i].var) - left++; - - if (!(fp = fopen("/proc/meminfo", "r"))) { - warn("fopen '/proc/meminfo':"); - return 1; - } - - /* read file line by line and extract field information */ - while (left > 0 && getline(&line, &line_len, fp) >= 0) { - for (i = 0; i < LEN(ent); i++) { - if (ent[i].var && - !strncmp(line, ent[i].name, ent[i].len)) { - sscanf(line + ent[i].len + 1, - "%ld kB\n", ent[i].var); - left--; - break; - } - } - } - free(line); - if (ferror(fp)) { - warn("getline '/proc/meminfo':"); - return 1; - } - - fclose(fp); - return 0; - } - - const char * - swap_free(const char *unused) - { - long free; - - if (get_swap_info(NULL, &free, NULL)) - return NULL; - - return fmt_human(free * 1024, 1024); - } - - const char * - swap_perc(const char *unused) - { - long total, free, cached; - - if (get_swap_info(&total, &free, &cached) || total == 0) - return NULL; - - return bprintf("%d", 100 * (total - free - cached) / total); - } - - const char * - swap_total(const char *unused) - { - long total; - - if (get_swap_info(&total, NULL, NULL)) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - swap_used(const char *unused) - { - long total, free, cached; - - if (get_swap_info(&total, &free, &cached)) - return NULL; - - return fmt_human((total - free - cached) * 1024, 1024); - } -#elif defined(__OpenBSD__) - #include - #include - #include - #include - - static int - getstats(int *total, int *used) - { - struct swapent *sep, *fsep; - int rnswap, nswap, i; - - if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) { - warn("swaptctl 'SWAP_NSWAP':"); - return 1; - } - if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) { - warn("calloc 'nswap':"); - return 1; - } - if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) { - warn("swapctl 'SWAP_STATA':"); - return 1; - } - if (nswap != rnswap) { - warn("getstats: SWAP_STATS != SWAP_NSWAP"); - return 1; - } - - *total = 0; - *used = 0; - - for (i = 0; i < rnswap; i++) { - *total += sep->se_nblks >> 1; - *used += sep->se_inuse >> 1; - } - - free(fsep); - - return 0; - } - - const char * - swap_free(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human((total - used) * 1024, 1024); - } - - const char * - swap_perc(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - if (total == 0) - return NULL; - - return bprintf("%d", 100 * used / total); - } - - const char * - swap_total(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - swap_used(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human(used * 1024, 1024); - } -#elif defined(__FreeBSD__) - #include - #include - #include - #include - #include - - static int getswapinfo(struct kvm_swap *swap_info, size_t size) - { - kvm_t *kd; - - kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL); - if (kd == NULL) { - warn("kvm_openfiles '/dev/null':"); - return 0; - } - - if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) { - warn("kvm_getswapinfo:"); - kvm_close(kd); - return 0; - } - - kvm_close(kd); - return 1; - } - - const char * - swap_free(const char *unused) - { - struct kvm_swap swap_info[1]; - long used, total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - used = swap_info[0].ksw_used; - - return fmt_human((total - used) * getpagesize(), 1024); - } - - const char * - swap_perc(const char *unused) - { - struct kvm_swap swap_info[1]; - long used, total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - used = swap_info[0].ksw_used; - - return bprintf("%d", used * 100 / total); - } - - const char * - swap_total(const char *unused) - { - struct kvm_swap swap_info[1]; - long total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - - return fmt_human(total * getpagesize(), 1024); - } - - const char * - swap_used(const char *unused) - { - struct kvm_swap swap_info[1]; - long used; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - used = swap_info[0].ksw_used; - - return fmt_human(used * getpagesize(), 1024); - } -#endif diff --git a/suckless/slstatus/components/swap.o b/suckless/slstatus/components/swap.o deleted file mode 100644 index dfdca6c..0000000 Binary files a/suckless/slstatus/components/swap.o and /dev/null differ diff --git a/suckless/slstatus/components/temperature.c b/suckless/slstatus/components/temperature.c deleted file mode 100644 index 7cf1394..0000000 --- a/suckless/slstatus/components/temperature.c +++ /dev/null @@ -1,73 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include - -#include "../slstatus.h" -#include "../util.h" - - -#if defined(__linux__) - #include - - const char * - temp(const char *file) - { - uintmax_t temp; - - if (pscanf(file, "%ju", &temp) != 1) - return NULL; - - return bprintf("%ju", temp / 1000); - } -#elif defined(__OpenBSD__) - #include - #include /* before for struct timeval */ - #include - #include - - const char * - temp(const char *unused) - { - int mib[5]; - size_t size; - struct sensor temp; - - mib[0] = CTL_HW; - mib[1] = HW_SENSORS; - mib[2] = 0; /* cpu0 */ - mib[3] = SENSOR_TEMP; - mib[4] = 0; /* temp0 */ - - size = sizeof(temp); - - if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) { - warn("sysctl 'SENSOR_TEMP':"); - return NULL; - } - - /* kelvin to celsius */ - return bprintf("%d", (int)((float)(temp.value-273150000) / 1E6)); - } -#elif defined(__FreeBSD__) - #include - #include - #include - - #define ACPI_TEMP "hw.acpi.thermal.%s.temperature" - - const char * - temp(const char *zone) - { - char buf[256]; - int temp; - size_t len; - - len = sizeof(temp); - snprintf(buf, sizeof(buf), ACPI_TEMP, zone); - if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 - || !len) - return NULL; - - /* kelvin to decimal celcius */ - return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); - } -#endif diff --git a/suckless/slstatus/components/temperature.o b/suckless/slstatus/components/temperature.o deleted file mode 100644 index 5663e46..0000000 Binary files a/suckless/slstatus/components/temperature.o and /dev/null differ diff --git a/suckless/slstatus/components/uptime.c b/suckless/slstatus/components/uptime.c deleted file mode 100644 index 6227f73..0000000 --- a/suckless/slstatus/components/uptime.c +++ /dev/null @@ -1,34 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(CLOCK_BOOTTIME) - #define UPTIME_FLAG CLOCK_BOOTTIME -#elif defined(CLOCK_UPTIME) - #define UPTIME_FLAG CLOCK_UPTIME -#else - #define UPTIME_FLAG CLOCK_MONOTONIC -#endif - -const char * -uptime(const char *unused) -{ - char warn_buf[256]; - uintmax_t h, m; - struct timespec uptime; - - if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { - snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); - warn(warn_buf); - return NULL; - } - - h = uptime.tv_sec / 3600; - m = uptime.tv_sec % 3600 / 60; - - return bprintf("%juh %jum", h, m); -} diff --git a/suckless/slstatus/components/uptime.o b/suckless/slstatus/components/uptime.o deleted file mode 100644 index aa75195..0000000 Binary files a/suckless/slstatus/components/uptime.o and /dev/null differ diff --git a/suckless/slstatus/components/user.c b/suckless/slstatus/components/user.c deleted file mode 100644 index 3517495..0000000 --- a/suckless/slstatus/components/user.c +++ /dev/null @@ -1,33 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -const char * -gid(const char *unused) -{ - return bprintf("%d", getgid()); -} - -const char * -username(const char *unused) -{ - struct passwd *pw; - - if (!(pw = getpwuid(geteuid()))) { - warn("getpwuid '%d':", geteuid()); - return NULL; - } - - return bprintf("%s", pw->pw_name); -} - -const char * -uid(const char *unused) -{ - return bprintf("%d", geteuid()); -} diff --git a/suckless/slstatus/components/user.o b/suckless/slstatus/components/user.o deleted file mode 100644 index f58bb3a..0000000 Binary files a/suckless/slstatus/components/user.o and /dev/null differ diff --git a/suckless/slstatus/components/volume.c b/suckless/slstatus/components/volume.c deleted file mode 100644 index 6cec556..0000000 --- a/suckless/slstatus/components/volume.c +++ /dev/null @@ -1,219 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__OpenBSD__) | defined(__FreeBSD__) - #include - #include - #include - #include - - struct control { - LIST_ENTRY(control) next; - unsigned int addr; - #define CTRL_NONE 0 - #define CTRL_LEVEL 1 - #define CTRL_MUTE 2 - unsigned int type; - unsigned int maxval; - unsigned int val; - }; - - static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls); - static struct pollfd *pfds; - static struct sioctl_hdl *hdl; - static int initialized; - - /* - * Call-back to obtain the description of all audio controls. - */ - static void - ondesc(void *unused, struct sioctl_desc *desc, int val) - { - struct control *c, *ctmp; - unsigned int type = CTRL_NONE; - - if (desc == NULL) - return; - - /* Delete existing audio control with the same address. */ - LIST_FOREACH_SAFE(c, &controls, next, ctmp) { - if (desc->addr == c->addr) { - LIST_REMOVE(c, next); - free(c); - break; - } - } - - /* Only match output.level and output.mute audio controls. */ - if (desc->group[0] != 0 || - strcmp(desc->node0.name, "output") != 0) - return; - if (desc->type == SIOCTL_NUM && - strcmp(desc->func, "level") == 0) - type = CTRL_LEVEL; - else if (desc->type == SIOCTL_SW && - strcmp(desc->func, "mute") == 0) - type = CTRL_MUTE; - else - return; - - c = malloc(sizeof(struct control)); - if (c == NULL) { - warn("sndio: failed to allocate audio control\n"); - return; - } - - c->addr = desc->addr; - c->type = type; - c->maxval = desc->maxval; - c->val = val; - LIST_INSERT_HEAD(&controls, c, next); - } - - /* - * Call-back invoked whenever an audio control changes. - */ - static void - onval(void *unused, unsigned int addr, unsigned int val) - { - struct control *c; - - LIST_FOREACH(c, &controls, next) { - if (c->addr == addr) - break; - } - c->val = val; - } - - static void - cleanup(void) - { - struct control *c; - - if (hdl) { - sioctl_close(hdl); - hdl = NULL; - } - - free(pfds); - pfds = NULL; - - while (!LIST_EMPTY(&controls)) { - c = LIST_FIRST(&controls); - LIST_REMOVE(c, next); - free(c); - } - } - - static int - init(void) - { - hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); - if (hdl == NULL) { - warn("sndio: cannot open device"); - goto failed; - } - - if (!sioctl_ondesc(hdl, ondesc, NULL)) { - warn("sndio: cannot set control description call-back"); - goto failed; - } - - if (!sioctl_onval(hdl, onval, NULL)) { - warn("sndio: cannot set control values call-back"); - goto failed; - } - - pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd)); - if (pfds == NULL) { - warn("sndio: cannot allocate pollfd structures"); - goto failed; - } - - return 1; - failed: - cleanup(); - return 0; - } - - const char * - vol_perc(const char *unused) - { - struct control *c; - int n, v, value; - - if (!initialized) - initialized = init(); - - if (hdl == NULL) - return NULL; - - n = sioctl_pollfd(hdl, pfds, POLLIN); - if (n > 0) { - n = poll(pfds, n, 0); - if (n > 0) { - if (sioctl_revents(hdl, pfds) & POLLHUP) { - warn("sndio: disconnected"); - cleanup(); - initialized = 0; - return NULL; - } - } - } - - value = 100; - LIST_FOREACH(c, &controls, next) { - if (c->type == CTRL_MUTE && c->val == 1) - value = 0; - else if (c->type == CTRL_LEVEL) { - v = (c->val * 100 + c->maxval / 2) / c->maxval; - /* For multiple channels return the minimum. */ - if (v < value) - value = v; - } - } - - return bprintf("%d", value); - } -#else - #include - - const char * - vol_perc(const char *card) - { - size_t i; - int v, afd, devmask; - char *vnames[] = SOUND_DEVICE_NAMES; - - if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { - warn("open '%s':", card); - return NULL; - } - - if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); - close(afd); - return NULL; - } - for (i = 0; i < LEN(vnames); i++) { - if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { - if (ioctl(afd, MIXER_READ(i), &v) < 0) { - warn("ioctl 'MIXER_READ(%ld)':", i); - close(afd); - return NULL; - } - } - } - - close(afd); - - return bprintf("%d", v & 0xff); - } -#endif diff --git a/suckless/slstatus/components/volume.o b/suckless/slstatus/components/volume.o deleted file mode 100644 index e42a586..0000000 Binary files a/suckless/slstatus/components/volume.o and /dev/null differ diff --git a/suckless/slstatus/components/wifi.c b/suckless/slstatus/components/wifi.c deleted file mode 100644 index 4543d32..0000000 --- a/suckless/slstatus/components/wifi.c +++ /dev/null @@ -1,267 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include - -#include "../slstatus.h" -#include "../util.h" - -#define RSSI_TO_PERC(rssi) \ - rssi >= -50 ? 100 : \ - (rssi <= -100 ? 0 : \ - (2 * (rssi + 100))) - -#if defined(__linux__) - #include - #include - - #define NET_OPERSTATE "/sys/class/net/%s/operstate" - - const char * - wifi_perc(const char *interface) - { - int cur; - size_t i; - char *p, *datastart; - char path[PATH_MAX]; - char status[5]; - FILE *fp; - - if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) - return NULL; - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); - return NULL; - } - p = fgets(status, 5, fp); - fclose(fp); - if (!p || strcmp(status, "up\n") != 0) - return NULL; - - if (!(fp = fopen("/proc/net/wireless", "r"))) { - warn("fopen '/proc/net/wireless':"); - return NULL; - } - - for (i = 0; i < 3; i++) - if (!(p = fgets(buf, sizeof(buf) - 1, fp))) - break; - - fclose(fp); - if (i < 2 || !p) - return NULL; - - if (!(datastart = strstr(buf, interface))) - return NULL; - - datastart = (datastart+(strlen(interface)+1)); - sscanf(datastart + 1, " %*d %d %*d %*d\t\t %*d\t " - "%*d\t\t%*d\t\t %*d\t %*d\t\t %*d", &cur); - - /* 70 is the max of /proc/net/wireless */ - return bprintf("%d", (int)((float)cur / 70 * 100)); - } - - const char * - wifi_essid(const char *interface) - { - static char id[IW_ESSID_MAX_SIZE+1]; - int sockfd; - struct iwreq wreq; - - memset(&wreq, 0, sizeof(struct iwreq)); - wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; - if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", - interface) < 0) - return NULL; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - wreq.u.essid.pointer = id; - if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { - warn("ioctl 'SIOCGIWESSID':"); - close(sockfd); - return NULL; - } - - close(sockfd); - - if (!strcmp(id, "")) - return NULL; - - return id; - } -#elif defined(__OpenBSD__) - #include - #include - #include - #include /* before for NBBY */ - #include - #include - #include - - static int - load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr) - { - struct ieee80211_bssid bssid; - int sockfd; - uint8_t zero_bssid[IEEE80211_ADDR_LEN]; - - memset(&bssid, 0, sizeof(bssid)); - memset(nr, 0, sizeof(struct ieee80211_nodereq)); - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return 0; - } - strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); - if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) { - warn("ioctl 'SIOCG80211BSSID':"); - close(sockfd); - return 0; - } - memset(&zero_bssid, 0, sizeof(zero_bssid)); - if (memcmp(bssid.i_bssid, zero_bssid, - IEEE80211_ADDR_LEN) == 0) { - close(sockfd); - return 0; - } - strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname)); - memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr)); - if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) { - warn("ioctl 'SIOCG80211NODE':"); - close(sockfd); - return 0; - } - - return close(sockfd), 1; - } - - const char * - wifi_perc(const char *interface) - { - struct ieee80211_nodereq nr; - int q; - - if (load_ieee80211_nodereq(interface, &nr)) { - if (nr.nr_max_rssi) - q = IEEE80211_NODEREQ_RSSI(&nr); - else - q = RSSI_TO_PERC(nr.nr_rssi); - - return bprintf("%d", q); - } - - return NULL; - } - - const char * - wifi_essid(const char *interface) - { - struct ieee80211_nodereq nr; - - if (load_ieee80211_nodereq(interface, &nr)) - return bprintf("%s", nr.nr_nwid); - - return NULL; - } -#elif defined(__FreeBSD__) - #include - #include - - int - load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len) - { - char warn_buf[256]; - struct ieee80211req ireq; - memset(&ireq, 0, sizeof(ireq)); - ireq.i_type = type; - ireq.i_data = (caddr_t) data; - ireq.i_len = *len; - - strlcpy(ireq.i_name, interface, sizeof(ireq.i_name)); - if (ioctl(sock, SIOCG80211, &ireq) < 0) { - snprintf(warn_buf, sizeof(warn_buf), - "ioctl: 'SIOCG80211': %d", type); - warn(warn_buf); - return 0; - } - - *len = ireq.i_len; - return 1; - } - - const char * - wifi_perc(const char *interface) - { - union { - struct ieee80211req_sta_req sta; - uint8_t buf[24 * 1024]; - } info; - uint8_t bssid[IEEE80211_ADDR_LEN]; - int rssi_dbm; - int sockfd; - size_t len; - const char *fmt; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - - /* Retreive MAC address of interface */ - len = IEEE80211_ADDR_LEN; - fmt = NULL; - if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len)) - { - /* Retrieve info on station with above BSSID */ - memset(&info, 0, sizeof(info)); - memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid)); - - len = sizeof(info); - if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) { - rssi_dbm = info.sta.info[0].isi_noise + - info.sta.info[0].isi_rssi / 2; - - fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm)); - } - } - - close(sockfd); - return fmt; - } - - const char * - wifi_essid(const char *interface) - { - char ssid[IEEE80211_NWID_LEN + 1]; - size_t len; - int sockfd; - const char *fmt; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - - fmt = NULL; - len = sizeof(ssid); - memset(&ssid, 0, len); - if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) { - if (len < sizeof(ssid)) - len += 1; - else - len = sizeof(ssid); - - ssid[len - 1] = '\0'; - fmt = bprintf("%s", ssid); - } - - close(sockfd); - return fmt; - } -#endif diff --git a/suckless/slstatus/components/wifi.o b/suckless/slstatus/components/wifi.o deleted file mode 100644 index 2c7a79c..0000000 Binary files a/suckless/slstatus/components/wifi.o and /dev/null differ diff --git a/suckless/slstatus/config.def.h b/suckless/slstatus/config.def.h deleted file mode 100644 index 70f58da..0000000 --- a/suckless/slstatus/config.def.h +++ /dev/null @@ -1,81 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* interval between updates (in ms) */ -const unsigned int interval = 1000; - -/* text to show if no value can be retrieved */ -static const char unknown_str[] = "n/a"; - -/* maximum output string length */ -#define MAXLEN 2048 - -/* - * function description argument (example) - * - * battery_perc battery percentage battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_remaining battery remaining HH:MM battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_state battery charging state battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * cat read arbitrary file path - * cpu_freq cpu frequency in MHz NULL - * cpu_perc cpu usage in percent NULL - * datetime date and time format string (%F %T) - * disk_free free disk space in GB mountpoint path (/) - * disk_perc disk usage in percent mountpoint path (/) - * disk_total total disk space in GB mountpoint path (/) - * disk_used used disk space in GB mountpoint path (/) - * entropy available entropy NULL - * gid GID of current user NULL - * hostname hostname NULL - * ipv4 IPv4 address interface name (eth0) - * ipv6 IPv6 address interface name (eth0) - * kernel_release `uname -r` NULL - * keyboard_indicators caps/num lock indicators format string (c?n?) - * see keyboard_indicators.c - * keymap layout (variant) of current NULL - * keymap - * load_avg load average NULL - * netspeed_rx receive network speed interface name (wlan0) - * netspeed_tx transfer network speed interface name (wlan0) - * num_files number of files in a directory path - * (/home/foo/Inbox/cur) - * ram_free free memory in GB NULL - * ram_perc memory usage in percent NULL - * ram_total total memory size in GB NULL - * ram_used used memory in GB NULL - * run_command custom shell command command (echo foo) - * swap_free free swap in GB NULL - * swap_perc swap usage in percent NULL - * swap_total total swap size in GB NULL - * swap_used used swap in GB NULL - * temp temperature in degree celsius sensor file - * (/sys/class/thermal/...) - * NULL on OpenBSD - * thermal zone on FreeBSD - * (tz0, tz1, etc.) - * uid UID of current user NULL - * uptime system uptime NULL - * username username of current user NULL - * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) - * NULL on OpenBSD/FreeBSD - * wifi_essid WiFi ESSID interface name (wlan0) - * wifi_perc WiFi signal in percent interface name (wlan0) - */ -static const struct arg args[] = { - /* function format argument */ - {battery_state, " %s /", "BAT1"}, - {battery_perc, "  %s% |", "BAT1"}, - {run_command, "  %s% |", "light -G | awk '{print int($1)}'"}, - {run_command, "  %s% |", "pamixer --get-volume"}, - {cpu_perc, "  %s% /", NULL}, - {temp, "  %s󰔄 |", "/sys/class/thermal/thermal_zone3/temp"}, - {ram_used, "  %s |", NULL}, - {run_command, " 󰸗 %s |", "date +'%b %d'"}, - {run_command, " 󱑃 %s |", "date +%H:%M"}, - {disk_perc, "  %s% |", "/home"}, - {wifi_essid, "  %s |", "wlan0"}, - {keymap, "  %s ", NULL}, - -}; diff --git a/suckless/slstatus/config.h b/suckless/slstatus/config.h deleted file mode 100644 index 8ae8a78..0000000 --- a/suckless/slstatus/config.h +++ /dev/null @@ -1,74 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* interval between updates (in ms) */ -const unsigned int interval = 1000; - -/* text to show if no value can be retrieved */ -static const char unknown_str[] = "n/a"; - -/* maximum output string length */ -#define MAXLEN 2048 - -/* - * function description argument (example) - * - * battery_perc battery percentage battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_remaining battery remaining HH:MM battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_state battery charging state battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * cat read arbitrary file path - * cpu_freq cpu frequency in MHz NULL - * cpu_perc cpu usage in percent NULL - * datetime date and time format string (%F %T) - * disk_free free disk space in GB mountpoint path (/) - * disk_perc disk usage in percent mountpoint path (/) - * disk_total total disk space in GB mountpoint path (/) - * disk_used used disk space in GB mountpoint path (/) - * entropy available entropy NULL - * gid GID of current user NULL - * hostname hostname NULL - * ipv4 IPv4 address interface name (eth0) - * ipv6 IPv6 address interface name (eth0) - * kernel_release `uname -r` NULL - * keyboard_indicators caps/num lock indicators format string (c?n?) - * see keyboard_indicators.c - * keymap layout (variant) of current NULL - * keymap - * load_avg load average NULL - * netspeed_rx receive network speed interface name (wlan0) - * netspeed_tx transfer network speed interface name (wlan0) - * num_files number of files in a directory path - * (/home/foo/Inbox/cur) - * ram_free free memory in GB NULL - * ram_perc memory usage in percent NULL - * ram_total total memory size in GB NULL - * ram_used used memory in GB NULL - * run_command custom shell command command (echo foo) - * swap_free free swap in GB NULL - * swap_perc swap usage in percent NULL - * swap_total total swap size in GB NULL - * swap_used used swap in GB NULL - * temp temperature in degree celsius sensor file - * (/sys/class/thermal/...) - * NULL on OpenBSD - * thermal zone on FreeBSD - * (tz0, tz1, etc.) - * uid UID of current user NULL - * uptime system uptime NULL - * username username of current user NULL - * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) - * NULL on OpenBSD/FreeBSD - * wifi_essid WiFi ESSID interface name (wlan0) - * wifi_perc WiFi signal in percent interface name (wlan0) - */ -static const struct arg args[] = { - /* function format argument */ - {run_command, "[ %s%]", "amixer get Master | grep -o '[0-9]*%' | head -1"}, - {ram_used, " [ %s] ", NULL}, - {battery_state, "[%s", "BAT1"}, - {battery_perc, " %s%] ", "BAT1"}, - {run_command, "[󱑃 %s] ", "date +%I:%M-%p"}, - -}; diff --git a/suckless/slstatus/config.h~ b/suckless/slstatus/config.h~ deleted file mode 100644 index 81616f0..0000000 --- a/suckless/slstatus/config.h~ +++ /dev/null @@ -1,77 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* interval between updates (in ms) */ -const unsigned int interval = 1000; - -/* text to show if no value can be retrieved */ -static const char unknown_str[] = "n/a"; - -/* maximum output string length */ -#define MAXLEN 2048 - -/* - * function description argument (example) - * - * battery_perc battery percentage battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_remaining battery remaining HH:MM battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_state battery charging state battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * cat read arbitrary file path - * cpu_freq cpu frequency in MHz NULL - * cpu_perc cpu usage in percent NULL - * datetime date and time format string (%F %T) - * disk_free free disk space in GB mountpoint path (/) - * disk_perc disk usage in percent mountpoint path (/) - * disk_total total disk space in GB mountpoint path (/) - * disk_used used disk space in GB mountpoint path (/) - * entropy available entropy NULL - * gid GID of current user NULL - * hostname hostname NULL - * ipv4 IPv4 address interface name (eth0) - * ipv6 IPv6 address interface name (eth0) - * kernel_release `uname -r` NULL - * keyboard_indicators caps/num lock indicators format string (c?n?) - * see keyboard_indicators.c - * keymap layout (variant) of current NULL - * keymap - * load_avg load average NULL - * netspeed_rx receive network speed interface name (wlan0) - * netspeed_tx transfer network speed interface name (wlan0) - * num_files number of files in a directory path - * (/home/foo/Inbox/cur) - * ram_free free memory in GB NULL - * ram_perc memory usage in percent NULL - * ram_total total memory size in GB NULL - * ram_used used memory in GB NULL - * run_command custom shell command command (echo foo) - * swap_free free swap in GB NULL - * swap_perc swap usage in percent NULL - * swap_total total swap size in GB NULL - * swap_used used swap in GB NULL - * temp temperature in degree celsius sensor file - * (/sys/class/thermal/...) - * NULL on OpenBSD - * thermal zone on FreeBSD - * (tz0, tz1, etc.) - * uid UID of current user NULL - * uptime system uptime NULL - * username username of current user NULL - * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) - * NULL on OpenBSD/FreeBSD - * wifi_essid WiFi ESSID interface name (wlan0) - * wifi_perc WiFi signal in percent interface name (wlan0) - */ -static const struct arg args[] = { - /* function format argument */ - {battery_state, " [%s", "BAT1"}, - {battery_perc, " %s% ]", "BAT1"}, - {run_command, " [ %s%] ", "pamixer --get-volume"}, - {cpu_perc, " [ %s%] ", NULL}, - {temp, " [ %s󰔄] ", "/sys/class/thermal/thermal_zone3/temp"}, - {ram_used, " [ %s] ", NULL}, - {run_command, " [󰸗 %s] ", "date +'%b %d'"}, - {run_command, " [󱑃 %s] ", "date +%H:%M"}, - -}; diff --git a/suckless/slstatus/config.mk b/suckless/slstatus/config.mk deleted file mode 100644 index 07af883..0000000 --- a/suckless/slstatus/config.mk +++ /dev/null @@ -1,22 +0,0 @@ -# slstatus version -VERSION = 1.0 - -# customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# flags -CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" -CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os -LDFLAGS = -L$(X11LIB) -s -# OpenBSD: add -lsndio -# FreeBSD: add -lkvm -lsndio -LDLIBS = -lX11 - -# compiler and linker -CC = cc diff --git a/suckless/slstatus/slstatus b/suckless/slstatus/slstatus deleted file mode 100755 index 042803c..0000000 Binary files a/suckless/slstatus/slstatus and /dev/null differ diff --git a/suckless/slstatus/slstatus.1 b/suckless/slstatus/slstatus.1 deleted file mode 100644 index 73e7a60..0000000 --- a/suckless/slstatus/slstatus.1 +++ /dev/null @@ -1,47 +0,0 @@ -.Dd 2023-04-23 -.Dt SLSTATUS 1 -.Os -.Sh NAME -.Nm slstatus -.Nd suckless status -.Sh SYNOPSIS -.Nm -.Op Fl s -.Op Fl 1 -.Sh DESCRIPTION -.Nm -is a small tool for providing system status information to other programs -over the EWMH -.Em WM_NAME -property of the root window (used by -.Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by -only issuing the minimum of system calls required. -.P -By default, -.Nm -outputs to WM_NAME. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl v -Print version information to stderr, then exit. -.It Fl s -Write to stdout instead of WM_NAME. -.It Fl 1 -Write once to stdout and quit. -.El -.Sh CUSTOMIZATION -.Nm -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.Sh SIGNALS -.Nm -responds to the following signals: -.Pp -.Bl -tag -width TERM -compact -.It USR1 -Triggers an instant redraw. -.El -.Sh AUTHORS -See the LICENSE file for the authors. -.Sh SEE ALSO -.Xr dwm 1 diff --git a/suckless/slstatus/slstatus.c b/suckless/slstatus/slstatus.c deleted file mode 100644 index fd31313..0000000 --- a/suckless/slstatus/slstatus.c +++ /dev/null @@ -1,134 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include -#include - -#include "arg.h" -#include "slstatus.h" -#include "util.h" - -struct arg { - const char *(*func)(const char *); - const char *fmt; - const char *args; -}; - -char buf[1024]; -static volatile sig_atomic_t done; -static Display *dpy; - -#include "config.h" - -static void -terminate(const int signo) -{ - if (signo != SIGUSR1) - done = 1; -} - -static void -difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) -{ - res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); - res->tv_nsec = a->tv_nsec - b->tv_nsec + - (a->tv_nsec < b->tv_nsec) * 1E9; -} - -static void -usage(void) -{ - die("usage: %s [-v] [-s] [-1]", argv0); -} - -int -main(int argc, char *argv[]) -{ - struct sigaction act; - struct timespec start, current, diff, intspec, wait; - size_t i, len; - int sflag, ret; - char status[MAXLEN]; - const char *res; - - sflag = 0; - ARGBEGIN { - case 'v': - die("slstatus-"VERSION); - case '1': - done = 1; - /* FALLTHROUGH */ - case 's': - sflag = 1; - break; - default: - usage(); - } ARGEND - - if (argc) - usage(); - - memset(&act, 0, sizeof(act)); - act.sa_handler = terminate; - sigaction(SIGINT, &act, NULL); - sigaction(SIGTERM, &act, NULL); - act.sa_flags |= SA_RESTART; - sigaction(SIGUSR1, &act, NULL); - - if (!sflag && !(dpy = XOpenDisplay(NULL))) - die("XOpenDisplay: Failed to open display"); - - do { - if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) - die("clock_gettime:"); - - status[0] = '\0'; - for (i = len = 0; i < LEN(args); i++) { - if (!(res = args[i].func(args[i].args))) - res = unknown_str; - - if ((ret = esnprintf(status + len, sizeof(status) - len, - args[i].fmt, res)) < 0) - break; - - len += ret; - } - - if (sflag) { - puts(status); - fflush(stdout); - if (ferror(stdout)) - die("puts:"); - } else { - if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) - die("XStoreName: Allocation failed"); - XFlush(dpy); - } - - if (!done) { - if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) - die("clock_gettime:"); - difftimespec(&diff, ¤t, &start); - - intspec.tv_sec = interval / 1000; - intspec.tv_nsec = (interval % 1000) * 1E6; - difftimespec(&wait, &intspec, &diff); - - if (wait.tv_sec >= 0 && - nanosleep(&wait, NULL) < 0 && - errno != EINTR) - die("nanosleep:"); - } - } while (!done); - - if (!sflag) { - XStoreName(dpy, DefaultRootWindow(dpy), NULL); - if (XCloseDisplay(dpy) < 0) - die("XCloseDisplay: Failed to close display"); - } - - return 0; -} diff --git a/suckless/slstatus/slstatus.h b/suckless/slstatus/slstatus.h deleted file mode 100644 index 8ef5874..0000000 --- a/suckless/slstatus/slstatus.h +++ /dev/null @@ -1,84 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* battery */ -const char *battery_perc(const char *); -const char *battery_remaining(const char *); -const char *battery_state(const char *); - -/* cat */ -const char *cat(const char *path); - -/* cpu */ -const char *cpu_freq(const char *unused); -const char *cpu_perc(const char *unused); - -/* datetime */ -const char *datetime(const char *fmt); - -/* disk */ -const char *disk_free(const char *path); -const char *disk_perc(const char *path); -const char *disk_total(const char *path); -const char *disk_used(const char *path); - -/* entropy */ -const char *entropy(const char *unused); - -/* hostname */ -const char *hostname(const char *unused); - -/* ip */ -const char *ipv4(const char *interface); -const char *ipv6(const char *interface); - -/* kernel_release */ -const char *kernel_release(const char *unused); - -/* keyboard_indicators */ -const char *keyboard_indicators(const char *fmt); - -/* keymap */ -const char *keymap(const char *unused); - -/* load_avg */ -const char *load_avg(const char *unused); - -/* netspeeds */ -const char *netspeed_rx(const char *interface); -const char *netspeed_tx(const char *interface); - -/* num_files */ -const char *num_files(const char *path); - -/* ram */ -const char *ram_free(const char *unused); -const char *ram_perc(const char *unused); -const char *ram_total(const char *unused); -const char *ram_used(const char *unused); - -/* run_command */ -const char *run_command(const char *cmd); - -/* swap */ -const char *swap_free(const char *unused); -const char *swap_perc(const char *unused); -const char *swap_total(const char *unused); -const char *swap_used(const char *unused); - -/* temperature */ -const char *temp(const char *); - -/* uptime */ -const char *uptime(const char *unused); - -/* user */ -const char *gid(const char *unused); -const char *uid(const char *unused); -const char *username(const char *unused); - -/* volume */ -const char *vol_perc(const char *card); - -/* wifi */ -const char *wifi_essid(const char *interface); -const char *wifi_perc(const char *interface); diff --git a/suckless/slstatus/slstatus.o b/suckless/slstatus/slstatus.o deleted file mode 100644 index d457825..0000000 Binary files a/suckless/slstatus/slstatus.o and /dev/null differ diff --git a/suckless/slstatus/util.c b/suckless/slstatus/util.c deleted file mode 100644 index bca9b2e..0000000 --- a/suckless/slstatus/util.c +++ /dev/null @@ -1,141 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include - -#include "util.h" - -char *argv0; - -static void -verr(const char *fmt, va_list ap) -{ - vfprintf(stderr, fmt, ap); - - if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } -} - -void -warn(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); -} - -void -die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); - - exit(1); -} - -static int -evsnprintf(char *str, size_t size, const char *fmt, va_list ap) -{ - int ret; - - ret = vsnprintf(str, size, fmt, ap); - - if (ret < 0) { - warn("vsnprintf:"); - return -1; - } else if ((size_t)ret >= size) { - warn("vsnprintf: Output truncated"); - return -1; - } - - return ret; -} - -int -esnprintf(char *str, size_t size, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = evsnprintf(str, size, fmt, ap); - va_end(ap); - - return ret; -} - -const char * -bprintf(const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = evsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - return (ret < 0) ? NULL : buf; -} - -const char * -fmt_human(uintmax_t num, int base) -{ - double scaled; - size_t i, prefixlen; - const char **prefix; - const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", - "Y" }; - const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", - "Zi", "Yi" }; - - switch (base) { - case 1000: - prefix = prefix_1000; - prefixlen = LEN(prefix_1000); - break; - case 1024: - prefix = prefix_1024; - prefixlen = LEN(prefix_1024); - break; - default: - warn("fmt_human: Invalid base"); - return NULL; - } - - scaled = num; - for (i = 0; i < prefixlen && scaled >= base; i++) - scaled /= base; - - return bprintf("%.1f %s", scaled, prefix[i]); -} - -int -pscanf(const char *path, const char *fmt, ...) -{ - FILE *fp; - va_list ap; - int n; - - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); - return -1; - } - va_start(ap, fmt); - n = vfscanf(fp, fmt, ap); - va_end(ap); - fclose(fp); - - return (n == EOF) ? -1 : n; -} diff --git a/suckless/slstatus/util.h b/suckless/slstatus/util.h deleted file mode 100644 index cf4b027..0000000 --- a/suckless/slstatus/util.h +++ /dev/null @@ -1,16 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include - -extern char buf[1024]; - -#define LEN(x) (sizeof(x) / sizeof((x)[0])) - -extern char *argv0; - -void warn(const char *, ...); -void die(const char *, ...); - -int esnprintf(char *str, size_t size, const char *fmt, ...); -const char *bprintf(const char *fmt, ...); -const char *fmt_human(uintmax_t num, int base); -int pscanf(const char *path, const char *fmt, ...); diff --git a/suckless/slstatus/util.o b/suckless/slstatus/util.o deleted file mode 100644 index b5454d1..0000000 Binary files a/suckless/slstatus/util.o and /dev/null differ diff --git a/suckless/st/LEGACY b/suckless/st/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/suckless/st/LEGACY +++ /dev/null @@ -1,17 +0,0 @@ -A STATEMENT ON LEGACY SUPPORT - -In the terminal world there is much cruft that comes from old and unsup‐ -ported terminals that inherit incompatible modes and escape sequences -which noone is able to know, except when he/she comes from that time and -developed a graphical vt100 emulator at that time. - -One goal of st is to only support what is really needed. When you en‐ -counter a sequence which you really need, implement it. But while you -are at it, do not add the other cruft you might encounter while sneek‐ -ing at other terminal emulators. History has bloated them and there is -no real evidence that most of the sequences are used today. - - -Christoph Lohmann <20h@r-36.net> -2012-09-13T07:00:36.081271045+02:00 - diff --git a/suckless/st/LICENSE b/suckless/st/LICENSE deleted file mode 100644 index 3cbf420..0000000 --- a/suckless/st/LICENSE +++ /dev/null @@ -1,34 +0,0 @@ -MIT/X Consortium License - -© 2014-2022 Hiltjo Posthuma -© 2018 Devin J. Pohly -© 2014-2017 Quentin Rameau -© 2009-2012 Aurélien APTEL -© 2008-2017 Anselm R Garbe -© 2012-2017 Roberto E. Vargas Caballero -© 2012-2016 Christoph Lohmann <20h at r-36 dot net> -© 2013 Eon S. Jeon -© 2013 Alexander Sedov -© 2013 Mark Edgar -© 2013-2014 Eric Pruitt -© 2013 Michael Forney -© 2013-2014 Markus Teich -© 2014-2015 Laslo Hunhold - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/suckless/st/Makefile b/suckless/st/Makefile deleted file mode 100644 index dfcea0f..0000000 --- a/suckless/st/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# st - simple terminal -# See LICENSE file for copyright and license details. -.POSIX: - -include config.mk - -SRC = st.c x.c hb.c -OBJ = $(SRC:.c=.o) - -all: st - -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 hb.h -hb.o: st.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 clean dist install uninstall diff --git a/suckless/st/README b/suckless/st/README deleted file mode 100644 index 6a846ed..0000000 --- a/suckless/st/README +++ /dev/null @@ -1,34 +0,0 @@ -st - simple terminal --------------------- -st is a simple terminal emulator for X which sucks less. - - -Requirements ------------- -In order to build st you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (st is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install st (if -necessary as root): - - make clean install - - -Running st ----------- -If you did not install st with make clean install, you must compile -the st terminfo entry with the following command: - - tic -sx st.info - -See the man page for additional details. - -Credits -------- -Based on Aurélien APTEL bt source code. - diff --git a/suckless/st/TODO b/suckless/st/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/suckless/st/TODO +++ /dev/null @@ -1,28 +0,0 @@ -vt emulation ------------- - -* double-height support - -code & interface ----------------- - -* add a simple way to do multiplexing - -drawing -------- -* add diacritics support to xdraws() - * switch to a suckless font drawing library -* make the font cache simpler -* add better support for brightening of the upper colors - -bugs ----- - -* fix shift up/down (shift selection in emacs) -* remove DEC test sequence when appropriate - -misc ----- - - $ grep -nE 'XXX|TODO' st.c - diff --git a/suckless/st/arg.h b/suckless/st/arg.h deleted file mode 100644 index a22e019..0000000 --- a/suckless/st/arg.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - int i_;\ - for (i_ = 1, brk_ = 0, argv_ = argv;\ - argv[0][i_] && !brk_;\ - i_++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][i_];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/suckless/st/boxdraw.c b/suckless/st/boxdraw.c deleted file mode 100644 index 28a92d0..0000000 --- a/suckless/st/boxdraw.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih - * MIT/X Consortium License - */ - -#include -#include "st.h" -#include "boxdraw_data.h" - -/* Rounded non-negative integers division of n / d */ -#define DIV(n, d) (((n) + (d) / 2) / (d)) - -static Display *xdpy; -static Colormap xcmap; -static XftDraw *xd; -static Visual *xvis; - -static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); -static void drawboxlines(int, int, int, int, XftColor *, ushort); - -/* public API */ - -void -boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) -{ - xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; -} - -int -isboxdraw(Rune u) -{ - Rune block = u & ~0xff; - return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || - (boxdraw_braille && block == 0x2800); -} - -/* the "index" is actually the entire shape data encoded as ushort */ -ushort -boxdrawindex(const Glyph *g) -{ - if (boxdraw_braille && (g->u & ~0xff) == 0x2800) - return BRL | (uint8_t)g->u; - if (boxdraw_bold && (g->mode & ATTR_BOLD)) - return BDB | boxdata[(uint8_t)g->u]; - return boxdata[(uint8_t)g->u]; -} - -void -drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, - const XftGlyphFontSpec *specs, int len) -{ - for ( ; len-- > 0; x += cw, specs++) - drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); -} - -/* implementation */ - -void -drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) -{ - ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ - if (bd & (BDL | BDA)) { - /* lines (light/double/heavy/arcs) */ - drawboxlines(x, y, w, h, fg, bd); - - } else if (cat == BBD) { - /* lower (8-X)/8 block */ - int d = DIV((uint8_t)bd * h, 8); - XftDrawRect(xd, fg, x, y + d, w, h - d); - - } else if (cat == BBU) { - /* upper X/8 block */ - XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); - - } else if (cat == BBL) { - /* left X/8 block */ - XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); - - } else if (cat == BBR) { - /* right (8-X)/8 block */ - int d = DIV((uint8_t)bd * w, 8); - XftDrawRect(xd, fg, x + d, y, w - d, h); - - } else if (cat == BBQ) { - /* Quadrants */ - int w2 = DIV(w, 2), h2 = DIV(h, 2); - if (bd & TL) - XftDrawRect(xd, fg, x, y, w2, h2); - if (bd & TR) - XftDrawRect(xd, fg, x + w2, y, w - w2, h2); - if (bd & BL) - XftDrawRect(xd, fg, x, y + h2, w2, h - h2); - if (bd & BR) - XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); - - } else if (bd & BBS) { - /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ - int d = (uint8_t)bd; - XftColor xfc; - XRenderColor xrc = { .alpha = 0xffff }; - - xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); - xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); - xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); - - XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); - XftDrawRect(xd, &xfc, x, y, w, h); - XftColorFree(xdpy, xvis, xcmap, &xfc); - - } else if (cat == BRL) { - /* braille, each data bit corresponds to one dot at 2x4 grid */ - int w1 = DIV(w, 2); - int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); - - if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); - if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); - if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); - if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); - if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); - if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); - if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); - if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); - - } -} - -void -drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) -{ - /* s: stem thickness. width/8 roughly matches underscore thickness. */ - /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ - /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ - int mwh = MIN(w, h); - int base_s = MAX(1, DIV(mwh, 8)); - int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ - int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; - int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); - /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ - /* The base length (per direction till edge) includes this square. */ - - int light = bd & (LL | LU | LR | LD); - int double_ = bd & (DL | DU | DR | DD); - - if (light) { - /* d: additional (negative) length to not-draw the center */ - /* texel - at arcs and avoid drawing inside (some) doubles */ - int arc = bd & BDA; - int multi_light = light & (light - 1); - int multi_double = double_ & (double_ - 1); - /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ - int d = arc || (multi_double && !multi_light) ? -s : 0; - - if (bd & LL) - XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); - if (bd & LU) - XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); - if (bd & LR) - XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); - if (bd & LD) - XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); - } - - /* double lines - also align with light to form heavy when combined */ - if (double_) { - /* - * going clockwise, for each double-ray: p is additional length - * to the single-ray nearer to the previous direction, and n to - * the next. p and n adjust from the base length to lengths - * which consider other doubles - shorter to avoid intersections - * (p, n), or longer to draw the far-corner texel (n). - */ - int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; - if (dl) { - int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; - XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); - XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); - } - if (du) { - int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; - XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); - XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); - } - if (dr) { - int p = du ? -s : 0, n = dd ? -s : du ? s : 0; - XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); - XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); - } - if (dd) { - int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; - XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); - XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); - } - } -} diff --git a/suckless/st/boxdraw_data.h b/suckless/st/boxdraw_data.h deleted file mode 100644 index 7890500..0000000 --- a/suckless/st/boxdraw_data.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih - * MIT/X Consortium License - */ - -/* - * U+25XX codepoints data - * - * References: - * http://www.unicode.org/charts/PDF/U2500.pdf - * http://www.unicode.org/charts/PDF/U2580.pdf - * - * Test page: - * https://github.com/GNOME/vte/blob/master/doc/boxes.txt - */ - -/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ -/* Categories (mutually exclusive except BDB): */ -/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ -#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ -#define BDA (1<<9) /* Box Draw Arc (light) */ - -#define BBD (1<<10) /* Box Block Down (lower) X/8 */ -#define BBL (2<<10) /* Box Block Left X/8 */ -#define BBU (3<<10) /* Box Block Upper X/8 */ -#define BBR (4<<10) /* Box Block Right X/8 */ -#define BBQ (5<<10) /* Box Block Quadrants */ -#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ - -#define BBS (1<<14) /* Box Block Shades */ -#define BDB (1<<15) /* Box Draw is Bold */ - -/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ -/* Heavy is light+double (literally drawing light+double align to form heavy) */ -#define LL (1<<0) -#define LU (1<<1) -#define LR (1<<2) -#define LD (1<<3) -#define LH (LL+LR) -#define LV (LU+LD) - -#define DL (1<<4) -#define DU (1<<5) -#define DR (1<<6) -#define DD (1<<7) -#define DH (DL+DR) -#define DV (DU+DD) - -#define HL (LL+DL) -#define HU (LU+DU) -#define HR (LR+DR) -#define HD (LD+DD) -#define HH (HL+HR) -#define HV (HU+HD) - -/* (BBQ) Quadrants Top/Bottom x Left/Right */ -#define TL (1<<0) -#define TR (1<<1) -#define BL (1<<2) -#define BR (1<<3) - -/* Data for U+2500 - U+259F except dashes/diagonals */ -static const unsigned short boxdata[256] = { - /* light lines */ - [0x00] = BDL + LH, /* light horizontal */ - [0x02] = BDL + LV, /* light vertical */ - [0x0c] = BDL + LD + LR, /* light down and right */ - [0x10] = BDL + LD + LL, /* light down and left */ - [0x14] = BDL + LU + LR, /* light up and right */ - [0x18] = BDL + LU + LL, /* light up and left */ - [0x1c] = BDL + LV + LR, /* light vertical and right */ - [0x24] = BDL + LV + LL, /* light vertical and left */ - [0x2c] = BDL + LH + LD, /* light horizontal and down */ - [0x34] = BDL + LH + LU, /* light horizontal and up */ - [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ - [0x74] = BDL + LL, /* light left */ - [0x75] = BDL + LU, /* light up */ - [0x76] = BDL + LR, /* light right */ - [0x77] = BDL + LD, /* light down */ - - /* heavy [+light] lines */ - [0x01] = BDL + HH, - [0x03] = BDL + HV, - [0x0d] = BDL + HR + LD, - [0x0e] = BDL + HD + LR, - [0x0f] = BDL + HD + HR, - [0x11] = BDL + HL + LD, - [0x12] = BDL + HD + LL, - [0x13] = BDL + HD + HL, - [0x15] = BDL + HR + LU, - [0x16] = BDL + HU + LR, - [0x17] = BDL + HU + HR, - [0x19] = BDL + HL + LU, - [0x1a] = BDL + HU + LL, - [0x1b] = BDL + HU + HL, - [0x1d] = BDL + HR + LV, - [0x1e] = BDL + HU + LD + LR, - [0x1f] = BDL + HD + LR + LU, - [0x20] = BDL + HV + LR, - [0x21] = BDL + HU + HR + LD, - [0x22] = BDL + HD + HR + LU, - [0x23] = BDL + HV + HR, - [0x25] = BDL + HL + LV, - [0x26] = BDL + HU + LD + LL, - [0x27] = BDL + HD + LU + LL, - [0x28] = BDL + HV + LL, - [0x29] = BDL + HU + HL + LD, - [0x2a] = BDL + HD + HL + LU, - [0x2b] = BDL + HV + HL, - [0x2d] = BDL + HL + LD + LR, - [0x2e] = BDL + HR + LL + LD, - [0x2f] = BDL + HH + LD, - [0x30] = BDL + HD + LH, - [0x31] = BDL + HD + HL + LR, - [0x32] = BDL + HR + HD + LL, - [0x33] = BDL + HH + HD, - [0x35] = BDL + HL + LU + LR, - [0x36] = BDL + HR + LU + LL, - [0x37] = BDL + HH + LU, - [0x38] = BDL + HU + LH, - [0x39] = BDL + HU + HL + LR, - [0x3a] = BDL + HU + HR + LL, - [0x3b] = BDL + HH + HU, - [0x3d] = BDL + HL + LV + LR, - [0x3e] = BDL + HR + LV + LL, - [0x3f] = BDL + HH + LV, - [0x40] = BDL + HU + LH + LD, - [0x41] = BDL + HD + LH + LU, - [0x42] = BDL + HV + LH, - [0x43] = BDL + HU + HL + LD + LR, - [0x44] = BDL + HU + HR + LD + LL, - [0x45] = BDL + HD + HL + LU + LR, - [0x46] = BDL + HD + HR + LU + LL, - [0x47] = BDL + HH + HU + LD, - [0x48] = BDL + HH + HD + LU, - [0x49] = BDL + HV + HL + LR, - [0x4a] = BDL + HV + HR + LL, - [0x4b] = BDL + HV + HH, - [0x78] = BDL + HL, - [0x79] = BDL + HU, - [0x7a] = BDL + HR, - [0x7b] = BDL + HD, - [0x7c] = BDL + HR + LL, - [0x7d] = BDL + HD + LU, - [0x7e] = BDL + HL + LR, - [0x7f] = BDL + HU + LD, - - /* double [+light] lines */ - [0x50] = BDL + DH, - [0x51] = BDL + DV, - [0x52] = BDL + DR + LD, - [0x53] = BDL + DD + LR, - [0x54] = BDL + DR + DD, - [0x55] = BDL + DL + LD, - [0x56] = BDL + DD + LL, - [0x57] = BDL + DL + DD, - [0x58] = BDL + DR + LU, - [0x59] = BDL + DU + LR, - [0x5a] = BDL + DU + DR, - [0x5b] = BDL + DL + LU, - [0x5c] = BDL + DU + LL, - [0x5d] = BDL + DL + DU, - [0x5e] = BDL + DR + LV, - [0x5f] = BDL + DV + LR, - [0x60] = BDL + DV + DR, - [0x61] = BDL + DL + LV, - [0x62] = BDL + DV + LL, - [0x63] = BDL + DV + DL, - [0x64] = BDL + DH + LD, - [0x65] = BDL + DD + LH, - [0x66] = BDL + DD + DH, - [0x67] = BDL + DH + LU, - [0x68] = BDL + DU + LH, - [0x69] = BDL + DH + DU, - [0x6a] = BDL + DH + LV, - [0x6b] = BDL + DV + LH, - [0x6c] = BDL + DH + DV, - - /* (light) arcs */ - [0x6d] = BDA + LD + LR, - [0x6e] = BDA + LD + LL, - [0x6f] = BDA + LU + LL, - [0x70] = BDA + LU + LR, - - /* Lower (Down) X/8 block (data is 8 - X) */ - [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, - [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, - - /* Left X/8 block (data is X) */ - [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, - [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, - - /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ - [0x80] = BBU + 4, [0x94] = BBU + 1, - [0x90] = BBR + 4, [0x95] = BBR + 7, - - /* Quadrants */ - [0x96] = BBQ + BL, - [0x97] = BBQ + BR, - [0x98] = BBQ + TL, - [0x99] = BBQ + TL + BL + BR, - [0x9a] = BBQ + TL + BR, - [0x9b] = BBQ + TL + TR + BL, - [0x9c] = BBQ + TL + TR + BR, - [0x9d] = BBQ + TR, - [0x9e] = BBQ + BL + TR, - [0x9f] = BBQ + BL + TR + BR, - - /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ - [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, - - /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ - /* U+2571 - U+2573: unsupported (diagonals) */ -}; diff --git a/suckless/st/config.def.h b/suckless/st/config.def.h deleted file mode 100644 index e3c30ed..0000000 --- a/suckless/st/config.def.h +++ /dev/null @@ -1,517 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static const char *font = "CaskaydiaMonoNerdFontMono-Bold:size=14:style=Bold"; -/* Spare fonts */ - -static char *font2[] = { - "CaskaydiaMonoNerdFontMono-Bold:pixelsize=12:antialias=true:autohint=true"}; -static int borderpx = 6; - -/* How to align the content in the window when the size of the terminal - * doesn't perfectly match the size of the window. The values are percentages. - * 50 means center, 0 means flush left/top, 100 means flush right/bottom. - */ -static int anysize_halign = 50; -static int anysize_valign = 50; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -/* By default, use the same one as kitty. */ - -char *vtiden = "\033[?62c"; -//char *vtiden = "\x1b[?62;4c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1; -static float chscale = 1; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 1; -static double maxlatency = 10; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 100; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * 1: render most of the lines/blocks characters without using the font for - * perfect alignment between cells (U2500 - U259F except dashes/diagonals). - * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. - * 0: disable (render all U25XX glyphs normally from the font). - */ -const int boxdraw = 1; -const int boxdraw_bold = 1; - -/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 0; - -/* - * 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"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", "red3", "green3", "yellow3", "blue2", "magenta3", "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", "red", "green", "yellow", "#5c5cff", "magenta", "cyan", "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", "#555555", "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 258; -unsigned int defaultbg = 259; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 2; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Graphics configuration - */ - -/// The template for the cache directory. -const char graphics_cache_dir_template[] = "/tmp/st-images-XXXXXX"; -/// The max size of a single image file, in bytes. -unsigned graphics_max_single_image_file_size = 20 * 1024 * 1024; -/// The max size of the cache, in bytes. -unsigned graphics_total_file_cache_size = 300 * 1024 * 1024; -/// The max ram size of an image or placement, in bytes. -unsigned graphics_max_single_image_ram_size = 100 * 1024 * 1024; -/// The max total size of all images loaded into RAM. -unsigned graphics_max_total_ram_size = 300 * 1024 * 1024; -/// The max total number of image placements and images. -unsigned graphics_max_total_placements = 4096; -/// The ratio by which limits can be exceeded. This is to reduce the frequency -/// of image removal. -double graphics_excess_tolerance_ratio = 0.05; -/// The minimum delay between redraws caused by animations, in milliseconds. -unsigned graphics_animation_min_delay = 20; - -/* - * 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 keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask | ShiftMask) - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - {TERMMOD, Button3, previewimage, {.s = "feh"}}, - {TERMMOD, Button2, showimageinfo, {}, 1}, - {XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1}, - {ShiftMask, Button4, kscrollup, {.i = 1}}, - {ShiftMask, Button5, kscrolldown, {.i = 1}}, - {ShiftMask, Button4, ttysend, {.s = "\033[5;2~"}}, - {XK_ANY_MOD, Button4, ttysend, {.s = "\031"}}, - {ShiftMask, Button5, ttysend, {.s = "\033[6;2~"}}, - {XK_ANY_MOD, Button5, ttysend, {.s = "\005"}}, -}; - -/* Internal keyboard shortcuts. */ - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - {TERMMOD, XK_F1, togglegrdebug, {.i = 0}}, - {TERMMOD, XK_F6, dumpgrstate, {.i = 0}}, - {TERMMOD, XK_F7, unloadimages, {.i = 0}}, - {TERMMOD, XK_F8, toggleimages, {.i = 0}}, - {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_C, clipcopy, {.i = 0}}, - {TERMMOD, XK_V, clippaste, {.i = 0}}, - {TERMMOD, XK_Y, selpaste, {.i = 0}}, - {ShiftMask, XK_Page_Up, kscrollup, {.i = -1}}, - {ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}}, - {ShiftMask, XK_Insert, selpaste, {.i = 0}}, - {TERMMOD, XK_Num_Lock, numlock, {.i = 0}}, - {TERMMOD, XK_plus, zoom, {.f = +1}}, - {TERMMOD, XK_underscore, zoom, {.f = -1}}, - {TERMMOD, XK_equal, zoomreset, {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 deleted file mode 100644 index 7c73a85..0000000 --- a/suckless/st/config.h +++ /dev/null @@ -1,479 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "monospace:size=12:antialias=true:autohint=true"; -static int borderpx = 4; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Background opacity */ -float alpha_def; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "#282828", // black (soft bg) - "#fb4934", // red - "#b8bb26", // green - "#fabd2f", // yellow - "#83a598", // blue - "#d3869b", // magenta - "#8ec07c", // cyan - "#ebdbb2", // white (light fg) - - /* 8 bright colors */ - "#3c3836", // bright black - "#cc241d", // bright red - "#98971a", // bright green - "#d79921", // bright yellow - "#458588", // bright blue - "#b16286", // bright magenta - "#689d6a", // bright cyan - "#f9f5d7", // bright white - - [255] = 0, - "gray90", // default foreground colour - "#000000", // default background colour -}; - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 256; -unsigned int defaultbg = 257; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 2; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 140; -static unsigned int rows = 40; - -/* - * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|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} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { MODKEY, XK_k, kscrollup, {.i = 1} }, - { MODKEY, XK_j, kscrolldown, {.i = 1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F16, 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.save b/suckless/st/config.h.save deleted file mode 100644 index b25362c..0000000 --- a/suckless/st/config.h.save +++ /dev/null @@ -1,486 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Terminus-9:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Background opacity */ -float alpha_def; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - - /* 8 normal colors */ - "#0a0a0a", /* black */ - "#44516d", /* red */ - "#c95d38", /* green */ - "#de9e68", /* yellow */ - "#8b7675", /* blue */ - "#7e5f8c", /* magenta */ - "#8c82c2", /* cyan */ - "#eff7d0", /* white */ - - /* 8 bright colors */ - "#181818", /* black */ - "#7d87a1", /* red */ - "#e9673c", /* green */ - "#e0b18b", /* yellow */ - "#b9a192", /* blue */ - "#9a7ebd", /* magenta */ - "#bccce2", /* cyan */ - "#ffffff", /* white */ - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#gray90", /* default foreground colour */ - "#black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 256; -unsigned int defaultbg = 257; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 6; - -/* - * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|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} }, - { ControlMask, XK_j, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { MODKEY, XK_k, kscrollup, {.i = 1} }, - { MODKEY, XK_j, kscrolldown, {.i = 1} }, - { MODKEY, XK_a, chgalpha, {.f = -1} }, - { MODKEY, XK_s, chgalpha, {.f = +1} }, - { MODKEY, XK_d, chgalpha, {.f = 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.save.1 b/suckless/st/config.h.save.1 deleted file mode 100644 index d608c5a..0000000 --- a/suckless/st/config.h.save.1 +++ /dev/null @@ -1,486 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Terminus-9:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Background opacity */ -float alpha_def; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - - /* 8 normal colors */ - "#0a0a0a", /* black */ - "#44516d", /* red */ - "#c95d38", /* green */ - "#de9e68", /* yellow */ - "#8b7675", /* blue */ - "#7e5f8c", /* magenta */ - "#8c82c2", /* cyan */ - "#eff7d0", /* white */ - - /* 8 bright colors */ - "#181818", /* black */ - "#7d87a1", /* red */ - "#e9673c", /* green */ - "#e0b18b", /* yellow */ - "#b9a192", /* blue */ - "#9a7ebd", /* magenta */ - "#bccce2", /* cyan */ - "#ffffff", /* white */ - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 256; -unsigned int defaultbg = 257; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 6; - -/* - * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|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} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ControlMask, XK_k, kscrollup, {.i = 1} }, - { ControlMask, XK_j, kscrolldown, {.i = 1} }, - { MODKEY, XK_a, chgalpha, {.f = -1} }, - { MODKEY, XK_s, chgalpha, {.f = +1} }, - { MODKEY, XK_d, chgalpha, {.f = 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.save.2 b/suckless/st/config.h.save.2 deleted file mode 100644 index 4869423..0000000 --- a/suckless/st/config.h.save.2 +++ /dev/null @@ -1,486 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Terminus-9:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Background opacity */ -float alpha_def; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - - /* 8 normal colors */ - "#0a0a0a", /* black */ - "#44516d", /* red */ - "#c95d38", /* green */ - "#de9e68", /* yellow */ - "#8b7675", /* blue */ - "#7e5f8c", /* magenta */ - "#8c82c2", /* cyan */ - "#eff7d0", /* white */ - - /* 8 bright colors */ - "#181818", /* black */ - "#7d87a1", /* red */ - "#e9673c", /* green */ - "#e0b18b", /* yellow */ - "#b9a192", /* blue */ - "#9a7ebd", /* magenta */ - "#bccce2", /* cyan */ - "#ffffff", /* white */ - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 256; -unsigned int defaultbg = 257; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 6; - -/* - * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|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} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { ControlMask|Shift, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ControlMask, XK_k, kscrollup, {.i = 1} }, - { ControlMask, XK_j, kscrolldown, {.i = 1} }, - { MODKEY, XK_a, chgalpha, {.f = -1} }, - { MODKEY, XK_s, chgalpha, {.f = +1} }, - { MODKEY, XK_d, chgalpha, {.f = 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.save.3 b/suckless/st/config.h.save.3 deleted file mode 100644 index e2169a7..0000000 --- a/suckless/st/config.h.save.3 +++ /dev/null @@ -1,486 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Terminus-9:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Background opacity */ -float alpha_def; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - - /* 8 normal colors */ - "#333e21", /* black */ - "#757849", /* red */ - "#FF432A", /* green */ - "#c83e72", /* yellow */ - "#448C2C", /* blue */ - "#7d5f5f", /* magenta */ - "#bd8c77", /* cyan */ - "#efdceb", /* white */ - - /* 8 bright colors */ - "#686e50", /* black */ - "#A6AA6A", /* red */ - "#fa6d5a", /* green */ - "#d3658e", /* yellow */ - "#80BD6C", /* blue */ - "#B38887", /* magenta */ - "#f0bfaa", /* cyan */ - "#ffffff", /* white */ - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 256; -unsigned int defaultbg = 257; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 6; - -/* - * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (Mod1Mask|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} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_k, kscrollup, {.i = 1} }, - { ShiftMask, XK_j, kscrolldown, {.i = 1} }, - { MODKEY, XK_a, chgalpha, {.f = -1} }, - { MODKEY, XK_s, chgalpha, {.f = +1} }, - { MODKEY, XK_d, chgalpha, {.f = 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 deleted file mode 100644 index b6458af..0000000 --- a/suckless/st/config.mk +++ /dev/null @@ -1,38 +0,0 @@ -# st version -VERSION = 0.9.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` \ - `$(PKG_CONFIG) --cflags harfbuzz` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender \ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` \ - `$(PKG_CONFIG) --libs harfbuzz` - -# 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` -#MANPREFIX = ${PREFIX}/man - -# compiler and linker -# CC = c99 diff --git a/suckless/st/graphics.c b/suckless/st/graphics.c deleted file mode 100644 index 64e6fe0..0000000 --- a/suckless/st/graphics.c +++ /dev/null @@ -1,3812 +0,0 @@ -/* The MIT License - - Copyright (c) 2021-2024 Sergei Grechanik - - 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. -*/ - -//////////////////////////////////////////////////////////////////////////////// -// -// This file implements a subset of the kitty graphics protocol. -// -//////////////////////////////////////////////////////////////////////////////// - -#define _POSIX_C_SOURCE 200809L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "graphics.h" -#include "khash.h" -#include "kvec.h" - -extern char **environ; - -#define MAX_FILENAME_SIZE 256 -#define MAX_INFO_LEN 256 -#define MAX_IMAGE_RECTS 20 - -/// The type used in this file to represent time. Used both for time differences -/// and absolute times (as milliseconds since an arbitrary point in time, see -/// `initialization_time`). -typedef int64_t Milliseconds; - -enum ScaleMode { - SCALE_MODE_UNSET = 0, - /// Stretch or shrink the image to fill the box, ignoring aspect ratio. - SCALE_MODE_FILL = 1, - /// Preserve aspect ratio and fit to width or to height so that the - /// whole image is visible. - SCALE_MODE_CONTAIN = 2, - /// Do not scale. The image may be cropped if the box is too small. - SCALE_MODE_NONE = 3, - /// Do not scale, unless the box is too small, in which case the image - /// will be shrunk like with `SCALE_MODE_CONTAIN`. - SCALE_MODE_NONE_OR_CONTAIN = 4, -}; - -enum AnimationState { - ANIMATION_STATE_UNSET = 0, - /// The animation is stopped. Display the current frame, but don't - /// advance to the next one. - ANIMATION_STATE_STOPPED = 1, - /// Run the animation to then end, then wait for the next frame. - ANIMATION_STATE_LOADING = 2, - /// Run the animation in a loop. - ANIMATION_STATE_LOOPING = 3, -}; - -/// The status of an image. Each image uploaded to the terminal is cached on -/// disk, then it is loaded to ram when needed. -enum ImageStatus { - STATUS_UNINITIALIZED = 0, - STATUS_UPLOADING = 1, - STATUS_UPLOADING_ERROR = 2, - STATUS_UPLOADING_SUCCESS = 3, - STATUS_RAM_LOADING_ERROR = 4, - STATUS_RAM_LOADING_IN_PROGRESS = 5, - STATUS_RAM_LOADING_SUCCESS = 6, -}; - -const char *image_status_strings[6] = { - "STATUS_UNINITIALIZED", - "STATUS_UPLOADING", - "STATUS_UPLOADING_ERROR", - "STATUS_UPLOADING_SUCCESS", - "STATUS_RAM_LOADING_ERROR", - "STATUS_RAM_LOADING_SUCCESS", -}; - -enum ImageUploadingFailure { - ERROR_OVER_SIZE_LIMIT = 1, - ERROR_CANNOT_OPEN_CACHED_FILE = 2, - ERROR_UNEXPECTED_SIZE = 3, - ERROR_CANNOT_COPY_FILE = 4, -}; - -const char *image_uploading_failure_strings[5] = { - "NO_ERROR", - "ERROR_OVER_SIZE_LIMIT", - "ERROR_CANNOT_OPEN_CACHED_FILE", - "ERROR_UNEXPECTED_SIZE", - "ERROR_CANNOT_COPY_FILE", -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// We use the following structures to represent images and placements: -// -// - Image: this is the main structure representing an image, usually created -// by actions 'a=t', 'a=T`. Each image has an id (image id aka client id, -// specified by 'i='). An image may have multiple frames (ImageFrame) and -// placements (ImagePlacement). -// -// - ImageFrame: represents a single frame of an image, usually created by -// the action 'a=f' (and the first frame is created with the image itself). -// Each frame has an index and also: -// - a file containing the frame data (considered to be "on disk", although -// it's probably in tmpfs), -// - an imlib object containing the fully composed frame (i.e. the frame -// data from the file composed onto the background frame or color). It is -// not ready for display yet, because it needs to be scaled and uploaded -// to the X server. -// -// - ImagePlacement: represents a placement of an image, created by 'a=p' and -// 'a=T'. Each placement has an id (placement id, specified by 'p='). Also -// each placement has an array of pixmaps: one for each frame of the image. -// Each pixmap is a scaled and uploaded image ready to be displayed. -// -// Images are store in the `images` hash table, mapping image ids to Image -// objects (allocated on the heap). -// -// Placements are stored in the `placements` hash table of each Image object, -// mapping placement ids to ImagePlacement objects (also allocated on the heap). -// -// ImageFrames are stored in the `first_frame` field and in the -// `frames_beyond_the_first` array of each Image object. They are stored by -// value, so ImageFrame pointer may be invalidated when frames are -// added/deleted, be careful. -// -//////////////////////////////////////////////////////////////////////////////// - -struct Image; -struct ImageFrame; -struct ImagePlacement; - -KHASH_MAP_INIT_INT(id2image, struct Image *) -KHASH_MAP_INIT_INT(id2placement, struct ImagePlacement *) - -typedef struct ImageFrame { - /// The image this frame belongs to. - struct Image *image; - /// The 1-based index of the frame. Zero if the frame isn't initialized. - int index; - /// The last time when the frame was displayed or otherwise touched. - Milliseconds atime; - /// The background color of the frame in the 0xRRGGBBAA format. - uint32_t background_color; - /// The index of the background frame. Zero to use the color instead. - int background_frame_index; - /// The duration of the frame in milliseconds. - int gap; - /// The expected size of the frame image file (specified with 'S='), - /// used to check if uploading succeeded. - unsigned expected_size; - /// Format specification (see the `f=` key). - int format; - /// Pixel width and height of the non-composed (on-disk) frame data. May - /// differ from the image (i.e. first frame) dimensions. - int data_pix_width, data_pix_height; - /// The offset of the frame relative to the first frame. - int x, y; - /// Compression mode (see the `o=` key). - char compression; - /// The status (see `ImageStatus`). - char status; - /// The reason of uploading failure (see `ImageUploadingFailure`). - char uploading_failure; - /// Whether failures and successes should be reported ('q='). - char quiet; - /// Whether to blend the frame with the background or replace it. - char blend; - /// The file corresponding to the on-disk cache, used when uploading. - FILE *open_file; - /// The size of the corresponding file cached on disk. - unsigned disk_size; - /// The imlib object containing the fully composed frame. It's not - /// scaled for screen display yet. - Imlib_Image imlib_object; -} ImageFrame; - -typedef struct Image { - /// The client id (the one specified with 'i='). Must be nonzero. - uint32_t image_id; - /// The client id specified in the query command (`a=q`). This one must - /// be used to create the response if it's non-zero. - uint32_t query_id; - /// The number specified in the transmission command (`I=`). If - /// non-zero, it may be used to identify the image instead of the - /// image_id, and it also should be mentioned in responses. - uint32_t image_number; - /// The last time when the image was displayed or otherwise touched. - Milliseconds atime; - /// The total duration of the animation in milliseconds. - int total_duration; - /// The total size of cached image files for all frames. - int total_disk_size; - /// The global index of the creation command. Used to decide which image - /// is newer if they have the same image number. - uint64_t global_command_index; - /// The 1-based index of the currently displayed frame. - int current_frame; - /// The state of the animation, see `AnimationState`. - char animation_state; - /// The absolute time that is assumed to be the start of the current - /// frame (in ms since initialization). - Milliseconds current_frame_time; - /// The absolute time of the last redraw (in ms since initialization). - /// Used to check whether it's the first time we draw the image in the - /// current redraw cycle. - Milliseconds last_redraw; - /// The absolute time of the next redraw (in ms since initialization). - /// 0 means no redraw is scheduled. - Milliseconds next_redraw; - /// The unscaled pixel width and height of the image. Usually inherited - /// from the first frame. - int pix_width, pix_height; - /// The first frame. - ImageFrame first_frame; - /// The array of frames beyond the first one. - kvec_t(ImageFrame) frames_beyond_the_first; - /// Image placements. - khash_t(id2placement) *placements; - /// The default placement. - uint32_t default_placement; - /// The initial placement id, specified with the transmission command, - /// used to report success or failure. - uint32_t initial_placement_id; -} Image; - -typedef struct ImagePlacement { - /// The image this placement belongs to. - Image *image; - /// The id of the placement. Must be nonzero. - uint32_t placement_id; - /// The last time when the placement was displayed or otherwise touched. - Milliseconds atime; - /// The 1-based index of the protected pixmap. We protect a pixmap in - /// gr_load_pixmap to avoid unloading it right after it was loaded. - int protected_frame; - /// Whether the placement is used only for Unicode placeholders. - char virtual; - /// The scaling mode (see `ScaleMode`). - char scale_mode; - /// Height and width in cells. - uint16_t rows, cols; - /// Top-left corner of the source rectangle ('x=' and 'y='). - int src_pix_x, src_pix_y; - /// Height and width of the source rectangle (zero if full image). - int src_pix_width, src_pix_height; - /// The image appropriately scaled and uploaded to the X server. This - /// pixmap is premultiplied by alpha. - Pixmap first_pixmap; - /// The array of pixmaps beyond the first one. - kvec_t(Pixmap) pixmaps_beyond_the_first; - /// The dimensions of the cell used to scale the image. If cell - /// dimensions are changed (font change), the image will be rescaled. - uint16_t scaled_cw, scaled_ch; - /// If true, do not move the cursor when displaying this placement - /// (non-virtual placements only). - char do_not_move_cursor; -} ImagePlacement; - -/// A rectangular piece of an image to be drawn. -typedef struct { - uint32_t image_id; - uint32_t placement_id; - /// The position of the rectangle in pixels. - int screen_x_pix, screen_y_pix; - /// The starting row on the screen. - int screen_y_row; - /// The part of the whole image to be drawn, in cells. Starts are - /// zero-based, ends are exclusive. - int img_start_col, img_end_col, img_start_row, img_end_row; - /// The current cell width and height in pixels. - int cw, ch; - /// Whether colors should be inverted. - int reverse; -} ImageRect; - -/// Executes `code` for each frame of an image. Example: -/// -/// foreach_frame(image, frame, { -/// printf("Frame %d\n", frame->index); -/// }); -/// -#define foreach_frame(image, framevar, code) { size_t __i; \ - for (__i = 0; __i <= kv_size((image).frames_beyond_the_first); ++__i) { \ - ImageFrame *framevar = \ - __i == 0 ? &(image).first_frame \ - : &kv_A((image).frames_beyond_the_first, __i - 1); \ - code; \ - } } - -/// Executes `code` for each pixmap of a placement. Example: -/// -/// foreach_pixmap(placement, pixmap, { -/// ... -/// }); -/// -#define foreach_pixmap(placement, pixmapvar, code) { size_t __i; \ - for (__i = 0; __i <= kv_size((placement).pixmaps_beyond_the_first); ++__i) { \ - Pixmap pixmapvar = \ - __i == 0 ? (placement).first_pixmap \ - : kv_A((placement).pixmaps_beyond_the_first, __i - 1); \ - code; \ - } } - - -static Image *gr_find_image(uint32_t image_id); -static void gr_get_frame_filename(ImageFrame *frame, char *out, size_t max_len); -static void gr_delete_image(Image *img); -static void gr_check_limits(); -static char *gr_base64dec(const char *src, size_t *size); -static void sanitize_str(char *str, size_t max_len); -static const char *sanitized_filename(const char *str); - -/// The array of image rectangles to draw. It is reset each frame. -static ImageRect image_rects[MAX_IMAGE_RECTS] = {{0}}; -/// The known images (including the ones being uploaded). -static khash_t(id2image) *images = NULL; -/// The total number of placements in all images. -static unsigned total_placement_count = 0; -/// The total size of all image files stored in the on-disk cache. -static int64_t images_disk_size = 0; -/// The total size of all images and placements loaded into ram. -static int64_t images_ram_size = 0; -/// The id of the last loaded image. -static uint32_t last_image_id = 0; -/// Current cell width and heigh in pixels. -static int current_cw = 0, current_ch = 0; -/// The id of the currently uploaded image (when using direct uploading). -static uint32_t current_upload_image_id = 0; -/// The index of the frame currently being uploaded. -static int current_upload_frame_index = 0; -/// The time when the graphics module was initialized. -static struct timespec initialization_time = {0}; -/// The time when the current frame drawing started, used for debugging fps and -/// to calculate the current frame for animations. -static Milliseconds drawing_start_time; -/// The global index of the current command. -static uint64_t global_command_counter = 0; -/// The next redraw times for each row of the terminal. Used for animations. -/// 0 means no redraw is scheduled. -static kvec_t(Milliseconds) next_redraw_times = {0, 0, NULL}; -/// The number of files loaded in the current redraw cycle. -static int this_redraw_cycle_loaded_files = 0; -/// The number of pixmaps loaded in the current redraw cycle. -static int this_redraw_cycle_loaded_pixmaps = 0; - -/// The directory where the cache files are stored. -static char cache_dir[MAX_FILENAME_SIZE - 16]; - -/// The table used for color inversion. -static unsigned char reverse_table[256]; - -// Declared in the header. -GraphicsDebugMode graphics_debug_mode = GRAPHICS_DEBUG_NONE; -char graphics_display_images = 1; -GraphicsCommandResult graphics_command_result = {0}; -int graphics_next_redraw_delay = INT_MAX; - -// Defined in config.h -extern const char graphics_cache_dir_template[]; -extern unsigned graphics_max_single_image_file_size; -extern unsigned graphics_total_file_cache_size; -extern unsigned graphics_max_single_image_ram_size; -extern unsigned graphics_max_total_ram_size; -extern unsigned graphics_max_total_placements; -extern double graphics_excess_tolerance_ratio; -extern unsigned graphics_animation_min_delay; - - -//////////////////////////////////////////////////////////////////////////////// -// Basic helpers. -//////////////////////////////////////////////////////////////////////////////// - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) - -/// Returns the difference between `end` and `start` in milliseconds. -static int64_t gr_timediff_ms(const struct timespec *end, - const struct timespec *start) { - return (end->tv_sec - start->tv_sec) * 1000 + - (end->tv_nsec - start->tv_nsec) / 1000000; -} - -/// Returns the current time in milliseconds since the initialization. -static Milliseconds gr_now_ms() { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return gr_timediff_ms(&now, &initialization_time); -} - -//////////////////////////////////////////////////////////////////////////////// -// Logging. -//////////////////////////////////////////////////////////////////////////////// - -#define GR_LOG(...) \ - do { if(graphics_debug_mode) fprintf(stderr, __VA_ARGS__); } while(0) - -//////////////////////////////////////////////////////////////////////////////// -// Basic image management functions (create, delete, find, etc). -//////////////////////////////////////////////////////////////////////////////// - -/// Returns the 1-based index of the last frame. Note that you may want to use -/// `gr_last_uploaded_frame_index` instead since the last frame may be not -/// fully uploaded yet. -static inline int gr_last_frame_index(Image *img) { - return kv_size(img->frames_beyond_the_first) + 1; -} - -/// Returns the frame with the given index. Returns NULL if the index is out of -/// bounds. The index is 1-based. -static ImageFrame *gr_get_frame(Image *img, int index) { - if (!img) - return NULL; - if (index == 1) - return &img->first_frame; - if (2 <= index && index <= gr_last_frame_index(img)) - return &kv_A(img->frames_beyond_the_first, index - 2); - return NULL; -} - -/// Returns the last frame of the image. Returns NULL if `img` is NULL. -static ImageFrame *gr_get_last_frame(Image *img) { - if (!img) - return NULL; - return gr_get_frame(img, gr_last_frame_index(img)); -} - -/// Returns the 1-based index of the last frame or the second-to-last frame if -/// the last frame is not fully uploaded yet. -static inline int gr_last_uploaded_frame_index(Image *img) { - int last_index = gr_last_frame_index(img); - if (last_index > 1 && - gr_get_frame(img, last_index)->status < STATUS_UPLOADING_SUCCESS) - return last_index - 1; - return last_index; -} - -/// Returns the pixmap for the frame with the given index. Returns 0 if the -/// index is out of bounds. The index is 1-based. -static Pixmap gr_get_frame_pixmap(ImagePlacement *placement, int index) { - if (index == 1) - return placement->first_pixmap; - if (2 <= index && - index <= kv_size(placement->pixmaps_beyond_the_first) + 1) - return kv_A(placement->pixmaps_beyond_the_first, index - 2); - return 0; -} - -/// Sets the pixmap for the frame with the given index. The index is 1-based. -/// The array of pixmaps is resized if needed. -static void gr_set_frame_pixmap(ImagePlacement *placement, int index, - Pixmap pixmap) { - if (index == 1) { - placement->first_pixmap = pixmap; - return; - } - // Resize the array if needed. - size_t old_size = kv_size(placement->pixmaps_beyond_the_first); - if (old_size < index - 1) { - kv_a(Pixmap, placement->pixmaps_beyond_the_first, index - 2); - for (size_t i = old_size; i < index - 1; i++) - kv_A(placement->pixmaps_beyond_the_first, i) = 0; - } - kv_A(placement->pixmaps_beyond_the_first, index - 2) = pixmap; -} - -/// Finds the image corresponding to the client id. Returns NULL if cannot find. -static Image *gr_find_image(uint32_t image_id) { - khiter_t k = kh_get(id2image, images, image_id); - if (k == kh_end(images)) - return NULL; - Image *res = kh_value(images, k); - return res; -} - -/// Finds the newest image corresponding to the image number. Returns NULL if -/// cannot find. -static Image *gr_find_image_by_number(uint32_t image_number) { - if (image_number == 0) - return NULL; - Image *newest_img = NULL; - Image *img = NULL; - kh_foreach_value(images, img, { - if (img->image_number == image_number && - (!newest_img || newest_img->global_command_index < - img->global_command_index)) - newest_img = img; - }); - if (!newest_img) - GR_LOG("Image number %u not found\n", image_number); - else - GR_LOG("Found image number %u, its id is %u\n", image_number, - img->image_id); - return newest_img; -} - -/// Finds the placement corresponding to the id. If the placement id is 0, -/// returns some default placement. -static ImagePlacement *gr_find_placement(Image *img, uint32_t placement_id) { - if (!img) - return NULL; - if (placement_id == 0) { - // Try to get the default placement. - ImagePlacement *dflt = NULL; - if (img->default_placement != 0) - dflt = gr_find_placement(img, img->default_placement); - if (dflt) - return dflt; - // If there is no default placement, return the first one and - // set it as the default. - kh_foreach_value(img->placements, dflt, { - img->default_placement = dflt->placement_id; - return dflt; - }); - // If there are no placements, return NULL. - return NULL; - } - khiter_t k = kh_get(id2placement, img->placements, placement_id); - if (k == kh_end(img->placements)) - return NULL; - ImagePlacement *res = kh_value(img->placements, k); - return res; -} - -/// Finds the placement by image id and placement id. -static ImagePlacement *gr_find_image_and_placement(uint32_t image_id, - uint32_t placement_id) { - return gr_find_placement(gr_find_image(image_id), placement_id); -} - -/// Writes the name of the on-disk cache file to `out`. `max_len` should be the -/// size of `out`. The name will be something like -/// "/tmp/st-images-xxx/img-ID-FRAME". -static void gr_get_frame_filename(ImageFrame *frame, char *out, - size_t max_len) { - snprintf(out, max_len, "%s/img-%.3u-%.3u", cache_dir, - frame->image->image_id, frame->index); -} - -/// Returns the (estimation) of the RAM size used by the frame right now. -static unsigned gr_frame_current_ram_size(ImageFrame *frame) { - if (!frame->imlib_object) - return 0; - return (unsigned)frame->image->pix_width * frame->image->pix_height * 4; -} - -/// Returns the (estimation) of the RAM size used by a single frame pixmap. -static unsigned gr_placement_single_frame_ram_size(ImagePlacement *placement) { - return (unsigned)placement->rows * placement->cols * - placement->scaled_ch * placement->scaled_cw * 4; -} - -/// Returns the (estimation) of the RAM size used by the placemenet right now. -static unsigned gr_placement_current_ram_size(ImagePlacement *placement) { - unsigned single_frame_size = - gr_placement_single_frame_ram_size(placement); - unsigned result = 0; - foreach_pixmap(*placement, pixmap, { - if (pixmap) - result += single_frame_size; - }); - return result; -} - -/// Unload the frame from RAM (i.e. delete the corresponding imlib object). -/// If the on-disk file of the frame is preserved, it can be reloaded later. -static void gr_unload_frame(ImageFrame *frame) { - if (!frame->imlib_object) - return; - - unsigned frame_ram_size = gr_frame_current_ram_size(frame); - images_ram_size -= frame_ram_size; - - imlib_context_set_image(frame->imlib_object); - imlib_free_image_and_decache(); - frame->imlib_object = NULL; - - GR_LOG("After unloading image %u frame %u (atime %ld ms ago) " - "ram: %ld KiB (- %u KiB)\n", - frame->image->image_id, frame->index, - drawing_start_time - frame->atime, images_ram_size / 1024, - frame_ram_size / 1024); -} - -/// Unload all frames of the image. -static void gr_unload_all_frames(Image *img) { - foreach_frame(*img, frame, { - gr_unload_frame(frame); - }); -} - -/// Unload the placement from RAM (i.e. free all of the corresponding pixmaps). -/// If the on-disk files or imlib objects of the corresponding image are -/// preserved, the placement can be reloaded later. -static void gr_unload_placement(ImagePlacement *placement) { - unsigned placement_ram_size = gr_placement_current_ram_size(placement); - images_ram_size -= placement_ram_size; - - Display *disp = imlib_context_get_display(); - foreach_pixmap(*placement, pixmap, { - if (pixmap) - XFreePixmap(disp, pixmap); - }); - - placement->first_pixmap = 0; - placement->pixmaps_beyond_the_first.n = 0; - placement->scaled_ch = placement->scaled_cw = 0; - - GR_LOG("After unloading placement %u/%u (atime %ld ms ago) " - "ram: %ld KiB (- %u KiB)\n", - placement->image->image_id, placement->placement_id, - drawing_start_time - placement->atime, images_ram_size / 1024, - placement_ram_size / 1024); -} - -/// Unload a single pixmap of the placement from RAM. -static void gr_unload_pixmap(ImagePlacement *placement, int frameidx) { - Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx); - if (!pixmap) - return; - - Display *disp = imlib_context_get_display(); - XFreePixmap(disp, pixmap); - gr_set_frame_pixmap(placement, frameidx, 0); - images_ram_size -= gr_placement_single_frame_ram_size(placement); - - GR_LOG("After unloading pixmap %ld of " - "placement %u/%u (atime %ld ms ago) " - "frame %u (atime %ld ms ago) " - "ram: %ld KiB (- %u KiB)\n", - pixmap, placement->image->image_id, placement->placement_id, - drawing_start_time - placement->atime, frameidx, - drawing_start_time - - gr_get_frame(placement->image, frameidx)->atime, - images_ram_size / 1024, - gr_placement_single_frame_ram_size(placement) / 1024); -} - -/// Deletes the on-disk cache file corresponding to the frame. The in-ram image -/// object (if it exists) is not deleted, placements are not unloaded either. -static void gr_delete_imagefile(ImageFrame *frame) { - // It may still be being loaded. Close the file in this case. - if (frame->open_file) { - fclose(frame->open_file); - frame->open_file = NULL; - } - - if (frame->disk_size == 0) - return; - - char filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); - remove(filename); - - unsigned disk_size = frame->disk_size; - images_disk_size -= disk_size; - frame->image->total_disk_size -= disk_size; - frame->disk_size = 0; - - GR_LOG("After deleting image file %u frame %u (atime %ld ms ago) " - "disk: %ld KiB (- %u KiB)\n", - frame->image->image_id, frame->index, - drawing_start_time - frame->atime, images_disk_size / 1024, - disk_size / 1024); -} - -/// Deletes all on-disk cache files of the image (for each frame). -static void gr_delete_imagefiles(Image *img) { - foreach_frame(*img, frame, { - gr_delete_imagefile(frame); - }); -} - -/// Deletes the given placement: unloads, frees the object, but doesn't change -/// the `placements` hash table. -static void gr_delete_placement_keep_id(ImagePlacement *placement) { - if (!placement) - return; - GR_LOG("Deleting placement %u/%u\n", placement->image->image_id, - placement->placement_id); - gr_unload_placement(placement); - kv_destroy(placement->pixmaps_beyond_the_first); - free(placement); - total_placement_count--; -} - -/// Deletes all placements of `img`. -static void gr_delete_all_placements(Image *img) { - ImagePlacement *placement = NULL; - kh_foreach_value(img->placements, placement, { - gr_delete_placement_keep_id(placement); - }); - kh_clear(id2placement, img->placements); -} - -/// Deletes the given image: unloads, deletes the file, frees the Image object, -/// but doesn't change the `images` hash table. -static void gr_delete_image_keep_id(Image *img) { - if (!img) - return; - GR_LOG("Deleting image %u\n", img->image_id); - foreach_frame(*img, frame, { - gr_delete_imagefile(frame); - gr_unload_frame(frame); - }); - kv_destroy(img->frames_beyond_the_first); - gr_delete_all_placements(img); - kh_destroy(id2placement, img->placements); - free(img); -} - -/// Deletes the given image: unloads, deletes the file, frees the Image object, -/// and also removes it from `images`. -static void gr_delete_image(Image *img) { - if (!img) - return; - uint32_t id = img->image_id; - gr_delete_image_keep_id(img); - khiter_t k = kh_get(id2image, images, id); - kh_del(id2image, images, k); -} - -/// Deletes the given placement: unloads, frees the object, and also removes it -/// from `placements`. -static void gr_delete_placement(ImagePlacement *placement) { - if (!placement) - return; - uint32_t id = placement->placement_id; - Image *img = placement->image; - gr_delete_placement_keep_id(placement); - khiter_t k = kh_get(id2placement, img->placements, id); - kh_del(id2placement, img->placements, k); -} - -/// Deletes all images and clears `images`. -static void gr_delete_all_images() { - Image *img = NULL; - kh_foreach_value(images, img, { - gr_delete_image_keep_id(img); - }); - kh_clear(id2image, images); -} - -/// Update the atime of the image. -static void gr_touch_image(Image *img) { - img->atime = gr_now_ms(); -} - -/// Update the atime of the frame. -static void gr_touch_frame(ImageFrame *frame) { - frame->image->atime = frame->atime = gr_now_ms(); -} - -/// Update the atime of the placement. Touches the images too. -static void gr_touch_placement(ImagePlacement *placement) { - placement->image->atime = placement->atime = gr_now_ms(); -} - -/// Creates a new image with the given id. If an image with that id already -/// exists, it is deleted first. If the provided id is 0, generates a -/// random id. -static Image *gr_new_image(uint32_t id) { - if (id == 0) { - do { - id = rand(); - // Avoid IDs that don't need full 32 bits. - } while ((id & 0xFF000000) == 0 || (id & 0x00FFFF00) == 0 || - gr_find_image(id)); - GR_LOG("Generated random image id %u\n", id); - } - Image *img = gr_find_image(id); - gr_delete_image_keep_id(img); - GR_LOG("Creating image %u\n", id); - img = malloc(sizeof(Image)); - memset(img, 0, sizeof(Image)); - img->placements = kh_init(id2placement); - int ret; - khiter_t k = kh_put(id2image, images, id, &ret); - kh_value(images, k) = img; - img->image_id = id; - gr_touch_image(img); - img->global_command_index = global_command_counter; - return img; -} - -/// Creates a new frame at the end of the frame array. It may be the first frame -/// if there are no frames yet. -static ImageFrame *gr_append_new_frame(Image *img) { - ImageFrame *frame = NULL; - if (img->first_frame.index == 0 && - kv_size(img->frames_beyond_the_first) == 0) { - frame = &img->first_frame; - frame->index = 1; - } else { - frame = kv_pushp(ImageFrame, img->frames_beyond_the_first); - memset(frame, 0, sizeof(ImageFrame)); - frame->index = kv_size(img->frames_beyond_the_first) + 1; - } - frame->image = img; - gr_touch_frame(frame); - GR_LOG("Appending frame %d to image %u\n", frame->index, img->image_id); - return frame; -} - -/// Creates a new placement with the given id. If a placement with that id -/// already exists, it is deleted first. If the provided id is 0, generates a -/// random id. -static ImagePlacement *gr_new_placement(Image *img, uint32_t id) { - if (id == 0) { - do { - // Currently we support only 24-bit IDs. - id = rand() & 0xFFFFFF; - // Avoid IDs that need only one byte. - } while ((id & 0x00FFFF00) == 0 || gr_find_placement(img, id)); - } - ImagePlacement *placement = gr_find_placement(img, id); - gr_delete_placement_keep_id(placement); - GR_LOG("Creating placement %u/%u\n", img->image_id, id); - placement = malloc(sizeof(ImagePlacement)); - memset(placement, 0, sizeof(ImagePlacement)); - total_placement_count++; - int ret; - khiter_t k = kh_put(id2placement, img->placements, id, &ret); - kh_value(img->placements, k) = placement; - placement->image = img; - placement->placement_id = id; - gr_touch_placement(placement); - if (img->default_placement == 0) - img->default_placement = id; - return placement; -} - -static int64_t ceil_div(int64_t a, int64_t b) { - return (a + b - 1) / b; -} - -/// Computes the best number of rows and columns for a placement if it's not -/// specified, and also adjusts the source rectangle size. -static void gr_infer_placement_size_maybe(ImagePlacement *placement) { - // The size of the image. - int image_pix_width = placement->image->pix_width; - int image_pix_height = placement->image->pix_height; - // Negative values are not allowed. Quietly set them to 0. - if (placement->src_pix_x < 0) - placement->src_pix_x = 0; - if (placement->src_pix_y < 0) - placement->src_pix_y = 0; - if (placement->src_pix_width < 0) - placement->src_pix_width = 0; - if (placement->src_pix_height < 0) - placement->src_pix_height = 0; - // If the source rectangle is outside the image, truncate it. - if (placement->src_pix_x > image_pix_width) - placement->src_pix_x = image_pix_width; - if (placement->src_pix_y > image_pix_height) - placement->src_pix_y = image_pix_height; - // If the source rectangle is not specified, use the whole image. If - // it's partially outside the image, truncate it. - if (placement->src_pix_width == 0 || - placement->src_pix_x + placement->src_pix_width > image_pix_width) - placement->src_pix_width = - image_pix_width - placement->src_pix_x; - if (placement->src_pix_height == 0 || - placement->src_pix_y + placement->src_pix_height > image_pix_height) - placement->src_pix_height = - image_pix_height - placement->src_pix_y; - - if (placement->cols != 0 && placement->rows != 0) - return; - if (placement->src_pix_width == 0 || placement->src_pix_height == 0) - return; - if (current_cw == 0 || current_ch == 0) - return; - - // If no size is specified, use the image size. - if (placement->cols == 0 && placement->rows == 0) { - placement->cols = - ceil_div(placement->src_pix_width, current_cw); - placement->rows = - ceil_div(placement->src_pix_height, current_ch); - return; - } - - // Some applications specify only one of the dimensions. - if (placement->scale_mode == SCALE_MODE_CONTAIN) { - // If we preserve aspect ratio and fit to width/height, the most - // logical thing is to find the minimum size of the - // non-specified dimension that allows the image to fit the - // specified dimension. - if (placement->cols == 0) { - placement->cols = ceil_div( - placement->src_pix_width * placement->rows * - current_ch, - placement->src_pix_height * current_cw); - return; - } - if (placement->rows == 0) { - placement->rows = - ceil_div(placement->src_pix_height * - placement->cols * current_cw, - placement->src_pix_width * current_ch); - return; - } - } else { - // Otherwise we stretch the image or preserve the original size. - // In both cases we compute the best number of columns from the - // pixel size and cell size. - // TODO: In the case of stretching it's not the most logical - // thing to do, may need to revisit in the future. - // Currently we switch to SCALE_MODE_CONTAIN when only one - // of the dimensions is specified, so this case shouldn't - // happen in practice. - if (!placement->cols) - placement->cols = - ceil_div(placement->src_pix_width, current_cw); - if (!placement->rows) - placement->rows = - ceil_div(placement->src_pix_height, current_ch); - } -} - -/// Adjusts the current frame index if enough time has passed since the display -/// of the current frame. Also computes the time of the next redraw of this -/// image (`img->next_redraw`). The current time is passed as an argument so -/// that all animations are in sync. -static void gr_update_frame_index(Image *img, Milliseconds now) { - if (img->current_frame == 0) { - img->current_frame_time = now; - img->current_frame = 1; - img->next_redraw = now + MAX(1, img->first_frame.gap); - return; - } - // If the animation is stopped, show the current frame. - if (!img->animation_state || - img->animation_state == ANIMATION_STATE_STOPPED || - img->animation_state == ANIMATION_STATE_UNSET) { - // The next redraw is never (unless the state is changed). - img->next_redraw = 0; - return; - } - int last_uploaded_frame_index = gr_last_uploaded_frame_index(img); - // If we are loading and we reached the last frame, show the last frame. - if (img->animation_state == ANIMATION_STATE_LOADING && - img->current_frame == last_uploaded_frame_index) { - // The next redraw is never (unless the state is changed or - // frames are added). - img->next_redraw = 0; - return; - } - - // Check how many milliseconds passed since the current frame was shown. - int passed_ms = now - img->current_frame_time; - // If the animation is looping and too much time has passes, we can - // make a shortcut. - if (img->animation_state == ANIMATION_STATE_LOOPING && - img->total_duration > 0 && passed_ms >= img->total_duration) { - passed_ms %= img->total_duration; - img->current_frame_time = now - passed_ms; - } - // Find the next frame. - int original_frame_index = img->current_frame; - while (1) { - ImageFrame *frame = gr_get_frame(img, img->current_frame); - if (!frame) { - // The frame doesn't exist, go to the first frame. - img->current_frame = 1; - img->current_frame_time = now; - img->next_redraw = now + MAX(1, img->first_frame.gap); - return; - } - if (frame->gap >= 0 && passed_ms < frame->gap) { - // Not enough time has passed, we are still in the same - // frame, and it's not a gapless frame. - img->next_redraw = - img->current_frame_time + MAX(1, frame->gap); - return; - } - // Otherwise go to the next frame. - passed_ms -= MAX(0, frame->gap); - if (img->current_frame >= last_uploaded_frame_index) { - // It's the last frame, if the animation is loading, - // remain on it. - if (img->animation_state == ANIMATION_STATE_LOADING) { - img->next_redraw = 0; - return; - } - // Otherwise the animation is looping. - img->current_frame = 1; - // TODO: Support finite number of loops. - } else { - img->current_frame++; - } - // Make sure we don't get stuck in an infinite loop. - if (img->current_frame == original_frame_index) { - // We looped through all frames, but haven't reached the - // next frame yet. This may happen if too much time has - // passed since the last redraw or all the frames are - // gapless. Just move on to the next frame. - img->current_frame++; - if (img->current_frame > - last_uploaded_frame_index) - img->current_frame = 1; - img->current_frame_time = now; - img->next_redraw = now + MAX( - 1, gr_get_frame(img, img->current_frame)->gap); - return; - } - // Adjust the start time of the frame. The next redraw time will - // be set in the next iteration. - img->current_frame_time += MAX(0, frame->gap); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Unloading and deleting images to save resources. -//////////////////////////////////////////////////////////////////////////////// - -/// A helper to compare frames by atime for qsort. -static int gr_cmp_frames_by_atime(const void *a, const void *b) { - ImageFrame *frame_a = *(ImageFrame *const *)a; - ImageFrame *frame_b = *(ImageFrame *const *)b; - if (frame_a->atime == frame_b->atime) - return frame_a->image->global_command_index - - frame_b->image->global_command_index; - return frame_a->atime - frame_b->atime; -} - -/// A helper to compare images by atime for qsort. -static int gr_cmp_images_by_atime(const void *a, const void *b) { - Image *img_a = *(Image *const *)a; - Image *img_b = *(Image *const *)b; - if (img_a->atime == img_b->atime) - return img_a->global_command_index - - img_b->global_command_index; - return img_a->atime - img_b->atime; -} - -/// A helper to compare placements by atime for qsort. -static int gr_cmp_placements_by_atime(const void *a, const void *b) { - ImagePlacement *p_a = *(ImagePlacement **)a; - ImagePlacement *p_b = *(ImagePlacement **)b; - if (p_a->atime == p_b->atime) - return p_a->image->global_command_index - - p_b->image->global_command_index; - return p_a->atime - p_b->atime; -} - -typedef kvec_t(Image *) ImageVec; -typedef kvec_t(ImagePlacement *) ImagePlacementVec; -typedef kvec_t(ImageFrame *) ImageFrameVec; - -/// Returns an array of pointers to all images sorted by atime. -static ImageVec gr_get_images_sorted_by_atime() { - ImageVec vec; - kv_init(vec); - if (kh_size(images) == 0) - return vec; - kv_resize(Image *, vec, kh_size(images)); - Image *img = NULL; - kh_foreach_value(images, img, { kv_push(Image *, vec, img); }); - qsort(vec.a, kv_size(vec), sizeof(Image *), gr_cmp_images_by_atime); - return vec; -} - -/// Returns an array of pointers to all placements sorted by atime. -static ImagePlacementVec gr_get_placements_sorted_by_atime() { - ImagePlacementVec vec; - kv_init(vec); - if (total_placement_count == 0) - return vec; - kv_resize(ImagePlacement *, vec, total_placement_count); - Image *img = NULL; - ImagePlacement *placement = NULL; - kh_foreach_value(images, img, { - kh_foreach_value(img->placements, placement, { - kv_push(ImagePlacement *, vec, placement); - }); - }); - qsort(vec.a, kv_size(vec), sizeof(ImagePlacement *), - gr_cmp_placements_by_atime); - return vec; -} - -/// Returns an array of pointers to all frames sorted by atime. -static ImageFrameVec gr_get_frames_sorted_by_atime() { - ImageFrameVec frames; - kv_init(frames); - Image *img = NULL; - kh_foreach_value(images, img, { - foreach_frame(*img, frame, { - kv_push(ImageFrame *, frames, frame); - }); - }); - qsort(frames.a, kv_size(frames), sizeof(ImageFrame *), - gr_cmp_frames_by_atime); - return frames; -} - -/// An object that can be unloaded from RAM. -typedef struct { - /// Some score, probably based on access time. The lower the score, the - /// more likely that the object should be unloaded. - int64_t score; - union { - ImagePlacement *placement; - ImageFrame *frame; - }; - /// If zero, the object is the imlib object of `frame`, if non-zero, - /// the object is a pixmap of `frameidx`-th frame of `placement`. - int frameidx; -} UnloadableObject; - -typedef kvec_t(UnloadableObject) UnloadableObjectVec; - -/// A helper to compare unloadable objects by score for qsort. -static int gr_cmp_unloadable_objects(const void *a, const void *b) { - UnloadableObject *obj_a = (UnloadableObject *)a; - UnloadableObject *obj_b = (UnloadableObject *)b; - return obj_a->score - obj_b->score; -} - -/// Unloads an unloadable object from RAM. -static void gr_unload_object(UnloadableObject *obj) { - if (obj->frameidx) { - if (obj->placement->protected_frame == obj->frameidx) - return; - gr_unload_pixmap(obj->placement, obj->frameidx); - } else { - gr_unload_frame(obj->frame); - } -} - -/// Returns the recency threshold for an image. Frames that were accessed within -/// this threshold from now are considered recent and may be handled -/// differently because we may need them again very soon. -static Milliseconds gr_recency_threshold(Image *img) { - return img->total_duration * 2 + 1000; -} - -/// Creates an unloadable object for the imlib object of a frame. -static UnloadableObject gr_unloadable_object_for_frame(Milliseconds now, - ImageFrame *frame) { - UnloadableObject obj = {0}; - obj.frameidx = 0; - obj.frame = frame; - Milliseconds atime = frame->atime; - obj.score = atime; - if (atime >= now - gr_recency_threshold(frame->image)) { - // This is a recent frame, probably from an active animation. - // Score it above `now` to prefer unloading non-active frames. - // Randomize the score because it's not very clear in which - // order we want to unload them: reloading a frame may require - // reloading other frames. - obj.score = now + 1000 + rand() % 1000; - } - return obj; -} - -/// Creates an unloadable object for a pixmap. -static UnloadableObject -gr_unloadable_object_for_pixmap(Milliseconds now, ImageFrame *frame, - ImagePlacement *placement) { - UnloadableObject obj = {0}; - obj.frameidx = frame->index; - obj.placement = placement; - obj.score = placement->atime; - // Since we don't store pixmap atimes, use the - // oldest atime of the frame and the placement. - Milliseconds atime = MIN(placement->atime, frame->atime); - obj.score = atime; - if (atime >= now - gr_recency_threshold(frame->image)) { - // This is a recent pixmap, probably from an active animation. - // Score it above `now` to prefer unloading non-active frames. - // Also assign higher scores to frames that are closer to the - // current frame (more likely to be used soon). - int num_frames = gr_last_frame_index(frame->image); - int dist = frame->index - frame->image->current_frame; - if (dist < 0) - dist += num_frames; - obj.score = - now + 1000 + (num_frames - dist) * 1000 / num_frames; - // If the pixmap is much larger than the imlib image, prefer to - // unload the pixmap by adding up to -1000 to the score. If the - // imlib image is larger, add up to +1000. - float imlib_size = gr_frame_current_ram_size(frame); - float pixmap_size = - gr_placement_single_frame_ram_size(placement); - obj.score += - 2000 * (imlib_size / (imlib_size + pixmap_size) - 0.5); - } - return obj; -} - -/// Returns an array of unloadable objects sorted by score. -static UnloadableObjectVec -gr_get_unloadable_objects_sorted_by_score(Milliseconds now) { - UnloadableObjectVec objects; - kv_init(objects); - Image *img = NULL; - ImagePlacement *placement = NULL; - kh_foreach_value(images, img, { - foreach_frame(*img, frame, { - if (!frame->imlib_object) - continue; - kv_push(UnloadableObject, objects, - gr_unloadable_object_for_frame(now, frame)); - int frameidx = frame->index; - kh_foreach_value(img->placements, placement, { - if (!gr_get_frame_pixmap(placement, frameidx)) - continue; - kv_push(UnloadableObject, objects, - gr_unloadable_object_for_pixmap( - now, frame, placement)); - }); - }); - }); - qsort(objects.a, kv_size(objects), sizeof(UnloadableObject), - gr_cmp_unloadable_objects); - return objects; -} - -/// Returns the limit adjusted by the excess tolerance ratio. -static inline unsigned apply_tolerance(unsigned limit) { - return limit + (unsigned)(limit * graphics_excess_tolerance_ratio); -} - -/// Checks RAM and disk cache limits and deletes/unloads some images. -static void gr_check_limits() { - Milliseconds now = gr_now_ms(); - ImageVec images_sorted = {0}; - ImagePlacementVec placements_sorted = {0}; - ImageFrameVec frames_sorted = {0}; - UnloadableObjectVec objects_sorted = {0}; - int images_begin = 0; - int placements_begin = 0; - char changed = 0; - // First reduce the number of images if there are too many. - if (kh_size(images) > apply_tolerance(graphics_max_total_placements)) { - GR_LOG("Too many images: %d\n", kh_size(images)); - changed = 1; - images_sorted = gr_get_images_sorted_by_atime(); - int to_delete = kv_size(images_sorted) - - graphics_max_total_placements; - for (; images_begin < to_delete; images_begin++) - gr_delete_image(images_sorted.a[images_begin]); - } - // Then reduce the number of placements if there are too many. - if (total_placement_count > - apply_tolerance(graphics_max_total_placements)) { - GR_LOG("Too many placements: %d\n", total_placement_count); - changed = 1; - placements_sorted = gr_get_placements_sorted_by_atime(); - int to_delete = kv_size(placements_sorted) - - graphics_max_total_placements; - for (; placements_begin < to_delete; placements_begin++) { - ImagePlacement *placement = - placements_sorted.a[placements_begin]; - if (placement->protected_frame) - break; - gr_delete_placement(placement); - } - } - // Then reduce the size of the image file cache. The files correspond to - // image frames. - if (images_disk_size > - apply_tolerance(graphics_total_file_cache_size)) { - GR_LOG("Too big disk cache: %ld KiB\n", - images_disk_size / 1024); - changed = 1; - frames_sorted = gr_get_frames_sorted_by_atime(); - for (int i = 0; i < kv_size(frames_sorted); i++) { - if (images_disk_size <= graphics_total_file_cache_size) - break; - gr_delete_imagefile(kv_A(frames_sorted, i)); - } - } - // Then unload images from RAM. - if (images_ram_size > apply_tolerance(graphics_max_total_ram_size)) { - changed = 1; - int frames_begin = 0; - GR_LOG("Too much ram: %ld KiB\n", images_ram_size / 1024); - objects_sorted = gr_get_unloadable_objects_sorted_by_score(now); - for (int i = 0; i < kv_size(objects_sorted); i++) { - if (images_ram_size <= graphics_max_total_ram_size) - break; - gr_unload_object(&kv_A(objects_sorted, i)); - } - } - if (changed) { - GR_LOG("After cleaning: ram: %ld KiB disk: %ld KiB " - "img count: %d placement count: %d\n", - images_ram_size / 1024, images_disk_size / 1024, - kh_size(images), total_placement_count); - } - kv_destroy(images_sorted); - kv_destroy(placements_sorted); - kv_destroy(frames_sorted); - kv_destroy(objects_sorted); -} - -/// Unloads all images by user request. -void gr_unload_images_to_reduce_ram() { - Image *img = NULL; - ImagePlacement *placement = NULL; - kh_foreach_value(images, img, { - kh_foreach_value(img->placements, placement, { - if (placement->protected_frame) - continue; - gr_unload_placement(placement); - }); - gr_unload_all_frames(img); - }); -} - -//////////////////////////////////////////////////////////////////////////////// -// Image loading. -//////////////////////////////////////////////////////////////////////////////// - -/// Copies `num_pixels` pixels (not bytes!) from a buffer `from` to an imlib2 -/// image data `to`. The format may be 24 (RGB) or 32 (RGBA), and it's converted -/// to imlib2's representation, which is 0xAARRGGBB (having BGRA memory layout -/// on little-endian architectures). -static inline void gr_copy_pixels(DATA32 *to, unsigned char *from, int format, - size_t num_pixels) { - size_t pixel_size = format == 24 ? 3 : 4; - if (format == 32) { - for (unsigned i = 0; i < num_pixels; ++i) { - unsigned byte_i = i * pixel_size; - to[i] = ((DATA32)from[byte_i + 2]) | - ((DATA32)from[byte_i + 1]) << 8 | - ((DATA32)from[byte_i]) << 16 | - ((DATA32)from[byte_i + 3]) << 24; - } - } else { - for (unsigned i = 0; i < num_pixels; ++i) { - unsigned byte_i = i * pixel_size; - to[i] = ((DATA32)from[byte_i + 2]) | - ((DATA32)from[byte_i + 1]) << 8 | - ((DATA32)from[byte_i]) << 16 | 0xFF000000; - } - } -} - -/// Loads uncompressed RGB or RGBA image data from a file. -static void gr_load_raw_pixel_data_uncompressed(DATA32 *data, FILE *file, - int format, - size_t total_pixels) { - unsigned char chunk[BUFSIZ]; - size_t pixel_size = format == 24 ? 3 : 4; - size_t chunk_size_pix = BUFSIZ / 4; - size_t chunk_size_bytes = chunk_size_pix * pixel_size; - size_t bytes = total_pixels * pixel_size; - for (size_t chunk_start_pix = 0; chunk_start_pix < total_pixels; - chunk_start_pix += chunk_size_pix) { - size_t read_size = fread(chunk, 1, chunk_size_bytes, file); - size_t read_pixels = read_size / pixel_size; - if (chunk_start_pix + read_pixels > total_pixels) - read_pixels = total_pixels - chunk_start_pix; - gr_copy_pixels(data + chunk_start_pix, chunk, format, - read_pixels); - } -} - -#define COMPRESSED_CHUNK_SIZE BUFSIZ -#define DECOMPRESSED_CHUNK_SIZE (BUFSIZ * 4) - -/// Loads compressed RGB or RGBA image data from a file. -static int gr_load_raw_pixel_data_compressed(DATA32 *data, FILE *file, - int format, size_t total_pixels) { - size_t pixel_size = format == 24 ? 3 : 4; - unsigned char compressed_chunk[COMPRESSED_CHUNK_SIZE]; - unsigned char decompressed_chunk[DECOMPRESSED_CHUNK_SIZE]; - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.next_out = decompressed_chunk; - strm.avail_out = DECOMPRESSED_CHUNK_SIZE; - strm.avail_in = 0; - strm.next_in = Z_NULL; - int ret = inflateInit(&strm); - if (ret != Z_OK) - return 1; - - int error = 0; - int progress = 0; - size_t total_copied_pixels = 0; - while (1) { - // If we don't have enough data in the input buffer, try to read - // from the file. - if (strm.avail_in <= COMPRESSED_CHUNK_SIZE / 4) { - // Move the existing data to the beginning. - memmove(compressed_chunk, strm.next_in, strm.avail_in); - strm.next_in = compressed_chunk; - // Read more data. - size_t bytes_read = fread( - compressed_chunk + strm.avail_in, 1, - COMPRESSED_CHUNK_SIZE - strm.avail_in, file); - strm.avail_in += bytes_read; - if (bytes_read != 0) - progress = 1; - } - - // Try to inflate the data. - int ret = inflate(&strm, Z_SYNC_FLUSH); - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) { - error = 1; - fprintf(stderr, - "error: could not decompress the image, error " - "%s\n", - ret == Z_MEM_ERROR ? "Z_MEM_ERROR" - : "Z_DATA_ERROR"); - break; - } - - // Copy the data from the output buffer to the image. - size_t full_pixels = - (DECOMPRESSED_CHUNK_SIZE - strm.avail_out) / pixel_size; - // Make sure we don't overflow the image. - if (full_pixels > total_pixels - total_copied_pixels) - full_pixels = total_pixels - total_copied_pixels; - if (full_pixels > 0) { - // Copy pixels. - gr_copy_pixels(data, decompressed_chunk, format, - full_pixels); - data += full_pixels; - total_copied_pixels += full_pixels; - if (total_copied_pixels >= total_pixels) { - // We filled the whole image, there may be some - // data left, but we just truncate it. - break; - } - // Move the remaining data to the beginning. - size_t copied_bytes = full_pixels * pixel_size; - size_t leftover = - (DECOMPRESSED_CHUNK_SIZE - strm.avail_out) - - copied_bytes; - memmove(decompressed_chunk, - decompressed_chunk + copied_bytes, leftover); - strm.next_out -= copied_bytes; - strm.avail_out += copied_bytes; - progress = 1; - } - - // If we haven't made any progress, then we have reached the end - // of both the file and the inflated data. - if (!progress) - break; - progress = 0; - } - - inflateEnd(&strm); - return error; -} - -#undef COMPRESSED_CHUNK_SIZE -#undef DECOMPRESSED_CHUNK_SIZE - -/// Load the image from a file containing raw pixel data (RGB or RGBA), the data -/// may be compressed. -static Imlib_Image gr_load_raw_pixel_data(ImageFrame *frame, - const char *filename) { - size_t total_pixels = frame->data_pix_width * frame->data_pix_height; - if (total_pixels * 4 > graphics_max_single_image_ram_size) { - fprintf(stderr, - "error: image %u frame %u is too big too load: %zu > %u\n", - frame->image->image_id, frame->index, total_pixels * 4, - graphics_max_single_image_ram_size); - return NULL; - } - - FILE* file = fopen(filename, "rb"); - if (!file) { - fprintf(stderr, - "error: could not open image file: %s\n", - sanitized_filename(filename)); - return NULL; - } - - Imlib_Image image = imlib_create_image(frame->data_pix_width, - frame->data_pix_height); - if (!image) { - fprintf(stderr, - "error: could not create an image of size %d x %d\n", - frame->data_pix_width, frame->data_pix_height); - fclose(file); - return NULL; - } - - imlib_context_set_image(image); - imlib_image_set_has_alpha(1); - DATA32* data = imlib_image_get_data(); - - // The default format is 32. - int format = frame->format ? frame->format : 32; - - if (frame->compression == 0) { - gr_load_raw_pixel_data_uncompressed(data, file, format, - total_pixels); - } else { - int ret = gr_load_raw_pixel_data_compressed(data, file, format, - total_pixels); - if (ret != 0) { - imlib_image_put_back_data(data); - imlib_free_image(); - fclose(file); - return NULL; - } - } - - fclose(file); - imlib_image_put_back_data(data); - return image; -} - -/// Loads the unscaled frame into RAM as an imlib object. The frame imlib object -/// is fully composed on top of the background frame. If the frame is already -/// loaded, does nothing. Loading may fail, in which case the status of the -/// frame will be set to STATUS_RAM_LOADING_ERROR. -static void gr_load_imlib_object(ImageFrame *frame) { - if (frame->imlib_object) - return; - - // If the image is uninitialized or uploading has failed, or the file - // has been deleted, we cannot load the image. - if (frame->status < STATUS_UPLOADING_SUCCESS) - return; - if (frame->disk_size == 0) { - if (frame->status != STATUS_RAM_LOADING_ERROR) { - fprintf(stderr, - "error: cached image was deleted: %u frame %u\n", - frame->image->image_id, frame->index); - } - frame->status = STATUS_RAM_LOADING_ERROR; - return; - } - - // Prevent recursive dependences between frames. - if (frame->status == STATUS_RAM_LOADING_IN_PROGRESS) { - fprintf(stderr, - "error: recursive loading of image %u frame %u\n", - frame->image->image_id, frame->index); - frame->status = STATUS_RAM_LOADING_ERROR; - return; - } - frame->status = STATUS_RAM_LOADING_IN_PROGRESS; - - // Load the background frame if needed. Hopefully it's not recursive. - ImageFrame *bg_frame = NULL; - if (frame->background_frame_index) { - bg_frame = gr_get_frame(frame->image, - frame->background_frame_index); - if (!bg_frame) { - fprintf(stderr, - "error: could not find background " - "frame %d for image %u frame %d\n", - frame->background_frame_index, - frame->image->image_id, frame->index); - frame->status = STATUS_RAM_LOADING_ERROR; - return; - } - gr_load_imlib_object(bg_frame); - if (!bg_frame->imlib_object) { - fprintf(stderr, - "error: could not load background frame %d for " - "image %u frame %d\n", - frame->background_frame_index, - frame->image->image_id, frame->index); - frame->status = STATUS_RAM_LOADING_ERROR; - return; - } - } - - // Load the frame data image. - Imlib_Image frame_data_image = NULL; - char filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); - GR_LOG("Loading image: %s\n", sanitized_filename(filename)); - if (frame->format == 100 || frame->format == 0) - frame_data_image = imlib_load_image(filename); - if (frame->format == 32 || frame->format == 24 || - (!frame_data_image && frame->format == 0)) - frame_data_image = gr_load_raw_pixel_data(frame, filename); - this_redraw_cycle_loaded_files++; - - if (!frame_data_image) { - if (frame->status != STATUS_RAM_LOADING_ERROR) { - fprintf(stderr, "error: could not load image: %s\n", - sanitized_filename(filename)); - } - frame->status = STATUS_RAM_LOADING_ERROR; - return; - } - - imlib_context_set_image(frame_data_image); - int frame_data_width = imlib_image_get_width(); - int frame_data_height = imlib_image_get_height(); - GR_LOG("Successfully loaded, size %d x %d\n", frame_data_width, - frame_data_height); - // If imlib loading succeeded, and it is the first frame, set the - // information about the original image size, unless it's already set. - if (frame->index == 1 && frame->image->pix_width == 0 && - frame->image->pix_height == 0) { - frame->image->pix_width = frame_data_width; - frame->image->pix_height = frame_data_height; - } - - int image_width = frame->image->pix_width; - int image_height = frame->image->pix_height; - - // Compose the image with the background color or frame. - if (frame->background_color != 0 || bg_frame || - image_width != frame_data_width || - image_height != frame_data_height) { - GR_LOG("Composing the frame bg = 0x%08X, bgframe = %d\n", - frame->background_color, frame->background_frame_index); - Imlib_Image composed_image = imlib_create_image( - image_width, image_height); - imlib_context_set_image(composed_image); - imlib_image_set_has_alpha(1); - imlib_context_set_anti_alias(0); - - // Start with the background frame or color. - imlib_context_set_blend(0); - if (bg_frame && bg_frame->imlib_object) { - imlib_blend_image_onto_image( - bg_frame->imlib_object, 1, 0, 0, - image_width, image_height, 0, 0, - image_width, image_height); - } else { - int r = (frame->background_color >> 24) & 0xFF; - int g = (frame->background_color >> 16) & 0xFF; - int b = (frame->background_color >> 8) & 0xFF; - int a = frame->background_color & 0xFF; - imlib_context_set_color(r, g, b, a); - imlib_image_fill_rectangle(0, 0, image_width, - image_height); - } - - // Blend the frame data image onto the background. - imlib_context_set_blend(1); - imlib_blend_image_onto_image( - frame_data_image, 1, 0, 0, frame->data_pix_width, - frame->data_pix_height, frame->x, frame->y, - frame->data_pix_width, frame->data_pix_height); - - // Free the frame data image. - imlib_context_set_image(frame_data_image); - imlib_free_image(); - - frame_data_image = composed_image; - } - - frame->imlib_object = frame_data_image; - - images_ram_size += gr_frame_current_ram_size(frame); - frame->status = STATUS_RAM_LOADING_SUCCESS; - - GR_LOG("After loading image %u frame %d ram: %ld KiB (+ %u KiB)\n", - frame->image->image_id, frame->index, - images_ram_size / 1024, gr_frame_current_ram_size(frame) / 1024); -} - -/// Premultiplies the alpha channel of the image data. The data is an array of -/// pixels such that each pixel is a 32-bit integer in the format 0xAARRGGBB. -static void gr_premultiply_alpha(DATA32 *data, size_t num_pixels) { - for (size_t i = 0; i < num_pixels; ++i) { - DATA32 pixel = data[i]; - unsigned char a = pixel >> 24; - if (a == 0) { - data[i] = 0; - } else if (a != 255) { - unsigned char b = (pixel & 0xFF) * a / 255; - unsigned char g = ((pixel >> 8) & 0xFF) * a / 255; - unsigned char r = ((pixel >> 16) & 0xFF) * a / 255; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - } -} - -/// Creates a pixmap for the frame of an image placement. The pixmap contain the -/// image data correctly scaled and fit to the box defined by the number of -/// rows/columns of the image placement and the provided cell dimensions in -/// pixels. If the placement is already loaded, it will be reloaded only if the -/// cell dimensions have changed. -Pixmap gr_load_pixmap(ImagePlacement *placement, int frameidx, int cw, int ch) { - Image *img = placement->image; - ImageFrame *frame = gr_get_frame(img, frameidx); - - // Update the atime uncoditionally. - gr_touch_placement(placement); - if (frame) - gr_touch_frame(frame); - - // If cw or ch are different, unload all the pixmaps. - if (placement->scaled_cw != cw || placement->scaled_ch != ch) { - gr_unload_placement(placement); - placement->scaled_cw = cw; - placement->scaled_ch = ch; - } - - // If it's already loaded, do nothing. - Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx); - if (pixmap) - return pixmap; - - GR_LOG("Loading placement: %u/%u frame %u\n", img->image_id, - placement->placement_id, frameidx); - - // Load the imlib object for the frame. - if (!frame) { - fprintf(stderr, - "error: could not find frame %u for image %u\n", - frameidx, img->image_id); - return 0; - } - gr_load_imlib_object(frame); - if (!frame->imlib_object) - return 0; - - // Infer the placement size if needed. - gr_infer_placement_size_maybe(placement); - - // Create the scaled image. This is temporary, we will scale it - // appropriately, upload to the X server, and then delete immediately. - int scaled_w = (int)placement->cols * cw; - int scaled_h = (int)placement->rows * ch; - if (scaled_w * scaled_h * 4 > graphics_max_single_image_ram_size) { - fprintf(stderr, - "error: placement %u/%u would be too big to load: %d x " - "%d x 4 > %u\n", - img->image_id, placement->placement_id, scaled_w, - scaled_h, graphics_max_single_image_ram_size); - return 0; - } - Imlib_Image scaled_image = imlib_create_image(scaled_w, scaled_h); - if (!scaled_image) { - fprintf(stderr, - "error: imlib_create_image(%d, %d) returned " - "null\n", - scaled_w, scaled_h); - return 0; - } - imlib_context_set_image(scaled_image); - imlib_image_set_has_alpha(1); - - // First fill the scaled image with the transparent color. - imlib_context_set_blend(0); - imlib_context_set_color(0, 0, 0, 0); - imlib_image_fill_rectangle(0, 0, scaled_w, scaled_h); - imlib_context_set_anti_alias(1); - imlib_context_set_blend(1); - - // The source rectangle. - int src_x = placement->src_pix_x; - int src_y = placement->src_pix_y; - int src_w = placement->src_pix_width; - int src_h = placement->src_pix_height; - // Whether the box is too small to use the true size of the image. - char box_too_small = scaled_w < src_w || scaled_h < src_h; - char mode = placement->scale_mode; - - // Then blend the original image onto the transparent background. - if (src_w <= 0 || src_h <= 0) { - fprintf(stderr, "warning: image of zero size\n"); - } else if (mode == SCALE_MODE_FILL) { - imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, - src_y, src_w, src_h, 0, 0, - scaled_w, scaled_h); - } else if (mode == SCALE_MODE_NONE || - (mode == SCALE_MODE_NONE_OR_CONTAIN && !box_too_small)) { - imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, - src_y, src_w, src_h, 0, 0, src_w, - src_h); - } else { - if (mode != SCALE_MODE_CONTAIN && - mode != SCALE_MODE_NONE_OR_CONTAIN) { - fprintf(stderr, - "warning: unknown scale mode %u, using " - "'contain' instead\n", - mode); - } - int dest_x, dest_y; - int dest_w, dest_h; - if (scaled_w * src_h > src_w * scaled_h) { - // If the box is wider than the original image, fit to - // height. - dest_h = scaled_h; - dest_y = 0; - dest_w = src_w * scaled_h / src_h; - dest_x = (scaled_w - dest_w) / 2; - } else { - // Otherwise, fit to width. - dest_w = scaled_w; - dest_x = 0; - dest_h = src_h * scaled_w / src_w; - dest_y = (scaled_h - dest_h) / 2; - } - imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, - src_y, src_w, src_h, dest_x, - dest_y, dest_w, dest_h); - } - - // XRender needs the alpha channel premultiplied. - DATA32 *data = imlib_image_get_data(); - gr_premultiply_alpha(data, scaled_w * scaled_h); - - // Upload the image to the X server. - Display *disp = imlib_context_get_display(); - Visual *vis = imlib_context_get_visual(); - Colormap cmap = imlib_context_get_colormap(); - Drawable drawable = imlib_context_get_drawable(); - if (!drawable) - drawable = DefaultRootWindow(disp); - pixmap = XCreatePixmap(disp, drawable, scaled_w, scaled_h, 32); - XVisualInfo visinfo; - XMatchVisualInfo(disp, DefaultScreen(disp), 32, TrueColor, &visinfo); - XImage *ximage = XCreateImage(disp, visinfo.visual, 32, ZPixmap, 0, - (char *)data, scaled_w, scaled_h, 32, 0); - GC gc = XCreateGC(disp, pixmap, 0, NULL); - XPutImage(disp, pixmap, gc, ximage, 0, 0, 0, 0, scaled_w, - scaled_h); - XFreeGC(disp, gc); - // XDestroyImage will free the data as well, but it is managed by imlib, - // so set it to NULL. - ximage->data = NULL; - XDestroyImage(ximage); - imlib_image_put_back_data(data); - imlib_free_image(); - - // Assign the pixmap to the frame and increase the ram size. - gr_set_frame_pixmap(placement, frameidx, pixmap); - images_ram_size += gr_placement_single_frame_ram_size(placement); - this_redraw_cycle_loaded_pixmaps++; - - GR_LOG("After loading placement %u/%u frame %d ram: %ld KiB (+ %u " - "KiB)\n", - frame->image->image_id, placement->placement_id, frame->index, - images_ram_size / 1024, - gr_placement_single_frame_ram_size(placement) / 1024); - - // Free up ram if needed, but keep the pixmap we've loaded no matter - // what. - placement->protected_frame = frameidx; - gr_check_limits(); - placement->protected_frame = 0; - - return pixmap; -} - -//////////////////////////////////////////////////////////////////////////////// -// Initialization and deinitialization. -//////////////////////////////////////////////////////////////////////////////// - -/// Creates a temporary directory. -static int gr_create_cache_dir() { - strncpy(cache_dir, graphics_cache_dir_template, sizeof(cache_dir)); - if (!mkdtemp(cache_dir)) { - fprintf(stderr, - "error: could not create temporary dir from template " - "%s\n", - sanitized_filename(cache_dir)); - return 0; - } - fprintf(stderr, "Graphics cache directory: %s\n", cache_dir); - return 1; -} - -/// Checks whether `tmp_dir` exists and recreates it if it doesn't. -static void gr_make_sure_tmpdir_exists() { - struct stat st; - if (stat(cache_dir, &st) == 0 && S_ISDIR(st.st_mode)) - return; - fprintf(stderr, - "error: %s is not a directory, will need to create a new " - "graphics cache directory\n", - sanitized_filename(cache_dir)); - gr_create_cache_dir(); -} - -/// Initialize the graphics module. -void gr_init(Display *disp, Visual *vis, Colormap cm) { - // Set the initialization time. - clock_gettime(CLOCK_MONOTONIC, &initialization_time); - - // Create the temporary dir. - if (!gr_create_cache_dir()) - abort(); - - // Initialize imlib. - imlib_context_set_display(disp); - imlib_context_set_visual(vis); - imlib_context_set_colormap(cm); - imlib_context_set_anti_alias(1); - imlib_context_set_blend(1); - // Imlib2 checks only the file name when caching, which is not enough - // for us since we reuse file names. Disable caching. - imlib_set_cache_size(0); - - // Prepare for color inversion. - for (size_t i = 0; i < 256; ++i) - reverse_table[i] = 255 - i; - - // Create data structures. - images = kh_init(id2image); - kv_init(next_redraw_times); - - atexit(gr_deinit); -} - -/// Deinitialize the graphics module. -void gr_deinit() { - // Remove the cache dir. - remove(cache_dir); - kv_destroy(next_redraw_times); - if (images) { - // Delete all images. - gr_delete_all_images(); - // Destroy the data structures. - kh_destroy(id2image, images); - images = NULL; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Dumping, debugging, and image preview. -//////////////////////////////////////////////////////////////////////////////// - -/// Returns a string containing a time difference in a human-readable format. -/// Uses a static buffer, so be careful. -static const char *gr_ago(Milliseconds diff) { - static char result[32]; - double seconds = (double)diff / 1000.0; - if (seconds < 1) - snprintf(result, sizeof(result), "%.2f sec ago", seconds); - else if (seconds < 60) - snprintf(result, sizeof(result), "%d sec ago", (int)seconds); - else if (seconds < 3600) - snprintf(result, sizeof(result), "%d min %d sec ago", - (int)(seconds / 60), (int)(seconds) % 60); - else { - snprintf(result, sizeof(result), "%d hr %d min %d sec ago", - (int)(seconds / 3600), (int)(seconds) % 3600 / 60, - (int)(seconds) % 60); - } - return result; -} - -/// Prints to `file` with an indentation of `ind` spaces. -static void fprintf_ind(FILE *file, int ind, const char *format, ...) { - fprintf(file, "%*s", ind, ""); - va_list args; - va_start(args, format); - vfprintf(file, format, args); - va_end(args); -} - -/// Dumps the image info to `file` with an indentation of `ind` spaces. -static void gr_dump_image_info(FILE *file, Image *img, int ind) { - if (!img) { - fprintf_ind(file, ind, "Image is NULL\n"); - return; - } - Milliseconds now = gr_now_ms(); - fprintf_ind(file, ind, "Image %u\n", img->image_id); - ind += 4; - fprintf_ind(file, ind, "number: %u\n", img->image_number); - fprintf_ind(file, ind, "global command index: %lu\n", - img->global_command_index); - fprintf_ind(file, ind, "accessed: %ld %s\n", img->atime, - gr_ago(now - img->atime)); - fprintf_ind(file, ind, "pix size: %ux%u\n", img->pix_width, - img->pix_height); - fprintf_ind(file, ind, "cur frame start time: %ld %s\n", - img->current_frame_time, - gr_ago(now - img->current_frame_time)); - if (img->next_redraw) - fprintf_ind(file, ind, "next redraw: %ld in %ld ms\n", - img->next_redraw, img->next_redraw - now); - fprintf_ind(file, ind, "total disk size: %u KiB\n", - img->total_disk_size / 1024); - fprintf_ind(file, ind, "total duration: %d\n", img->total_duration); - fprintf_ind(file, ind, "frames: %d\n", gr_last_frame_index(img)); - fprintf_ind(file, ind, "cur frame: %d\n", img->current_frame); - fprintf_ind(file, ind, "animation state: %d\n", img->animation_state); - fprintf_ind(file, ind, "default_placement: %u\n", - img->default_placement); -} - -/// Dumps the frame info to `file` with an indentation of `ind` spaces. -static void gr_dump_frame_info(FILE *file, ImageFrame *frame, int ind) { - if (!frame) { - fprintf_ind(file, ind, "Frame is NULL\n"); - return; - } - Milliseconds now = gr_now_ms(); - fprintf_ind(file, ind, "Frame %d\n", frame->index); - ind += 4; - if (frame->index == 0) { - fprintf_ind(file, ind, "NOT INITIALIZED\n"); - return; - } - if (frame->uploading_failure) - fprintf_ind(file, ind, "uploading failure: %s\n", - image_uploading_failure_strings - [frame->uploading_failure]); - fprintf_ind(file, ind, "gap: %d\n", frame->gap); - fprintf_ind(file, ind, "accessed: %ld %s\n", frame->atime, - gr_ago(now - frame->atime)); - fprintf_ind(file, ind, "data pix size: %ux%u\n", frame->data_pix_width, - frame->data_pix_height); - char filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); - if (access(filename, F_OK) != -1) - fprintf_ind(file, ind, "file: %s\n", - sanitized_filename(filename)); - else - fprintf_ind(file, ind, "not on disk\n"); - fprintf_ind(file, ind, "disk size: %u KiB\n", frame->disk_size / 1024); - if (frame->imlib_object) { - unsigned ram_size = gr_frame_current_ram_size(frame); - fprintf_ind(file, ind, - "loaded into ram, size: %d " - "KiB\n", - ram_size / 1024); - } else { - fprintf_ind(file, ind, "not loaded into ram\n"); - } -} - -/// Dumps the placement info to `file` with an indentation of `ind` spaces. -static void gr_dump_placement_info(FILE *file, ImagePlacement *placement, - int ind) { - if (!placement) { - fprintf_ind(file, ind, "Placement is NULL\n"); - return; - } - Milliseconds now = gr_now_ms(); - fprintf_ind(file, ind, "Placement %u\n", placement->placement_id); - ind += 4; - fprintf_ind(file, ind, "accessed: %ld %s\n", placement->atime, - gr_ago(now - placement->atime)); - fprintf_ind(file, ind, "scale_mode: %u\n", placement->scale_mode); - fprintf_ind(file, ind, "size: %u cols x %u rows\n", placement->cols, - placement->rows); - fprintf_ind(file, ind, "cell size: %ux%u\n", placement->scaled_cw, - placement->scaled_ch); - fprintf_ind(file, ind, "ram per frame: %u KiB\n", - gr_placement_single_frame_ram_size(placement) / 1024); - unsigned ram_size = gr_placement_current_ram_size(placement); - fprintf_ind(file, ind, "ram size: %d KiB\n", ram_size / 1024); -} - -/// Dumps placement pixmaps to `file` with an indentation of `ind` spaces. -static void gr_dump_placement_pixmaps(FILE *file, ImagePlacement *placement, - int ind) { - if (!placement) - return; - int frameidx = 1; - foreach_pixmap(*placement, pixmap, { - fprintf_ind(file, ind, "Frame %d pixmap %lu\n", frameidx, - pixmap); - ++frameidx; - }); -} - -/// Dumps the internal state (images and placements) to stderr. -void gr_dump_state() { - FILE *file = stderr; - int ind = 0; - fprintf_ind(file, ind, "======= Graphics module state dump =======\n"); - fprintf_ind(file, ind, - "sizeof(Image) = %lu sizeof(ImageFrame) = %lu " - "sizeof(ImagePlacement) = %lu\n", - sizeof(Image), sizeof(ImageFrame), sizeof(ImagePlacement)); - fprintf_ind(file, ind, "Image count: %u\n", kh_size(images)); - fprintf_ind(file, ind, "Placement count: %u\n", total_placement_count); - fprintf_ind(file, ind, "Estimated RAM usage: %ld KiB\n", - images_ram_size / 1024); - fprintf_ind(file, ind, "Estimated Disk usage: %ld KiB\n", - images_disk_size / 1024); - - Milliseconds now = gr_now_ms(); - - int64_t images_ram_size_computed = 0; - int64_t images_disk_size_computed = 0; - - Image *img = NULL; - ImagePlacement *placement = NULL; - kh_foreach_value(images, img, { - fprintf_ind(file, ind, "----------------\n"); - gr_dump_image_info(file, img, 0); - int64_t total_disk_size_computed = 0; - int total_duration_computed = 0; - foreach_frame(*img, frame, { - gr_dump_frame_info(file, frame, 4); - if (frame->image != img) - fprintf_ind(file, 8, - "ERROR: WRONG IMAGE POINTER\n"); - total_duration_computed += frame->gap; - images_disk_size_computed += frame->disk_size; - total_disk_size_computed += frame->disk_size; - if (frame->imlib_object) - images_ram_size_computed += - gr_frame_current_ram_size(frame); - }); - if (img->total_disk_size != total_disk_size_computed) { - fprintf_ind(file, ind, - " ERROR: total_disk_size is %u, but " - "computed value is %ld\n", - img->total_disk_size, total_disk_size_computed); - } - if (img->total_duration != total_duration_computed) { - fprintf_ind(file, ind, - " ERROR: total_duration is %d, but computed " - "value is %d\n", - img->total_duration, total_duration_computed); - } - kh_foreach_value(img->placements, placement, { - gr_dump_placement_info(file, placement, 4); - if (placement->image != img) - fprintf_ind(file, 8, - "ERROR: WRONG IMAGE POINTER\n"); - fprintf_ind(file, 8, - "Pixmaps:\n"); - gr_dump_placement_pixmaps(file, placement, 12); - unsigned ram_size = - gr_placement_current_ram_size(placement); - images_ram_size_computed += ram_size; - }); - }); - if (images_ram_size != images_ram_size_computed) { - fprintf_ind(file, ind, - "ERROR: images_ram_size is %ld, but computed value " - "is %ld\n", - images_ram_size, images_ram_size_computed); - } - if (images_disk_size != images_disk_size_computed) { - fprintf_ind(file, ind, - "ERROR: images_disk_size is %ld, but computed value " - "is %ld\n", - images_disk_size, images_disk_size_computed); - } - fprintf_ind(file, ind, "===========================================\n"); -} - -/// Executes `command` with the name of the file corresponding to `image_id` as -/// the argument. Executes xmessage with an error message on failure. -// TODO: Currently we do this for the first frame only. Not sure what to do with -// animations. -void gr_preview_image(uint32_t image_id, const char *exec) { - char command[256]; - size_t len; - Image *img = gr_find_image(image_id); - if (img) { - ImageFrame *frame = &img->first_frame; - char filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); - if (frame->disk_size == 0) { - len = snprintf(command, 255, - "xmessage 'Image with id=%u is not " - "fully copied to %s'", - image_id, sanitized_filename(filename)); - } else { - len = snprintf(command, 255, "%s %s &", exec, - sanitized_filename(filename)); - } - } else { - len = snprintf(command, 255, - "xmessage 'Cannot find image with id=%u'", - image_id); - } - if (len > 255) { - fprintf(stderr, "error: command too long: %s\n", command); - snprintf(command, 255, "xmessage 'error: command too long'"); - } - if (system(command) != 0) { - fprintf(stderr, "error: could not execute command %s\n", - command); - } -} - -/// Executes ` -e less ` where is the name of a temporary file -/// containing the information about an image and placement, and is -/// specified with `st_executable`. -void gr_show_image_info(uint32_t image_id, uint32_t placement_id, - uint32_t imgcol, uint32_t imgrow, - char is_classic_placeholder, int32_t diacritic_count, - char *st_executable) { - char filename[MAX_FILENAME_SIZE]; - snprintf(filename, sizeof(filename), "%s/info-%u", cache_dir, image_id); - FILE *file = fopen(filename, "w"); - if (!file) { - perror("fopen"); - return; - } - // Basic information about the cell. - fprintf(file, "image_id = %u = 0x%08X\n", image_id, image_id); - fprintf(file, "placement_id = %u = 0x%08X\n", placement_id, placement_id); - fprintf(file, "column = %d, row = %d\n", imgcol, imgrow); - fprintf(file, "classic/unicode placeholder = %s\n", - is_classic_placeholder ? "classic" : "unicode"); - fprintf(file, "original diacritic count = %d\n", diacritic_count); - // Information about the image and the placement. - Image *img = gr_find_image(image_id); - ImagePlacement *placement = gr_find_placement(img, placement_id); - gr_dump_image_info(file, img, 0); - gr_dump_placement_info(file, placement, 0); - if (img) { - fprintf(file, "Frames:\n"); - foreach_frame(*img, frame, { - gr_dump_frame_info(file, frame, 4); - }); - } - if (placement) { - fprintf(file, "Placement pixmaps:\n"); - gr_dump_placement_pixmaps(file, placement, 4); - } - fclose(file); - char *argv[] = {st_executable, "-e", "less", filename, NULL}; - if (posix_spawnp(NULL, st_executable, NULL, NULL, argv, environ) != 0) { - perror("posix_spawnp"); - return; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Appending and displaying image rectangles. -//////////////////////////////////////////////////////////////////////////////// - -/// Displays debug information in the rectangle using colors col1 and col2. -static void gr_displayinfo(Drawable buf, ImageRect *rect, int col1, int col2, - const char *message) { - int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw; - int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch; - Display *disp = imlib_context_get_display(); - GC gc = XCreateGC(disp, buf, 0, NULL); - char info[MAX_INFO_LEN]; - if (rect->placement_id) - snprintf(info, MAX_INFO_LEN, "%s%u/%u [%d:%d)x[%d:%d)", message, - rect->image_id, rect->placement_id, - rect->img_start_col, rect->img_end_col, - rect->img_start_row, rect->img_end_row); - else - snprintf(info, MAX_INFO_LEN, "%s%u [%d:%d)x[%d:%d)", message, - rect->image_id, rect->img_start_col, rect->img_end_col, - rect->img_start_row, rect->img_end_row); - XSetForeground(disp, gc, col1); - XDrawString(disp, buf, gc, rect->screen_x_pix + 4, - rect->screen_y_pix + h_pix - 3, info, strlen(info)); - XSetForeground(disp, gc, col2); - XDrawString(disp, buf, gc, rect->screen_x_pix + 2, - rect->screen_y_pix + h_pix - 5, info, strlen(info)); - XFreeGC(disp, gc); -} - -/// Draws a rectangle (bounding box) for debugging. -static void gr_showrect(Drawable buf, ImageRect *rect) { - int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw; - int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch; - Display *disp = imlib_context_get_display(); - GC gc = XCreateGC(disp, buf, 0, NULL); - XSetForeground(disp, gc, 0xFF00FF00); - XDrawRectangle(disp, buf, gc, rect->screen_x_pix, rect->screen_y_pix, - w_pix - 1, h_pix - 1); - XSetForeground(disp, gc, 0xFFFF0000); - XDrawRectangle(disp, buf, gc, rect->screen_x_pix + 1, - rect->screen_y_pix + 1, w_pix - 3, h_pix - 3); - XFreeGC(disp, gc); -} - -/// Updates the next redraw time for the given row. Resizes the -/// next_redraw_times array if needed. -static void gr_update_next_redraw_time(int row, Milliseconds next_redraw) { - if (next_redraw == 0) - return; - if (row >= kv_size(next_redraw_times)) { - size_t old_size = kv_size(next_redraw_times); - kv_a(Milliseconds, next_redraw_times, row); - for (size_t i = old_size; i <= row; ++i) - kv_A(next_redraw_times, i) = 0; - } - Milliseconds old_value = kv_A(next_redraw_times, row); - if (old_value == 0 || old_value > next_redraw) - kv_A(next_redraw_times, row) = next_redraw; -} - -/// Draws the given part of an image. -static void gr_drawimagerect(Drawable buf, ImageRect *rect) { - ImagePlacement *placement = - gr_find_image_and_placement(rect->image_id, rect->placement_id); - // If the image does not exist or image display is switched off, draw - // the bounding box. - if (!placement || !graphics_display_images) { - gr_showrect(buf, rect); - if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) - gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); - return; - } - - Image *img = placement->image; - - if (img->last_redraw < drawing_start_time) { - // This is the first time we draw this image in this redraw - // cycle. Update the frame index we are going to display. Note - // that currently all image placements are synchronized. - int old_frame = img->current_frame; - gr_update_frame_index(img, drawing_start_time); - img->last_redraw = drawing_start_time; - } - - // Adjust next redraw times for the rows of this image rect. - if (img->next_redraw) { - for (int row = rect->screen_y_row; - row <= rect->screen_y_row + rect->img_end_row - - rect->img_start_row - 1; ++row) { - gr_update_next_redraw_time( - row, img->next_redraw); - } - } - - // Load the frame. - Pixmap pixmap = gr_load_pixmap(placement, img->current_frame, rect->cw, - rect->ch); - - // If the image couldn't be loaded, display the bounding box. - if (!pixmap) { - gr_showrect(buf, rect); - if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) - gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); - return; - } - - int src_x = rect->img_start_col * rect->cw; - int src_y = rect->img_start_row * rect->ch; - int width = (rect->img_end_col - rect->img_start_col) * rect->cw; - int height = (rect->img_end_row - rect->img_start_row) * rect->ch; - int dst_x = rect->screen_x_pix; - int dst_y = rect->screen_y_pix; - - // Display the image. - Display *disp = imlib_context_get_display(); - Visual *vis = imlib_context_get_visual(); - - // Create an xrender picture for the window. - XRenderPictFormat *win_format = - XRenderFindVisualFormat(disp, vis); - Picture window_pic = - XRenderCreatePicture(disp, buf, win_format, 0, NULL); - - // If needed, invert the image pixmap. Note that this naive approach of - // inverting the pixmap is not entirely correct, because the pixmap is - // premultiplied. But the result is good enough to visually indicate - // selection. - if (rect->reverse) { - unsigned pixmap_w = - (unsigned)placement->cols * placement->scaled_cw; - unsigned pixmap_h = - (unsigned)placement->rows * placement->scaled_ch; - Pixmap invpixmap = - XCreatePixmap(disp, buf, pixmap_w, pixmap_h, 32); - XGCValues gcv = {.function = GXcopyInverted}; - GC gc = XCreateGC(disp, invpixmap, GCFunction, &gcv); - XCopyArea(disp, pixmap, invpixmap, gc, 0, 0, pixmap_w, - pixmap_h, 0, 0); - XFreeGC(disp, gc); - pixmap = invpixmap; - } - - // Create a picture for the image pixmap. - XRenderPictFormat *pic_format = - XRenderFindStandardFormat(disp, PictStandardARGB32); - Picture pixmap_pic = - XRenderCreatePicture(disp, pixmap, pic_format, 0, NULL); - - // Composite the image onto the window. In the reverse mode we ignore - // the alpha channel of the image because the naive inversion above - // seems to invert the alpha channel as well. - int pictop = rect->reverse ? PictOpSrc : PictOpOver; - XRenderComposite(disp, pictop, pixmap_pic, 0, window_pic, - src_x, src_y, src_x, src_y, dst_x, dst_y, width, - height); - - // Free resources - XRenderFreePicture(disp, pixmap_pic); - XRenderFreePicture(disp, window_pic); - if (rect->reverse) - XFreePixmap(disp, pixmap); - - // In debug mode always draw bounding boxes and print info. - if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) { - gr_showrect(buf, rect); - gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); - } -} - -/// Removes the given image rectangle. -static void gr_freerect(ImageRect *rect) { memset(rect, 0, sizeof(ImageRect)); } - -/// Returns the bottom coordinate of the rect. -static int gr_getrectbottom(ImageRect *rect) { - return rect->screen_y_pix + - (rect->img_end_row - rect->img_start_row) * rect->ch; -} - -/// Prepare for image drawing. `cw` and `ch` are dimensions of the cell. -void gr_start_drawing(Drawable buf, int cw, int ch) { - current_cw = cw; - current_ch = ch; - this_redraw_cycle_loaded_files = 0; - this_redraw_cycle_loaded_pixmaps = 0; - drawing_start_time = gr_now_ms(); - imlib_context_set_drawable(buf); -} - -/// Finish image drawing. This functions will draw all the rectangles left to -/// draw. -void gr_finish_drawing(Drawable buf) { - // Draw and then delete all known image rectangles. - for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { - ImageRect *rect = &image_rects[i]; - if (!rect->image_id) - continue; - gr_drawimagerect(buf, rect); - gr_freerect(rect); - } - - // Compute the delay until the next redraw as the minimum of the next - // redraw delays for all rows. - Milliseconds drawing_end_time = gr_now_ms(); - graphics_next_redraw_delay = INT_MAX; - for (int row = 0; row < kv_size(next_redraw_times); ++row) { - Milliseconds row_next_redraw = kv_A(next_redraw_times, row); - if (row_next_redraw > 0) { - int delay = MAX(graphics_animation_min_delay, - row_next_redraw - drawing_end_time); - graphics_next_redraw_delay = - MIN(graphics_next_redraw_delay, delay); - } - } - - // In debug mode display additional info. - if (graphics_debug_mode) { - int milliseconds = drawing_end_time - drawing_start_time; - - Display *disp = imlib_context_get_display(); - GC gc = XCreateGC(disp, buf, 0, NULL); - const char *debug_mode_str = - graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES - ? "(boxes shown) " - : ""; - int redraw_delay = graphics_next_redraw_delay == INT_MAX - ? -1 - : graphics_next_redraw_delay; - char info[MAX_INFO_LEN]; - snprintf(info, MAX_INFO_LEN, - "%sRender time: %d ms ram %ld K disk %ld K count " - "%d cell %dx%d delay %d", - debug_mode_str, milliseconds, images_ram_size / 1024, - images_disk_size / 1024, kh_size(images), current_cw, - current_ch, redraw_delay); - XSetForeground(disp, gc, 0xFF000000); - XFillRectangle(disp, buf, gc, 0, 0, 600, 16); - XSetForeground(disp, gc, 0xFFFFFFFF); - XDrawString(disp, buf, gc, 0, 14, info, strlen(info)); - XFreeGC(disp, gc); - - if (milliseconds > 0) { - fprintf(stderr, "%s (loaded %d files, %d pixmaps)\n", - info, this_redraw_cycle_loaded_files, - this_redraw_cycle_loaded_pixmaps); - } - } - - // Check the limits in case we have used too much ram for placements. - gr_check_limits(); -} - -// Add an image rectangle to the list of rectangles to draw. -void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id, - int img_start_col, int img_end_col, int img_start_row, - int img_end_row, int x_col, int y_row, int x_pix, - int y_pix, int cw, int ch, int reverse) { - current_cw = cw; - current_ch = ch; - - ImageRect new_rect; - new_rect.image_id = image_id; - new_rect.placement_id = placement_id; - new_rect.img_start_col = img_start_col; - new_rect.img_end_col = img_end_col; - new_rect.img_start_row = img_start_row; - new_rect.img_end_row = img_end_row; - new_rect.screen_y_row = y_row; - new_rect.screen_x_pix = x_pix; - new_rect.screen_y_pix = y_pix; - new_rect.ch = ch; - new_rect.cw = cw; - new_rect.reverse = reverse; - - // Display some red text in debug mode. - if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) - gr_displayinfo(buf, &new_rect, 0xFF000000, 0xFFFF0000, "? "); - - // If it's the empty image (image_id=0) or an empty rectangle, do - // nothing. - if (image_id == 0 || img_end_col - img_start_col <= 0 || - img_end_row - img_start_row <= 0) - return; - // Try to find a rect to merge with. - ImageRect *free_rect = NULL; - for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { - ImageRect *rect = &image_rects[i]; - if (rect->image_id == 0) { - if (!free_rect) - free_rect = rect; - continue; - } - if (rect->image_id != image_id || - rect->placement_id != placement_id || rect->cw != cw || - rect->ch != ch || rect->reverse != reverse) - continue; - // We only support the case when the new stripe is added to the - // bottom of an existing rectangle and they are perfectly - // aligned. - if (rect->img_end_row == img_start_row && - gr_getrectbottom(rect) == y_pix) { - if (rect->img_start_col == img_start_col && - rect->img_end_col == img_end_col && - rect->screen_x_pix == x_pix) { - rect->img_end_row = img_end_row; - return; - } - } - } - // If we haven't merged the new rect with any existing rect, and there - // is no free rect, we have to render one of the existing rects. - if (!free_rect) { - for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { - ImageRect *rect = &image_rects[i]; - if (!free_rect || gr_getrectbottom(free_rect) > - gr_getrectbottom(rect)) - free_rect = rect; - } - gr_drawimagerect(buf, free_rect); - gr_freerect(free_rect); - } - // Start a new rectangle in `free_rect`. - *free_rect = new_rect; -} - -/// Mark rows containing animations as dirty if it's time to redraw them. Must -/// be called right after `gr_start_drawing`. -void gr_mark_dirty_animations(int *dirty, int rows) { - if (rows < kv_size(next_redraw_times)) - kv_size(next_redraw_times) = rows; - if (rows * 2 < kv_max(next_redraw_times)) - kv_resize(Milliseconds, next_redraw_times, rows); - for (int i = 0; i < MIN(rows, kv_size(next_redraw_times)); ++i) { - if (dirty[i]) { - kv_A(next_redraw_times, i) = 0; - continue; - } - Milliseconds next_update = kv_A(next_redraw_times, i); - if (next_update > 0 && next_update <= drawing_start_time) { - dirty[i] = 1; - kv_A(next_redraw_times, i) = 0; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Command parsing and handling. -//////////////////////////////////////////////////////////////////////////////// - -/// A parsed kitty graphics protocol command. -typedef struct { - /// The command itself, without the 'G'. - char *command; - /// The payload (after ';'). - char *payload; - /// 'a=', may be 't', 'q', 'f', 'T', 'p', 'd', 'a'. - char action; - /// 'q=', 1 to suppress OK response, 2 to suppress errors too. - int quiet; - /// 'f=', use 24 or 32 for raw pixel data, 100 to autodetect with - /// imlib2. If 'f=0', will try to load with imlib2, then fallback to - /// 32-bit pixel data. - int format; - /// 'o=', may be 'z' for RFC 1950 ZLIB. - int compression; - /// 't=', may be 'f', 't' or 'd'. - char transmission_medium; - /// 'd=' - char delete_specifier; - /// 's=', 'v=', if 'a=t' or 'a=T', used only when 'f=24' or 'f=32'. - /// When 'a=f', this is the size of the frame rectangle when composed on - /// top of another frame. - int frame_pix_width, frame_pix_height; - /// 'x=', 'y=' - top-left corner of the source rectangle. - int src_pix_x, src_pix_y; - /// 'w=', 'h=' - width and height of the source rectangle. - int src_pix_width, src_pix_height; - /// 'r=', 'c=' - int rows, columns; - /// 'i=' - uint32_t image_id; - /// 'I=' - uint32_t image_number; - /// 'p=' - uint32_t placement_id; - /// 'm=', may be 0 or 1. - int more; - /// True if either 'm=0' or 'm=1' is specified. - char is_data_transmission; - /// True if turns out that this command is a continuation of a data - /// transmission and not the first one for this image. Populated by - /// `gr_handle_transmit_command`. - char is_direct_transmission_continuation; - /// 'S=', used to check the size of uploaded data. - int size; - /// 'U=', whether it's a virtual placement for Unicode placeholders. - int virtual; - /// 'C=', if true, do not move the cursor when displaying this placement - /// (non-virtual placements only). - char do_not_move_cursor; - // --------------------------------------------------------------------- - // Animation-related fields. Their keys often overlap with keys of other - // commands, so these make sense only if the action is 'a=f' (frame - // transmission) or 'a=a' (animation control). - // - // 'x=' and 'y=', the relative position of the frame image when it's - // composed on top of another frame. - int frame_dst_pix_x, frame_dst_pix_y; - /// 'X=', 'X=1' to replace colors instead of alpha blending on top of - /// the background color or frame. - char replace_instead_of_blending; - /// 'Y=', the background color in the 0xRRGGBBAA format (still - /// transmitted as a decimal number). - uint32_t background_color; - /// (Only for 'a=f'). 'c=', the 1-based index of the background frame. - int background_frame; - /// (Only for 'a=a'). 'c=', sets the index of the current frame. - int current_frame; - /// 'r=', the 1-based index of the frame to edit. - int edit_frame; - /// 'z=', the duration of the frame. Zero if not specified, negative if - /// the frame is gapless (i.e. skipped). - int gap; - /// (Only for 'a=a'). 's=', if non-zero, sets the state of the - /// animation, 1 to stop, 2 to run in loading mode, 3 to loop. - int animation_state; - /// (Only for 'a=a'). 'v=', if non-zero, sets the number of times the - /// animation will loop. 1 to loop infinitely, N to loop N-1 times. - int loops; -} GraphicsCommand; - -/// Replaces all non-printed characters in `str` with '?' and truncates the -/// string to `max_size`, maybe inserting ellipsis at the end. -static void sanitize_str(char *str, size_t max_size) { - assert(max_size >= 4); - for (size_t i = 0; i < max_size; ++i) { - unsigned c = str[i]; - if (c == '\0') - return; - if (c >= 128 || !isprint(c)) - str[i] = '?'; - } - str[max_size - 1] = '\0'; - str[max_size - 2] = '.'; - str[max_size - 3] = '.'; - str[max_size - 4] = '.'; -} - -/// A non-destructive version of `sanitize_str`. Uses a static buffer, so be -/// careful. -static const char *sanitized_filename(const char *str) { - static char buf[MAX_FILENAME_SIZE]; - strncpy(buf, str, sizeof(buf)); - sanitize_str(buf, sizeof(buf)); - return buf; -} - -/// Creates a response to the current command in `graphics_command_result`. -static void gr_createresponse(uint32_t image_id, uint32_t image_number, - uint32_t placement_id, const char *msg) { - if (!image_id && !image_number && !placement_id) { - // Nobody expects the response in this case, so just print it to - // stderr. - fprintf(stderr, - "error: No image id or image number or placement_id, " - "but still there is a response: %s\n", - msg); - return; - } - char *buf = graphics_command_result.response; - size_t maxlen = MAX_GRAPHICS_RESPONSE_LEN; - size_t written; - written = snprintf(buf, maxlen, "\033_G"); - buf += written; - maxlen -= written; - if (image_id) { - written = snprintf(buf, maxlen, "i=%u,", image_id); - buf += written; - maxlen -= written; - } - if (image_number) { - written = snprintf(buf, maxlen, "I=%u,", image_number); - buf += written; - maxlen -= written; - } - if (placement_id) { - written = snprintf(buf, maxlen, "p=%u,", placement_id); - buf += written; - maxlen -= written; - } - buf[-1] = ';'; - written = snprintf(buf, maxlen, "%s\033\\", msg); - buf += written; - maxlen -= written; - buf[-2] = '\033'; - buf[-1] = '\\'; -} - -/// Creates the 'OK' response to the current command, unless suppressed or a -/// non-final data transmission. -static void gr_reportsuccess_cmd(GraphicsCommand *cmd) { - if (cmd->quiet < 1 && !cmd->more) - gr_createresponse(cmd->image_id, cmd->image_number, - cmd->placement_id, "OK"); -} - -/// Creates the 'OK' response to the current command (unless suppressed). -static void gr_reportsuccess_frame(ImageFrame *frame) { - uint32_t id = frame->image->query_id ? frame->image->query_id - : frame->image->image_id; - if (frame->quiet < 1) - gr_createresponse(id, frame->image->image_number, - frame->image->initial_placement_id, "OK"); -} - -/// Creates an error response to the current command (unless suppressed). -static void gr_reporterror_cmd(GraphicsCommand *cmd, const char *format, ...) { - char errmsg[MAX_GRAPHICS_RESPONSE_LEN]; - graphics_command_result.error = 1; - va_list args; - va_start(args, format); - vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args); - va_end(args); - - fprintf(stderr, "%s in command: %s\n", errmsg, cmd->command); - if (cmd->quiet < 2) - gr_createresponse(cmd->image_id, cmd->image_number, - cmd->placement_id, errmsg); -} - -/// Creates an error response to the current command (unless suppressed). -static void gr_reporterror_frame(ImageFrame *frame, const char *format, ...) { - char errmsg[MAX_GRAPHICS_RESPONSE_LEN]; - graphics_command_result.error = 1; - va_list args; - va_start(args, format); - vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args); - va_end(args); - - if (!frame) { - fprintf(stderr, "%s\n", errmsg); - gr_createresponse(0, 0, 0, errmsg); - } else { - uint32_t id = frame->image->query_id ? frame->image->query_id - : frame->image->image_id; - fprintf(stderr, "%s id=%u\n", errmsg, id); - if (frame->quiet < 2) - gr_createresponse(id, frame->image->image_number, - frame->image->initial_placement_id, - errmsg); - } -} - -/// Loads an image and creates a success/failure response. Returns `frame`, or -/// NULL if it's a query action and the image was deleted. -static ImageFrame *gr_loadimage_and_report(ImageFrame *frame) { - gr_load_imlib_object(frame); - if (!frame->imlib_object) { - gr_reporterror_frame(frame, "EBADF: could not load image"); - } else { - gr_reportsuccess_frame(frame); - } - // If it was a query action, discard the image. - if (frame->image->query_id) { - gr_delete_image(frame->image); - return NULL; - } - return frame; -} - -/// Creates an appropriate uploading failure response to the current command. -static void gr_reportuploaderror(ImageFrame *frame) { - switch (frame->uploading_failure) { - case 0: - return; - case ERROR_CANNOT_OPEN_CACHED_FILE: - gr_reporterror_frame(frame, - "EIO: could not create a file for image"); - break; - case ERROR_OVER_SIZE_LIMIT: - gr_reporterror_frame( - frame, - "EFBIG: the size of the uploaded image exceeded " - "the image size limit %u", - graphics_max_single_image_file_size); - break; - case ERROR_UNEXPECTED_SIZE: - gr_reporterror_frame(frame, - "EINVAL: the size of the uploaded image %u " - "doesn't match the expected size %u", - frame->disk_size, frame->expected_size); - break; - }; -} - -/// Displays a non-virtual placement. This functions records the information in -/// `graphics_command_result`, the placeholder itself is created by the terminal -/// after handling the current command in the graphics module. -static void gr_display_nonvirtual_placement(ImagePlacement *placement) { - if (placement->virtual) - return; - if (placement->image->first_frame.status < STATUS_RAM_LOADING_SUCCESS) - return; - // Infer the placement size if needed. - gr_infer_placement_size_maybe(placement); - // Populate the information about the placeholder which will be created - // by the terminal. - graphics_command_result.create_placeholder = 1; - graphics_command_result.placeholder.image_id = placement->image->image_id; - graphics_command_result.placeholder.placement_id = placement->placement_id; - graphics_command_result.placeholder.columns = placement->cols; - graphics_command_result.placeholder.rows = placement->rows; - graphics_command_result.placeholder.do_not_move_cursor = - placement->do_not_move_cursor; - GR_LOG("Creating a placeholder for %u/%u %d x %d\n", - placement->image->image_id, placement->placement_id, - placement->cols, placement->rows); -} - -/// Marks the rows that are occupied by the image as dirty. -static void gr_schedule_image_redraw(Image *img) { - if (!img) - return; - gr_schedule_image_redraw_by_id(img->image_id); -} - -/// Appends data from `payload` to the frame `frame` when using direct -/// transmission. Note that we report errors only for the final command -/// (`!more`) to avoid spamming the client. If the frame is not specified, use -/// the image id and frame index we are currently uploading. -static void gr_append_data(ImageFrame *frame, const char *payload, int more) { - if (!frame) { - Image *img = gr_find_image(current_upload_image_id); - frame = gr_get_frame(img, current_upload_frame_index); - GR_LOG("Appending data to image %u frame %d\n", - current_upload_image_id, current_upload_frame_index); - if (!img) - GR_LOG("ERROR: this image doesn't exist\n"); - if (!frame) - GR_LOG("ERROR: this frame doesn't exist\n"); - } - if (!more) { - current_upload_image_id = 0; - current_upload_frame_index = 0; - } - if (!frame) { - if (!more) - gr_reporterror_frame(NULL, "ENOENT: could not find the " - "image to append data to"); - return; - } - if (frame->status != STATUS_UPLOADING) { - if (!more) - gr_reportuploaderror(frame); - return; - } - - // Decode the data. - size_t data_size = 0; - char *data = gr_base64dec(payload, &data_size); - - GR_LOG("appending %u + %zu = %zu bytes\n", frame->disk_size, data_size, - frame->disk_size + data_size); - - // Do not append this data if the image exceeds the size limit. - if (frame->disk_size + data_size > - graphics_max_single_image_file_size || - frame->expected_size > graphics_max_single_image_file_size) { - free(data); - gr_delete_imagefile(frame); - frame->uploading_failure = ERROR_OVER_SIZE_LIMIT; - if (!more) - gr_reportuploaderror(frame); - return; - } - - // If there is no open file corresponding to the image, create it. - if (!frame->open_file) { - gr_make_sure_tmpdir_exists(); - char filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); - FILE *file = fopen(filename, frame->disk_size ? "a" : "w"); - if (!file) { - frame->status = STATUS_UPLOADING_ERROR; - frame->uploading_failure = ERROR_CANNOT_OPEN_CACHED_FILE; - if (!more) - gr_reportuploaderror(frame); - return; - } - frame->open_file = file; - } - - // Write data to the file and update disk size variables. - fwrite(data, 1, data_size, frame->open_file); - free(data); - frame->disk_size += data_size; - frame->image->total_disk_size += data_size; - images_disk_size += data_size; - gr_touch_frame(frame); - - if (more) { - current_upload_image_id = frame->image->image_id; - current_upload_frame_index = frame->index; - } else { - current_upload_image_id = 0; - current_upload_frame_index = 0; - // Close the file. - if (frame->open_file) { - fclose(frame->open_file); - frame->open_file = NULL; - } - frame->status = STATUS_UPLOADING_SUCCESS; - uint32_t placement_id = frame->image->default_placement; - if (frame->expected_size && - frame->expected_size != frame->disk_size) { - // Report failure if the uploaded image size doesn't - // match the expected size. - frame->status = STATUS_UPLOADING_ERROR; - frame->uploading_failure = ERROR_UNEXPECTED_SIZE; - gr_reportuploaderror(frame); - } else { - // Make sure to redraw all existing image instances. - gr_schedule_image_redraw(frame->image); - // Try to load the image into ram and report the result. - frame = gr_loadimage_and_report(frame); - // If there is a non-virtual image placement, we may - // need to display it. - if (frame && frame->index == 1) { - Image *img = frame->image; - ImagePlacement *placement = NULL; - kh_foreach_value(img->placements, placement, { - gr_display_nonvirtual_placement(placement); - }); - } - } - } - - // Check whether we need to delete old images. - gr_check_limits(); -} - -/// Finds the image either by id or by number specified in the command and sets -/// the image_id of `cmd` if the image was found. -static Image *gr_find_image_for_command(GraphicsCommand *cmd) { - if (cmd->image_id) - return gr_find_image(cmd->image_id); - Image *img = NULL; - // If the image number is not specified, we can't find the image, unless - // it's a put command, in which case we will try the last image. - if (cmd->image_number == 0 && cmd->action == 'p') - img = gr_find_image(last_image_id); - else - img = gr_find_image_by_number(cmd->image_number); - if (img) - cmd->image_id = img->image_id; - return img; -} - -/// Creates a new image or a new frame in an existing image (depending on the -/// command's action) and initializes its parameters from the command. -static ImageFrame *gr_new_image_or_frame_from_command(GraphicsCommand *cmd) { - if (cmd->format != 0 && cmd->format != 32 && cmd->format != 24 && - cmd->compression != 0) { - gr_reporterror_cmd(cmd, "EINVAL: compression is supported only " - "for raw pixel data (f=32 or f=24)"); - // Even though we report an error, we still create an image. - } - - Image *img = NULL; - if (cmd->action == 'f') { - // If it's a frame transmission action, there must be an - // existing image. - img = gr_find_image_for_command(cmd); - if (!img) { - gr_reporterror_cmd(cmd, "ENOENT: image not found"); - return NULL; - } - } else { - // Otherwise create a new image object. If the action is `q`, - // we'll use random id instead of the one specified in the - // command. - uint32_t image_id = cmd->action == 'q' ? 0 : cmd->image_id; - img = gr_new_image(image_id); - if (!img) - return NULL; - if (cmd->action == 'q') - img->query_id = cmd->image_id; - else if (!cmd->image_id) - cmd->image_id = img->image_id; - // Set the image number. - img->image_number = cmd->image_number; - } - - ImageFrame *frame = gr_append_new_frame(img); - // Initialize the frame. - frame->expected_size = cmd->size; - frame->format = cmd->format; - frame->compression = cmd->compression; - frame->background_color = cmd->background_color; - frame->background_frame_index = cmd->background_frame; - frame->gap = cmd->gap; - img->total_duration += frame->gap; - frame->blend = !cmd->replace_instead_of_blending; - frame->data_pix_width = cmd->frame_pix_width; - frame->data_pix_height = cmd->frame_pix_height; - if (cmd->action == 'f') { - frame->x = cmd->frame_dst_pix_x; - frame->y = cmd->frame_dst_pix_y; - } - // We save the quietness information in the frame because for direct - // transmission subsequent transmission command won't contain this info. - frame->quiet = cmd->quiet; - return frame; -} - -/// Removes a file if it actually looks like a temporary file. -static void gr_delete_tmp_file(const char *filename) { - if (strstr(filename, "tty-graphics-protocol") == NULL) - return; - if (strstr(filename, "/tmp/") != filename) { - const char *tmpdir = getenv("TMPDIR"); - if (!tmpdir || !tmpdir[0] || - strstr(filename, tmpdir) != filename) - return; - } - unlink(filename); -} - -/// Handles a data transmission command. -static ImageFrame *gr_handle_transmit_command(GraphicsCommand *cmd) { - // The default is direct transmission. - if (!cmd->transmission_medium) - cmd->transmission_medium = 'd'; - - // If neither id, nor image number is specified, and the transmission - // medium is 'd' (or unspecified), and there is an active direct upload, - // this is a continuation of the upload. - if (current_upload_image_id != 0 && cmd->image_id == 0 && - cmd->image_number == 0 && cmd->transmission_medium == 'd') { - cmd->image_id = current_upload_image_id; - GR_LOG("No images id is specified, continuing uploading %u\n", - cmd->image_id); - } - - ImageFrame *frame = NULL; - if (cmd->transmission_medium == 'f' || - cmd->transmission_medium == 't') { - // File transmission. - // Create a new image or a new frame of an existing image. - frame = gr_new_image_or_frame_from_command(cmd); - if (!frame) - return NULL; - last_image_id = frame->image->image_id; - // Decode the filename. - char *original_filename = gr_base64dec(cmd->payload, NULL); - GR_LOG("Copying image %s\n", - sanitized_filename(original_filename)); - // Stat the file and check that it's a regular file and not too - // big. - struct stat st; - int stat_res = stat(original_filename, &st); - const char *stat_error = NULL; - if (stat_res) - stat_error = strerror(errno); - else if (!S_ISREG(st.st_mode)) - stat_error = "Not a regular file"; - else if (st.st_size == 0) - stat_error = "The size of the file is zero"; - else if (st.st_size > graphics_max_single_image_file_size) - stat_error = "The file is too large"; - if (stat_error) { - gr_reporterror_cmd(cmd, - "EBADF: %s", stat_error); - fprintf(stderr, "Could not load the file %s\n", - sanitized_filename(original_filename)); - frame->status = STATUS_UPLOADING_ERROR; - frame->uploading_failure = ERROR_CANNOT_COPY_FILE; - } else { - gr_make_sure_tmpdir_exists(); - // Build the filename for the cached copy of the file. - char cache_filename[MAX_FILENAME_SIZE]; - gr_get_frame_filename(frame, cache_filename, - MAX_FILENAME_SIZE); - // We will create a symlink to the original file, and - // then copy the file to the temporary cache dir. We do - // this symlink trick mostly to be able to use cp for - // copying, and avoid escaping file name characters when - // calling system at the same time. - char tmp_filename_symlink[MAX_FILENAME_SIZE + 4] = {0}; - strcat(tmp_filename_symlink, cache_filename); - strcat(tmp_filename_symlink, ".sym"); - char command[MAX_FILENAME_SIZE + 256]; - size_t len = - snprintf(command, MAX_FILENAME_SIZE + 255, - "cp '%s' '%s'", tmp_filename_symlink, - cache_filename); - if (len > MAX_FILENAME_SIZE + 255 || - symlink(original_filename, tmp_filename_symlink) || - system(command) != 0) { - gr_reporterror_cmd(cmd, - "EBADF: could not copy the " - "image to the cache dir"); - fprintf(stderr, - "Could not copy the image " - "%s (symlink %s) to %s", - sanitized_filename(original_filename), - tmp_filename_symlink, cache_filename); - frame->status = STATUS_UPLOADING_ERROR; - frame->uploading_failure = ERROR_CANNOT_COPY_FILE; - } else { - // Get the file size of the copied file. - frame->status = STATUS_UPLOADING_SUCCESS; - frame->disk_size = st.st_size; - frame->image->total_disk_size += st.st_size; - images_disk_size += frame->disk_size; - if (frame->expected_size && - frame->expected_size != frame->disk_size) { - // The file has unexpected size. - frame->status = STATUS_UPLOADING_ERROR; - frame->uploading_failure = - ERROR_UNEXPECTED_SIZE; - gr_reportuploaderror(frame); - } else { - // Everything seems fine, try to load - // and redraw existing instances. - gr_schedule_image_redraw(frame->image); - frame = gr_loadimage_and_report(frame); - } - } - // Delete the symlink. - unlink(tmp_filename_symlink); - // Delete the original file if it's temporary. - if (cmd->transmission_medium == 't') - gr_delete_tmp_file(original_filename); - } - free(original_filename); - gr_check_limits(); - } else if (cmd->transmission_medium == 'd') { - // Direct transmission (default if 't' is not specified). - frame = gr_get_last_frame(gr_find_image_for_command(cmd)); - if (frame && frame->status == STATUS_UPLOADING) { - // This is a continuation of the previous transmission. - cmd->is_direct_transmission_continuation = 1; - gr_append_data(frame, cmd->payload, cmd->more); - return frame; - } - // If no action is specified, it's not the first transmission - // command. If we couldn't find the image, something went wrong - // and we should just drop this command. - if (cmd->action == 0) - return NULL; - // Otherwise create a new image or frame structure. - frame = gr_new_image_or_frame_from_command(cmd); - if (!frame) - return NULL; - last_image_id = frame->image->image_id; - frame->status = STATUS_UPLOADING; - // Start appending data. - gr_append_data(frame, cmd->payload, cmd->more); - } else { - gr_reporterror_cmd( - cmd, - "EINVAL: transmission medium '%c' is not supported", - cmd->transmission_medium); - return NULL; - } - - return frame; -} - -/// Handles the 'put' command by creating a placement. -static void gr_handle_put_command(GraphicsCommand *cmd) { - if (cmd->image_id == 0 && cmd->image_number == 0) { - gr_reporterror_cmd(cmd, - "EINVAL: neither image id nor image number " - "are specified or both are zero"); - return; - } - - // Find the image with the id or number. - Image *img = gr_find_image_for_command(cmd); - if (!img) { - gr_reporterror_cmd(cmd, "ENOENT: image not found"); - return; - } - - // Create a placement. If a placement with the same id already exists, - // it will be deleted. If the id is zero, a random id will be generated. - ImagePlacement *placement = gr_new_placement(img, cmd->placement_id); - placement->virtual = cmd->virtual; - placement->src_pix_x = cmd->src_pix_x; - placement->src_pix_y = cmd->src_pix_y; - placement->src_pix_width = cmd->src_pix_width; - placement->src_pix_height = cmd->src_pix_height; - placement->cols = cmd->columns; - placement->rows = cmd->rows; - placement->do_not_move_cursor = cmd->do_not_move_cursor; - - if (placement->virtual) { - placement->scale_mode = SCALE_MODE_CONTAIN; - } else if (placement->cols && placement->rows) { - // For classic placements the default is to stretch the image if - // both cols and rows are specified. - placement->scale_mode = SCALE_MODE_FILL; - } else if (placement->cols || placement->rows) { - // But if only one of them is specified, the default is to - // contain. - placement->scale_mode = SCALE_MODE_CONTAIN; - } else { - // If none of them are specified, the default is to use the - // original size. - placement->scale_mode = SCALE_MODE_NONE; - } - - // Display the placement unless it's virtual. - gr_display_nonvirtual_placement(placement); - - // Report success. - gr_reportsuccess_cmd(cmd); -} - -/// Information about what to delete. -typedef struct DeletionData { - uint32_t image_id; - uint32_t placement_id; - /// If true, delete the image object if there are no more placements. - char delete_image_if_no_ref; -} DeletionData; - -/// The callback called for each cell to perform deletion. -static int gr_deletion_callback(void *data, uint32_t image_id, - uint32_t placement_id, int col, - int row, char is_classic) { - DeletionData *del_data = data; - // Leave unicode placeholders alone. - if (!is_classic) - return 0; - if (del_data->image_id && del_data->image_id != image_id) - return 0; - if (del_data->placement_id && del_data->placement_id != placement_id) - return 0; - Image *img = gr_find_image(image_id); - // If the image is already deleted, just erase the placeholder. - if (!img) - return 1; - // Delete the placement. - if (placement_id) - gr_delete_placement(gr_find_placement(img, placement_id)); - // Delete the image if image deletion is requested (uppercase delete - // specifier) and there are no more placements. - if (del_data->delete_image_if_no_ref && kh_size(img->placements) == 0) - gr_delete_image(img); - return 1; -} - -/// Handles the delete command. -static void gr_handle_delete_command(GraphicsCommand *cmd) { - DeletionData del_data = {0}; - del_data.delete_image_if_no_ref = isupper(cmd->delete_specifier) != 0; - char d = tolower(cmd->delete_specifier); - - if (d == 'n') { - d = 'i'; - Image *img = gr_find_image_by_number(cmd->image_number); - if (!img) - return; - del_data.image_id = img->image_id; - } - - if (!d || d == 'a') { - // Delete all visible placements. - gr_for_each_image_cell(gr_deletion_callback, &del_data); - } else if (d == 'i') { - // Delete the specified image by image id and maybe placement - // id. - if (!del_data.image_id) - del_data.image_id = cmd->image_id; - if (!del_data.image_id) { - fprintf(stderr, - "ERROR: image id is not specified in the " - "delete command\n"); - return; - } - del_data.placement_id = cmd->placement_id; - // NOTE: It's not very clear whether we should delete the image - // even if there are no _visible_ placements to delete. We do - // this because otherwise there is no way to delete an image - // with virtual placements in one command. - if (!del_data.placement_id && del_data.delete_image_if_no_ref) - gr_delete_image(gr_find_image(cmd->image_id)); - gr_for_each_image_cell(gr_deletion_callback, &del_data); - } else { - fprintf(stderr, - "WARNING: unsupported value of the d key: '%c'. The " - "command is ignored.\n", - cmd->delete_specifier); - } -} - -static void gr_handle_animation_control_command(GraphicsCommand *cmd) { - if (cmd->image_id == 0 && cmd->image_number == 0) { - gr_reporterror_cmd(cmd, - "EINVAL: neither image id nor image number " - "are specified or both are zero"); - return; - } - - // Find the image with the id or number. - Image *img = gr_find_image_for_command(cmd); - if (!img) { - gr_reporterror_cmd(cmd, "ENOENT: image not found"); - return; - } - - // Find the frame to edit, if requested. - ImageFrame *frame = NULL; - if (cmd->edit_frame) - frame = gr_get_frame(img, cmd->edit_frame); - if (cmd->edit_frame || cmd->gap) { - if (!frame) { - gr_reporterror_cmd(cmd, "ENOENT: frame %d not found", - cmd->edit_frame); - return; - } - if (cmd->gap) { - img->total_duration -= frame->gap; - frame->gap = cmd->gap; - img->total_duration += frame->gap; - } - } - - // Set animation-related parameters of the image. - if (cmd->current_frame) - img->current_frame = cmd->current_frame; - if (cmd->animation_state) { - if (cmd->animation_state == 1) { - img->animation_state = ANIMATION_STATE_STOPPED; - } else if (cmd->animation_state == 2) { - img->animation_state = ANIMATION_STATE_LOADING; - } else if (cmd->animation_state == 3) { - img->animation_state = ANIMATION_STATE_LOOPING; - } else { - gr_reporterror_cmd( - cmd, "EINVAL: invalid animation state: %d", - cmd->animation_state); - } - } - // TODO: Set the number of loops to cmd->loops - - // Make sure we redraw all instances of the image. - gr_schedule_image_redraw(img); -} - -/// Handles a command. -static void gr_handle_command(GraphicsCommand *cmd) { - if (!cmd->image_id && !cmd->image_number) { - // If there is no image id or image number, nobody expects a - // response, so set quiet to 2. - cmd->quiet = 2; - } - ImageFrame *frame = NULL; - switch (cmd->action) { - case 0: - // If no action is specified, it may be a data transmission - // command if 'm=' is specified. - if (cmd->is_data_transmission) { - gr_handle_transmit_command(cmd); - break; - } - gr_reporterror_cmd(cmd, "EINVAL: no action specified"); - break; - case 't': - case 'q': - case 'f': - // Transmit data. 'q' means query, which is basically the same - // as transmit, but the image is discarded, and the id is fake. - // 'f' appends a frame to an existing image. - gr_handle_transmit_command(cmd); - break; - case 'p': - // Display (put) the image. - gr_handle_put_command(cmd); - break; - case 'T': - // Transmit and display. - frame = gr_handle_transmit_command(cmd); - if (frame && !cmd->is_direct_transmission_continuation) { - gr_handle_put_command(cmd); - if (cmd->placement_id) - frame->image->initial_placement_id = - cmd->placement_id; - } - break; - case 'd': - gr_handle_delete_command(cmd); - break; - case 'a': - gr_handle_animation_control_command(cmd); - break; - default: - gr_reporterror_cmd(cmd, "EINVAL: unsupported action: %c", - cmd->action); - return; - } -} - -/// A partially parsed key-value pair. -typedef struct KeyAndValue { - char *key_start; - char *val_start; - unsigned key_len, val_len; -} KeyAndValue; - -/// Parses the value of a key and assigns it to the appropriate field of `cmd`. -static void gr_set_keyvalue(GraphicsCommand *cmd, KeyAndValue *kv) { - char *key_start = kv->key_start; - char *key_end = key_start + kv->key_len; - char *value_start = kv->val_start; - char *value_end = value_start + kv->val_len; - // Currently all keys are one-character. - if (key_end - key_start != 1) { - gr_reporterror_cmd(cmd, "EINVAL: unknown key of length %ld: %s", - key_end - key_start, key_start); - return; - } - long num = 0; - if (*key_start == 'a' || *key_start == 't' || *key_start == 'd' || - *key_start == 'o') { - // Some keys have one-character values. - if (value_end - value_start != 1) { - gr_reporterror_cmd( - cmd, - "EINVAL: value of 'a', 't' or 'd' must be a " - "single char: %s", - key_start); - return; - } - } else { - // All the other keys have integer values. - char *num_end = NULL; - num = strtol(value_start, &num_end, 10); - if (num_end != value_end) { - gr_reporterror_cmd( - cmd, "EINVAL: could not parse number value: %s", - key_start); - return; - } - } - switch (*key_start) { - case 'a': - cmd->action = *value_start; - break; - case 't': - cmd->transmission_medium = *value_start; - break; - case 'd': - cmd->delete_specifier = *value_start; - break; - case 'q': - cmd->quiet = num; - break; - case 'f': - cmd->format = num; - if (num != 0 && num != 24 && num != 32 && num != 100) { - gr_reporterror_cmd( - cmd, - "EINVAL: unsupported format specification: %s", - key_start); - } - break; - case 'o': - cmd->compression = *value_start; - if (cmd->compression != 'z') { - gr_reporterror_cmd(cmd, - "EINVAL: unsupported compression " - "specification: %s", - key_start); - } - break; - case 's': - if (cmd->action == 'a') - cmd->animation_state = num; - else - cmd->frame_pix_width = num; - break; - case 'v': - if (cmd->action == 'a') - cmd->loops = num; - else - cmd->frame_pix_height = num; - break; - case 'i': - cmd->image_id = num; - break; - case 'I': - cmd->image_number = num; - break; - case 'p': - cmd->placement_id = num; - break; - case 'x': - cmd->src_pix_x = num; - cmd->frame_dst_pix_x = num; - break; - case 'y': - if (cmd->action == 'f') - cmd->frame_dst_pix_y = num; - else - cmd->src_pix_y = num; - break; - case 'w': - cmd->src_pix_width = num; - break; - case 'h': - cmd->src_pix_height = num; - break; - case 'c': - if (cmd->action == 'f') - cmd->background_frame = num; - else if (cmd->action == 'a') - cmd->current_frame = num; - else - cmd->columns = num; - break; - case 'r': - if (cmd->action == 'f' || cmd->action == 'a') - cmd->edit_frame = num; - else - cmd->rows = num; - break; - case 'm': - cmd->is_data_transmission = 1; - cmd->more = num; - break; - case 'S': - cmd->size = num; - break; - case 'U': - cmd->virtual = num; - break; - case 'X': - if (cmd->action == 'f') - cmd->replace_instead_of_blending = num; - else - break; /*ignore*/ - break; - case 'Y': - if (cmd->action == 'f') - cmd->background_color = num; - else - break; /*ignore*/ - break; - case 'z': - if (cmd->action == 'f' || cmd->action == 'a') - cmd->gap = num; - else - break; /*ignore*/ - break; - case 'C': - cmd->do_not_move_cursor = num; - break; - default: - gr_reporterror_cmd(cmd, "EINVAL: unsupported key: %s", - key_start); - return; - } -} - -/// Parse and execute a graphics command. `buf` must start with 'G' and contain -/// at least `len + 1` characters. Returns 1 on success. -int gr_parse_command(char *buf, size_t len) { - if (buf[0] != 'G') - return 0; - - memset(&graphics_command_result, 0, sizeof(GraphicsCommandResult)); - - global_command_counter++; - GR_LOG("### Command %lu: %.80s\n", global_command_counter, buf); - - // Eat the 'G'. - ++buf; - --len; - - GraphicsCommand cmd = {.command = buf}; - // The state of parsing. 'k' to parse key, 'v' to parse value, 'p' to - // parse the payload. - char state = 'k'; - // An array of partially parsed key-value pairs. - KeyAndValue key_vals[32]; - unsigned key_vals_count = 0; - char *key_start = buf; - char *key_end = NULL; - char *val_start = NULL; - char *val_end = NULL; - char *c = buf; - while (c - buf < len + 1) { - if (state == 'k') { - switch (*c) { - case ',': - case ';': - case '\0': - state = *c == ',' ? 'k' : 'p'; - key_end = c; - gr_reporterror_cmd( - &cmd, "EINVAL: key without value: %s ", - key_start); - break; - case '=': - key_end = c; - state = 'v'; - val_start = c + 1; - break; - default: - break; - } - } else if (state == 'v') { - switch (*c) { - case ',': - case ';': - case '\0': - state = *c == ',' ? 'k' : 'p'; - val_end = c; - if (key_vals_count >= - sizeof(key_vals) / sizeof(*key_vals)) { - gr_reporterror_cmd(&cmd, - "EINVAL: too many " - "key-value pairs"); - break; - } - key_vals[key_vals_count].key_start = key_start; - key_vals[key_vals_count].val_start = val_start; - key_vals[key_vals_count].key_len = - key_end - key_start; - key_vals[key_vals_count].val_len = - val_end - val_start; - ++key_vals_count; - key_start = c + 1; - break; - default: - break; - } - } else if (state == 'p') { - cmd.payload = c; - // break out of the loop, we don't check the payload - break; - } - ++c; - } - - // Set the action key ('a=') first because we need it to disambiguate - // some keys. Also set 'i=' and 'I=' for better error reporting. - for (unsigned i = 0; i < key_vals_count; ++i) { - if (key_vals[i].key_len == 1) { - char *start = key_vals[i].key_start; - if (*start == 'a' || *start == 'i' || *start == 'I') { - gr_set_keyvalue(&cmd, &key_vals[i]); - break; - } - } - } - // Set the rest of the keys. - for (unsigned i = 0; i < key_vals_count; ++i) - gr_set_keyvalue(&cmd, &key_vals[i]); - - if (!cmd.payload) - cmd.payload = buf + len; - - if (cmd.payload && cmd.payload[0]) - GR_LOG(" payload size: %ld\n", strlen(cmd.payload)); - - if (!graphics_command_result.error) - gr_handle_command(&cmd); - - if (graphics_debug_mode) { - fprintf(stderr, "Response: "); - for (const char *resp = graphics_command_result.response; - *resp != '\0'; ++resp) { - if (isprint(*resp)) - fprintf(stderr, "%c", *resp); - else - fprintf(stderr, "(0x%x)", *resp); - } - fprintf(stderr, "\n"); - } - - // Make sure that we suppress response if needed. Usually cmd.quiet is - // taken into account when creating the response, but it's not very - // reliable in the current implementation. - if (cmd.quiet) { - if (!graphics_command_result.error || cmd.quiet >= 2) - graphics_command_result.response[0] = '\0'; - } - - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// -// base64 decoding part is basically copied from st.c -//////////////////////////////////////////////////////////////////////////////// - -static const char gr_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}; - -static char gr_base64_getc(const char **src) { - while (**src && !isprint(**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char *gr_base64dec(const char *src, size_t *size) { - size_t in_len = strlen(src); - char *result, *dst; - - result = dst = malloc((in_len + 3) / 4 * 3 + 1); - while (*src) { - int a = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; - int b = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; - int c = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; - int d = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; - - 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'; - if (size) { - *size = dst - result; - } - return result; -} diff --git a/suckless/st/graphics.h b/suckless/st/graphics.h deleted file mode 100644 index 2e75dea..0000000 --- a/suckless/st/graphics.h +++ /dev/null @@ -1,107 +0,0 @@ - -#include -#include -#include - -/// Initialize the graphics module. -void gr_init(Display *disp, Visual *vis, Colormap cm); -/// Deinitialize the graphics module. -void gr_deinit(); - -/// Add an image rectangle to a list if rectangles to draw. This function may -/// actually draw some rectangles, or it may wait till more rectangles are -/// appended. Must be called between `gr_start_drawing` and `gr_finish_drawing`. -/// - `img_start_col..img_end_col` and `img_start_row..img_end_row` define the -/// part of the image to draw (row/col indices are zero-based, ends are -/// excluded). -/// - `x_col` and `y_row` are the coordinates of the top-left corner of the -/// image in the terminal grid. -/// - `x_pix` and `y_pix` are the same but in pixels. -/// - `reverse` indicates whether colors should be inverted. -void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id, - int img_start_col, int img_end_col, int img_start_row, - int img_end_row, int x_col, int y_row, int x_pix, - int y_pix, int cw, int ch, int reverse); -/// Prepare for image drawing. `cw` and `ch` are dimensions of the cell. -void gr_start_drawing(Drawable buf, int cw, int ch); -/// Finish image drawing. This functions will draw all the rectangles left to -/// draw. -void gr_finish_drawing(Drawable buf); -/// Mark rows containing animations as dirty if it's time to redraw them. Must -/// be called right after `gr_start_drawing`. -void gr_mark_dirty_animations(int *dirty, int rows); - -/// Parse and execute a graphics command. `buf` must start with 'G' and contain -/// at least `len + 1` characters (including '\0'). Returns 1 on success. -/// Additional informations is returned through `graphics_command_result`. -int gr_parse_command(char *buf, size_t len); - -/// Executes `command` with the name of the file corresponding to `image_id` as -/// the argument. Executes xmessage with an error message on failure. -void gr_preview_image(uint32_t image_id, const char *command); - -/// Executes ` -e less ` where is the name of a temporary file -/// containing the information about an image and placement, and is -/// specified with `st_executable`. -void gr_show_image_info(uint32_t image_id, uint32_t placement_id, - uint32_t imgcol, uint32_t imgrow, - char is_classic_placeholder, int32_t diacritic_count, - char *st_executable); - -/// Dumps the internal state (images and placements) to stderr. -void gr_dump_state(); - -/// Unloads images to reduce RAM usage. -void gr_unload_images_to_reduce_ram(); - -/// Executes `callback` for each image cell. `callback` may return 1 to erase -/// the cell or 0 to keep it. This function is implemented in `st.c`. -void gr_for_each_image_cell(int (*callback)(void *data, uint32_t image_id, - uint32_t placement_id, int col, - int row, char is_classic), - void *data); - -/// Marks all the rows containing the image with `image_id` as dirty. -void gr_schedule_image_redraw_by_id(uint32_t image_id); - -typedef enum { - GRAPHICS_DEBUG_NONE = 0, - GRAPHICS_DEBUG_LOG = 1, - GRAPHICS_DEBUG_LOG_AND_BOXES = 2, -} GraphicsDebugMode; - -/// Print additional information, draw bounding bounding boxes, etc. -extern GraphicsDebugMode graphics_debug_mode; - -/// Whether to display images or just draw bounding boxes. -extern char graphics_display_images; - -/// The time in milliseconds until the next redraw to update animations. -/// INT_MAX means no redraw is needed. Populated by `gr_finish_drawing`. -extern int graphics_next_redraw_delay; - -#define MAX_GRAPHICS_RESPONSE_LEN 256 - -/// A structure representing the result of a graphics command. -typedef struct { - /// Indicates if the terminal needs to be redrawn. - char redraw; - /// The response of the command that should be sent back to the client - /// (may be empty if the quiet flag is set). - char response[MAX_GRAPHICS_RESPONSE_LEN]; - /// Whether there was an error executing this command (not very useful, - /// the response must be sent back anyway). - char error; - /// Whether the terminal has to create a placeholder for a non-virtual - /// placement. - char create_placeholder; - /// The placeholder that needs to be created. - struct { - uint32_t rows, columns; - uint32_t image_id, placement_id; - char do_not_move_cursor; - } placeholder; -} GraphicsCommandResult; - -/// The result of a graphics command. -extern GraphicsCommandResult graphics_command_result; diff --git a/suckless/st/hb.c b/suckless/st/hb.c deleted file mode 100644 index 2bb334c..0000000 --- a/suckless/st/hb.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "st.h" -#include "hb.h" - -#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } -#define BUFFER_STEP 256 - -hb_font_t *hbfindfont(XftFont *match); - -typedef struct { - XftFont *match; - hb_font_t *font; -} HbFontMatch; - -typedef struct { - size_t capacity; - HbFontMatch *fonts; -} HbFontCache; - -static HbFontCache hbfontcache = { 0, NULL }; - -typedef struct { - size_t capacity; - Rune *runes; -} RuneBuffer; - -static RuneBuffer hbrunebuffer = { 0, NULL }; - -/* - * Poplulate the array with a list of font features, wrapped in FEATURE macro, - * e. g. - * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') - */ -hb_feature_t features[] = {0}; - -void -hbunloadfonts() -{ - for (int i = 0; i < hbfontcache.capacity; i++) { - hb_font_destroy(hbfontcache.fonts[i].font); - XftUnlockFace(hbfontcache.fonts[i].match); - } - - if (hbfontcache.fonts != NULL) { - free(hbfontcache.fonts); - hbfontcache.fonts = NULL; - } - hbfontcache.capacity = 0; -} - -hb_font_t * -hbfindfont(XftFont *match) -{ - for (int i = 0; i < hbfontcache.capacity; i++) { - if (hbfontcache.fonts[i].match == match) - return hbfontcache.fonts[i].font; - } - - /* Font not found in cache, caching it now. */ - hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1)); - FT_Face face = XftLockFace(match); - hb_font_t *font = hb_ft_font_create(face, NULL); - if (font == NULL) - die("Failed to load Harfbuzz font."); - - hbfontcache.fonts[hbfontcache.capacity].match = match; - hbfontcache.fonts[hbfontcache.capacity].font = font; - hbfontcache.capacity += 1; - - return font; -} - -void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) { - ushort mode = USHRT_MAX; - unsigned int glyph_count; - int rune_idx, glyph_idx, end = start + length; - - hb_font_t *font = hbfindfont(xfont); - if (font == NULL) - return; - - hb_buffer_t *buffer = hb_buffer_create(); - hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); - hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); - - /* Resize the buffer if required length is larger. */ - if (hbrunebuffer.capacity < length) { - hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP; - hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune)); - } - - /* Fill buffer with codepoints. */ - for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) { - hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u; - mode = glyphs[glyph_idx].mode; - if (mode & ATTR_WDUMMY) - hbrunebuffer.runes[rune_idx] = 0x0020; - } - hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); - - /* Shape the segment. */ - hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); - - /* Get new glyph info. */ - hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count); - - /* Fill the output. */ - data->buffer = buffer; - data->glyphs = info; - data->positions = pos; - data->count = glyph_count; -} - -void hbcleanup(HbTransformData *data) { - hb_buffer_destroy(data->buffer); - memset(data, 0, sizeof(HbTransformData)); -} diff --git a/suckless/st/hb.h b/suckless/st/hb.h deleted file mode 100644 index 3b0ef44..0000000 --- a/suckless/st/hb.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include - -typedef struct { - hb_buffer_t *buffer; - hb_glyph_info_t *glyphs; - hb_glyph_position_t *positions; - unsigned int count; -} HbTransformData; - -void hbunloadfonts(); -void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); -void hbcleanup(HbTransformData *); diff --git a/suckless/st/hb.o b/suckless/st/hb.o deleted file mode 100644 index 34d5bbe..0000000 Binary files a/suckless/st/hb.o and /dev/null differ diff --git a/suckless/st/icat-mini.sh b/suckless/st/icat-mini.sh deleted file mode 100755 index cd822f3..0000000 --- a/suckless/st/icat-mini.sh +++ /dev/null @@ -1,800 +0,0 @@ -#!/bin/sh - -# vim: shiftwidth=4 - -script_name="$(basename "$0")" - -short_help="Usage: $script_name [OPTIONS] - -This is a script to display images in the terminal using the kitty graphics -protocol with Unicode placeholders. It is very basic, please use something else -if you have alternatives. - -Options: - -h Show this help. - -s SCALE The scale of the image, may be floating point. - -c N, --cols N The number of columns. - -r N, --rows N The number of rows. - --max-cols N The maximum number of columns. - --max-rows N The maximum number of rows. - --cell-size WxH The cell size in pixels. - -m METHOD The uploading method, may be 'file', 'direct' or 'auto'. - --speed SPEED The multiplier for the animation speed (float). -" - -# Exit the script on keyboard interrupt -trap "echo 'icat-mini was interrupted' >&2; exit 1" INT - -cols="" -rows="" -file="" -tty="/dev/tty" -uploading_method="auto" -cell_size="" -scale=1 -max_cols="" -max_rows="" -speed="" - -# Parse the command line. -while [ $# -gt 0 ]; do - case "$1" in - -c|--columns|--cols) - cols="$2" - shift 2 - ;; - -r|--rows|-l|--lines) - rows="$2" - shift 2 - ;; - -s|--scale) - scale="$2" - shift 2 - ;; - -h|--help) - echo "$short_help" - exit 0 - ;; - -m|--upload-method|--uploading-method) - uploading_method="$2" - shift 2 - ;; - --cell-size) - cell_size="$2" - shift 2 - ;; - --max-cols) - max_cols="$2" - shift 2 - ;; - --max-rows) - max_rows="$2" - shift 2 - ;; - --speed) - speed="$2" - shift 2 - ;; - --) - file="$2" - shift 2 - ;; - -*) - echo "Unknown option: $1" >&2 - exit 1 - ;; - *) - if [ -n "$file" ]; then - echo "Multiple image files are not supported: $file and $1" >&2 - exit 1 - fi - file="$1" - shift - ;; - esac -done - -file="$(realpath "$file")" - -##################################################################### -# Adjust the terminal state -##################################################################### - -stty_orig="$(stty -g < "$tty")" -stty -echo < "$tty" -# Disable ctrl-z. Pressing ctrl-z during image uploading may cause some -# horrible issues otherwise. -stty susp undef < "$tty" -stty -icanon < "$tty" - -restore_echo() { - [ -n "$stty_orig" ] || return - stty $stty_orig < "$tty" -} - -trap restore_echo EXIT TERM - -##################################################################### -# Detect imagemagick -##################################################################### - -# If there is the 'magick' command, use it instead of separate 'convert' and -# 'identify' commands. -if command -v magick > /dev/null; then - identify="magick identify" - convert="magick" -else - identify="identify" - convert="convert" -fi - -##################################################################### -# Detect tmux -##################################################################### - -# Check if we are inside tmux. -inside_tmux="" -if [ -n "$TMUX" ]; then - case "$TERM" in - *tmux*|*screen*) - inside_tmux=1 - ;; - esac -fi - -##################################################################### -# Compute the number of rows and columns -##################################################################### - -is_pos_int() { - if [ -z "$1" ]; then - return 1 # false - fi - if [ -z "$(printf '%s' "$1" | tr -d '[:digit:]')" ]; then - if [ "$1" -gt 0 ]; then - return 0 # true - fi - fi - return 1 # false -} - -if [ -n "$cols" ] || [ -n "$rows" ]; then - if [ -n "$max_cols" ] || [ -n "$max_rows" ]; then - echo "You can't specify both max-cols/rows and cols/rows" >&2 - exit 1 - fi -fi -# Get the max number of cols and rows. -[ -n "$max_cols" ] || max_cols="$(tput cols)" -[ -n "$max_rows" ] || max_rows="$(tput lines)" -if [ "$max_rows" -gt 255 ]; then - max_rows=255 -fi - -python_ioctl_command="import array, fcntl, termios -buf = array.array('H', [0, 0, 0, 0]) -fcntl.ioctl(0, termios.TIOCGWINSZ, buf) -print(int(buf[2]/buf[1]), int(buf[3]/buf[0]))" - -# Get the cell size in pixels if either cols or rows are not specified. -if [ -z "$cols" ] || [ -z "$rows" ]; then - cell_width="" - cell_height="" - # If the cell size is specified, use it. - if [ -n "$cell_size" ]; then - cell_width="${cell_size%x*}" - cell_height="${cell_size#*x}" - if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then - echo "Invalid cell size: $cell_size" >&2 - exit 1 - fi - fi - # Otherwise try to use TIOCGWINSZ ioctl via python. - if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then - cell_size_ioctl="$(python3 -c "$python_ioctl_command" < "$tty" 2> /dev/null)" - cell_width="${cell_size_ioctl% *}" - cell_height="${cell_size_ioctl#* }" - if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then - cell_width="" - cell_height="" - fi - fi - # If it didn't work, try to use csi XTWINOPS. - if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then - if [ -n "$inside_tmux" ]; then - printf '\ePtmux;\e\e[16t\e\\' >> "$tty" - else - printf '\e[16t' >> "$tty" - fi - # The expected response will look like ^[[6;;t - term_response="" - while true; do - char=$(dd bs=1 count=1 <"$tty" 2>/dev/null) - if [ "$char" = "t" ]; then - break - fi - term_response="$term_response$char" - done - cell_height="$(printf '%s' "$term_response" | cut -d ';' -f 2)" - cell_width="$(printf '%s' "$term_response" | cut -d ';' -f 3)" - if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then - cell_width=8 - cell_height=16 - fi - fi -fi - -# Compute a formula with bc and round to the nearest integer. -bc_round() { - LC_NUMERIC=C printf '%.0f' "$(printf '%s\n' "scale=2;($1) + 0.5" | bc)" -} - -# Compute the number of rows and columns of the image. -if [ -z "$cols" ] || [ -z "$rows" ]; then - # Get the size of the image and its resolution. If it's an animation, use - # the first frame. - format_output="$($identify -format '%w %h\n' "$file" | head -1)" - img_width="$(printf '%s' "$format_output" | cut -d ' ' -f 1)" - img_height="$(printf '%s' "$format_output" | cut -d ' ' -f 2)" - if ! is_pos_int "$img_width" || ! is_pos_int "$img_height"; then - echo "Couldn't get image size from identify: $format_output" >&2 - echo >&2 - exit 1 - fi - opt_cols_expr="(${scale}*${img_width}/${cell_width})" - opt_rows_expr="(${scale}*${img_height}/${cell_height})" - if [ -z "$cols" ] && [ -z "$rows" ]; then - # If columns and rows are not specified, compute the optimal values - # using the information about rows and columns per inch. - cols="$(bc_round "$opt_cols_expr")" - rows="$(bc_round "$opt_rows_expr")" - # Make sure that automatically computed rows and columns are within some - # sane limits - if [ "$cols" -gt "$max_cols" ]; then - rows="$(bc_round "$rows * $max_cols / $cols")" - cols="$max_cols" - fi - if [ "$rows" -gt "$max_rows" ]; then - cols="$(bc_round "$cols * $max_rows / $rows")" - rows="$max_rows" - fi - elif [ -z "$cols" ]; then - # If only one dimension is specified, compute the other one to match the - # aspect ratio as close as possible. - cols="$(bc_round "${opt_cols_expr}*${rows}/${opt_rows_expr}")" - elif [ -z "$rows" ]; then - rows="$(bc_round "${opt_rows_expr}*${cols}/${opt_cols_expr}")" - fi - - if [ "$cols" -lt 1 ]; then - cols=1 - fi - if [ "$rows" -lt 1 ]; then - rows=1 - fi -fi - -##################################################################### -# Generate an image id -##################################################################### - -image_id="" -while [ -z "$image_id" ]; do - image_id="$(shuf -i 16777217-4294967295 -n 1)" - # Check that the id requires 24-bit fg colors. - if [ "$(expr \( "$image_id" / 256 \) % 65536)" -eq 0 ]; then - image_id="" - fi -done - -##################################################################### -# Uploading the image -##################################################################### - -# Choose the uploading method -if [ "$uploading_method" = "auto" ]; then - if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] || [ -n "$SSH_CONNECTION" ]; then - uploading_method="direct" - else - uploading_method="file" - fi -fi - -# Functions to emit the start and the end of a graphics command. -if [ -n "$inside_tmux" ]; then - # If we are in tmux we have to wrap the command in Ptmux. - graphics_command_start='\ePtmux;\e\e_G' - graphics_command_end='\e\e\\\e\\' -else - graphics_command_start='\e_G' - graphics_command_end='\e\\' -fi - -start_gr_command() { - printf "$graphics_command_start" >> "$tty" -} -end_gr_command() { - printf "$graphics_command_end" >> "$tty" -} - -# Send a graphics command with the correct start and end -gr_command() { - start_gr_command - printf '%s' "$1" >> "$tty" - end_gr_command -} - -# Send an uploading command. Usage: gr_upload -# Where is a part of command that specifies the action, it will be -# repeated for every chunk (if the method is direct), and is the rest -# of the command that specifies the image parameters. and -# must not include the transmission method or ';'. -# Example: -# gr_upload "a=T,q=2" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file" -gr_upload() { - arg_action="$1" - arg_command="$2" - arg_file="$3" - if [ "$uploading_method" = "file" ]; then - # base64-encode the filename - encoded_filename=$(printf '%s' "$arg_file" | base64 -w0) - gr_command "${arg_action},${arg_command},t=f;${encoded_filename}" - fi - if [ "$uploading_method" = "direct" ]; then - # Create a temporary directory to store the chunked image. - chunkdir="$(mktemp -d)" - if [ ! "$chunkdir" ] || [ ! -d "$chunkdir" ]; then - echo "Can't create a temp dir" >&2 - exit 1 - fi - # base64-encode the file and split it into chunks. The size of each - # graphics command shouldn't be more than 4096, so we set the size of an - # encoded chunk to be 3968, slightly less than that. - chunk_size=3968 - cat "$arg_file" | base64 -w0 | split -b "$chunk_size" - "$chunkdir/chunk_" - - # Issue a command indicating that we want to start data transmission for - # a new image. - gr_command "${arg_action},${arg_command},t=d,m=1" - - # Transmit chunks. - for chunk in "$chunkdir/chunk_"*; do - start_gr_command - printf '%s' "${arg_action},i=${image_id},m=1;" >> "$tty" - cat "$chunk" >> "$tty" - end_gr_command - rm "$chunk" - done - - # Tell the terminal that we are done. - gr_command "${arg_action},i=$image_id,m=0" - - # Remove the temporary directory. - rmdir "$chunkdir" - fi -} - -delayed_frame_dir_cleanup() { - arg_frame_dir="$1" - sleep 2 - if [ -n "$arg_frame_dir" ]; then - for frame in "$arg_frame_dir"/frame_*.png; do - rm "$frame" - done - rmdir "$arg_frame_dir" - fi -} - -upload_image_and_print_placeholder() { - # Check if the file is an animation. - frame_count=$($identify -format '%n\n' "$file" | head -n 1) - if [ "$frame_count" -gt 1 ]; then - # The file is an animation, decompose into frames and upload each frame. - frame_dir="$(mktemp -d)" - frame_dir="$HOME/temp/frames${frame_dir}" - mkdir -p "$frame_dir" - if [ ! "$frame_dir" ] || [ ! -d "$frame_dir" ]; then - echo "Can't create a temp dir for frames" >&2 - exit 1 - fi - - # Decompose the animation into separate frames. - $convert "$file" -coalesce "$frame_dir/frame_%06d.png" - - # Get all frame delays at once, in centiseconds, as a space-separated - # string. - delays=$($identify -format "%T " "$file") - - frame_number=1 - for frame in "$frame_dir"/frame_*.png; do - # Read the delay for the current frame and convert it from - # centiseconds to milliseconds. - delay=$(printf '%s' "$delays" | cut -d ' ' -f "$frame_number") - delay=$((delay * 10)) - # If the delay is 0, set it to 100ms. - if [ "$delay" -eq 0 ]; then - delay=100 - fi - - if [ -n "$speed" ]; then - delay=$(bc_round "$delay / $speed") - fi - - if [ "$frame_number" -eq 1 ]; then - # Upload the first frame with a=T - gr_upload "q=2,a=T" "f=100,U=1,i=${image_id},c=${cols},r=${rows}" "$frame" - # Set the delay for the first frame and also play the animation - # in loading mode (s=2). - gr_command "a=a,v=1,s=2,r=${frame_number},z=${delay},i=${image_id}" - # Print the placeholder after the first frame to reduce the wait - # time. - print_placeholder - else - # Upload subsequent frames with a=f - gr_upload "q=2,a=f" "f=100,i=${image_id},z=${delay}" "$frame" - fi - - frame_number=$((frame_number + 1)) - done - - # Play the animation in loop mode (s=3). - gr_command "a=a,v=1,s=3,i=${image_id}" - - # Remove the temporary directory, but do it in the background with a - # delay to avoid removing files before they are loaded by the terminal. - delayed_frame_dir_cleanup "$frame_dir" 2> /dev/null & - else - # The file is not an animation, upload it directly - gr_upload "q=2,a=T" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file" - # Print the placeholder - print_placeholder - fi -} - -##################################################################### -# Printing the image placeholder -##################################################################### - -print_placeholder() { - # Each line starts with the escape sequence to set the foreground color to - # the image id. - blue="$(expr "$image_id" % 256 )" - green="$(expr \( "$image_id" / 256 \) % 256 )" - red="$(expr \( "$image_id" / 65536 \) % 256 )" - line_start="$(printf "\e[38;2;%d;%d;%dm" "$red" "$green" "$blue")" - line_end="$(printf "\e[39;m")" - - id4th="$(expr \( "$image_id" / 16777216 \) % 256 )" - eval "id_diacritic=\$d${id4th}" - - # Reset the brush state, mostly to reset the underline color. - printf "\e[0m" - - # Fill the output with characters representing the image - for y in $(seq 0 "$(expr "$rows" - 1)"); do - eval "row_diacritic=\$d${y}" - printf '%s' "$line_start" - for x in $(seq 0 "$(expr "$cols" - 1)"); do - eval "col_diacritic=\$d${x}" - # Note that when $x is out of bounds, the column diacritic will - # be empty, meaning that the column should be guessed by the - # terminal. - if [ "$x" -ge "$num_diacritics" ]; then - printf '%s' "${placeholder}${row_diacritic}" - else - printf '%s' "${placeholder}${row_diacritic}${col_diacritic}${id_diacritic}" - fi - done - printf '%s\n' "$line_end" - done - - printf "\e[0m" -} - -d0="̅" -d1="̍" -d2="̎" -d3="̐" -d4="̒" -d5="̽" -d6="̾" -d7="̿" -d8="͆" -d9="͊" -d10="͋" -d11="͌" -d12="͐" -d13="͑" -d14="͒" -d15="͗" -d16="͛" -d17="ͣ" -d18="ͤ" -d19="ͥ" -d20="ͦ" -d21="ͧ" -d22="ͨ" -d23="ͩ" -d24="ͪ" -d25="ͫ" -d26="ͬ" -d27="ͭ" -d28="ͮ" -d29="ͯ" -d30="҃" -d31="҄" -d32="҅" -d33="҆" -d34="҇" -d35="֒" -d36="֓" -d37="֔" -d38="֕" -d39="֗" -d40="֘" -d41="֙" -d42="֜" -d43="֝" -d44="֞" -d45="֟" -d46="֠" -d47="֡" -d48="֨" -d49="֩" -d50="֫" -d51="֬" -d52="֯" -d53="ׄ" -d54="ؐ" -d55="ؑ" -d56="ؒ" -d57="ؓ" -d58="ؔ" -d59="ؕ" -d60="ؖ" -d61="ؗ" -d62="ٗ" -d63="٘" -d64="ٙ" -d65="ٚ" -d66="ٛ" -d67="ٝ" -d68="ٞ" -d69="ۖ" -d70="ۗ" -d71="ۘ" -d72="ۙ" -d73="ۚ" -d74="ۛ" -d75="ۜ" -d76="۟" -d77="۠" -d78="ۡ" -d79="ۢ" -d80="ۤ" -d81="ۧ" -d82="ۨ" -d83="۫" -d84="۬" -d85="ܰ" -d86="ܲ" -d87="ܳ" -d88="ܵ" -d89="ܶ" -d90="ܺ" -d91="ܽ" -d92="ܿ" -d93="݀" -d94="݁" -d95="݃" -d96="݅" -d97="݇" -d98="݉" -d99="݊" -d100="߫" -d101="߬" -d102="߭" -d103="߮" -d104="߯" -d105="߰" -d106="߱" -d107="߳" -d108="ࠖ" -d109="ࠗ" -d110="࠘" -d111="࠙" -d112="ࠛ" -d113="ࠜ" -d114="ࠝ" -d115="ࠞ" -d116="ࠟ" -d117="ࠠ" -d118="ࠡ" -d119="ࠢ" -d120="ࠣ" -d121="ࠥ" -d122="ࠦ" -d123="ࠧ" -d124="ࠩ" -d125="ࠪ" -d126="ࠫ" -d127="ࠬ" -d128="࠭" -d129="॑" -d130="॓" -d131="॔" -d132="ྂ" -d133="ྃ" -d134="྆" -d135="྇" -d136="፝" -d137="፞" -d138="፟" -d139="៝" -d140="᤺" -d141="ᨗ" -d142="᩵" -d143="᩶" -d144="᩷" -d145="᩸" -d146="᩹" -d147="᩺" -d148="᩻" -d149="᩼" -d150="᭫" -d151="᭭" -d152="᭮" -d153="᭯" -d154="᭰" -d155="᭱" -d156="᭲" -d157="᭳" -d158="᳐" -d159="᳑" -d160="᳒" -d161="᳚" -d162="᳛" -d163="᳠" -d164="᷀" -d165="᷁" -d166="᷃" -d167="᷄" -d168="᷅" -d169="᷆" -d170="᷇" -d171="᷈" -d172="᷉" -d173="᷋" -d174="᷌" -d175="᷑" -d176="᷒" -d177="ᷓ" -d178="ᷔ" -d179="ᷕ" -d180="ᷖ" -d181="ᷗ" -d182="ᷘ" -d183="ᷙ" -d184="ᷚ" -d185="ᷛ" -d186="ᷜ" -d187="ᷝ" -d188="ᷞ" -d189="ᷟ" -d190="ᷠ" -d191="ᷡ" -d192="ᷢ" -d193="ᷣ" -d194="ᷤ" -d195="ᷥ" -d196="ᷦ" -d197="᷾" -d198="⃐" -d199="⃑" -d200="⃔" -d201="⃕" -d202="⃖" -d203="⃗" -d204="⃛" -d205="⃜" -d206="⃡" -d207="⃧" -d208="⃩" -d209="⃰" -d210="⳯" -d211="⳰" -d212="⳱" -d213="ⷠ" -d214="ⷡ" -d215="ⷢ" -d216="ⷣ" -d217="ⷤ" -d218="ⷥ" -d219="ⷦ" -d220="ⷧ" -d221="ⷨ" -d222="ⷩ" -d223="ⷪ" -d224="ⷫ" -d225="ⷬ" -d226="ⷭ" -d227="ⷮ" -d228="ⷯ" -d229="ⷰ" -d230="ⷱ" -d231="ⷲ" -d232="ⷳ" -d233="ⷴ" -d234="ⷵ" -d235="ⷶ" -d236="ⷷ" -d237="ⷸ" -d238="ⷹ" -d239="ⷺ" -d240="ⷻ" -d241="ⷼ" -d242="ⷽ" -d243="ⷾ" -d244="ⷿ" -d245="꙯" -d246="꙼" -d247="꙽" -d248="꛰" -d249="꛱" -d250="꣠" -d251="꣡" -d252="꣢" -d253="꣣" -d254="꣤" -d255="꣥" -d256="꣦" -d257="꣧" -d258="꣨" -d259="꣩" -d260="꣪" -d261="꣫" -d262="꣬" -d263="꣭" -d264="꣮" -d265="꣯" -d266="꣰" -d267="꣱" -d268="ꪰ" -d269="ꪲ" -d270="ꪳ" -d271="ꪷ" -d272="ꪸ" -d273="ꪾ" -d274="꪿" -d275="꫁" -d276="︠" -d277="︡" -d278="︢" -d279="︣" -d280="︤" -d281="︥" -d282="︦" -d283="𐨏" -d284="𐨸" -d285="𝆅" -d286="𝆆" -d287="𝆇" -d288="𝆈" -d289="𝆉" -d290="𝆪" -d291="𝆫" -d292="𝆬" -d293="𝆭" -d294="𝉂" -d295="𝉃" -d296="𝉄" - -num_diacritics="297" - -placeholder="􎻮" - -##################################################################### -# Upload the image and print the placeholder -##################################################################### - -upload_image_and_print_placeholder diff --git a/suckless/st/khash.h b/suckless/st/khash.h deleted file mode 100644 index f75f347..0000000 --- a/suckless/st/khash.h +++ /dev/null @@ -1,627 +0,0 @@ -/* The MIT License - - Copyright (c) 2008, 2009, 2011 by Attractive Chaos - - 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. -*/ - -/* - An example: - -#include "khash.h" -KHASH_MAP_INIT_INT(32, char) -int main() { - int ret, is_missing; - khiter_t k; - khash_t(32) *h = kh_init(32); - k = kh_put(32, h, 5, &ret); - kh_value(h, k) = 10; - k = kh_get(32, h, 10); - is_missing = (k == kh_end(h)); - k = kh_get(32, h, 5); - kh_del(32, h, k); - for (k = kh_begin(h); k != kh_end(h); ++k) - if (kh_exist(h, k)) kh_value(h, k) = 1; - kh_destroy(32, h); - return 0; -} -*/ - -/* - 2013-05-02 (0.2.8): - - * Use quadratic probing. When the capacity is power of 2, stepping function - i*(i+1)/2 guarantees to traverse each bucket. It is better than double - hashing on cache performance and is more robust than linear probing. - - In theory, double hashing should be more robust than quadratic probing. - However, my implementation is probably not for large hash tables, because - the second hash function is closely tied to the first hash function, - which reduce the effectiveness of double hashing. - - Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php - - 2011-12-29 (0.2.7): - - * Minor code clean up; no actual effect. - - 2011-09-16 (0.2.6): - - * The capacity is a power of 2. This seems to dramatically improve the - speed for simple keys. Thank Zilong Tan for the suggestion. Reference: - - - http://code.google.com/p/ulib/ - - http://nothings.org/computer/judy/ - - * Allow to optionally use linear probing which usually has better - performance for random input. Double hashing is still the default as it - is more robust to certain non-random input. - - * Added Wang's integer hash function (not used by default). This hash - function is more robust to certain non-random input. - - 2011-02-14 (0.2.5): - - * Allow to declare global functions. - - 2009-09-26 (0.2.4): - - * Improve portability - - 2008-09-19 (0.2.3): - - * Corrected the example - * Improved interfaces - - 2008-09-11 (0.2.2): - - * Improved speed a little in kh_put() - - 2008-09-10 (0.2.1): - - * Added kh_clear() - * Fixed a compiling error - - 2008-09-02 (0.2.0): - - * Changed to token concatenation which increases flexibility. - - 2008-08-31 (0.1.2): - - * Fixed a bug in kh_get(), which has not been tested previously. - - 2008-08-31 (0.1.1): - - * Added destructor -*/ - - -#ifndef __AC_KHASH_H -#define __AC_KHASH_H - -/*! - @header - - Generic hash table library. - */ - -#define AC_VERSION_KHASH_H "0.2.8" - -#include -#include -#include - -/* compiler specific configuration */ - -#if UINT_MAX == 0xffffffffu -typedef unsigned int khint32_t; -#elif ULONG_MAX == 0xffffffffu -typedef unsigned long khint32_t; -#endif - -#if ULONG_MAX == ULLONG_MAX -typedef unsigned long khint64_t; -#else -typedef unsigned long long khint64_t; -#endif - -#ifndef kh_inline -#ifdef _MSC_VER -#define kh_inline __inline -#else -#define kh_inline inline -#endif -#endif /* kh_inline */ - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -typedef khint32_t khint_t; -typedef khint_t khiter_t; - -#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) -#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) -#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) -#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) -#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) -#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) -#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) - -#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) - -#ifndef kroundup32 -#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) -#endif - -#ifndef kcalloc -#define kcalloc(N,Z) calloc(N,Z) -#endif -#ifndef kmalloc -#define kmalloc(Z) malloc(Z) -#endif -#ifndef krealloc -#define krealloc(P,Z) realloc(P,Z) -#endif -#ifndef kfree -#define kfree(P) free(P) -#endif - -static const double __ac_HASH_UPPER = 0.77; - -#define __KHASH_TYPE(name, khkey_t, khval_t) \ - typedef struct kh_##name##_s { \ - khint_t n_buckets, size, n_occupied, upper_bound; \ - khint32_t *flags; \ - khkey_t *keys; \ - khval_t *vals; \ - } kh_##name##_t; - -#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ - extern kh_##name##_t *kh_init_##name(void); \ - extern void kh_destroy_##name(kh_##name##_t *h); \ - extern void kh_clear_##name(kh_##name##_t *h); \ - extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ - extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ - extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ - extern void kh_del_##name(kh_##name##_t *h, khint_t x); - -#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - SCOPE kh_##name##_t *kh_init_##name(void) { \ - return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \ - } \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - { \ - if (h) { \ - kfree((void *)h->keys); kfree(h->flags); \ - kfree((void *)h->vals); \ - kfree(h); \ - } \ - } \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - { \ - if (h && h->flags) { \ - memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ - h->size = h->n_occupied = 0; \ - } \ - } \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - { \ - if (h->n_buckets) { \ - khint_t k, i, last, mask, step = 0; \ - mask = h->n_buckets - 1; \ - k = __hash_func(key); i = k & mask; \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ - i = (i + (++step)) & mask; \ - if (i == last) return h->n_buckets; \ - } \ - return __ac_iseither(h->flags, i)? h->n_buckets : i; \ - } else return 0; \ - } \ - SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ - khint32_t *new_flags = 0; \ - khint_t j = 1; \ - { \ - kroundup32(new_n_buckets); \ - if (new_n_buckets < 4) new_n_buckets = 4; \ - if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ - else { /* hash table size to be changed (shrink or expand); rehash */ \ - new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (!new_flags) return -1; \ - memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (h->n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (!new_keys) { kfree(new_flags); return -1; } \ - h->keys = new_keys; \ - if (kh_is_map) { \ - khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - if (!new_vals) { kfree(new_flags); return -1; } \ - h->vals = new_vals; \ - } \ - } /* otherwise shrink */ \ - } \ - } \ - if (j) { /* rehashing is needed */ \ - for (j = 0; j != h->n_buckets; ++j) { \ - if (__ac_iseither(h->flags, j) == 0) { \ - khkey_t key = h->keys[j]; \ - khval_t val; \ - khint_t new_mask; \ - new_mask = new_n_buckets - 1; \ - if (kh_is_map) val = h->vals[j]; \ - __ac_set_isdel_true(h->flags, j); \ - while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ - khint_t k, i, step = 0; \ - k = __hash_func(key); \ - i = k & new_mask; \ - while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ - __ac_set_isempty_false(new_flags, i); \ - if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ - { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ - if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ - __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ - } else { /* write the element and jump out of the loop */ \ - h->keys[i] = key; \ - if (kh_is_map) h->vals[i] = val; \ - break; \ - } \ - } \ - } \ - } \ - if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ - h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - } \ - kfree(h->flags); /* free the working space */ \ - h->flags = new_flags; \ - h->n_buckets = new_n_buckets; \ - h->n_occupied = h->size; \ - h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ - } \ - return 0; \ - } \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - { \ - khint_t x; \ - if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ - if (h->n_buckets > (h->size<<1)) { \ - if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ - *ret = -1; return h->n_buckets; \ - } \ - } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ - *ret = -1; return h->n_buckets; \ - } \ - } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ - { \ - khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ - x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ - if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ - else { \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ - if (__ac_isdel(h->flags, i)) site = i; \ - i = (i + (++step)) & mask; \ - if (i == last) { x = site; break; } \ - } \ - if (x == h->n_buckets) { \ - if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ - else x = i; \ - } \ - } \ - } \ - if (__ac_isempty(h->flags, x)) { /* not present at all */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - ++h->size; ++h->n_occupied; \ - *ret = 1; \ - } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - ++h->size; \ - *ret = 2; \ - } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ - return x; \ - } \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - { \ - if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ - __ac_set_isdel_true(h->flags, x); \ - --h->size; \ - } \ - } - -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_PROTOTYPES(name, khkey_t, khval_t) - -#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -/* --- BEGIN OF HASH FUNCTIONS --- */ - -/*! @function - @abstract Integer hash function - @param key The integer [khint32_t] - @return The hash value [khint_t] - */ -#define kh_int_hash_func(key) (khint32_t)(key) -/*! @function - @abstract Integer comparison function - */ -#define kh_int_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract 64-bit integer hash function - @param key The integer [khint64_t] - @return The hash value [khint_t] - */ -#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) -/*! @function - @abstract 64-bit integer comparison function - */ -#define kh_int64_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract const char* hash function - @param s Pointer to a null terminated string - @return The hash value - */ -static kh_inline khint_t __ac_X31_hash_string(const char *s) -{ - khint_t h = (khint_t)*s; - if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; - return h; -} -/*! @function - @abstract Another interface to const char* hash function - @param key Pointer to a null terminated string [const char*] - @return The hash value [khint_t] - */ -#define kh_str_hash_func(key) __ac_X31_hash_string(key) -/*! @function - @abstract Const char* comparison function - */ -#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) - -static kh_inline khint_t __ac_Wang_hash(khint_t key) -{ - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} -#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) - -/* --- END OF HASH FUNCTIONS --- */ - -/* Other convenient macros... */ - -/*! - @abstract Type of the hash table. - @param name Name of the hash table [symbol] - */ -#define khash_t(name) kh_##name##_t - -/*! @function - @abstract Initiate a hash table. - @param name Name of the hash table [symbol] - @return Pointer to the hash table [khash_t(name)*] - */ -#define kh_init(name) kh_init_##name() - -/*! @function - @abstract Destroy a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_destroy(name, h) kh_destroy_##name(h) - -/*! @function - @abstract Reset a hash table without deallocating memory. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_clear(name, h) kh_clear_##name(h) - -/*! @function - @abstract Resize a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param s New size [khint_t] - */ -#define kh_resize(name, h, s) kh_resize_##name(h, s) - -/*! @function - @abstract Insert a key to the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @param r Extra return code: -1 if the operation failed; - 0 if the key is present in the hash table; - 1 if the bucket is empty (never used); 2 if the element in - the bucket has been deleted [int*] - @return Iterator to the inserted element [khint_t] - */ -#define kh_put(name, h, k, r) kh_put_##name(h, k, r) - -/*! @function - @abstract Retrieve a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] - */ -#define kh_get(name, h, k) kh_get_##name(h, k) - -/*! @function - @abstract Remove a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Iterator to the element to be deleted [khint_t] - */ -#define kh_del(name, h, k) kh_del_##name(h, k) - -/*! @function - @abstract Test whether a bucket contains data. - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return 1 if containing data; 0 otherwise [int] - */ -#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) - -/*! @function - @abstract Get key given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Key [type of keys] - */ -#define kh_key(h, x) ((h)->keys[x]) - -/*! @function - @abstract Get value given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Value [type of values] - @discussion For hash sets, calling this results in segfault. - */ -#define kh_val(h, x) ((h)->vals[x]) - -/*! @function - @abstract Alias of kh_val() - */ -#define kh_value(h, x) ((h)->vals[x]) - -/*! @function - @abstract Get the start iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The start iterator [khint_t] - */ -#define kh_begin(h) (khint_t)(0) - -/*! @function - @abstract Get the end iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The end iterator [khint_t] - */ -#define kh_end(h) ((h)->n_buckets) - -/*! @function - @abstract Get the number of elements in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of elements in the hash table [khint_t] - */ -#define kh_size(h) ((h)->size) - -/*! @function - @abstract Get the number of buckets in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of buckets in the hash table [khint_t] - */ -#define kh_n_buckets(h) ((h)->n_buckets) - -/*! @function - @abstract Iterate over the entries in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which key will be assigned - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h,__i)) continue; \ - (kvar) = kh_key(h,__i); \ - (vvar) = kh_val(h,__i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the values in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_value(h, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h,__i)) continue; \ - (vvar) = kh_val(h,__i); \ - code; \ - } } - -/* More convenient interfaces */ - -/*! @function - @abstract Instantiate a hash set containing integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT(name) \ - KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT(name, khval_t) \ - KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash set containing 64-bit integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT64(name) \ - KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT64(name, khval_t) \ - KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) - -typedef const char *kh_cstr_t; -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_STR(name) \ - KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_STR(name, khval_t) \ - KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) - -#endif /* __AC_KHASH_H */ diff --git a/suckless/st/kvec.h b/suckless/st/kvec.h deleted file mode 100644 index 10f1c5b..0000000 --- a/suckless/st/kvec.h +++ /dev/null @@ -1,90 +0,0 @@ -/* The MIT License - - Copyright (c) 2008, by Attractive Chaos - - 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. -*/ - -/* - An example: - -#include "kvec.h" -int main() { - kvec_t(int) array; - kv_init(array); - kv_push(int, array, 10); // append - kv_a(int, array, 20) = 5; // dynamic - kv_A(array, 20) = 4; // static - kv_destroy(array); - return 0; -} -*/ - -/* - 2008-09-22 (0.1.0): - - * The initial version. - -*/ - -#ifndef AC_KVEC_H -#define AC_KVEC_H - -#include - -#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) - -#define kvec_t(type) struct { size_t n, m; type *a; } -#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) -#define kv_destroy(v) free((v).a) -#define kv_A(v, i) ((v).a[(i)]) -#define kv_pop(v) ((v).a[--(v).n]) -#define kv_size(v) ((v).n) -#define kv_max(v) ((v).m) - -#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) - -#define kv_copy(type, v1, v0) do { \ - if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ - (v1).n = (v0).n; \ - memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ - } while (0) \ - -#define kv_push(type, v, x) do { \ - if ((v).n == (v).m) { \ - (v).m = (v).m? (v).m<<1 : 2; \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ - } \ - (v).a[(v).n++] = (x); \ - } while (0) - -#define kv_pushp(type, v) ((((v).n == (v).m)? \ - ((v).m = ((v).m? (v).m<<1 : 2), \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ - : 0), ((v).a + ((v).n++))) - -#define kv_a(type, v, i) (((v).m <= (size_t)(i)? \ - ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ - : (v).n <= (size_t)(i)? (v).n = (i) + 1 \ - : 0), (v).a[(i)]) - -#endif diff --git a/suckless/st/rowcolumn_diacritics_helpers.c b/suckless/st/rowcolumn_diacritics_helpers.c deleted file mode 100644 index 829c0fc..0000000 --- a/suckless/st/rowcolumn_diacritics_helpers.c +++ /dev/null @@ -1,391 +0,0 @@ -#include - -uint16_t diacritic_to_num(uint32_t code) -{ - switch (code) { - case 0x305: - return code - 0x305 + 1; - case 0x30d: - case 0x30e: - return code - 0x30d + 2; - case 0x310: - return code - 0x310 + 4; - case 0x312: - return code - 0x312 + 5; - case 0x33d: - case 0x33e: - case 0x33f: - return code - 0x33d + 6; - case 0x346: - return code - 0x346 + 9; - case 0x34a: - case 0x34b: - case 0x34c: - return code - 0x34a + 10; - case 0x350: - case 0x351: - case 0x352: - return code - 0x350 + 13; - case 0x357: - return code - 0x357 + 16; - case 0x35b: - return code - 0x35b + 17; - case 0x363: - case 0x364: - case 0x365: - case 0x366: - case 0x367: - case 0x368: - case 0x369: - case 0x36a: - case 0x36b: - case 0x36c: - case 0x36d: - case 0x36e: - case 0x36f: - return code - 0x363 + 18; - case 0x483: - case 0x484: - case 0x485: - case 0x486: - case 0x487: - return code - 0x483 + 31; - case 0x592: - case 0x593: - case 0x594: - case 0x595: - return code - 0x592 + 36; - case 0x597: - case 0x598: - case 0x599: - return code - 0x597 + 40; - case 0x59c: - case 0x59d: - case 0x59e: - case 0x59f: - case 0x5a0: - case 0x5a1: - return code - 0x59c + 43; - case 0x5a8: - case 0x5a9: - return code - 0x5a8 + 49; - case 0x5ab: - case 0x5ac: - return code - 0x5ab + 51; - case 0x5af: - return code - 0x5af + 53; - case 0x5c4: - return code - 0x5c4 + 54; - case 0x610: - case 0x611: - case 0x612: - case 0x613: - case 0x614: - case 0x615: - case 0x616: - case 0x617: - return code - 0x610 + 55; - case 0x657: - case 0x658: - case 0x659: - case 0x65a: - case 0x65b: - return code - 0x657 + 63; - case 0x65d: - case 0x65e: - return code - 0x65d + 68; - case 0x6d6: - case 0x6d7: - case 0x6d8: - case 0x6d9: - case 0x6da: - case 0x6db: - case 0x6dc: - return code - 0x6d6 + 70; - case 0x6df: - case 0x6e0: - case 0x6e1: - case 0x6e2: - return code - 0x6df + 77; - case 0x6e4: - return code - 0x6e4 + 81; - case 0x6e7: - case 0x6e8: - return code - 0x6e7 + 82; - case 0x6eb: - case 0x6ec: - return code - 0x6eb + 84; - case 0x730: - return code - 0x730 + 86; - case 0x732: - case 0x733: - return code - 0x732 + 87; - case 0x735: - case 0x736: - return code - 0x735 + 89; - case 0x73a: - return code - 0x73a + 91; - case 0x73d: - return code - 0x73d + 92; - case 0x73f: - case 0x740: - case 0x741: - return code - 0x73f + 93; - case 0x743: - return code - 0x743 + 96; - case 0x745: - return code - 0x745 + 97; - case 0x747: - return code - 0x747 + 98; - case 0x749: - case 0x74a: - return code - 0x749 + 99; - case 0x7eb: - case 0x7ec: - case 0x7ed: - case 0x7ee: - case 0x7ef: - case 0x7f0: - case 0x7f1: - return code - 0x7eb + 101; - case 0x7f3: - return code - 0x7f3 + 108; - case 0x816: - case 0x817: - case 0x818: - case 0x819: - return code - 0x816 + 109; - case 0x81b: - case 0x81c: - case 0x81d: - case 0x81e: - case 0x81f: - case 0x820: - case 0x821: - case 0x822: - case 0x823: - return code - 0x81b + 113; - case 0x825: - case 0x826: - case 0x827: - return code - 0x825 + 122; - case 0x829: - case 0x82a: - case 0x82b: - case 0x82c: - case 0x82d: - return code - 0x829 + 125; - case 0x951: - return code - 0x951 + 130; - case 0x953: - case 0x954: - return code - 0x953 + 131; - case 0xf82: - case 0xf83: - return code - 0xf82 + 133; - case 0xf86: - case 0xf87: - return code - 0xf86 + 135; - case 0x135d: - case 0x135e: - case 0x135f: - return code - 0x135d + 137; - case 0x17dd: - return code - 0x17dd + 140; - case 0x193a: - return code - 0x193a + 141; - case 0x1a17: - return code - 0x1a17 + 142; - case 0x1a75: - case 0x1a76: - case 0x1a77: - case 0x1a78: - case 0x1a79: - case 0x1a7a: - case 0x1a7b: - case 0x1a7c: - return code - 0x1a75 + 143; - case 0x1b6b: - return code - 0x1b6b + 151; - case 0x1b6d: - case 0x1b6e: - case 0x1b6f: - case 0x1b70: - case 0x1b71: - case 0x1b72: - case 0x1b73: - return code - 0x1b6d + 152; - case 0x1cd0: - case 0x1cd1: - case 0x1cd2: - return code - 0x1cd0 + 159; - case 0x1cda: - case 0x1cdb: - return code - 0x1cda + 162; - case 0x1ce0: - return code - 0x1ce0 + 164; - case 0x1dc0: - case 0x1dc1: - return code - 0x1dc0 + 165; - case 0x1dc3: - case 0x1dc4: - case 0x1dc5: - case 0x1dc6: - case 0x1dc7: - case 0x1dc8: - case 0x1dc9: - return code - 0x1dc3 + 167; - case 0x1dcb: - case 0x1dcc: - return code - 0x1dcb + 174; - case 0x1dd1: - case 0x1dd2: - case 0x1dd3: - case 0x1dd4: - case 0x1dd5: - case 0x1dd6: - case 0x1dd7: - case 0x1dd8: - case 0x1dd9: - case 0x1dda: - case 0x1ddb: - case 0x1ddc: - case 0x1ddd: - case 0x1dde: - case 0x1ddf: - case 0x1de0: - case 0x1de1: - case 0x1de2: - case 0x1de3: - case 0x1de4: - case 0x1de5: - case 0x1de6: - return code - 0x1dd1 + 176; - case 0x1dfe: - return code - 0x1dfe + 198; - case 0x20d0: - case 0x20d1: - return code - 0x20d0 + 199; - case 0x20d4: - case 0x20d5: - case 0x20d6: - case 0x20d7: - return code - 0x20d4 + 201; - case 0x20db: - case 0x20dc: - return code - 0x20db + 205; - case 0x20e1: - return code - 0x20e1 + 207; - case 0x20e7: - return code - 0x20e7 + 208; - case 0x20e9: - return code - 0x20e9 + 209; - case 0x20f0: - return code - 0x20f0 + 210; - case 0x2cef: - case 0x2cf0: - case 0x2cf1: - return code - 0x2cef + 211; - case 0x2de0: - case 0x2de1: - case 0x2de2: - case 0x2de3: - case 0x2de4: - case 0x2de5: - case 0x2de6: - case 0x2de7: - case 0x2de8: - case 0x2de9: - case 0x2dea: - case 0x2deb: - case 0x2dec: - case 0x2ded: - case 0x2dee: - case 0x2def: - case 0x2df0: - case 0x2df1: - case 0x2df2: - case 0x2df3: - case 0x2df4: - case 0x2df5: - case 0x2df6: - case 0x2df7: - case 0x2df8: - case 0x2df9: - case 0x2dfa: - case 0x2dfb: - case 0x2dfc: - case 0x2dfd: - case 0x2dfe: - case 0x2dff: - return code - 0x2de0 + 214; - case 0xa66f: - return code - 0xa66f + 246; - case 0xa67c: - case 0xa67d: - return code - 0xa67c + 247; - case 0xa6f0: - case 0xa6f1: - return code - 0xa6f0 + 249; - case 0xa8e0: - case 0xa8e1: - case 0xa8e2: - case 0xa8e3: - case 0xa8e4: - case 0xa8e5: - case 0xa8e6: - case 0xa8e7: - case 0xa8e8: - case 0xa8e9: - case 0xa8ea: - case 0xa8eb: - case 0xa8ec: - case 0xa8ed: - case 0xa8ee: - case 0xa8ef: - case 0xa8f0: - case 0xa8f1: - return code - 0xa8e0 + 251; - case 0xaab0: - return code - 0xaab0 + 269; - case 0xaab2: - case 0xaab3: - return code - 0xaab2 + 270; - case 0xaab7: - case 0xaab8: - return code - 0xaab7 + 272; - case 0xaabe: - case 0xaabf: - return code - 0xaabe + 274; - case 0xaac1: - return code - 0xaac1 + 276; - case 0xfe20: - case 0xfe21: - case 0xfe22: - case 0xfe23: - case 0xfe24: - case 0xfe25: - case 0xfe26: - return code - 0xfe20 + 277; - case 0x10a0f: - return code - 0x10a0f + 284; - case 0x10a38: - return code - 0x10a38 + 285; - case 0x1d185: - case 0x1d186: - case 0x1d187: - case 0x1d188: - case 0x1d189: - return code - 0x1d185 + 286; - case 0x1d1aa: - case 0x1d1ab: - case 0x1d1ac: - case 0x1d1ad: - return code - 0x1d1aa + 291; - case 0x1d242: - case 0x1d243: - case 0x1d244: - return code - 0x1d242 + 295; - } - return 0; -} diff --git a/suckless/st/st b/suckless/st/st deleted file mode 100755 index a80dd98..0000000 Binary files a/suckless/st/st and /dev/null differ diff --git a/suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff b/suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff deleted file mode 100644 index 9d8bf6e..0000000 --- a/suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff +++ /dev/null @@ -1,194 +0,0 @@ -diff --git a/st/config.def.h b/st_patched/config.def.h -index 91ab8ca..59fc2a9 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -93,6 +93,10 @@ char *termname = "st-256color"; - */ - unsigned int tabspaces = 8; - -+/* bg opacity */ -+float alpha = 0.8; -+float alpha_def; -+ - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { - /* 8 normal colors */ -@@ -201,6 +205,9 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { MODKEY, XK_bracketleft, chgalpha, {.f = -1} }, /* Decrease opacity */ -+ { MODKEY|ShiftMask, XK_braceright, chgalpha, {.f = +1} }, /* Increase opacity */ -+ { MODKEY, XK_bracketright,chgalpha, {.f = 0} }, /* Reset opacity */ - }; - - /* -diff --git a/st/st.h b/st_patched/st.h -index fd3b0d8..cda8c13 100644 ---- a/st.h -+++ b/st.h -@@ -124,3 +124,4 @@ extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; - extern unsigned int defaultcs; -+extern float alpha, alpha_def; -diff --git a/st/config.mk b/st_patched/config.mk -index 1e306f8..47c615e 100644 ---- a/config.mk -+++ b/config.mk -@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config - INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` --LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ -+LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -diff --git a/st/x.c b/st_patched/x.c -index aa09997..3b05a55 100644 ---- a/x.c -+++ b/x.c -@@ -59,6 +59,7 @@ static void zoom(const Arg *); - static void zoomabs(const Arg *); - static void zoomreset(const Arg *); - static void ttysend(const Arg *); -+static void chgalpha(const Arg *); - - /* config.h for applying patches and the configuration. */ - #include "config.h" -@@ -105,6 +106,7 @@ typedef struct { - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ -+ int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ - } XWindow; -@@ -243,6 +245,7 @@ static char *usedfont = NULL; - static double usedfontsize = 0; - static double defaultfontsize = 0; - -+static char *opt_alpha = NULL; - static char *opt_class = NULL; - static char **opt_cmd = NULL; - static char *opt_embed = NULL; -@@ -752,7 +755,7 @@ xresize(int col, int row) - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - -@@ -812,6 +815,13 @@ xloadcols(void) - else - die("could not allocate color %d\n", i); - } -+ -+ /* set alpha value of bg color */ -+ if (opt_alpha) -+ alpha = strtof(opt_alpha, NULL); -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; - } - -@@ -1134,11 +1144,23 @@ xinit(int cols, int rows) - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ XWindowAttributes attr; -+ XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); -- xw.vis = XDefaultVisual(xw.dpy, xw.scr); -+ -+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { -+ parent = XRootWindow(xw.dpy, xw.scr); -+ xw.depth = 32; -+ } else { -+ XGetWindowAttributes(xw.dpy, parent, &attr); -+ xw.depth = attr.depth; -+ } -+ -+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); -+ xw.vis = vis.visual; - - /* font */ - if (!FcInit()) -@@ -1147,8 +1169,11 @@ xinit(int cols, int rows) - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - -+ /* Backup default alpha value */ -+ alpha_def = alpha; -+ - /* colors */ -- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ -@@ -1168,19 +1193,15 @@ xinit(int cols, int rows) - | 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, -+ win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; -- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, -- &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); -+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -1371,6 +1392,24 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x - return numspecs; - } - -+void -+chgalpha(const Arg *arg) -+{ -+ if (arg->f == -1.0f && alpha >= 0.1f) -+ alpha -= 0.1f; -+ else if (arg->f == 1.0f && alpha < 1.0f) -+ alpha += 0.1f; -+ else if (arg->f == 0.0f) -+ alpha = alpha_def; -+ else -+ return; -+ -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xFFFF * alpha); -+ /* Required to remove artifacting from borderpx */ -+ cresize(0, 0); -+ redraw(); -+} -+ - void - xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) - { -@@ -2038,6 +2077,9 @@ main(int argc, char *argv[]) - case 'a': - allowaltscreen = 0; - break; -+ case 'A': -+ opt_alpha = EARGF(usage()); -+ break; - case 'c': - opt_class = EARGF(usage()); - break; diff --git a/suckless/st/st.1 b/suckless/st/st.1 deleted file mode 100644 index ef8c956..0000000 --- a/suckless/st/st.1 +++ /dev/null @@ -1,177 +0,0 @@ -.TH ST 1 st\-VERSION -.SH NAME -st \- simple terminal (bread's build) -.SH SYNOPSIS -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-l -.IR line ] -.RB [ \-w -.IR windowid ] -.RB [[ \-e ] -.IR command -.RI [ arguments ...]] -.PP -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-w -.IR windowid ] -.RB \-l -.IR line -.RI [ stty_args ...] -.SH DESCRIPTION -.B st -is a simple terminal emulator. -.SH OPTIONS -.TP -.B \-a -disable alternate screens in terminal -.TP -.BI \-c " class" -defines the window class (default $TERM). -.TP -.BI \-f " font" -defines the -.I font -to use when st is run. -.TP -.BI \-g " geometry" -defines the X11 geometry string. -The form is [=][{xX}][{+-}{+-}]. See -.BR XParseGeometry (3) -for further details. -.TP -.B \-i -will fixate the position given with the -g option. -.TP -.BI \-n " name" -defines the window instance name (default $TERM). -.TP -.BI \-o " iofile" -writes all the I/O to -.I iofile. -This feature is useful when recording st sessions. A value of "-" means -standard output. -.TP -.BI \-T " title" -defines the window title (default 'st'). -.TP -.BI \-t " title" -defines the window title (default 'st'). -.TP -.BI \-w " windowid" -embeds st within the window identified by -.I windowid -.TP -.BI \-l " line" -use a tty -.I line -instead of a pseudo terminal. -.I line -should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port -0). -When this flag is given -remaining arguments are used as flags for -.BR stty(1). -By default st initializes the serial line to 8 bits, no parity, 1 stop bit -and a 38400 baud rate. The speed is set by appending it as last argument -(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are -.BR stty(1) -flags. If you want to set odd parity on 115200 baud use for example 'st -l -/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for -example 'st -l /dev/ttyS0 cs7 115200'. See -.BR stty(1) -for more arguments and cases. -.TP -.B \-v -prints version information to stderr, then exits. -.TP -.BI \-e " command " [ " arguments " "... ]" -st executes -.I command -instead of the shell. If this is used it -.B must be the last option -on the command line, as in xterm / rxvt. -This option is only intended for compatibility, -and all the remaining arguments are used as a command -even without it. -.SH SHORTCUTS -.TP -.B Break -Send a break in the serial line. -Break key is obtained in PC keyboards -pressing at the same time control and pause. -.TP -.B Ctrl-Print Screen -Toggle if st should print to the -.I iofile. -.TP -.B Shift-Print Screen -Print the full screen to the -.I iofile. -.TP -.B Print Screen -Print the selection to the -.I iofile. -.TP -.B Ctrl-Shift-Page Up -Increase font size. -.TP -.B Ctrl-Shift-Page Down -Decrease font size. -.TP -.B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). -.TP -.B Ctrl-Shift-c -Copy the selected text to the clipboard selection. -.TP -.B Ctrl-Shift-v -Paste from the clipboard selection. -.SH CUSTOMIZATION -.B st -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH AUTHORS -See the LICENSE file for the authors. -.SH LICENSE -See the LICENSE file for the terms of redistribution. -.SH SEE ALSO -.BR tabbed (1), -.BR utmp (1), -.BR stty (1), -.BR scroll (1) -.SH BUGS -See the TODO file in the distribution. - diff --git a/suckless/st/st.c b/suckless/st/st.c deleted file mode 100644 index 367a3bb..0000000 --- a/suckless/st/st.c +++ /dev/null @@ -1,2799 +0,0 @@ -/* See LICENSE for license details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "st.h" -#include "win.h" - -#if defined(__linux) - #include -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include -#elif defined(__FreeBSD__) || defined(__DragonFly__) - #include -#endif - -/* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ - -/* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) - -#define TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)] -#define TLINEOFFSET(y) (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size) -#define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)]) - -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, -}; - -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; - -enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 -}; - -enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN -}; - -enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, -}; - -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - -/* Screen lines */ -typedef struct { - Line* buffer; /* ring buffer */ - int size; /* size of buffer */ - int cur; /* start of active screen */ - int off; /* scrollback line offset */ - TCursor sc; /* saved cursor */ -} LineBuffer; - -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - LineBuffer screen[2]; /* screen and alternate screen */ - int linelen; /* allocated line length */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ -} Term; - -/* CSI Escape sequence structs */ -/* ESC '[' [[ [] [;]] []] */ -typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; -} CSIEscape; - -/* STR Escape sequence structs */ -/* ESC type [[ [] [;]] ] ESC '\' */ -typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ -} STREscape; - -static void execsh(char *, char **); -static void stty(char **); -static void sigchld(int); -static void ttywriteraw(const char *, size_t); - -static void csidump(void); -static void csihandle(void); -static void csiparse(void); -static void csireset(void); -static void osc_color_response(int, int, int); -static int eschandle(uchar); -static void strdump(void); -static void strhandle(void); -static void strparse(void); -static void strreset(void); - -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int); -static void tcursor(int); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(int); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int); -static void tscrolldown(int, int); -static void tsetattr(const int *, int); -static void tsetchar(Rune, const Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, const int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); -static void tdefutf8(char); -static int32_t tdefcolor(const int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); - -static void drawregion(int, int, int, int); -static void clearline(Line, Glyph, int, int); -static Line ensureline(Line); - -static void selnormalize(void); -static void selscroll(int, int); -static void selsnap(int *, int *, int); - -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); - -static char *base64dec(const char *); -static char base64dec_getc(const char **); - -static ssize_t xwrite(int, const char *, size_t); - -/* Globals */ -static Term term; -static Selection sel; -static CSIEscape csiescseq; -static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; - -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; - - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } - - return aux; -} - -void * -xmalloc(size_t len) -{ - void *p; - - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); - - return p; -} - -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); - - return p; -} - -char * -xstrdup(const char *s) -{ - char *p; - - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return p; -} - -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; -} - -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; - - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); - - return len; -} - -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); -} - -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; -} - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; -} - -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - -int -tlinelen(int y) -{ - int i = term.col; - Line line = TLINE(y); - - if (line[i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && line[i - 1].u == ' ') - --i; - - return i; -} - -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; - - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } - - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; - - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; - - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -} - -void -selnormalize(void) -{ - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; -} - -int -selected(int x, int y) -{ - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; - - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) - && BETWEEN(x, sel.nb.x, sel.ne.x); - - return BETWEEN(y, sel.nb.y, sel.ne.y) - && (y != sel.nb.y || x >= sel.nb.x) - && (y != sel.ne.y || x <= sel.ne.x); -} - -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int delim, prevdelim; - const Glyph *gp, *prevgp; - - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; - - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - - gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) - break; - - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { - if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - const Glyph *gp, *last; - - if (sel.ob.x == -1) - return NULL; - - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - - for ( ; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; -} - -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; - - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } - - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); -} - -void -sigchld(int a) -{ - int stat; - pid_t p; - - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); -} - -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; - - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} - -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; - - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } - - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; -} - -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; - - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } -} - -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } -} - -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; - - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); - - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; - -write_error: - die("write error on tty: %s\n", strerror(errno)); -} - -void -ttyresize(int tw, int th) -{ - struct winsize w; - - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); -} - -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); -} - -int -tattrset(int attr) -{ - int i, j; - int y = TLINEOFFSET(0); - - for (i = 0; i < term.row-1; i++) { - Line line = TSCREEN.buffer[y]; - for (j = 0; j < term.col-1; j++) { - if (line[j].mode & attr) - return 1; - } - y = (y+1) % TSCREEN.size; - } - - 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; - int y = TLINEOFFSET(0); - - for (i = 0; i < term.row-1; i++) { - Line line = TSCREEN.buffer[y]; - for (j = 0; j < term.col-1; j++) { - if (line[j].mode & attr) { - tsetdirt(i, i); - break; - } - } - y = (y+1) % TSCREEN.size; - } -} - -void -tfulldirt(void) -{ - tsetdirt(0, term.row-1); -} - -void -tcursor(int mode) -{ - if (mode == CURSOR_SAVE) { - TSCREEN.sc = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = TSCREEN.sc; - tmoveto(term.c.x, term.c.y); - } -} - -void -treset(void) -{ - int i, j; - Glyph g = (Glyph){ .fg = defaultfg, .bg = defaultbg}; - - 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++) { - term.screen[i].sc = (TCursor){{ - .fg = defaultfg, - .bg = defaultbg - }}; - term.screen[i].cur = 0; - term.screen[i].off = 0; - for (j = 0; j < term.row; ++j) { - if (term.col != term.linelen) - term.screen[i].buffer[j] = xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph)); - clearline(term.screen[i].buffer[j], g, 0, term.col); - } - for (j = term.row; j < term.screen[i].size; ++j) { - free(term.screen[i].buffer[j]); - term.screen[i].buffer[j] = NULL; - } - } - tcursor(CURSOR_LOAD); - term.linelen = term.col; - tfulldirt(); -} - -void -tnew(int col, int row) -{ - int i; - term = (Term){0}; - term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line)); - term.screen[0].size = HISTSIZE; - term.screen[1].buffer = NULL; - for (i = 0; i < HISTSIZE; ++i) term.screen[0].buffer[i] = NULL; - - tresize(col, row); - treset(); -} - -void -tswapscreen(void) -{ - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); -} - -void -kscrollup(const Arg *a) -{ - int n = a->i; - - if (IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) n = (-n) * term.row; - if (n > TSCREEN.size - term.row - TSCREEN.off) n = TSCREEN.size - term.row - TSCREEN.off; - while (!TLINE(-n)) --n; - TSCREEN.off += n; - selscroll(0, n); - tfulldirt(); -} - -void -kscrolldown(const Arg *a) -{ - - int n = a->i; - - if (IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) n = (-n) * term.row; - if (n > TSCREEN.off) n = TSCREEN.off; - TSCREEN.off -= n; - selscroll(0, -n); - tfulldirt(); -} - -void -tscrolldown(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - /* Ensure that lines are allocated */ - for (i = -n; i < 0; i++) { - TLINE(i) = ensureline(TLINE(i)); - } - - /* Shift non-scrolling areas in ring buffer */ - for (i = term.bot+1; i < term.row; i++) { - temp = TLINE(i); - TLINE(i) = TLINE(i-n); - TLINE(i-n) = temp; - } - for (i = 0; i < orig; i++) { - temp = TLINE(i); - TLINE(i) = TLINE(i-n); - TLINE(i-n) = temp; - } - - /* Scroll buffer */ - TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size; - /* Clear lines that have entered the view */ - tclearregion(0, orig, term.linelen-1, orig+n-1); - /* Redraw portion of the screen that has scrolled */ - tsetdirt(orig+n-1, term.bot); - selscroll(orig, n); -} - -void -tscrollup(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - /* Ensure that lines are allocated */ - for (i = term.row; i < term.row + n; i++) { - TLINE(i) = ensureline(TLINE(i)); - } - - /* Shift non-scrolling areas in ring buffer */ - for (i = orig-1; i >= 0; i--) { - temp = TLINE(i); - TLINE(i) = TLINE(i+n); - TLINE(i+n) = temp; - } - for (i = term.row-1; i >term.bot; i--) { - temp = TLINE(i); - TLINE(i) = TLINE(i+n); - TLINE(i+n) = temp; - } - - /* Scroll buffer */ - TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size; - /* Clear lines that have entered the view */ - tclearregion(0, term.bot-n+1, term.linelen-1, term.bot); - /* Redraw portion of the screen that has scrolled */ - tsetdirt(orig, term.bot-n+1); - selscroll(orig, -n); -} - -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) - return; - - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || - sel.oe.y < term.top || sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } -} - -void -tnewline(int first_col) -{ - int y = term.c.y; - - if (y == term.bot) { - tscrollup(term.top, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - int sep = ';'; /* colon or semi-colon, but not both */ - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (sep == ';' && *p == ':') - sep = ':'; /* allow override to colon once */ - if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; -} - -/* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); -} - -void -tmoveto(int x, int y) -{ - int miny, maxy; - - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); -} - -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - Line line = TLINE(y); - - /* - * 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 (line[x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - line[x+1].u = ' '; - line[x+1].mode &= ~ATTR_WDUMMY; - } - } else if (line[x].mode & ATTR_WDUMMY) { - line[x-1].u = ' '; - line[x-1].mode &= ~ATTR_WIDE; - } - - term.dirty[y] = 1; - line[x] = *attr; - line[x].u = u; -} - -void -tclearregion(int x1, int y1, int x2, int y2) -{ - int x, y, L, S, 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.linelen-1); - LIMIT(x2, 0, term.linelen-1); - LIMIT(y1, 0, term.row-1); - LIMIT(y2, 0, term.row-1); - - L = TLINEOFFSET(y1); - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &TSCREEN.buffer[L][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; - } - L = (L + 1) % TSCREEN.size; - } -} - -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 = TLINE(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 = TLINE(term.c.y); - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); -} - -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); -} - -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; - - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - - return idx; -} - -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; - - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } -} - -void -tsetscroll(int t, int b) -{ - int temp; - - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; -} - -void -tsetmode(int priv, int set, const int *args, int narg) -{ - int alt; const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col-1, - term.row-1); - } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } -} - -void -csihandle(void) -{ - char buf[40]; - int len; - - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor Down */ - case 'e': /* VPR --Cursor Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it more times */ - LIMIT(csiescseq.arg[0], 1, 65535); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor Forward */ - case 'a': /* HPR -- Cursor Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, - term.row-1); - } - break; - case 1: /* above */ - if (term.c.y > 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 */ - if (csiescseq.priv) break; - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, - term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR -- Device Status Report */ - switch (csiescseq.arg[0]) { - case 5: /* Status Report "OK" `0n` */ - ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); - break; - case 6: /* Report Cursor Position (CPR) ";R" */ - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - break; - default: - goto unknown; - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } -} - -void -csidump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); -} - -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); -} - -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } - - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } -} - -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; - - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: - case 11: - case 12: - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) { - xloadcols(); - return; /* color reset without parameter */ - } - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); -} - -void -strparse(void) -{ - int c; - char *p = strescseq.buf; - - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } -} - -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; -} - -void -printscreen(const Arg *arg) -{ - tdump(); -} - -void -printsel(const Arg *arg) -{ - tdumpsel(); -} - -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } -} - -void -tdumpline(int n) -{ - char buf[UTF_SIZ]; - const Glyph *bp, *end; - - bp = &TLINE(n)[0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for ( ; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); -} - -void -tdump(void) -{ - int i; - - for (i = 0; i < term.row; ++i) - tdumpline(i); -} - -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); -} - -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); -} - -/* - * returns 1 when the sequence is finished and it hasn't to read - * more characters for this sequence, otherwise 0 - */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - xsetmode(0, MODE_HIDE); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; -} - -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; - - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } - - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } - - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - -check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - /* in UTF-8 mode ignore handling C1 control characters */ - if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) - return; - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); - - gp = &TLINE(term.c.y)[term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &TLINE(term.c.y)[term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - gp->mode &= ~ATTR_WIDE; - } - - if (term.c.x+width > term.col) { - if (IS_SET(MODE_WRAP)) - tnewline(1); - else - tmoveto(term.col - width, term.c.y); - gp = &TLINE(term.c.y)[term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } -} - -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; - - if (TSCREEN.off) { - TSCREEN.off = 0; - tfulldirt(); - } - - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; -} - -void -clearline(Line line, Glyph g, int x, int xend) -{ - int i; - g.mode = 0; - g.u = ' '; - for (i = x; i < xend; ++i) { - line[i] = g; - } -} - -Line -ensureline(Line line) -{ - if (!line) { - line = xmalloc(term.linelen * sizeof(Glyph)); - } - return line; -} - -void -tresize(int col, int row) -{ - int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int linelen = MAX(col, term.linelen); - int *bp; - - if (col < 1 || row < 1 || row > HISTSIZE) { - fprintf(stderr, - "tresize: error resizing to %dx%d\n", col, row); - return; - } - - /* Shift buffer to keep the cursor where we expect it */ - if (row <= term.c.y) { - term.screen[0].cur = (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size; - } - - /* Resize and clear line buffers as needed */ - if (linelen > term.linelen) { - for (i = 0; i < term.screen[0].size; ++i) { - if (term.screen[0].buffer[i]) { - term.screen[0].buffer[i] = xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph)); - clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen); - } - } - for (i = 0; i < minrow; ++i) { - term.screen[1].buffer[i] = xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph)); - clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen); - } - } - /* Allocate all visible lines for regular line buffer */ - for (j = term.screen[0].cur, i = 0; i < row; ++i, j = (j + 1) % term.screen[0].size) - { - if (!term.screen[0].buffer[j]) { - term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph)); - } - if (i >= term.row) { - clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen); - } - } - /* Resize alt screen */ - term.screen[1].cur = 0; - term.screen[1].size = row; - for (i = row; i < term.row; ++i) { - free(term.screen[1].buffer[i]); - } - term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line)); - for (i = term.row; i < row; ++i) { - term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph)); - clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen); - } - - /* resize to new height */ - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - - /* fix tabstops */ - 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; - term.linelen = linelen; - /* reset scrolling region */ - tsetscroll(0, row-1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - tfulldirt(); -} - -void -resettitle(void) -{ - xsettitle(NULL); -} - -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y, L; - - L = TLINEOFFSET(y1); - for (y = y1; y < y2; y++) { - if (term.dirty[y]) { - term.dirty[y] = 0; - xdrawline(TSCREEN.buffer[L], x1, y, x2); - } - L = (L + 1) % TSCREEN.size; - } -} - -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - if (TSCREEN.off == 0) - xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], - term.ocx, term.ocy, TLINE(term.ocy)[term.ocx], - TLINE(term.ocy), term.col); - - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); -} diff --git a/suckless/st/st.h b/suckless/st/st.h deleted file mode 100644 index 4649646..0000000 --- a/suckless/st/st.h +++ /dev/null @@ -1,130 +0,0 @@ -/* See LICENSE for license details. */ - -#include -#include - -/* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b).mode & (~ATTR_WRAP)) || \ - (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)) -#define HISTSIZE 2000 - -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(const char *, char *, const 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(const char *); - -/* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; -extern unsigned int tabspaces; -extern unsigned int defaultfg; -extern unsigned int defaultbg; -extern unsigned int defaultcs; -extern float alpha; -extern float alpha_def; diff --git a/suckless/st/st.info b/suckless/st/st.info deleted file mode 100644 index efab2cf..0000000 --- a/suckless/st/st.info +++ /dev/null @@ -1,243 +0,0 @@ -st-mono| simpleterm monocolor, - acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, - am, - bce, - bel=^G, - blink=\E[5m, - bold=\E[1m, - cbt=\E[Z, - cvvis=\E[?25h, - civis=\E[?25l, - clear=\E[H\E[2J, - cnorm=\E[?12l\E[?25h, - colors#2, - cols#80, - cr=^M, - csr=\E[%i%p1%d;%p2%dr, - cub=\E[%p1%dD, - cub1=^H, - cud1=^J, - cud=\E[%p1%dB, - cuf1=\E[C, - cuf=\E[%p1%dC, - cup=\E[%i%p1%d;%p2%dH, - cuu1=\E[A, - cuu=\E[%p1%dA, - dch=\E[%p1%dP, - dch1=\E[P, - dim=\E[2m, - dl=\E[%p1%dM, - dl1=\E[M, - ech=\E[%p1%dX, - ed=\E[J, - el=\E[K, - el1=\E[1K, - enacs=\E)0, - flash=\E[?5h$<80/>\E[?5l, - fsl=^G, - home=\E[H, - hpa=\E[%i%p1%dG, - hs, - ht=^I, - hts=\EH, - ich=\E[%p1%d@, - il1=\E[L, - il=\E[%p1%dL, - ind=^J, - indn=\E[%p1%dS, - invis=\E[8m, - is2=\E[4l\E>\E[?1034l, - it#8, - kel=\E[1;2F, - ked=\E[1;5F, - ka1=\E[1~, - ka3=\E[5~, - kc1=\E[4~, - kc3=\E[6~, - kbs=\177, - kcbt=\E[Z, - kb2=\EOu, - kcub1=\EOD, - kcud1=\EOB, - kcuf1=\EOC, - kcuu1=\EOA, - kDC=\E[3;2~, - kent=\EOM, - kEND=\E[1;2F, - kIC=\E[2;2~, - kNXT=\E[6;2~, - kPRV=\E[5;2~, - kHOM=\E[1;2H, - kLFT=\E[1;2D, - kRIT=\E[1;2C, - kind=\E[1;2B, - kri=\E[1;2A, - kclr=\E[3;5~, - kdl1=\E[3;2~, - kdch1=\E[3~, - kich1=\E[2~, - kend=\E[4~, - kf1=\EOP, - kf2=\EOQ, - kf3=\EOR, - kf4=\EOS, - kf5=\E[15~, - kf6=\E[17~, - kf7=\E[18~, - kf8=\E[19~, - kf9=\E[20~, - kf10=\E[21~, - kf11=\E[23~, - kf12=\E[24~, - kf13=\E[1;2P, - kf14=\E[1;2Q, - kf15=\E[1;2R, - kf16=\E[1;2S, - kf17=\E[15;2~, - kf18=\E[17;2~, - kf19=\E[18;2~, - kf20=\E[19;2~, - kf21=\E[20;2~, - kf22=\E[21;2~, - kf23=\E[23;2~, - kf24=\E[24;2~, - kf25=\E[1;5P, - kf26=\E[1;5Q, - kf27=\E[1;5R, - kf28=\E[1;5S, - kf29=\E[15;5~, - kf30=\E[17;5~, - kf31=\E[18;5~, - kf32=\E[19;5~, - kf33=\E[20;5~, - kf34=\E[21;5~, - kf35=\E[23;5~, - kf36=\E[24;5~, - kf37=\E[1;6P, - kf38=\E[1;6Q, - kf39=\E[1;6R, - kf40=\E[1;6S, - kf41=\E[15;6~, - kf42=\E[17;6~, - kf43=\E[18;6~, - kf44=\E[19;6~, - kf45=\E[20;6~, - kf46=\E[21;6~, - kf47=\E[23;6~, - kf48=\E[24;6~, - kf49=\E[1;3P, - kf50=\E[1;3Q, - kf51=\E[1;3R, - kf52=\E[1;3S, - kf53=\E[15;3~, - kf54=\E[17;3~, - kf55=\E[18;3~, - kf56=\E[19;3~, - kf57=\E[20;3~, - kf58=\E[21;3~, - kf59=\E[23;3~, - kf60=\E[24;3~, - kf61=\E[1;4P, - kf62=\E[1;4Q, - kf63=\E[1;4R, - khome=\E[1~, - kil1=\E[2;5~, - krmir=\E[2;2~, - knp=\E[6~, - kmous=\E[M, - kpp=\E[5~, - lines#24, - mir, - msgr, - npc, - op=\E[39;49m, - pairs#64, - mc0=\E[i, - mc4=\E[4i, - mc5=\E[5i, - rc=\E8, - rev=\E[7m, - ri=\EM, - rin=\E[%p1%dT, - ritm=\E[23m, - rmacs=\E(B, - rmcup=\E[?1049l, - rmir=\E[4l, - rmkx=\E[?1l\E>, - rmso=\E[27m, - rmul=\E[24m, - rs1=\Ec, - rs2=\E[4l\E>\E[?1034l, - sc=\E7, - sitm=\E[3m, - sgr0=\E[0m, - smacs=\E(0, - smcup=\E[?1049h, - smir=\E[4h, - smkx=\E[?1h\E=, - smso=\E[7m, - smul=\E[4m, - tbc=\E[3g, - tsl=\E]0;, - xenl, - vpa=\E[%i%p1%dd, -# XTerm extensions - rmxx=\E[29m, - smxx=\E[9m, - BE=\E[?2004h, - BD=\E[?2004l, - PS=\E[200~, - PE=\E[201~, -# disabled rep for now: causes some issues with older ncurses versions. -# rep=%p1%c\E[%p2%{1}%-%db, -# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) - Tc, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, - -st| simpleterm, - use=st-mono, - colors#8, - setab=\E[4%p1%dm, - setaf=\E[3%p1%dm, - setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, - -st-256color| simpleterm with 256 colors, - use=st, - ccc, - colors#256, - oc=\E]104\007, - pairs#32767, -# Nicked from xterm-256color - initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, - setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, - setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, - -st-meta| simpleterm with meta key, - use=st, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-meta-256color| simpleterm with meta key and 256 colors, - use=st-256color, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-bs| simpleterm with backspace as backspace, - use=st, - kbs=\010, - kdch1=\177, - -st-bs-256color| simpleterm with backspace as backspace and 256colors, - use=st-256color, - kbs=\010, - kdch1=\177, diff --git a/suckless/st/st.o b/suckless/st/st.o deleted file mode 100644 index 53e6ffd..0000000 Binary files a/suckless/st/st.o and /dev/null differ diff --git a/suckless/st/win.h b/suckless/st/win.h deleted file mode 100644 index 94679e4..0000000 --- a/suckless/st/win.h +++ /dev/null @@ -1,41 +0,0 @@ -/* See LICENSE for license details. */ - -enum win_mode { - MODE_VISIBLE = 1 << 0, - MODE_FOCUSED = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_MOUSEBTN = 1 << 3, - MODE_MOUSEMOTION = 1 << 4, - MODE_REVERSE = 1 << 5, - MODE_KBDLOCK = 1 << 6, - MODE_HIDE = 1 << 7, - MODE_APPCURSOR = 1 << 8, - MODE_MOUSESGR = 1 << 9, - MODE_8BIT = 1 << 10, - MODE_BLINK = 1 << 11, - MODE_FBLINK = 1 << 12, - MODE_FOCUS = 1 << 13, - MODE_MOUSEX10 = 1 << 14, - MODE_MOUSEMANY = 1 << 15, - MODE_BRCKTPASTE = 1 << 16, - MODE_NUMLOCK = 1 << 17, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ - |MODE_MOUSEMANY, -}; - -void xbell(void); -void xclipcopy(void); -void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int); -void xdrawline(Line, int, int, int); -void xfinishdraw(void); -void xloadcols(void); -int xsetcolorname(int, const char *); -int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); -void xseticontitle(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 deleted file mode 100644 index 0cb35e8..0000000 --- a/suckless/st/x.c +++ /dev/null @@ -1,2319 +0,0 @@ -/* See LICENSE for license details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -char *argv0; -#include "arg.h" -#include "st.h" -#include "win.h" -#include "hb.h" - -/* types used in config.h */ -typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Shortcut; - -typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; -} MouseShortcut; - -typedef struct { - KeySym k; - uint mask; - char *s; - /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ -} Key; - -/* X modifiers */ -#define XK_ANY_MOD UINT_MAX -#define XK_NO_MOD 0 -#define XK_SWITCH_MOD (1<<13|1<<14) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); -static void chgalpha(const Arg *); -void kscrollup(const Arg *); -void kscrolldown(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static void xresetfontsettings(ushort mode, Font **font, int *frcflags); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(const char *, double); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_alpha = NULL; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static uint buttons; /* bit field of pressed buttons */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, btn, code; - int x = evcol(e), y = evrow(e); - int state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - if (e->type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MODE_MOUSEMOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) - return; - /* Set btn to lowest-numbered pressed button, or 12 if no - * buttons are pressed. */ - for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) - ; - code = 32; - } else { - btn = e->xbutton.button; - /* Only buttons 1 through 11 can be encoded */ - if (btn < 1 || btn > 11) - return; - if (e->type == ButtonRelease) { - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - /* Don't send release events for the scroll wheel */ - if (btn == 4 || btn == 5) - return; - } - code = 0; - } - - ox = x; - oy = y; - - /* Encode btn into code. If no button is pressed for a motion event in - * MODE_MOUSEMANY, then encode it as a release. */ - if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) - code += 3; - else if (btn >= 8) - code += 128 + btn - 8; - else if (btn >= 4) - code += 64 + btn - 4; - else - code += btn - 1; - - if (!IS_SET(MODE_MOUSEX10)) { - code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - code, x+1, y+1, - e->type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+code, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Buttonmask for Button - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - -void -bpress(XEvent *e) -{ - int btn = e->xbutton.button; - struct timespec now; - int snap; - - if (1 <= btn && btn <= 11) - buttons |= 1 << (btn-1); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (btn == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - int btn = e->xbutton.button; - - if (1 <= btn && btn <= 11) - buttons &= ~(1 << (btn-1)); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (btn == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4); -} - -ushort -sixd_to_16bit(int x) -{ - return x == 0 ? 0 : 0x3737 + 0x2828 * x; -} - -int -xloadcolor(int i, const char *name, Color *ncolor) -{ - XRenderColor color = { .alpha = 0xffff }; - - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6*6*6+16) { /* same colors as xterm */ - color.red = sixd_to_16bit( ((i-16)/36)%6 ); - color.green = sixd_to_16bit( ((i-16)/6) %6 ); - color.blue = sixd_to_16bit( ((i-16)/1) %6 ); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, - xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } - - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); -} - -void -xloadcols(void) -{ - int i; - static int loaded; - Color *cp; - - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } - - /* set alpha value of bg color */ - if (opt_alpha) - alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; -} - -int -xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) -{ - if (!BETWEEN(x, 0, dc.collen - 1)) - return 1; - - *r = dc.col[x].color.red >> 8; - *g = dc.col[x].color.green >> 8; - *b = dc.col[x].color.blue >> 8; - - return 0; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen - 1)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(const char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((const FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Clear Harfbuzz font cache. */ - hbunloadfonts(); - - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent, root; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - XWindowAttributes attr; - XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* Backup default alpha value */ - alpha_def = alpha; - - /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask - | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - - root = XRootWindow(xw.dpy, xw.scr); - xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t, - win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - if (parent != root) - XReparentWindow(xw.dpy, xw.win, parent, xw.l, xw.t); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -void -xresetfontsettings(ushort mode, Font **font, int *frcflags) -{ - *font = &dc.font; - 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; - } -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, length = 0, start = 0, numspecs = 0; - float cluster_xp = xp, cluster_yp = yp; - HbTransformData shaped = { 0 }; - - /* Initial values. */ - mode = prevmode = glyphs[0].mode & ~ATTR_WRAP; - xresetfontsettings(mode, &font, &frcflags); - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - mode = glyphs[i].mode & ~ATTR_WRAP; - - /* Skip dummy wide-character spacing. */ - if (mode & ATTR_WDUMMY && i < (len - 1)) - continue; - - if ( - prevmode != mode - || ATTRCMP(glyphs[start], glyphs[i]) - || selected(x + i, y) != selected(x + start, y) - || i == (len - 1) - ) { - /* Handle 1-character wide segments and end of line */ - length = i - start; - if (i == start) { - length = 1; - } else if (i == (len - 1)) { - length = (i - start + 1); - } - - /* Shape the segment. */ - hbtransform(&shaped, font->match, glyphs, start, length); - runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f); - cluster_xp = xp; cluster_yp = yp; - for (int code_idx = 0; code_idx < shaped.count; code_idx++) { - int idx = shaped.glyphs[code_idx].cluster; - - if (glyphs[start + idx].mode & ATTR_WDUMMY) - continue; - - /* Advance the drawing cursor if we've moved to a new cluster */ - if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) { - xp += runewidth; - cluster_xp = xp; - cluster_yp = yp; - runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f); - } - - if (shaped.glyphs[code_idx].codepoint != 0) { - /* If symbol is found, put it into the specs. */ - specs[numspecs].font = font->match; - specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; - specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.); - specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.); - cluster_xp += shaped.positions[code_idx].x_advance / 64.; - cluster_yp += shaped.positions[code_idx].y_advance / 64.; - numspecs++; - } else { - /* If it's not found, try to fetch it through the font cache. */ - rune = glyphs[start + idx].u; - 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; - numspecs++; - } - } - - /* Cleanup and get ready for next segment. */ - hbcleanup(&shaped); - start = i; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - xresetfontsettings(mode, &font, &frcflags); - yp = winy + font->ascent; - } - } - } - - return numspecs; -} - -void -chgalpha(const Arg *arg) -{ - if (arg->f == -1.0f && alpha >= 0.1f) - alpha -= 0.1f; - else if (arg->f == 1.0f && alpha < 1.0f) - alpha += 0.1f; - else if (arg->f == 0.0f) - alpha = alpha_def; - else - return; - - dc.col[defaultbg].color.alpha = (unsigned short)(0xFFFF * alpha); - /* Required to remove artifacting from borderpx */ - cresize(0, 0); - redraw(); -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int charlen) -{ - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, - width, 1); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y); - xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 : 1); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - - /* Redraw the line where cursor was previously. - * It will restore the ligatures broken by the cursor. */ - xdrawline(line, 0, oy, len); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ - xdrawglyph(g, cx, cy); - break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - \ - cursorthickness, - win.cw, cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - cursorthickness, win.ch); - break; - } - } else { - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, - win.cw, 1); - } -} - -void -xsetenv(void) -{ - char buf[sizeof(long) * 8 + 1]; - - snprintf(buf, sizeof(buf), "%lu", xw.win); - setenv("WINDOWID", buf, 1); -} - -void -xseticontitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (p[0] == '\0') - p = opt_title; - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); -} - -void -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (p[0] == '\0') - p = opt_title; - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - i = ox = 0; - for (x = x1; x < x2; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if ((i > 0) && ATTRCMP(base, new)) { - numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); - xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - ox); - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) { - numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); - xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox); - } -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym = NoSymbol; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) { - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - if (status == XBufferOverflow) - return; - } else { - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - } - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - - -#define XRESOURCE_LOAD_META(NAME) \ - if(!XrmGetResource(xrdb, "st." NAME, "st." NAME, &type, &ret)) \ - XrmGetResource(xrdb, "*." NAME, "*." NAME, &type, &ret); \ - if (ret.addr != NULL && !strncmp("String", type, 64)) - -#define XRESOURCE_LOAD_STRING(NAME, DST) \ - XRESOURCE_LOAD_META(NAME) \ - DST = ret.addr; - -#define XRESOURCE_LOAD_CHAR(NAME, DST) \ - XRESOURCE_LOAD_META(NAME) \ - DST = ret.addr[0]; - -#define XRESOURCE_LOAD_INTEGER(NAME, DST) \ - XRESOURCE_LOAD_META(NAME) \ - DST = strtoul(ret.addr, NULL, 10); - -#define XRESOURCE_LOAD_FLOAT(NAME, DST) \ - XRESOURCE_LOAD_META(NAME) \ - DST = strtof(ret.addr, NULL); - -void -xrdb_load(void) -{ - /* XXX */ - char *xrm; - char *type; - XrmDatabase xrdb; - XrmValue ret; - Display *dpy; - - if(!(dpy = XOpenDisplay(NULL))) - die("Can't open display\n"); - - XrmInitialize(); - xrm = XResourceManagerString(dpy); - - if (xrm != NULL) { - xrdb = XrmGetStringDatabase(xrm); - - /* handling colors here without macros to do via loop. */ - int i = 0; - char loadValue[12] = ""; - for (i = 0; i < 256; i++) - { - sprintf(loadValue, "%s%d", "st.color", i); - - if(!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) - { - sprintf(loadValue, "%s%d", "*.color", i); - if (!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) - /* reset if not found (unless in range for defaults). */ - if (i > 15) - colorname[i] = NULL; - } - - if (ret.addr != NULL && !strncmp("String", type, 64)) - colorname[i] = ret.addr; - } - - XRESOURCE_LOAD_STRING("foreground", colorname[defaultfg]); - XRESOURCE_LOAD_STRING("background", colorname[defaultbg]); - XRESOURCE_LOAD_STRING("cursorColor", colorname[defaultcs]) - else { - // this looks confusing because we are chaining off of the if - // in the macro. probably we should be wrapping everything blocks - // so this isn't possible... - defaultcs = defaultfg; - } - XRESOURCE_LOAD_STRING("reverse-cursor", colorname[defaultrcs]) - else { - // see above. - defaultrcs = defaultbg; - } - - XRESOURCE_LOAD_STRING("font", font); - XRESOURCE_LOAD_STRING("termname", termname); - - XRESOURCE_LOAD_INTEGER("blinktimeout", blinktimeout); - XRESOURCE_LOAD_INTEGER("bellvolume", bellvolume); - XRESOURCE_LOAD_INTEGER("borderpx", borderpx); - XRESOURCE_LOAD_INTEGER("cursorshape", cursorshape); - - XRESOURCE_LOAD_FLOAT("cwscale", cwscale); - XRESOURCE_LOAD_FLOAT("chscale", chscale); - } - XFlush(dpy); -} - -void -reload(int sig) -{ - xrdb_load(); - - /* colors, fonts */ - xloadcols(); - xunloadfonts(); - xloadfonts(font, 0); - - /* pretend the window just got resized */ - cresize(win.w, win.h); - - redraw(); - - /* triggers re-render if we're visible. */ - ttywrite("\033[O", 3, 1); - - signal(SIGUSR1, reload); -} - - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'A': - opt_alpha = EARGF(usage()); - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), - &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s " VERSION "\n", argv0); - break; - default: - usage(); - } ARGEND; - -run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; - - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - xrdb_load(); - signal(SIGUSR1, reload); - 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 deleted file mode 100644 index cde21ef..0000000 Binary files a/suckless/st/x.o and /dev/null differ