├── dmenu ├── LICENSE ├── Makefile ├── README ├── arg.h ├── config.def.h ├── config.mk ├── dmenu.1 ├── dmenu.c ├── dmenu_path ├── dmenu_run ├── drw.c ├── drw.h ├── stest.1 ├── stest.c ├── util.c └── util.h ├── dwm ├── LICENSE ├── Makefile ├── README ├── config.def.h ├── config.mk ├── drw.c ├── drw.h ├── dwm.1 ├── dwm.c ├── movestack.c ├── patches │ ├── dwm-bar-height-spacing-6.3.diff │ ├── dwm-barpadding-20211020-a786211.diff │ ├── dwm-fullgaps-6.4.diff │ ├── dwm-notitle-20210715-138b405.diff │ ├── dwm-preserveonrestart-6.3.diff │ ├── dwm-restartsig-20180523-6.2.diff │ ├── dwm-statusallmons-6.2.diff │ ├── dwm-warp-6.4.diff │ └── dwm-xrdb-6.4.diff ├── transient.c ├── util.c └── util.h ├── slstatus ├── LICENSE ├── Makefile ├── arg.h ├── components │ ├── battery.c │ ├── cat.c │ ├── cpu.c │ ├── datetime.c │ ├── disk.c │ ├── entropy.c │ ├── hostname.c │ ├── ip.c │ ├── kernel_release.c │ ├── keyboard_indicators.c │ ├── keymap.c │ ├── load_avg.c │ ├── netspeeds.c │ ├── num_files.c │ ├── pixVol.sh │ ├── ram.c │ ├── run_command.c │ ├── swap.c │ ├── temperature.c │ ├── uptime.c │ ├── user.c │ ├── volume.c │ └── wifi.c ├── config.def.h ├── config.mk ├── slstatus.1 ├── slstatus.c ├── slstatus.h ├── util.c └── util.h └── st ├── LEGACY ├── LICENSE ├── Makefile ├── README ├── TODO ├── arg.h ├── boxdraw.c ├── boxdraw_data.h ├── config.def.h ├── config.mk ├── graphics.c ├── graphics.h ├── icat-mini.sh ├── khash.h ├── kvec.h ├── rowcolumn_diacritics_helpers.c ├── st.1 ├── st.c ├── st.h ├── st.info ├── win.h └── x.c /dmenu/LICENSE: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | © 2006-2019 Anselm R Garbe 4 | © 2006-2008 Sander van Dijk 5 | © 2006-2007 Michał Janeczek 6 | © 2007 Kris Maglione 7 | © 2009 Gottox 8 | © 2009 Markus Schnalke 9 | © 2009 Evan Gates 10 | © 2010-2012 Connor Lane Smith 11 | © 2014-2022 Hiltjo Posthuma 12 | © 2015-2019 Quentin Rameau 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a 15 | copy of this software and associated documentation files (the "Software"), 16 | to deal in the Software without restriction, including without limitation 17 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 | and/or sell copies of the Software, and to permit persons to whom the 19 | Software is furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in 22 | all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 | DEALINGS IN THE SOFTWARE. 31 | -------------------------------------------------------------------------------- /dmenu/Makefile: -------------------------------------------------------------------------------- 1 | # dmenu - dynamic menu 2 | # See LICENSE file for copyright and license details. 3 | 4 | include config.mk 5 | 6 | SRC = drw.c dmenu.c stest.c util.c 7 | OBJ = $(SRC:.c=.o) 8 | 9 | all: dmenu stest 10 | 11 | .c.o: 12 | $(CC) -c $(CFLAGS) $< 13 | 14 | config.h: 15 | cp config.def.h $@ 16 | 17 | $(OBJ): arg.h config.h config.mk drw.h 18 | 19 | dmenu: dmenu.o drw.o util.o 20 | $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) 21 | 22 | stest: stest.o 23 | $(CC) -o $@ stest.o $(LDFLAGS) 24 | 25 | clean: 26 | rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz 27 | 28 | dist: clean 29 | mkdir -p dmenu-$(VERSION) 30 | cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\ 31 | drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ 32 | dmenu-$(VERSION) 33 | tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) 34 | gzip dmenu-$(VERSION).tar 35 | rm -rf dmenu-$(VERSION) 36 | 37 | install: all 38 | mkdir -p $(DESTDIR)$(PREFIX)/bin 39 | cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin 40 | chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu 41 | chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path 42 | chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run 43 | chmod 755 $(DESTDIR)$(PREFIX)/bin/stest 44 | mkdir -p $(DESTDIR)$(MANPREFIX)/man1 45 | sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 46 | sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1 47 | chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 48 | chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1 49 | 50 | uninstall: 51 | rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ 52 | $(DESTDIR)$(PREFIX)/bin/dmenu_path\ 53 | $(DESTDIR)$(PREFIX)/bin/dmenu_run\ 54 | $(DESTDIR)$(PREFIX)/bin/stest\ 55 | $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ 56 | $(DESTDIR)$(MANPREFIX)/man1/stest.1 57 | 58 | .PHONY: all clean dist install uninstall 59 | -------------------------------------------------------------------------------- /dmenu/README: -------------------------------------------------------------------------------- 1 | dmenu - dynamic menu 2 | ==================== 3 | dmenu is an efficient dynamic menu for X. 4 | 5 | 6 | Requirements 7 | ------------ 8 | In order to build dmenu you need the Xlib header files. 9 | 10 | 11 | Installation 12 | ------------ 13 | Edit config.mk to match your local setup (dmenu is installed into 14 | the /usr/local namespace by default). 15 | 16 | Afterwards enter the following command to build and install dmenu 17 | (if necessary as root): 18 | 19 | make clean install 20 | 21 | 22 | Running dmenu 23 | ------------- 24 | See the man page for details. 25 | -------------------------------------------------------------------------------- /dmenu/arg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copy me if you can. 3 | * by 20h 4 | */ 5 | 6 | #ifndef ARG_H__ 7 | #define ARG_H__ 8 | 9 | extern char *argv0; 10 | 11 | /* use main(int argc, char *argv[]) */ 12 | #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ 13 | argv[0] && argv[0][0] == '-'\ 14 | && argv[0][1];\ 15 | argc--, argv++) {\ 16 | char argc_;\ 17 | char **argv_;\ 18 | int brk_;\ 19 | if (argv[0][1] == '-' && argv[0][2] == '\0') {\ 20 | argv++;\ 21 | argc--;\ 22 | break;\ 23 | }\ 24 | for (brk_ = 0, argv[0]++, argv_ = argv;\ 25 | argv[0][0] && !brk_;\ 26 | argv[0]++) {\ 27 | if (argv_ != argv)\ 28 | break;\ 29 | argc_ = argv[0][0];\ 30 | switch (argc_) 31 | 32 | #define ARGEND }\ 33 | } 34 | 35 | #define ARGC() argc_ 36 | 37 | #define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ 38 | ((x), abort(), (char *)0) :\ 39 | (brk_ = 1, (argv[0][1] != '\0')?\ 40 | (&argv[0][1]) :\ 41 | (argc--, argv++, argv[0]))) 42 | 43 | #define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ 44 | (char *)0 :\ 45 | (brk_ = 1, (argv[0][1] != '\0')?\ 46 | (&argv[0][1]) :\ 47 | (argc--, argv++, argv[0]))) 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /dmenu/config.def.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | /* Default settings; can be overriden by command line. */ 3 | 4 | static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ 5 | static int centered = 1; /* -c option; centers dmenu on screen */ 6 | static int min_width = 80; /* minimum width when centered */ 7 | static const float menu_height_ratio = 8 | 2.0f; /* This is the ratio used in the original calculation */ 9 | /* -fn option overrides fonts[0]; default X11 font or font set */ 10 | static const char *fonts[] = {"monospace:size=10"}; 11 | static const char *prompt = 12 | NULL; /* -p option; prompt to the left of input field */ 13 | 14 | #include "/home/pixel/.cache/wal/colors-wal-dmenu.h" 15 | // static const char *colors[SchemeLast][2] = { 16 | /* fg bg */ 17 | /* [SchemeNorm] = {"#bbbbbb", "#222222"}, 18 | [SchemeSel] = {"#eeeeee", "#005577"}, 19 | [SchemeOut] = {"#000000", "#00ffff"}, 20 | }; 21 | */ 22 | /* -l and -g options; controls number of lines and columns in grid if > 0 */ 23 | static unsigned int lines = 9; 24 | static unsigned int columns = 1; 25 | 26 | /* 27 | * Characters not considered part of a word while deleting words 28 | * for example: " /?\"&[]" 29 | */ 30 | static const char worddelimiters[] = " "; 31 | 32 | /* Size of the window border */ 33 | static unsigned int border_width = 3; 34 | -------------------------------------------------------------------------------- /dmenu/config.mk: -------------------------------------------------------------------------------- 1 | # dmenu version 2 | VERSION = 5.3 3 | 4 | # paths 5 | PREFIX = /usr/local 6 | MANPREFIX = $(PREFIX)/share/man 7 | 8 | X11INC = /usr/X11R6/include 9 | X11LIB = /usr/X11R6/lib 10 | 11 | # Xinerama, comment if you don't want it 12 | XINERAMALIBS = -lXinerama 13 | XINERAMAFLAGS = -DXINERAMA 14 | 15 | # freetype 16 | FREETYPELIBS = -lfontconfig -lXft 17 | FREETYPEINC = /usr/include/freetype2 18 | # OpenBSD (uncomment) 19 | #FREETYPEINC = $(X11INC)/freetype2 20 | #MANPREFIX = ${PREFIX}/man 21 | 22 | # includes and libs 23 | INCS = -I$(X11INC) -I$(FREETYPEINC) 24 | LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) 25 | 26 | # flags 27 | CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) 28 | CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) 29 | LDFLAGS = $(LIBS) 30 | 31 | # compiler and linker 32 | CC = cc 33 | -------------------------------------------------------------------------------- /dmenu/dmenu.1: -------------------------------------------------------------------------------- 1 | .TH DMENU 1 dmenu\-VERSION 2 | .SH NAME 3 | dmenu \- dynamic menu 4 | .SH SYNOPSIS 5 | .B dmenu 6 | .RB [ \-bfiv ] 7 | .RB [ \-g 8 | .IR columns ] 9 | .RB [ \-l 10 | .IR lines ] 11 | .RB [ \-m 12 | .IR monitor ] 13 | .RB [ \-p 14 | .IR prompt ] 15 | .RB [ \-fn 16 | .IR font ] 17 | .RB [ \-nb 18 | .IR color ] 19 | .RB [ \-nf 20 | .IR color ] 21 | .RB [ \-sb 22 | .IR color ] 23 | .RB [ \-sf 24 | .IR color ] 25 | .RB [ \-w 26 | .IR windowid ] 27 | .P 28 | .BR dmenu_run " ..." 29 | .SH DESCRIPTION 30 | .B dmenu 31 | is a dynamic menu for X, which reads a list of newline\-separated items from 32 | stdin. When the user selects an item and presses Return, their choice is printed 33 | to stdout and dmenu terminates. Entering text will narrow the items to those 34 | matching the tokens in the input. 35 | .P 36 | .B dmenu_run 37 | is a script used by 38 | .IR dwm (1) 39 | which lists programs in the user's $PATH and runs the result in their $SHELL. 40 | .SH OPTIONS 41 | .TP 42 | .B \-b 43 | dmenu appears at the bottom of the screen. 44 | .TP 45 | .B \-c 46 | dmenu appears centered on the screen. 47 | .TP 48 | .B \-f 49 | dmenu grabs the keyboard before reading stdin if not reading from a tty. This 50 | is faster, but will lock up X until stdin reaches end\-of\-file. 51 | .TP 52 | .B \-i 53 | dmenu matches menu items case insensitively. 54 | .TP 55 | .BI \-g " columns" 56 | dmenu lists items in a grid with the given number of columns. 57 | .TP 58 | .BI \-l " lines" 59 | dmenu lists items in a grid with the given number of lines. 60 | .TP 61 | .BI \-m " monitor" 62 | dmenu is displayed on the monitor number supplied. Monitor numbers are starting 63 | from 0. 64 | .TP 65 | .BI \-p " prompt" 66 | defines the prompt to be displayed to the left of the input field. 67 | .TP 68 | .BI \-fn " font" 69 | defines the font or font set used. 70 | .TP 71 | .BI \-nb " color" 72 | defines the normal background color. 73 | .IR #RGB , 74 | .IR #RRGGBB , 75 | and X color names are supported. 76 | .TP 77 | .BI \-nf " color" 78 | defines the normal foreground color. 79 | .TP 80 | .BI \-sb " color" 81 | defines the selected background color. 82 | .TP 83 | .BI \-sf " color" 84 | defines the selected foreground color. 85 | .TP 86 | .B \-v 87 | prints version information to stdout, then exits. 88 | .TP 89 | .BI \-w " windowid" 90 | embed into windowid. 91 | .SH USAGE 92 | dmenu is completely controlled by the keyboard. Items are selected using the 93 | arrow keys, page up, page down, home, and end. 94 | .TP 95 | .B Tab 96 | Copy the selected item to the input field. 97 | .TP 98 | .B Return 99 | Confirm selection. Prints the selected item to stdout and exits, returning 100 | success. 101 | .TP 102 | .B Ctrl-Return 103 | Confirm selection. Prints the selected item to stdout and continues. 104 | .TP 105 | .B Shift\-Return 106 | Confirm input. Prints the input text to stdout and exits, returning success. 107 | .TP 108 | .B Escape 109 | Exit without selecting an item, returning failure. 110 | .TP 111 | .B Ctrl-Left 112 | Move cursor to the start of the current word 113 | .TP 114 | .B Ctrl-Right 115 | Move cursor to the end of the current word 116 | .TP 117 | .B C\-a 118 | Home 119 | .TP 120 | .B C\-b 121 | Left 122 | .TP 123 | .B C\-c 124 | Escape 125 | .TP 126 | .B C\-d 127 | Delete 128 | .TP 129 | .B C\-e 130 | End 131 | .TP 132 | .B C\-f 133 | Right 134 | .TP 135 | .B C\-g 136 | Escape 137 | .TP 138 | .B C\-h 139 | Backspace 140 | .TP 141 | .B C\-i 142 | Tab 143 | .TP 144 | .B C\-j 145 | Return 146 | .TP 147 | .B C\-J 148 | Shift-Return 149 | .TP 150 | .B C\-k 151 | Delete line right 152 | .TP 153 | .B C\-m 154 | Return 155 | .TP 156 | .B C\-M 157 | Shift-Return 158 | .TP 159 | .B C\-n 160 | Down 161 | .TP 162 | .B C\-p 163 | Up 164 | .TP 165 | .B C\-u 166 | Delete line left 167 | .TP 168 | .B C\-w 169 | Delete word left 170 | .TP 171 | .B C\-y 172 | Paste from primary X selection 173 | .TP 174 | .B C\-Y 175 | Paste from X clipboard 176 | .TP 177 | .B M\-b 178 | Move cursor to the start of the current word 179 | .TP 180 | .B M\-f 181 | Move cursor to the end of the current word 182 | .TP 183 | .B M\-g 184 | Home 185 | .TP 186 | .B M\-G 187 | End 188 | .TP 189 | .B M\-h 190 | Up 191 | .TP 192 | .B M\-j 193 | Page down 194 | .TP 195 | .B M\-k 196 | Page up 197 | .TP 198 | .B M\-l 199 | Down 200 | .SH SEE ALSO 201 | .IR dwm (1), 202 | .IR stest (1) 203 | -------------------------------------------------------------------------------- /dmenu/dmenu_path: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" 4 | cache="$cachedir/dmenu_run" 5 | 6 | [ ! -e "$cachedir" ] && mkdir -p "$cachedir" 7 | 8 | IFS=: 9 | if stest -dqr -n "$cache" $PATH; then 10 | stest -flx $PATH | sort -u | tee "$cache" 11 | else 12 | cat "$cache" 13 | fi 14 | -------------------------------------------------------------------------------- /dmenu/dmenu_run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & 3 | -------------------------------------------------------------------------------- /dmenu/drw.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | typedef struct { 4 | Cursor cursor; 5 | } Cur; 6 | 7 | typedef struct Fnt { 8 | Display *dpy; 9 | unsigned int h; 10 | XftFont *xfont; 11 | FcPattern *pattern; 12 | struct Fnt *next; 13 | } Fnt; 14 | 15 | enum { ColFg, ColBg }; /* Clr scheme index */ 16 | typedef XftColor Clr; 17 | 18 | typedef struct { 19 | unsigned int w, h; 20 | Display *dpy; 21 | int screen; 22 | Window root; 23 | Drawable drawable; 24 | GC gc; 25 | Clr *scheme; 26 | Fnt *fonts; 27 | } Drw; 28 | 29 | /* Drawable abstraction */ 30 | Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); 31 | void drw_resize(Drw *drw, unsigned int w, unsigned int h); 32 | void drw_free(Drw *drw); 33 | 34 | /* Fnt abstraction */ 35 | Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); 36 | void drw_fontset_free(Fnt* set); 37 | unsigned int drw_fontset_getwidth(Drw *drw, const char *text); 38 | unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); 39 | void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); 40 | 41 | /* Colorscheme abstraction */ 42 | void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 43 | Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); 44 | 45 | /* Cursor abstraction */ 46 | Cur *drw_cur_create(Drw *drw, int shape); 47 | void drw_cur_free(Drw *drw, Cur *cursor); 48 | 49 | /* Drawing context manipulation */ 50 | void drw_setfontset(Drw *drw, Fnt *set); 51 | void drw_setscheme(Drw *drw, Clr *scm); 52 | 53 | /* Drawing functions */ 54 | void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 55 | int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); 56 | 57 | /* Map functions */ 58 | void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 59 | -------------------------------------------------------------------------------- /dmenu/stest.1: -------------------------------------------------------------------------------- 1 | .TH STEST 1 dmenu\-VERSION 2 | .SH NAME 3 | stest \- filter a list of files by properties 4 | .SH SYNOPSIS 5 | .B stest 6 | .RB [ -abcdefghlpqrsuwx ] 7 | .RB [ -n 8 | .IR file ] 9 | .RB [ -o 10 | .IR file ] 11 | .RI [ file ...] 12 | .SH DESCRIPTION 13 | .B stest 14 | takes a list of files and filters by the files' properties, analogous to 15 | .IR test (1). 16 | Files which pass all tests are printed to stdout. If no files are given, stest 17 | reads files from stdin. 18 | .SH OPTIONS 19 | .TP 20 | .B \-a 21 | Test hidden files. 22 | .TP 23 | .B \-b 24 | Test that files are block specials. 25 | .TP 26 | .B \-c 27 | Test that files are character specials. 28 | .TP 29 | .B \-d 30 | Test that files are directories. 31 | .TP 32 | .B \-e 33 | Test that files exist. 34 | .TP 35 | .B \-f 36 | Test that files are regular files. 37 | .TP 38 | .B \-g 39 | Test that files have their set-group-ID flag set. 40 | .TP 41 | .B \-h 42 | Test that files are symbolic links. 43 | .TP 44 | .B \-l 45 | Test the contents of a directory given as an argument. 46 | .TP 47 | .BI \-n " file" 48 | Test that files are newer than 49 | .IR file . 50 | .TP 51 | .BI \-o " file" 52 | Test that files are older than 53 | .IR file . 54 | .TP 55 | .B \-p 56 | Test that files are named pipes. 57 | .TP 58 | .B \-q 59 | No files are printed, only the exit status is returned. 60 | .TP 61 | .B \-r 62 | Test that files are readable. 63 | .TP 64 | .B \-s 65 | Test that files are not empty. 66 | .TP 67 | .B \-u 68 | Test that files have their set-user-ID flag set. 69 | .TP 70 | .B \-v 71 | Invert the sense of tests, only failing files pass. 72 | .TP 73 | .B \-w 74 | Test that files are writable. 75 | .TP 76 | .B \-x 77 | Test that files are executable. 78 | .SH EXIT STATUS 79 | .TP 80 | .B 0 81 | At least one file passed all tests. 82 | .TP 83 | .B 1 84 | No files passed all tests. 85 | .TP 86 | .B 2 87 | An error occurred. 88 | .SH SEE ALSO 89 | .IR dmenu (1), 90 | .IR test (1) 91 | -------------------------------------------------------------------------------- /dmenu/stest.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "arg.h" 12 | char *argv0; 13 | 14 | #define FLAG(x) (flag[(x)-'a']) 15 | 16 | static void test(const char *, const char *); 17 | static void usage(void); 18 | 19 | static int match = 0; 20 | static int flag[26]; 21 | static struct stat old, new; 22 | 23 | static void 24 | test(const char *path, const char *name) 25 | { 26 | struct stat st, ln; 27 | 28 | if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ 29 | && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ 30 | && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ 31 | && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ 32 | && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ 33 | && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ 34 | && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ 35 | && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ 36 | && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ 37 | && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ 38 | && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ 39 | && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ 40 | && (!FLAG('s') || st.st_size > 0) /* not empty */ 41 | && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ 42 | && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ 43 | && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ 44 | if (FLAG('q')) 45 | exit(0); 46 | match = 1; 47 | puts(name); 48 | } 49 | } 50 | 51 | static void 52 | usage(void) 53 | { 54 | fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " 55 | "[-n file] [-o file] [file...]\n", argv0); 56 | exit(2); /* like test(1) return > 1 on error */ 57 | } 58 | 59 | int 60 | main(int argc, char *argv[]) 61 | { 62 | struct dirent *d; 63 | char path[PATH_MAX], *line = NULL, *file; 64 | size_t linesiz = 0; 65 | ssize_t n; 66 | DIR *dir; 67 | int r; 68 | 69 | ARGBEGIN { 70 | case 'n': /* newer than file */ 71 | case 'o': /* older than file */ 72 | file = EARGF(usage()); 73 | if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) 74 | perror(file); 75 | break; 76 | default: 77 | /* miscellaneous operators */ 78 | if (strchr("abcdefghlpqrsuvwx", ARGC())) 79 | FLAG(ARGC()) = 1; 80 | else 81 | usage(); /* unknown flag */ 82 | } ARGEND; 83 | 84 | if (!argc) { 85 | /* read list from stdin */ 86 | while ((n = getline(&line, &linesiz, stdin)) > 0) { 87 | if (line[n - 1] == '\n') 88 | line[n - 1] = '\0'; 89 | test(line, line); 90 | } 91 | free(line); 92 | } else { 93 | for (; argc; argc--, argv++) { 94 | if (FLAG('l') && (dir = opendir(*argv))) { 95 | /* test directory contents */ 96 | while ((d = readdir(dir))) { 97 | r = snprintf(path, sizeof path, "%s/%s", 98 | *argv, d->d_name); 99 | if (r >= 0 && (size_t)r < sizeof path) 100 | test(path, d->d_name); 101 | } 102 | closedir(dir); 103 | } else { 104 | test(*argv, *argv); 105 | } 106 | } 107 | } 108 | return match ? 0 : 1; 109 | } 110 | -------------------------------------------------------------------------------- /dmenu/util.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | void 11 | die(const char *fmt, ...) 12 | { 13 | va_list ap; 14 | int saved_errno; 15 | 16 | saved_errno = errno; 17 | 18 | va_start(ap, fmt); 19 | vfprintf(stderr, fmt, ap); 20 | va_end(ap); 21 | 22 | if (fmt[0] && fmt[strlen(fmt)-1] == ':') 23 | fprintf(stderr, " %s", strerror(saved_errno)); 24 | fputc('\n', stderr); 25 | 26 | exit(1); 27 | } 28 | 29 | void * 30 | ecalloc(size_t nmemb, size_t size) 31 | { 32 | void *p; 33 | 34 | if (!(p = calloc(nmemb, size))) 35 | die("calloc:"); 36 | return p; 37 | } 38 | -------------------------------------------------------------------------------- /dmenu/util.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) 4 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) 5 | #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) 6 | #define LENGTH(X) (sizeof (X) / sizeof (X)[0]) 7 | 8 | void die(const char *fmt, ...); 9 | void *ecalloc(size_t nmemb, size_t size); 10 | -------------------------------------------------------------------------------- /dwm/LICENSE: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | © 2006-2019 Anselm R Garbe 4 | © 2006-2009 Jukka Salmi 5 | © 2006-2007 Sander van Dijk 6 | © 2007-2011 Peter Hartlich 7 | © 2007-2009 Szabolcs Nagy 8 | © 2007-2009 Christof Musik 9 | © 2007-2009 Premysl Hruby 10 | © 2007-2008 Enno Gottox Boland 11 | © 2008 Martin Hurton 12 | © 2008 Neale Pickett 13 | © 2009 Mate Nagy 14 | © 2010-2016 Hiltjo Posthuma 15 | © 2010-2012 Connor Lane Smith 16 | © 2011 Christoph Lohmann <20h@r-36.net> 17 | © 2015-2016 Quentin Rameau 18 | © 2015-2016 Eric Pruitt 19 | © 2016-2017 Markus Teich 20 | © 2020-2022 Chris Down 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a 23 | copy of this software and associated documentation files (the "Software"), 24 | to deal in the Software without restriction, including without limitation 25 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 26 | and/or sell copies of the Software, and to permit persons to whom the 27 | Software is furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in 30 | all copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 35 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 37 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 38 | DEALINGS IN THE SOFTWARE. 39 | -------------------------------------------------------------------------------- /dwm/Makefile: -------------------------------------------------------------------------------- 1 | # dwm - dynamic window manager 2 | # See LICENSE file for copyright and license details. 3 | 4 | include config.mk 5 | 6 | SRC = drw.c dwm.c util.c 7 | OBJ = ${SRC:.c=.o} 8 | 9 | all: dwm 10 | 11 | .c.o: 12 | ${CC} -c ${CFLAGS} $< 13 | 14 | ${OBJ}: config.h config.mk 15 | 16 | config.h: 17 | cp config.def.h $@ 18 | 19 | dwm: ${OBJ} 20 | ${CC} -o $@ ${OBJ} ${LDFLAGS} 21 | 22 | clean: 23 | rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz 24 | 25 | dist: clean 26 | mkdir -p dwm-${VERSION} 27 | cp -R LICENSE Makefile README config.def.h config.mk\ 28 | dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} 29 | tar -cf dwm-${VERSION}.tar dwm-${VERSION} 30 | gzip dwm-${VERSION}.tar 31 | rm -rf dwm-${VERSION} 32 | 33 | install: all 34 | mkdir -p ${DESTDIR}${PREFIX}/bin 35 | cp -f dwm ${DESTDIR}${PREFIX}/bin 36 | chmod 755 ${DESTDIR}${PREFIX}/bin/dwm 37 | mkdir -p ${DESTDIR}${MANPREFIX}/man1 38 | sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 39 | chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 40 | 41 | uninstall: 42 | rm -f ${DESTDIR}${PREFIX}/bin/dwm\ 43 | ${DESTDIR}${MANPREFIX}/man1/dwm.1 44 | 45 | .PHONY: all clean dist install uninstall 46 | -------------------------------------------------------------------------------- /dwm/README: -------------------------------------------------------------------------------- 1 | dwm - dynamic window manager 2 | ============================ 3 | dwm is an extremely fast, small, and dynamic window manager for X. 4 | 5 | 6 | Requirements 7 | ------------ 8 | In order to build dwm you need the Xlib header files. 9 | 10 | 11 | Installation 12 | ------------ 13 | Edit config.mk to match your local setup (dwm is installed into 14 | the /usr/local namespace by default). 15 | 16 | Afterwards enter the following command to build and install dwm (if 17 | necessary as root): 18 | 19 | make clean install 20 | 21 | 22 | Running dwm 23 | ----------- 24 | Add the following line to your .xinitrc to start dwm using startx: 25 | 26 | exec dwm 27 | 28 | In order to connect dwm to a specific display, make sure that 29 | the DISPLAY environment variable is set correctly, e.g.: 30 | 31 | DISPLAY=foo.bar:1 exec dwm 32 | 33 | (This will start dwm on display :1 of the host foo.bar.) 34 | 35 | In order to display status info in the bar, you can do something 36 | like this in your .xinitrc: 37 | 38 | while xsetroot -name "`date` `uptime | sed 's/.*,//'`" 39 | do 40 | sleep 1 41 | done & 42 | exec dwm 43 | 44 | 45 | Configuration 46 | ------------- 47 | The configuration of dwm is done by creating a custom config.h 48 | and (re)compiling the source code. 49 | -------------------------------------------------------------------------------- /dwm/config.def.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | /* appearance */ 4 | static const unsigned int borderpx = 2; /* border pixel of windows */ 5 | static const unsigned int gappx = 14; /* gaps between windows */ 6 | static const unsigned int snap = 3; /* snap pixel */ 7 | static const int user_bh = 14; /* 2 is the default spacing around the bar's font */ 8 | static const int showbar = 1; /* 0 means no bar */ 9 | static const int topbar = 1; /* 0 means bottom bar */ 10 | static const int vertpad = 10; /* vertical padding of bar */ 11 | static const int sidepad = 216; /* horizontal padding of bar */ 12 | static const char *fonts[] = {"CaskaydiaMonoNerdFont-Bold:size=9:style:Bold"}; 13 | static const char dmenufont[] = "CaskaydiaMonoNerdFont-Bold:size=10.6"; 14 | static char normbgcolor[] = "#222222"; 15 | static char normbordercolor[] = "#444444"; 16 | static char normfgcolor[] = "#bbbbbb"; 17 | static char selfgcolor[] = "#eeeeee"; 18 | static char selbordercolor[] = "#005577"; 19 | static char selbgcolor[] = "#005577"; 20 | static char *colors[][3] = { 21 | /* fg bg border */ 22 | [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, 23 | [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, 24 | }; 25 | 26 | /* tagging */ 27 | // static const char *tags[] = { "","","","","", }; 28 | static const char *tags[] = { "あ","い","う","え","お", }; 29 | 30 | static const Rule rules[] = { 31 | /* xprop(1): 32 | * WM_CLASS(STRING) = instance, class 33 | * WM_NAME(STRING) = title 34 | */ 35 | /* class instance title tags mask isfloating monitor */ 36 | { NULL, NULL, NULL, 0, 0, -1 }, 37 | { "mpv", NULL, NULL, 0, 1, -1 }, 38 | }; 39 | 40 | /* layout(s) */ 41 | static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ 42 | static const int nmaster = 1; /* number of clients in master area */ 43 | static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ 44 | static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ 45 | 46 | // static const Layout layouts[] = { 47 | // /* symbol arrange function */ 48 | // {"", tile}, /* first entry is default */ 49 | // {"󰭩", NULL}, /* no layout function means floating behavior */ 50 | // {"", monocle}, 51 | // }; 52 | // 53 | 54 | static const Layout layouts[] = { 55 | /* symbol arrange function */ 56 | {"", tile}, /* first entry is default */ 57 | {"", NULL}, /* no layout function means floating behavior */ 58 | {"", monocle}, 59 | }; 60 | 61 | 62 | 63 | /* key definitions */ 64 | #define MODKEY Mod4Mask 65 | #define TAGKEYS(KEY,TAG) \ 66 | { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ 67 | { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 68 | { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 69 | { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, 70 | 71 | /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 72 | #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 73 | 74 | /* commands */ 75 | static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ 76 | static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; 77 | static const char *termcmd[] = {"st", NULL}; 78 | 79 | 80 | #include "movestack.c" 81 | static const Key keys[] = { 82 | /* modifier key function argument */ 83 | { MODKEY, XK_n, xrdb, {.v = NULL } }, 84 | { MODKEY, XK_p, spawn, {.v = dmenucmd } }, 85 | { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, 86 | { MODKEY, XK_b, togglebar, {0} }, 87 | { MODKEY, XK_j, focusstack, {.i = +1 } }, 88 | { MODKEY, XK_k, focusstack, {.i = -1 } }, 89 | { MODKEY, XK_i, incnmaster, {.i = +1 } }, 90 | { MODKEY, XK_d, incnmaster, {.i = -1 } }, 91 | { MODKEY, XK_h, setmfact, {.f = -0.05} }, 92 | { MODKEY, XK_l, setmfact, {.f = +0.05} }, 93 | { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, 94 | { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, 95 | { MODKEY, XK_Return, zoom, {0} }, 96 | { MODKEY, XK_Tab, view, {0} }, 97 | { MODKEY|ShiftMask, XK_c, killclient, {0} }, 98 | { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, 99 | { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, 100 | { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, 101 | { MODKEY, XK_space, setlayout, {0} }, 102 | { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, 103 | { MODKEY, XK_0, view, {.ui = ~0 } }, 104 | { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, 105 | { MODKEY, XK_comma, focusmon, {.i = -1 } }, 106 | { MODKEY, XK_period, focusmon, {.i = +1 } }, 107 | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 108 | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 109 | { MODKEY, XK_minus, setgaps, {.i = -1 } }, 110 | { MODKEY, XK_equal, setgaps, {.i = +1 } }, 111 | { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, 112 | TAGKEYS( XK_1, 0) 113 | TAGKEYS( XK_2, 1) 114 | TAGKEYS( XK_3, 2) 115 | TAGKEYS( XK_4, 3) 116 | TAGKEYS( XK_5, 4) 117 | TAGKEYS( XK_6, 5) 118 | TAGKEYS( XK_7, 6) 119 | TAGKEYS( XK_8, 7) 120 | TAGKEYS( XK_9, 8) 121 | { MODKEY|ShiftMask, XK_q, quit, {0} }, 122 | { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, 123 | }; 124 | 125 | /* button definitions */ 126 | /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ 127 | static const Button buttons[] = { 128 | /* click event mask button function argument */ 129 | { ClkLtSymbol, 0, Button1, setlayout, {0} }, 130 | { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, 131 | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 132 | { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 133 | { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, 134 | { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, 135 | { ClkTagBar, 0, Button1, view, {0} }, 136 | { ClkTagBar, 0, Button3, toggleview, {0} }, 137 | { ClkTagBar, MODKEY, Button1, tag, {0} }, 138 | { ClkTagBar, MODKEY, Button3, toggletag, {0} }, 139 | }; 140 | 141 | -------------------------------------------------------------------------------- /dwm/config.mk: -------------------------------------------------------------------------------- 1 | # dwm version 2 | VERSION = 6.5 3 | 4 | # Customize below to fit your system 5 | 6 | # paths 7 | PREFIX = /usr/local 8 | MANPREFIX = ${PREFIX}/share/man 9 | 10 | X11INC = /usr/X11R6/include 11 | X11LIB = /usr/X11R6/lib 12 | 13 | # Xinerama, comment if you don't want it 14 | XINERAMALIBS = -lXinerama 15 | XINERAMAFLAGS = -DXINERAMA 16 | 17 | # freetype 18 | FREETYPELIBS = -lfontconfig -lXft 19 | FREETYPEINC = /usr/include/freetype2 20 | # OpenBSD (uncomment) 21 | #FREETYPEINC = ${X11INC}/freetype2 22 | #MANPREFIX = ${PREFIX}/man 23 | 24 | # includes and libs 25 | INCS = -I${X11INC} -I${FREETYPEINC} 26 | LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 27 | 28 | # flags 29 | CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 30 | #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} 31 | CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} 32 | LDFLAGS = ${LIBS} 33 | 34 | # Solaris 35 | #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" 36 | #LDFLAGS = ${LIBS} 37 | 38 | # compiler and linker 39 | CC = cc 40 | -------------------------------------------------------------------------------- /dwm/drw.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | typedef struct { 4 | Cursor cursor; 5 | } Cur; 6 | 7 | typedef struct Fnt { 8 | Display *dpy; 9 | unsigned int h; 10 | XftFont *xfont; 11 | FcPattern *pattern; 12 | struct Fnt *next; 13 | } Fnt; 14 | 15 | enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ 16 | typedef XftColor Clr; 17 | 18 | typedef struct { 19 | unsigned int w, h; 20 | Display *dpy; 21 | int screen; 22 | Window root; 23 | Drawable drawable; 24 | GC gc; 25 | Clr *scheme; 26 | Fnt *fonts; 27 | } Drw; 28 | 29 | /* Drawable abstraction */ 30 | Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); 31 | void drw_resize(Drw *drw, unsigned int w, unsigned int h); 32 | void drw_free(Drw *drw); 33 | 34 | /* Fnt abstraction */ 35 | Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); 36 | void drw_fontset_free(Fnt* set); 37 | unsigned int drw_fontset_getwidth(Drw *drw, const char *text); 38 | unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); 39 | void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); 40 | 41 | /* Colorscheme abstraction */ 42 | void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 43 | Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); 44 | 45 | /* Cursor abstraction */ 46 | Cur *drw_cur_create(Drw *drw, int shape); 47 | void drw_cur_free(Drw *drw, Cur *cursor); 48 | 49 | /* Drawing context manipulation */ 50 | void drw_setfontset(Drw *drw, Fnt *set); 51 | void drw_setscheme(Drw *drw, Clr *scm); 52 | 53 | /* Drawing functions */ 54 | void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 55 | int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); 56 | 57 | /* Map functions */ 58 | void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 59 | -------------------------------------------------------------------------------- /dwm/dwm.1: -------------------------------------------------------------------------------- 1 | .TH DWM 1 dwm\-VERSION 2 | .SH NAME 3 | dwm \- dynamic window manager 4 | .SH SYNOPSIS 5 | .B dwm 6 | .RB [ \-v ] 7 | .SH DESCRIPTION 8 | dwm is a dynamic window manager for X. It manages windows in tiled, monocle 9 | and floating layouts. Either layout can be applied dynamically, optimising the 10 | environment for the application in use and the task performed. 11 | .P 12 | In tiled layouts windows are managed in a master and stacking area. The master 13 | area on the left contains one window by default, and the stacking area on the 14 | right contains all other windows. The number of master area windows can be 15 | adjusted from zero to an arbitrary number. In monocle layout all windows are 16 | maximised to the screen size. In floating layout windows can be resized and 17 | moved freely. Dialog windows are always managed floating, regardless of the 18 | layout applied. 19 | .P 20 | Windows are grouped by tags. Each window can be tagged with one or multiple 21 | tags. Selecting certain tags displays all windows with these tags. 22 | .P 23 | Each screen contains a small status bar which displays all available tags, the 24 | layout, the title of the focused window, and the text read from the root window 25 | name property, if the screen is focused. A floating window is indicated with an 26 | empty square and a maximised floating window is indicated with a filled square 27 | before the windows title. The selected tags are indicated with a different 28 | color. The tags of the focused window are indicated with a filled square in the 29 | top left corner. The tags which are applied to one or more windows are 30 | indicated with an empty square in the top left corner. 31 | .P 32 | dwm draws a small border around windows to indicate the focus state. 33 | .SH OPTIONS 34 | .TP 35 | .B \-v 36 | prints version information to stderr, then exits. 37 | .SH USAGE 38 | .SS Status bar 39 | .TP 40 | .B X root window name 41 | is read and displayed in the status text area. It can be set with the 42 | .BR xsetroot (1) 43 | command. 44 | .TP 45 | .B Button1 46 | click on a tag label to display all windows with that tag, click on the layout 47 | label toggles between tiled and floating layout. 48 | .TP 49 | .B Button3 50 | click on a tag label adds/removes all windows with that tag to/from the view. 51 | .TP 52 | .B Mod1\-Button1 53 | click on a tag label applies that tag to the focused window. 54 | .TP 55 | .B Mod1\-Button3 56 | click on a tag label adds/removes that tag to/from the focused window. 57 | .SS Keyboard commands 58 | .TP 59 | .B Mod1\-Shift\-Return 60 | Start 61 | .BR st(1). 62 | .TP 63 | .B Mod1\-p 64 | Spawn 65 | .BR dmenu(1) 66 | for launching other programs. 67 | .TP 68 | .B Mod1\-, 69 | Focus previous screen, if any. 70 | .TP 71 | .B Mod1\-. 72 | Focus next screen, if any. 73 | .TP 74 | .B Mod1\-Shift\-, 75 | Send focused window to previous screen, if any. 76 | .TP 77 | .B Mod1\-Shift\-. 78 | Send focused window to next screen, if any. 79 | .TP 80 | .B Mod1\-b 81 | Toggles bar on and off. 82 | .TP 83 | .B Mod1\-t 84 | Sets tiled layout. 85 | .TP 86 | .B Mod1\-f 87 | Sets floating layout. 88 | .TP 89 | .B Mod1\-m 90 | Sets monocle layout. 91 | .TP 92 | .B Mod1\-space 93 | Toggles between current and previous layout. 94 | .TP 95 | .B Mod1\-j 96 | Focus next window. 97 | .TP 98 | .B Mod1\-k 99 | Focus previous window. 100 | .TP 101 | .B Mod1\-i 102 | Increase number of windows in master area. 103 | .TP 104 | .B Mod1\-d 105 | Decrease number of windows in master area. 106 | .TP 107 | .B Mod1\-l 108 | Increase master area size. 109 | .TP 110 | .B Mod1\-h 111 | Decrease master area size. 112 | .TP 113 | .B Mod1\-Return 114 | Zooms/cycles focused window to/from master area (tiled layouts only). 115 | .TP 116 | .B Mod1\-Shift\-c 117 | Close focused window. 118 | .TP 119 | .B Mod1\-Shift\-space 120 | Toggle focused window between tiled and floating state. 121 | .TP 122 | .B Mod1\-Tab 123 | Toggles to the previously selected tags. 124 | .TP 125 | .B Mod1\-Shift\-[1..n] 126 | Apply nth tag to focused window. 127 | .TP 128 | .B Mod1\-Shift\-0 129 | Apply all tags to focused window. 130 | .TP 131 | .B Mod1\-Control\-Shift\-[1..n] 132 | Add/remove nth tag to/from focused window. 133 | .TP 134 | .B Mod1\-[1..n] 135 | View all windows with nth tag. 136 | .TP 137 | .B Mod1\-0 138 | View all windows with any tag. 139 | .TP 140 | .B Mod1\-Control\-[1..n] 141 | Add/remove all windows with nth tag to/from the view. 142 | .TP 143 | .B Mod1\-Shift\-q 144 | Quit dwm. 145 | .TP 146 | .B Mod1\-Control\-Shift\-q 147 | Restart dwm. 148 | .SS Mouse commands 149 | .TP 150 | .B Mod1\-Button1 151 | Move focused window while dragging. Tiled windows will be toggled to the floating state. 152 | .TP 153 | .B Mod1\-Button2 154 | Toggles focused window between floating and tiled state. 155 | .TP 156 | .B Mod1\-Button3 157 | Resize focused window while dragging. Tiled windows will be toggled to the floating state. 158 | .SH CUSTOMIZATION 159 | dwm is customized by creating a custom config.h and (re)compiling the source 160 | code. This keeps it fast, secure and simple. 161 | .SH SIGNALS 162 | .TP 163 | .B SIGHUP - 1 164 | Restart the dwm process. 165 | .TP 166 | .B SIGTERM - 15 167 | Cleanly terminate the dwm process. 168 | .SH SEE ALSO 169 | .BR dmenu (1), 170 | .BR st (1) 171 | .SH ISSUES 172 | Java applications which use the XToolkit/XAWT backend may draw grey windows 173 | only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early 174 | JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds 175 | are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the 176 | environment variable 177 | .BR AWT_TOOLKIT=MToolkit 178 | (to use the older Motif backend instead) or running 179 | .B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D 180 | or 181 | .B wmname LG3D 182 | (to pretend that a non-reparenting window manager is running that the 183 | XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable 184 | .BR _JAVA_AWT_WM_NONREPARENTING=1 . 185 | .SH BUGS 186 | Send all bug reports with a patch to hackers@suckless.org. 187 | -------------------------------------------------------------------------------- /dwm/movestack.c: -------------------------------------------------------------------------------- 1 | void 2 | movestack(const Arg *arg) { 3 | Client *c = NULL, *p = NULL, *pc = NULL, *i; 4 | 5 | if(arg->i > 0) { 6 | /* find the client after selmon->sel */ 7 | for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); 8 | if(!c) 9 | for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); 10 | 11 | } 12 | else { 13 | /* find the client before selmon->sel */ 14 | for(i = selmon->clients; i != selmon->sel; i = i->next) 15 | if(ISVISIBLE(i) && !i->isfloating) 16 | c = i; 17 | if(!c) 18 | for(; i; i = i->next) 19 | if(ISVISIBLE(i) && !i->isfloating) 20 | c = i; 21 | } 22 | /* find the client before selmon->sel and c */ 23 | for(i = selmon->clients; i && (!p || !pc); i = i->next) { 24 | if(i->next == selmon->sel) 25 | p = i; 26 | if(i->next == c) 27 | pc = i; 28 | } 29 | 30 | /* swap c and selmon->sel selmon->clients in the selmon->clients list */ 31 | if(c && c != selmon->sel) { 32 | Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; 33 | selmon->sel->next = c->next==selmon->sel?c:c->next; 34 | c->next = temp; 35 | 36 | if(p && p != c) 37 | p->next = c; 38 | if(pc && pc != selmon->sel) 39 | pc->next = selmon->sel; 40 | 41 | if(selmon->sel == selmon->clients) 42 | selmon->clients = c; 43 | else if(c == selmon->clients) 44 | selmon->clients = selmon->sel; 45 | 46 | arrange(selmon); 47 | } 48 | } -------------------------------------------------------------------------------- /dwm/patches/dwm-bar-height-spacing-6.3.diff: -------------------------------------------------------------------------------- 1 | diff --git a/config.def.h b/config.def.h 2 | index 1c0b587..9814500 100644 3 | --- a/config.def.h 4 | +++ b/config.def.h 5 | @@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ 6 | static const unsigned int snap = 32; /* snap pixel */ 7 | static const int showbar = 1; /* 0 means no bar */ 8 | static const int topbar = 1; /* 0 means bottom bar */ 9 | +static const int user_bh = 2; /* 2 is the default spacing around the bar's font */ 10 | static const char *fonts[] = { "monospace:size=10" }; 11 | static const char dmenufont[] = "monospace:size=10"; 12 | static const char col_gray1[] = "#222222"; 13 | diff --git a/dwm.c b/dwm.c 14 | index 4465af1..2c27cb3 100644 15 | --- a/dwm.c 16 | +++ b/dwm.c 17 | @@ -1545,7 +1545,7 @@ setup(void) 18 | if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) 19 | die("no fonts could be loaded."); 20 | lrpad = drw->fonts->h; 21 | - bh = drw->fonts->h + 2; 22 | + bh = drw->fonts->h + user_bh; 23 | updategeom(); 24 | /* init atoms */ 25 | utf8string = XInternAtom(dpy, "UTF8_STRING", False); 26 | -------------------------------------------------------------------------------- /dwm/patches/dwm-barpadding-20211020-a786211.diff: -------------------------------------------------------------------------------- 1 | From a3cfb215f7f647d83d67e33df8f33a73e43bd65f Mon Sep 17 00:00:00 2001 2 | From: Bakkeby 3 | Date: Wed, 20 Oct 2021 09:14:07 +0200 4 | Subject: [PATCH] barpadding: adds space between the statusbar and the edge of 5 | the screen 6 | 7 | --- 8 | config.def.h | 2 ++ 9 | dwm.c | 25 +++++++++++++++---------- 10 | 2 files changed, 17 insertions(+), 10 deletions(-) 11 | 12 | diff --git a/config.def.h b/config.def.h 13 | index a2ac963..f0b739f 100644 14 | --- a/config.def.h 15 | +++ b/config.def.h 16 | @@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ 17 | static const unsigned int snap = 32; /* snap pixel */ 18 | static const int showbar = 1; /* 0 means no bar */ 19 | static const int topbar = 1; /* 0 means bottom bar */ 20 | +static const int vertpad = 10; /* vertical padding of bar */ 21 | +static const int sidepad = 10; /* horizontal padding of bar */ 22 | static const char *fonts[] = { "monospace:size=10" }; 23 | static const char dmenufont[] = "monospace:size=10"; 24 | static const char col_gray1[] = "#222222"; 25 | diff --git a/dwm.c b/dwm.c 26 | index 5e4d494..df6d0d7 100644 27 | --- a/dwm.c 28 | +++ b/dwm.c 29 | @@ -242,6 +242,8 @@ static int screen; 30 | static int sw, sh; /* X display screen geometry width, height */ 31 | static int bh, blw = 0; /* bar geometry */ 32 | static int lrpad; /* sum of left and right padding for text */ 33 | +static int vp; /* vertical padding for bar */ 34 | +static int sp; /* side padding for bar */ 35 | static int (*xerrorxlib)(Display *, XErrorEvent *); 36 | static unsigned int numlockmask = 0; 37 | static void (*handler[LASTEvent]) (XEvent *) = { 38 | @@ -568,7 +570,7 @@ configurenotify(XEvent *e) 39 | for (c = m->clients; c; c = c->next) 40 | if (c->isfullscreen) 41 | resizeclient(c, m->mx, m->my, m->mw, m->mh); 42 | - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); 43 | + XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); 44 | } 45 | focus(NULL); 46 | arrange(NULL); 47 | @@ -706,7 +708,7 @@ drawbar(Monitor *m) 48 | if (m == selmon) { /* status is only drawn on selected monitor */ 49 | drw_setscheme(drw, scheme[SchemeNorm]); 50 | tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ 51 | - drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); 52 | + drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); 53 | } 54 | 55 | for (c = m->clients; c; c = c->next) { 56 | @@ -732,12 +734,12 @@ drawbar(Monitor *m) 57 | if ((w = m->ww - tw - x) > bh) { 58 | if (m->sel) { 59 | drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 60 | - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 61 | + drw_text(drw, x, 0, w - 2 * sp, bh, lrpad / 2, m->sel->name, 0); 62 | if (m->sel->isfloating) 63 | drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 64 | } else { 65 | drw_setscheme(drw, scheme[SchemeNorm]); 66 | - drw_rect(drw, x, 0, w, bh, 1, 1); 67 | + drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); 68 | } 69 | } 70 | drw_map(drw, m->barwin, 0, 0, m->ww, bh); 71 | @@ -1547,7 +1549,10 @@ setup(void) 72 | die("no fonts could be loaded."); 73 | lrpad = drw->fonts->h; 74 | bh = drw->fonts->h + 2; 75 | + sp = sidepad; 76 | + vp = (topbar == 1) ? vertpad : - vertpad; 77 | updategeom(); 78 | + 79 | /* init atoms */ 80 | utf8string = XInternAtom(dpy, "UTF8_STRING", False); 81 | wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); 82 | @@ -1704,7 +1709,7 @@ togglebar(const Arg *arg) 83 | { 84 | selmon->showbar = !selmon->showbar; 85 | updatebarpos(selmon); 86 | - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); 87 | + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); 88 | arrange(selmon); 89 | } 90 | 91 | @@ -1814,7 +1819,7 @@ updatebars(void) 92 | for (m = mons; m; m = m->next) { 93 | if (m->barwin) 94 | continue; 95 | - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), 96 | + m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), 97 | CopyFromParent, DefaultVisual(dpy, screen), 98 | CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); 99 | XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); 100 | @@ -1829,11 +1834,11 @@ updatebarpos(Monitor *m) 101 | m->wy = m->my; 102 | m->wh = m->mh; 103 | if (m->showbar) { 104 | - m->wh -= bh; 105 | - m->by = m->topbar ? m->wy : m->wy + m->wh; 106 | - m->wy = m->topbar ? m->wy + bh : m->wy; 107 | + m->wh = m->wh - vertpad - bh; 108 | + m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; 109 | + m->wy = m->topbar ? m->wy + bh + vp : m->wy; 110 | } else 111 | - m->by = -bh; 112 | + m->by = -bh - vp; 113 | } 114 | 115 | void 116 | -- 117 | 2.33.0 118 | 119 | -------------------------------------------------------------------------------- /dwm/patches/dwm-fullgaps-6.4.diff: -------------------------------------------------------------------------------- 1 | diff -up a/config.def.h b/config.def.h 2 | --- a/config.def.h 3 | +++ b/config.def.h 4 | @@ -2,6 +2,7 @@ 5 | 6 | /* appearance */ 7 | static const unsigned int borderpx = 1; /* border pixel of windows */ 8 | +static const unsigned int gappx = 5; /* gaps between windows */ 9 | static const unsigned int snap = 32; /* snap pixel */ 10 | static const int showbar = 1; /* 0 means no bar */ 11 | static const int topbar = 1; /* 0 means bottom bar */ 12 | @@ -85,6 +86,9 @@ static const Key keys[] = { 13 | { MODKEY, XK_period, focusmon, {.i = +1 } }, 14 | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 15 | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 16 | + { MODKEY, XK_minus, setgaps, {.i = -1 } }, 17 | + { MODKEY, XK_equal, setgaps, {.i = +1 } }, 18 | + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, 19 | TAGKEYS( XK_1, 0) 20 | TAGKEYS( XK_2, 1) 21 | TAGKEYS( XK_3, 2) 22 | diff -up a/dwm.c b/dwm.c 23 | --- a/dwm.c 2023-04-30 24 | +++ b/dwm.c 2023-04-30 25 | @@ -119,6 +119,7 @@ struct Monitor { 26 | int by; /* bar geometry */ 27 | int mx, my, mw, mh; /* screen size */ 28 | int wx, wy, ww, wh; /* window area */ 29 | + int gappx; /* gaps between windows */ 30 | unsigned int seltags; 31 | unsigned int sellt; 32 | unsigned int tagset[2]; 33 | @@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor * 34 | static void setclientstate(Client *c, long state); 35 | static void setfocus(Client *c); 36 | static void setfullscreen(Client *c, int fullscreen); 37 | +static void setgaps(const Arg *arg); 38 | static void setlayout(const Arg *arg); 39 | static void setmfact(const Arg *arg); 40 | static void setup(void); 41 | @@ -641,6 +643,7 @@ createmon(void) 42 | m->nmaster = nmaster; 43 | m->showbar = showbar; 44 | m->topbar = topbar; 45 | + m->gappx = gappx; 46 | m->lt[0] = &layouts[0]; 47 | m->lt[1] = &layouts[1 % LENGTH(layouts)]; 48 | strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); 49 | @@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen) 50 | } 51 | 52 | void 53 | +setgaps(const Arg *arg) 54 | +{ 55 | + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) 56 | + selmon->gappx = 0; 57 | + else 58 | + selmon->gappx += arg->i; 59 | + arrange(selmon); 60 | +} 61 | + 62 | +void 63 | setlayout(const Arg *arg) 64 | { 65 | if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) 66 | @@ -1697,18 +1710,18 @@ tile(Monitor *m) 67 | if (n > m->nmaster) 68 | mw = m->nmaster ? m->ww * m->mfact : 0; 69 | else 70 | - mw = m->ww; 71 | - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 72 | - if (i < m->nmaster) { 73 | - h = (m->wh - my) / (MIN(n, m->nmaster) - i); 74 | - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); 75 | - if (my + HEIGHT(c) < m->wh) 76 | - my += HEIGHT(c); 77 | + mw = m->ww - m->gappx; 78 | + for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 79 | + if (i < m->nmaster) { 80 | + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; 81 | + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); 82 | + if (my + HEIGHT(c) + m->gappx < m->wh) 83 | + my += HEIGHT(c) + m->gappx; 84 | } else { 85 | - h = (m->wh - ty) / (n - i); 86 | - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); 87 | - if (ty + HEIGHT(c) < m->wh) 88 | - ty += HEIGHT(c); 89 | + h = (m->wh - ty) / (n - i) - m->gappx; 90 | + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); 91 | + if (ty + HEIGHT(c) + m->gappx < m->wh) 92 | + ty += HEIGHT(c) + m->gappx; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /dwm/patches/dwm-notitle-20210715-138b405.diff: -------------------------------------------------------------------------------- 1 | From a3a7e94f59553689656871a65ea9ce90169a7c91 Mon Sep 17 00:00:00 2001 2 | From: birdalicous 3 | Date: Thu, 15 Jul 2021 12:28:29 +0100 4 | Subject: [PATCH] notitle patch applied# 5 | 6 | --- 7 | config.def.h | 1 - 8 | dwm.c | 20 ++++---------------- 9 | 2 files changed, 4 insertions(+), 17 deletions(-) 10 | 11 | diff --git a/config.def.h b/config.def.h 12 | index a2ac963..eac20b4 100644 13 | --- a/config.def.h 14 | +++ b/config.def.h 15 | @@ -103,7 +103,6 @@ static Button buttons[] = { 16 | /* click event mask button function argument */ 17 | { ClkLtSymbol, 0, Button1, setlayout, {0} }, 18 | { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, 19 | - { ClkWinTitle, 0, Button2, zoom, {0} }, 20 | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 21 | { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 22 | { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, 23 | diff --git a/dwm.c b/dwm.c 24 | index 5e4d494..6cd9fb7 100644 25 | --- a/dwm.c 26 | +++ b/dwm.c 27 | @@ -64,8 +64,8 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 28 | NetWMFullscreen, NetActiveWindow, NetWMWindowType, 29 | NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 30 | enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 31 | -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 32 | - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 33 | +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, 34 | + ClkRootWin, ClkLast }; /* clicks */ 35 | 36 | typedef union { 37 | int i; 38 | @@ -440,10 +440,8 @@ buttonpress(XEvent *e) 39 | arg.ui = 1 << i; 40 | } else if (ev->x < x + blw) 41 | click = ClkLtSymbol; 42 | - else if (ev->x > selmon->ww - (int)TEXTW(stext)) 43 | - click = ClkStatusText; 44 | else 45 | - click = ClkWinTitle; 46 | + click = ClkStatusText; 47 | } else if ((c = wintoclient(ev->window))) { 48 | focus(c); 49 | restack(selmon); 50 | @@ -730,15 +728,8 @@ drawbar(Monitor *m) 51 | x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); 52 | 53 | if ((w = m->ww - tw - x) > bh) { 54 | - if (m->sel) { 55 | - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 56 | - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 57 | - if (m->sel->isfloating) 58 | - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 59 | - } else { 60 | drw_setscheme(drw, scheme[SchemeNorm]); 61 | drw_rect(drw, x, 0, w, bh, 1, 1); 62 | - } 63 | } 64 | drw_map(drw, m->barwin, 0, 0, m->ww, bh); 65 | } 66 | @@ -1236,11 +1227,8 @@ propertynotify(XEvent *e) 67 | drawbars(); 68 | break; 69 | } 70 | - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { 71 | + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) 72 | updatetitle(c); 73 | - if (c == c->mon->sel) 74 | - drawbar(c->mon); 75 | - } 76 | if (ev->atom == netatom[NetWMWindowType]) 77 | updatewindowtype(c); 78 | } 79 | -- 80 | 2.32.0 81 | 82 | -------------------------------------------------------------------------------- /dwm/patches/dwm-preserveonrestart-6.3.diff: -------------------------------------------------------------------------------- 1 | From 713fa8650f5a20006451ebcccf57a4512e83bae8 Mon Sep 17 00:00:00 2001 2 | From: Arda Atci 3 | Date: Wed, 18 May 2022 17:23:16 +0300 4 | Subject: [PATCH] preserve clients on old tags when renewing dwm 5 | 6 | --- 7 | dwm.c | 38 +++++++++++++++++++++++++++++++++++++- 8 | 1 file changed, 37 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/dwm.c b/dwm.c 11 | index 03baf42..b11eabc 100644 12 | --- a/dwm.c 13 | +++ b/dwm.c 14 | @@ -62,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 15 | enum { SchemeNorm, SchemeSel }; /* color schemes */ 16 | enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 17 | NetWMFullscreen, NetActiveWindow, NetWMWindowType, 18 | - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 19 | + NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */ 20 | enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 21 | enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 22 | ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 23 | @@ -198,6 +198,7 @@ static void scan(void); 24 | static int sendevent(Client *c, Atom proto); 25 | static void sendmon(Client *c, Monitor *m); 26 | static void setclientstate(Client *c, long state); 27 | +static void setclienttagprop(Client *c); 28 | static void setfocus(Client *c); 29 | static void setfullscreen(Client *c, int fullscreen); 30 | static void setlayout(const Arg *arg); 31 | @@ -1049,9 +1050,35 @@ manage(Window w, XWindowAttributes *wa) 32 | if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { 33 | c->mon = t->mon; 34 | c->tags = t->tags; 35 | + updatewindowtype(c); 36 | } else { 37 | c->mon = selmon; 38 | applyrules(c); 39 | + updatewindowtype(c); 40 | + { 41 | + int format; 42 | + unsigned long *data, n, extra; 43 | + Monitor *m; 44 | + Atom atom; 45 | + 46 | + if (XGetWindowProperty(dpy, c->win, netatom[NetClientInfo], 0L, 2L, False, XA_CARDINAL, 47 | + &atom, &format, &n, &extra, (unsigned char **)&data) == Success && n == 2) 48 | + { 49 | + c->tags = *data; 50 | + 51 | + for (m = mons; m; m = m->next) 52 | + { 53 | + if (m->num == *(data+1)) 54 | + { 55 | + c->mon = m; 56 | + break; 57 | + } 58 | + } 59 | + } 60 | + if (n > 0) 61 | + XFree(data); 62 | + } 63 | + setclienttagprop(c); 64 | } 65 | 66 | if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) 67 | @@ -1066,9 +1093,9 @@ manage(Window w, XWindowAttributes *wa) 68 | XConfigureWindow(dpy, w, CWBorderWidth, &wc); 69 | XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); 70 | configure(c); /* propagates border_width, if size doesn't change */ 71 | - updatewindowtype(c); 72 | updatesizehints(c); 73 | updatewmhints(c); 74 | + 75 | XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); 76 | grabbuttons(c, 0); 77 | if (!c->isfloating) 78 | @@ -1430,6 +1457,7 @@ sendmon(Client *c, Monitor *m) 79 | c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ 80 | attach(c); 81 | attachstack(c); 82 | + setclienttagprop(c); 83 | focus(NULL); 84 | arrange(NULL); 85 | } 86 | @@ -1573,6 +1601,7 @@ setup(void) 87 | netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); 88 | netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); 89 | netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); 90 | + netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False); 91 | /* init cursors */ 92 | cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); 93 | cursor[CurResize] = drw_cur_create(drw, XC_sizing); 94 | @@ -1596,6 +1625,7 @@ setup(void) 95 | XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, 96 | PropModeReplace, (unsigned char *) netatom, NetLast); 97 | XDeleteProperty(dpy, root, netatom[NetClientList]); 98 | + XDeleteProperty(dpy, root, netatom[NetClientInfo]); 99 | /* select events */ 100 | wa.cursor = cursor[CurNormal]->cursor; 101 | wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask 102 | @@ -1660,11 +1690,22 @@ spawn(const Arg *arg) 103 | } 104 | } 105 | 106 | +void 107 | +setclienttagprop(Client *c) 108 | +{ 109 | + long data[] = { (long) c->tags, (long) c->mon->num }; 110 | + XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32, 111 | + PropModeReplace, (unsigned char *) data, 2); 112 | +} 113 | + 114 | void 115 | tag(const Arg *arg) 116 | { 117 | + Client *c; 118 | if (selmon->sel && arg->ui & TAGMASK) { 119 | + c = selmon->sel; 120 | selmon->sel->tags = arg->ui & TAGMASK; 121 | + setclienttagprop(c); 122 | focus(NULL); 123 | arrange(selmon); 124 | } 125 | @@ -1739,6 +1780,7 @@ toggletag(const Arg *arg) 126 | newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); 127 | if (newtags) { 128 | selmon->sel->tags = newtags; 129 | + setclienttagprop(selmon->sel); 130 | focus(NULL); 131 | arrange(selmon); 132 | } 133 | -------------------------------------------------------------------------------- /dwm/patches/dwm-restartsig-20180523-6.2.diff: -------------------------------------------------------------------------------- 1 | From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 2 | From: Christopher Drelich 3 | Date: Wed, 23 May 2018 22:50:38 -0400 4 | Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM 5 | handlers. 6 | 7 | Modified quit() to restart if it receives arg .i = 1 8 | MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. 9 | 10 | Signal handlers were handled for SIGHUP and SIGTERM. 11 | If dwm receives these signals it calls quit() with 12 | arg .i = to 1 or 0, respectively. 13 | 14 | To restart dwm: 15 | MOD+CTRL+SHIFT+Q 16 | or 17 | kill -HUP dwmpid 18 | 19 | To quit dwm cleanly: 20 | MOD+SHIFT+Q 21 | or 22 | kill -TERM dwmpid 23 | --- 24 | config.def.h | 1 + 25 | dwm.1 | 10 ++++++++++ 26 | dwm.c | 22 ++++++++++++++++++++++ 27 | 3 files changed, 33 insertions(+) 28 | 29 | diff --git a/config.def.h b/config.def.h 30 | index a9ac303..e559429 100644 31 | --- a/config.def.h 32 | +++ b/config.def.h 33 | @@ -94,6 +94,7 @@ static Key keys[] = { 34 | TAGKEYS( XK_8, 7) 35 | TAGKEYS( XK_9, 8) 36 | { MODKEY|ShiftMask, XK_q, quit, {0} }, 37 | + { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, 38 | }; 39 | 40 | /* button definitions */ 41 | diff --git a/dwm.1 b/dwm.1 42 | index 13b3729..36a331c 100644 43 | --- a/dwm.1 44 | +++ b/dwm.1 45 | @@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. 46 | .TP 47 | .B Mod1\-Shift\-q 48 | Quit dwm. 49 | +.TP 50 | +.B Mod1\-Control\-Shift\-q 51 | +Restart dwm. 52 | .SS Mouse commands 53 | .TP 54 | .B Mod1\-Button1 55 | @@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float 56 | .SH CUSTOMIZATION 57 | dwm is customized by creating a custom config.h and (re)compiling the source 58 | code. This keeps it fast, secure and simple. 59 | +.SH SIGNALS 60 | +.TP 61 | +.B SIGHUP - 1 62 | +Restart the dwm process. 63 | +.TP 64 | +.B SIGTERM - 15 65 | +Cleanly terminate the dwm process. 66 | .SH SEE ALSO 67 | .BR dmenu (1), 68 | .BR st (1) 69 | diff --git a/dwm.c b/dwm.c 70 | index bb95e26..286eecd 100644 71 | --- a/dwm.c 72 | +++ b/dwm.c 73 | @@ -205,6 +205,8 @@ static void setup(void); 74 | static void seturgent(Client *c, int urg); 75 | static void showhide(Client *c); 76 | static void sigchld(int unused); 77 | +static void sighup(int unused); 78 | +static void sigterm(int unused); 79 | static void spawn(const Arg *arg); 80 | static void tag(const Arg *arg); 81 | static void tagmon(const Arg *arg); 82 | @@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { 83 | [UnmapNotify] = unmapnotify 84 | }; 85 | static Atom wmatom[WMLast], netatom[NetLast]; 86 | +static int restart = 0; 87 | static int running = 1; 88 | static Cur *cursor[CurLast]; 89 | static Clr **scheme; 90 | @@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) 91 | void 92 | quit(const Arg *arg) 93 | { 94 | + if(arg->i) restart = 1; 95 | running = 0; 96 | } 97 | 98 | @@ -1536,6 +1540,9 @@ setup(void) 99 | /* clean up any zombies immediately */ 100 | sigchld(0); 101 | 102 | + signal(SIGHUP, sighup); 103 | + signal(SIGTERM, sigterm); 104 | + 105 | /* init screen */ 106 | screen = DefaultScreen(dpy); 107 | sw = DisplayWidth(dpy, screen); 108 | @@ -1637,6 +1644,20 @@ sigchld(int unused) 109 | } 110 | 111 | void 112 | +sighup(int unused) 113 | +{ 114 | + Arg a = {.i = 1}; 115 | + quit(&a); 116 | +} 117 | + 118 | +void 119 | +sigterm(int unused) 120 | +{ 121 | + Arg a = {.i = 0}; 122 | + quit(&a); 123 | +} 124 | + 125 | +void 126 | spawn(const Arg *arg) 127 | { 128 | if (arg->v == dmenucmd) 129 | @@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) 130 | setup(); 131 | scan(); 132 | run(); 133 | + if(restart) execvp(argv[0], argv); 134 | cleanup(); 135 | XCloseDisplay(dpy); 136 | return EXIT_SUCCESS; 137 | -- 138 | 2.7.4 139 | 140 | -------------------------------------------------------------------------------- /dwm/patches/dwm-statusallmons-6.2.diff: -------------------------------------------------------------------------------- 1 | diff -up a/dwm.c b/dwm.c 2 | --- a/dwm.c 2020-07-09 16:49:10.023585649 +0200 3 | +++ b/dwm.c 2020-07-09 16:49:43.497542191 +0200 4 | @@ -702,7 +702,7 @@ drawbar(Monitor *m) 5 | Client *c; 6 | 7 | /* draw status first so it can be overdrawn by tags later */ 8 | - if (m == selmon) { /* status is only drawn on selected monitor */ 9 | + if (m == selmon || 1) { /* status is only drawn on selected monitor */ 10 | drw_setscheme(drw, scheme[SchemeNorm]); 11 | sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ 12 | drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); 13 | @@ -1987,9 +1987,11 @@ updatesizehints(Client *c) 14 | void 15 | updatestatus(void) 16 | { 17 | + Monitor* m; 18 | if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) 19 | strcpy(stext, "dwm-"VERSION); 20 | - drawbar(selmon); 21 | + for(m = mons; m; m = m->next) 22 | + drawbar(m); 23 | } 24 | 25 | void 26 | -------------------------------------------------------------------------------- /dwm/patches/dwm-warp-6.4.diff: -------------------------------------------------------------------------------- 1 | From a229c36f51ad6f8b40109ed53c643f242351962a Mon Sep 17 00:00:00 2001 2 | From: Jonas Dujava 3 | Date: Fri, 26 May 2023 22:14:48 +0200 4 | Subject: [PATCH] Warp patch 5 | 6 | Warps the mouse cursor to the center of the currently focused 7 | window or screen when the mouse cursor is 8 | (a) on a different screen, or 9 | (b) on top of a different window. 10 | 11 | This version properly handles warping to windows that have not been 12 | mapped yet (before it resulted in a change of the stack order). 13 | See the discussion in (thanks goes to Bakkeby): 14 | https://github.com/bakkeby/patches/issues/60 15 | --- 16 | dwm.c | 26 ++++++++++++++++++++++++++ 17 | 1 file changed, 26 insertions(+) 18 | 19 | diff --git a/dwm.c b/dwm.c 20 | index e5efb6a..7ea6c14 100644 21 | --- a/dwm.c 22 | +++ b/dwm.c 23 | @@ -228,6 +228,7 @@ static void updatetitle(Client *c); 24 | static void updatewindowtype(Client *c); 25 | static void updatewmhints(Client *c); 26 | static void view(const Arg *arg); 27 | +static void warp(const Client *c); 28 | static Client *wintoclient(Window w); 29 | static Monitor *wintomon(Window w); 30 | static int xerror(Display *dpy, XErrorEvent *ee); 31 | @@ -834,6 +835,7 @@ focusmon(const Arg *arg) 32 | unfocus(selmon->sel, 0); 33 | selmon = m; 34 | focus(NULL); 35 | + warp(selmon->sel); 36 | } 37 | 38 | void 39 | @@ -1366,6 +1368,8 @@ restack(Monitor *m) 40 | wc.sibling = c->win; 41 | } 42 | } 43 | + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) 44 | + warp(m->sel); 45 | XSync(dpy, False); 46 | while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 47 | } 48 | @@ -2044,6 +2048,28 @@ view(const Arg *arg) 49 | arrange(selmon); 50 | } 51 | 52 | +void 53 | +warp(const Client *c) 54 | +{ 55 | + int x, y; 56 | + 57 | + if (!c) { 58 | + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); 59 | + return; 60 | + } 61 | + 62 | + if (!getrootptr(&x, &y) || 63 | + (x > c->x - c->bw && 64 | + y > c->y - c->bw && 65 | + x < c->x + c->w + c->bw*2 && 66 | + y < c->y + c->h + c->bw*2) || 67 | + (y > c->mon->by && y < c->mon->by + bh) || 68 | + (c->mon->topbar && !y)) 69 | + return; 70 | + 71 | + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); 72 | +} 73 | + 74 | Client * 75 | wintoclient(Window w) 76 | { 77 | -- 78 | 2.40.1 79 | 80 | -------------------------------------------------------------------------------- /dwm/patches/dwm-xrdb-6.4.diff: -------------------------------------------------------------------------------- 1 | From e7c65d2ce902a19a20daa751b42f8ba0209fdb61 Mon Sep 17 00:00:00 2001 2 | From: NekoCWD 3 | Date: Sun, 22 Jan 2023 23:42:57 +0300 4 | Subject: [PATCH] [dwm] xrdb update 6.4 5 | 6 | --- 7 | config.def.h | 22 ++++++++++--------- 8 | drw.c | 2 +- 9 | drw.h | 2 +- 10 | dwm.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 11 | 4 files changed, 76 insertions(+), 12 deletions(-) 12 | 13 | diff --git a/config.def.h b/config.def.h 14 | index 061ad66..686b947 100644 15 | --- a/config.def.h 16 | +++ b/config.def.h 17 | @@ -7,15 +7,16 @@ static const int showbar = 1; /* 0 means no bar */ 18 | static const int topbar = 1; /* 0 means bottom bar */ 19 | static const char *fonts[] = { "monospace:size=10" }; 20 | static const char dmenufont[] = "monospace:size=10"; 21 | -static const char col_gray1[] = "#222222"; 22 | -static const char col_gray2[] = "#444444"; 23 | -static const char col_gray3[] = "#bbbbbb"; 24 | -static const char col_gray4[] = "#eeeeee"; 25 | -static const char col_cyan[] = "#005577"; 26 | -static const char *colors[][3] = { 27 | - /* fg bg border */ 28 | - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, 29 | - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, 30 | +static char normbgcolor[] = "#222222"; 31 | +static char normbordercolor[] = "#444444"; 32 | +static char normfgcolor[] = "#bbbbbb"; 33 | +static char selfgcolor[] = "#eeeeee"; 34 | +static char selbordercolor[] = "#005577"; 35 | +static char selbgcolor[] = "#005577"; 36 | +static char *colors[][3] = { 37 | + /* fg bg border */ 38 | + [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, 39 | + [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, 40 | }; 41 | 42 | /* tagging */ 43 | @@ -56,7 +57,7 @@ static const Layout layouts[] = { 44 | #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 45 | 46 | /* commands */ 47 | -static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; 48 | +static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; 49 | static const char *termcmd[] = { "st", NULL }; 50 | 51 | static const Key keys[] = { 52 | @@ -84,6 +85,7 @@ static const Key keys[] = { 53 | { MODKEY, XK_period, focusmon, {.i = +1 } }, 54 | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 55 | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 56 | + { MODKEY, XK_F5, xrdb, {.v = NULL } }, 57 | TAGKEYS( XK_1, 0) 58 | TAGKEYS( XK_2, 1) 59 | TAGKEYS( XK_3, 2) 60 | diff --git a/drw.c b/drw.c 61 | index a58a2b4..f8a82f5 100644 62 | --- a/drw.c 63 | +++ b/drw.c 64 | @@ -195,7 +195,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) 65 | /* Wrapper to create color schemes. The caller has to call free(3) on the 66 | * returned color scheme when done using it. */ 67 | Clr * 68 | -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) 69 | +drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount) 70 | { 71 | size_t i; 72 | Clr *ret; 73 | diff --git a/drw.h b/drw.h 74 | index 6471431..bdbf950 100644 75 | --- a/drw.h 76 | +++ b/drw.h 77 | @@ -40,7 +40,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in 78 | 79 | /* Colorscheme abstraction */ 80 | void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 81 | -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); 82 | +Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); 83 | 84 | /* Cursor abstraction */ 85 | Cur *drw_cur_create(Drw *drw, int shape); 86 | diff --git a/dwm.c b/dwm.c 87 | index e5efb6a..3fe76be 100644 88 | --- a/dwm.c 89 | +++ b/dwm.c 90 | @@ -35,6 +35,7 @@ 91 | #include 92 | #include 93 | #include 94 | +#include 95 | #include 96 | #ifdef XINERAMA 97 | #include 98 | @@ -56,6 +57,21 @@ 99 | #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 100 | #define TAGMASK ((1 << LENGTH(tags)) - 1) 101 | #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 102 | +#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ 103 | + if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ 104 | + int i = 1; \ 105 | + for (; i <= 6; i++) { \ 106 | + if (value.addr[i] < 48) break; \ 107 | + if (value.addr[i] > 57 && value.addr[i] < 65) break; \ 108 | + if (value.addr[i] > 70 && value.addr[i] < 97) break; \ 109 | + if (value.addr[i] > 102) break; \ 110 | + } \ 111 | + if (i == 7) { \ 112 | + strncpy(V, value.addr, 7); \ 113 | + V[7] = '\0'; \ 114 | + } \ 115 | + } \ 116 | + } 117 | 118 | /* enums */ 119 | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 120 | @@ -178,6 +194,7 @@ static void grabkeys(void); 121 | static void incnmaster(const Arg *arg); 122 | static void keypress(XEvent *e); 123 | static void killclient(const Arg *arg); 124 | +static void loadxrdb(void); 125 | static void manage(Window w, XWindowAttributes *wa); 126 | static void mappingnotify(XEvent *e); 127 | static void maprequest(XEvent *e); 128 | @@ -233,6 +250,7 @@ static Monitor *wintomon(Window w); 129 | static int xerror(Display *dpy, XErrorEvent *ee); 130 | static int xerrordummy(Display *dpy, XErrorEvent *ee); 131 | static int xerrorstart(Display *dpy, XErrorEvent *ee); 132 | +static void xrdb(const Arg *arg); 133 | static void zoom(const Arg *arg); 134 | 135 | /* variables */ 136 | @@ -1019,6 +1037,37 @@ killclient(const Arg *arg) 137 | } 138 | } 139 | 140 | +void 141 | +loadxrdb() 142 | +{ 143 | + Display *display; 144 | + char * resm; 145 | + XrmDatabase xrdb; 146 | + char *type; 147 | + XrmValue value; 148 | + 149 | + display = XOpenDisplay(NULL); 150 | + 151 | + if (display != NULL) { 152 | + resm = XResourceManagerString(display); 153 | + 154 | + if (resm != NULL) { 155 | + xrdb = XrmGetStringDatabase(resm); 156 | + 157 | + if (xrdb != NULL) { 158 | + XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); 159 | + XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); 160 | + XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); 161 | + XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); 162 | + XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); 163 | + XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); 164 | + } 165 | + } 166 | + } 167 | + 168 | + XCloseDisplay(display); 169 | +} 170 | + 171 | void 172 | manage(Window w, XWindowAttributes *wa) 173 | { 174 | @@ -2110,6 +2159,17 @@ xerrorstart(Display *dpy, XErrorEvent *ee) 175 | return -1; 176 | } 177 | 178 | +void 179 | +xrdb(const Arg *arg) 180 | +{ 181 | + loadxrdb(); 182 | + int i; 183 | + for (i = 0; i < LENGTH(colors); i++) 184 | + scheme[i] = drw_scm_create(drw, colors[i], 3); 185 | + focus(NULL); 186 | + arrange(NULL); 187 | +} 188 | + 189 | void 190 | zoom(const Arg *arg) 191 | { 192 | @@ -2134,6 +2194,8 @@ main(int argc, char *argv[]) 193 | if (!(dpy = XOpenDisplay(NULL))) 194 | die("dwm: cannot open display"); 195 | checkotherwm(); 196 | + XrmInitialize(); 197 | + loadxrdb(); 198 | setup(); 199 | #ifdef __OpenBSD__ 200 | if (pledge("stdio rpath proc exec", NULL) == -1) 201 | -- 202 | 2.38.2 203 | 204 | -------------------------------------------------------------------------------- /dwm/transient.c: -------------------------------------------------------------------------------- 1 | /* cc transient.c -o transient -lX11 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(void) { 9 | Display *d; 10 | Window r, f, t = None; 11 | XSizeHints h; 12 | XEvent e; 13 | 14 | d = XOpenDisplay(NULL); 15 | if (!d) 16 | exit(1); 17 | r = DefaultRootWindow(d); 18 | 19 | f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); 20 | h.min_width = h.max_width = h.min_height = h.max_height = 400; 21 | h.flags = PMinSize | PMaxSize; 22 | XSetWMNormalHints(d, f, &h); 23 | XStoreName(d, f, "floating"); 24 | XMapWindow(d, f); 25 | 26 | XSelectInput(d, f, ExposureMask); 27 | while (1) { 28 | XNextEvent(d, &e); 29 | 30 | if (t == None) { 31 | sleep(5); 32 | t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); 33 | XSetTransientForHint(d, t, f); 34 | XStoreName(d, t, "transient"); 35 | XMapWindow(d, t); 36 | XSelectInput(d, t, ExposureMask); 37 | } 38 | } 39 | 40 | XCloseDisplay(d); 41 | exit(0); 42 | } 43 | -------------------------------------------------------------------------------- /dwm/util.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | void 11 | die(const char *fmt, ...) 12 | { 13 | va_list ap; 14 | int saved_errno; 15 | 16 | saved_errno = errno; 17 | 18 | va_start(ap, fmt); 19 | vfprintf(stderr, fmt, ap); 20 | va_end(ap); 21 | 22 | if (fmt[0] && fmt[strlen(fmt)-1] == ':') 23 | fprintf(stderr, " %s", strerror(saved_errno)); 24 | fputc('\n', stderr); 25 | 26 | exit(1); 27 | } 28 | 29 | void * 30 | ecalloc(size_t nmemb, size_t size) 31 | { 32 | void *p; 33 | 34 | if (!(p = calloc(nmemb, size))) 35 | die("calloc:"); 36 | return p; 37 | } 38 | -------------------------------------------------------------------------------- /dwm/util.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) 4 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) 5 | #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) 6 | #define LENGTH(X) (sizeof (X) / sizeof (X)[0]) 7 | 8 | void die(const char *fmt, ...); 9 | void *ecalloc(size_t nmemb, size_t size); 10 | -------------------------------------------------------------------------------- /slstatus/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright 2016-2022 Aaron Marcher 4 | 5 | Copyright 2016 Roy Freytag 6 | Copyright 2016 Vincent Loupmon 7 | Copyright 2016 Daniel Walter 8 | Copyright 2016-2018 Ali H. Fardan 9 | Copyright 2016 Jody Leonard 10 | Copyright 2016-2018 Quentin Rameau 11 | Copyright 2016 Mike Coddington 12 | Copyright 2016-2018 Ivan J. 13 | Copyright 2017 Tobias Stoeckmann 14 | Copyright 2017-2018 Laslo Hunhold 15 | Copyright 2018 Darron Anderson 16 | Copyright 2018 Josuah Demangeon 17 | Copyright 2018 Tobias Tschinkowitz 18 | Copyright 2018 David Demelier 19 | Copyright 2018-2012 Michael Buch 20 | Copyright 2018 Ian Remmler 21 | Copyright 2016-2019 Joerg Jung 22 | Copyright 2019 Ryan Kes 23 | Copyright 2019 Cem Keylan 24 | Copyright 2019 Dimitris Papastamos 25 | Copyright 2019-2022 Ingo Feinerer 26 | Copyright 2020 Alexandre Ratchov 27 | Copyright 2020 Mart Lubbers 28 | Copyright 2020 Daniel Moch 29 | Copyright 2022 Nickolas Raymond Kaczynski 30 | Copyright 2022 Patrick Iacob 31 | Copyright 2021-2022 Steven Ward 32 | 33 | Permission to use, copy, modify, and/or distribute this software for any 34 | purpose with or without fee is hereby granted, provided that the above 35 | copyright notice and this permission notice appear in all copies. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 38 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 39 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 40 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 41 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 42 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 43 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44 | -------------------------------------------------------------------------------- /slstatus/Makefile: -------------------------------------------------------------------------------- 1 | # See LICENSE file for copyright and license details 2 | # slstatus - suckless status monitor 3 | .POSIX: 4 | 5 | include config.mk 6 | 7 | REQ = util 8 | COM =\ 9 | components/battery\ 10 | components/cat\ 11 | components/cpu\ 12 | components/datetime\ 13 | components/disk\ 14 | components/entropy\ 15 | components/hostname\ 16 | components/ip\ 17 | components/kernel_release\ 18 | components/keyboard_indicators\ 19 | components/keymap\ 20 | components/load_avg\ 21 | components/netspeeds\ 22 | components/num_files\ 23 | components/ram\ 24 | components/run_command\ 25 | components/swap\ 26 | components/temperature\ 27 | components/uptime\ 28 | components/user\ 29 | components/volume\ 30 | components/wifi 31 | 32 | all: slstatus 33 | 34 | $(COM:=.o): config.mk $(REQ:=.h) slstatus.h 35 | slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) 36 | 37 | .c.o: 38 | $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< 39 | 40 | config.h: 41 | cp config.def.h $@ 42 | 43 | slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) 44 | $(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) 45 | 46 | clean: 47 | rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz 48 | 49 | dist: 50 | rm -rf "slstatus-$(VERSION)" 51 | mkdir -p "slstatus-$(VERSION)/components" 52 | cp -R LICENSE Makefile README config.mk config.def.h \ 53 | arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ 54 | slstatus.1 "slstatus-$(VERSION)" 55 | cp -R $(COM:=.c) "slstatus-$(VERSION)/components" 56 | tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" 57 | rm -rf "slstatus-$(VERSION)" 58 | 59 | install: all 60 | mkdir -p "$(DESTDIR)$(PREFIX)/bin" 61 | cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" 62 | chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" 63 | mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" 64 | cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" 65 | chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" 66 | 67 | uninstall: 68 | rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" 69 | rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" 70 | -------------------------------------------------------------------------------- /slstatus/arg.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #ifndef ARG_H 3 | #define ARG_H 4 | 5 | extern char *argv0; 6 | 7 | /* int main(int argc, char *argv[]) */ 8 | #define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \ 9 | *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ 10 | int i_, argused_; \ 11 | if ((*argv)[1] == '-' && !(*argv)[2]) { \ 12 | argc--, argv++; \ 13 | break; \ 14 | } \ 15 | for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \ 16 | switch ((*argv)[i_]) 17 | #define ARGEND if (argused_) { \ 18 | if ((*argv)[i_ + 1]) { \ 19 | break; \ 20 | } else { \ 21 | argc--, argv++; \ 22 | break; \ 23 | } \ 24 | } \ 25 | } \ 26 | } 27 | #define ARGC() ((*argv)[i_]) 28 | #define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \ 29 | (*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x)) 30 | #define EARGF(x) ARGF_(((x), exit(1), (char *)0)) 31 | #define ARGF() ARGF_((char *)0) 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /slstatus/components/battery.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | #if defined(__linux__) 9 | /* 10 | * https://www.kernel.org/doc/html/latest/power/power_supply_class.html 11 | */ 12 | #include 13 | #include 14 | #include 15 | 16 | #define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" 17 | #define POWER_SUPPLY_STATUS "/sys/class/power_supply/%s/status" 18 | #define POWER_SUPPLY_CHARGE "/sys/class/power_supply/%s/charge_now" 19 | #define POWER_SUPPLY_ENERGY "/sys/class/power_supply/%s/energy_now" 20 | #define POWER_SUPPLY_CURRENT "/sys/class/power_supply/%s/current_now" 21 | #define POWER_SUPPLY_POWER "/sys/class/power_supply/%s/power_now" 22 | 23 | static const char * 24 | pick(const char *bat, const char *f1, const char *f2, char *path, 25 | size_t length) 26 | { 27 | if (esnprintf(path, length, f1, bat) > 0 && 28 | access(path, R_OK) == 0) 29 | return f1; 30 | 31 | if (esnprintf(path, length, f2, bat) > 0 && 32 | access(path, R_OK) == 0) 33 | return f2; 34 | 35 | return NULL; 36 | } 37 | 38 | const char * 39 | battery_perc(const char *bat) 40 | { 41 | int cap_perc; 42 | char path[PATH_MAX]; 43 | 44 | if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) 45 | return NULL; 46 | if (pscanf(path, "%d", &cap_perc) != 1) 47 | return NULL; 48 | 49 | return bprintf("%d", cap_perc); 50 | } 51 | 52 | const char * 53 | battery_state(const char *bat) 54 | { 55 | static struct { 56 | char *state; 57 | char *symbol; 58 | } map[] = { 59 | { "Charging", "󰚥" }, 60 | { "Discharging", "󰚦" }, 61 | { "Full", "󰚥" }, 62 | { "Not charging", "󰚥"}, 63 | }; 64 | size_t i; 65 | char path[PATH_MAX], state[12]; 66 | 67 | if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) 68 | return NULL; 69 | if (pscanf(path, "%12[a-zA-Z ]", state) != 1) 70 | return NULL; 71 | 72 | for (i = 0; i < LEN(map); i++) 73 | if (!strcmp(map[i].state, state)) 74 | break; 75 | 76 | return (i == LEN(map)) ? "?" : map[i].symbol; 77 | } 78 | 79 | const char * 80 | battery_remaining(const char *bat) 81 | { 82 | uintmax_t charge_now, current_now, m, h; 83 | double timeleft; 84 | char path[PATH_MAX], state[12]; 85 | 86 | if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) 87 | return NULL; 88 | if (pscanf(path, "%12[a-zA-Z ]", state) != 1) 89 | return NULL; 90 | 91 | if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, 92 | sizeof(path)) || 93 | pscanf(path, "%ju", &charge_now) < 0) 94 | return NULL; 95 | 96 | if (!strcmp(state, "Discharging")) { 97 | if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, 98 | sizeof(path)) || 99 | pscanf(path, "%ju", ¤t_now) < 0) 100 | return NULL; 101 | 102 | if (current_now == 0) 103 | return NULL; 104 | 105 | timeleft = (double)charge_now / (double)current_now; 106 | h = timeleft; 107 | m = (timeleft - (double)h) * 60; 108 | 109 | return bprintf("%juh %jum", h, m); 110 | } 111 | 112 | return ""; 113 | } 114 | #elif defined(__OpenBSD__) 115 | #include 116 | #include 117 | #include 118 | #include 119 | 120 | static int 121 | load_apm_power_info(struct apm_power_info *apm_info) 122 | { 123 | int fd; 124 | 125 | fd = open("/dev/apm", O_RDONLY); 126 | if (fd < 0) { 127 | warn("open '/dev/apm':"); 128 | return 0; 129 | } 130 | 131 | memset(apm_info, 0, sizeof(struct apm_power_info)); 132 | if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { 133 | warn("ioctl 'APM_IOC_GETPOWER':"); 134 | close(fd); 135 | return 0; 136 | } 137 | return close(fd), 1; 138 | } 139 | 140 | const char * 141 | battery_perc(const char *unused) 142 | { 143 | struct apm_power_info apm_info; 144 | 145 | if (load_apm_power_info(&apm_info)) 146 | return bprintf("%d", apm_info.battery_life); 147 | 148 | return NULL; 149 | } 150 | 151 | const char * 152 | battery_state(const char *unused) 153 | { 154 | struct { 155 | unsigned int state; 156 | char *symbol; 157 | } map[] = { 158 | { APM_AC_ON, "+" }, 159 | { APM_AC_OFF, "-" }, 160 | }; 161 | struct apm_power_info apm_info; 162 | size_t i; 163 | 164 | if (load_apm_power_info(&apm_info)) { 165 | for (i = 0; i < LEN(map); i++) 166 | if (map[i].state == apm_info.ac_state) 167 | break; 168 | 169 | return (i == LEN(map)) ? "?" : map[i].symbol; 170 | } 171 | 172 | return NULL; 173 | } 174 | 175 | const char * 176 | battery_remaining(const char *unused) 177 | { 178 | struct apm_power_info apm_info; 179 | unsigned int h, m; 180 | 181 | if (load_apm_power_info(&apm_info)) { 182 | if (apm_info.ac_state != APM_AC_ON) { 183 | h = apm_info.minutes_left / 60; 184 | m = apm_info.minutes_left % 60; 185 | return bprintf("%uh %02um", h, m); 186 | } else { 187 | return ""; 188 | } 189 | } 190 | 191 | return NULL; 192 | } 193 | #elif defined(__FreeBSD__) 194 | #include 195 | 196 | #define BATTERY_LIFE "hw.acpi.battery.life" 197 | #define BATTERY_STATE "hw.acpi.battery.state" 198 | #define BATTERY_TIME "hw.acpi.battery.time" 199 | 200 | const char * 201 | battery_perc(const char *unused) 202 | { 203 | int cap_perc; 204 | size_t len; 205 | 206 | len = sizeof(cap_perc); 207 | if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) 208 | return NULL; 209 | 210 | return bprintf("%d", cap_perc); 211 | } 212 | 213 | const char * 214 | battery_state(const char *unused) 215 | { 216 | int state; 217 | size_t len; 218 | 219 | len = sizeof(state); 220 | if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) 221 | return NULL; 222 | 223 | switch (state) { 224 | case 0: /* FALLTHROUGH */ 225 | case 2: 226 | return "+"; 227 | case 1: 228 | return "-"; 229 | default: 230 | return "?"; 231 | } 232 | } 233 | 234 | const char * 235 | battery_remaining(const char *unused) 236 | { 237 | int rem; 238 | size_t len; 239 | 240 | len = sizeof(rem); 241 | if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len 242 | || rem < 0) 243 | return NULL; 244 | 245 | return bprintf("%uh %02um", rem / 60, rem % 60); 246 | } 247 | #endif 248 | -------------------------------------------------------------------------------- /slstatus/components/cat.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | cat(const char *path) 10 | { 11 | char *f; 12 | FILE *fp; 13 | 14 | if (!(fp = fopen(path, "r"))) { 15 | warn("fopen '%s':", path); 16 | return NULL; 17 | } 18 | 19 | f = fgets(buf, sizeof(buf) - 1, fp); 20 | if (fclose(fp) < 0) { 21 | warn("fclose '%s':", path); 22 | return NULL; 23 | } 24 | if (!f) 25 | return NULL; 26 | 27 | if ((f = strrchr(buf, '\n'))) 28 | f[0] = '\0'; 29 | 30 | return buf[0] ? buf : NULL; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /slstatus/components/cpu.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../slstatus.h" 7 | #include "../util.h" 8 | 9 | #if defined(__linux__) 10 | #define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" 11 | 12 | const char * 13 | cpu_freq(const char *unused) 14 | { 15 | uintmax_t freq; 16 | 17 | /* in kHz */ 18 | if (pscanf(CPU_FREQ, "%ju", &freq) != 1) 19 | return NULL; 20 | 21 | return fmt_human(freq * 1000, 1000); 22 | } 23 | 24 | const char * 25 | cpu_perc(const char *unused) 26 | { 27 | static long double a[7]; 28 | long double b[7], sum; 29 | 30 | memcpy(b, a, sizeof(b)); 31 | /* cpu user nice system idle iowait irq softirq */ 32 | if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", 33 | &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) 34 | != 7) 35 | return NULL; 36 | 37 | if (b[0] == 0) 38 | return NULL; 39 | 40 | sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - 41 | (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); 42 | 43 | if (sum == 0) 44 | return NULL; 45 | 46 | return bprintf("%d", (int)(100 * 47 | ((b[0] + b[1] + b[2] + b[5] + b[6]) - 48 | (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); 49 | } 50 | #elif defined(__OpenBSD__) 51 | #include 52 | #include 53 | #include 54 | 55 | const char * 56 | cpu_freq(const char *unused) 57 | { 58 | int freq, mib[2]; 59 | size_t size; 60 | 61 | mib[0] = CTL_HW; 62 | mib[1] = HW_CPUSPEED; 63 | 64 | size = sizeof(freq); 65 | 66 | /* in MHz */ 67 | if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { 68 | warn("sysctl 'HW_CPUSPEED':"); 69 | return NULL; 70 | } 71 | 72 | return fmt_human(freq * 1E6, 1000); 73 | } 74 | 75 | const char * 76 | cpu_perc(const char *unused) 77 | { 78 | int mib[2]; 79 | static uintmax_t a[CPUSTATES]; 80 | uintmax_t b[CPUSTATES], sum; 81 | size_t size; 82 | 83 | mib[0] = CTL_KERN; 84 | mib[1] = KERN_CPTIME; 85 | 86 | size = sizeof(a); 87 | 88 | memcpy(b, a, sizeof(b)); 89 | if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { 90 | warn("sysctl 'KERN_CPTIME':"); 91 | return NULL; 92 | } 93 | if (b[0] == 0) 94 | return NULL; 95 | 96 | sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - 97 | (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); 98 | 99 | if (sum == 0) 100 | return NULL; 101 | 102 | return bprintf("%d", 100 * 103 | ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + 104 | a[CP_INTR]) - 105 | (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + 106 | b[CP_INTR])) / sum); 107 | } 108 | #elif defined(__FreeBSD__) 109 | #include 110 | #include 111 | #include 112 | 113 | const char * 114 | cpu_freq(const char *unused) 115 | { 116 | int freq; 117 | size_t size; 118 | 119 | size = sizeof(freq); 120 | /* in MHz */ 121 | if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { 122 | warn("sysctlbyname 'hw.clockrate':"); 123 | return NULL; 124 | } 125 | 126 | return fmt_human(freq * 1E6, 1000); 127 | } 128 | 129 | const char * 130 | cpu_perc(const char *unused) 131 | { 132 | size_t size; 133 | static long a[CPUSTATES]; 134 | long b[CPUSTATES], sum; 135 | 136 | size = sizeof(a); 137 | memcpy(b, a, sizeof(b)); 138 | if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { 139 | warn("sysctlbyname 'kern.cp_time':"); 140 | return NULL; 141 | } 142 | if (b[0] == 0) 143 | return NULL; 144 | 145 | sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - 146 | (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); 147 | 148 | if (sum == 0) 149 | return NULL; 150 | 151 | return bprintf("%d", 100 * 152 | ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + 153 | a[CP_INTR]) - 154 | (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + 155 | b[CP_INTR])) / sum); 156 | } 157 | #endif 158 | -------------------------------------------------------------------------------- /slstatus/components/datetime.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | datetime(const char *fmt) 10 | { 11 | time_t t; 12 | 13 | t = time(NULL); 14 | if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { 15 | warn("strftime: Result string exceeds buffer size"); 16 | return NULL; 17 | } 18 | 19 | return buf; 20 | } 21 | -------------------------------------------------------------------------------- /slstatus/components/disk.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | disk_free(const char *path) 10 | { 11 | struct statvfs fs; 12 | 13 | if (statvfs(path, &fs) < 0) { 14 | warn("statvfs '%s':", path); 15 | return NULL; 16 | } 17 | 18 | return fmt_human(fs.f_frsize * fs.f_bavail, 1024); 19 | } 20 | 21 | const char * 22 | disk_perc(const char *path) 23 | { 24 | struct statvfs fs; 25 | 26 | if (statvfs(path, &fs) < 0) { 27 | warn("statvfs '%s':", path); 28 | return NULL; 29 | } 30 | 31 | return bprintf("%d", (int)(100 * 32 | (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); 33 | } 34 | 35 | const char * 36 | disk_total(const char *path) 37 | { 38 | struct statvfs fs; 39 | 40 | if (statvfs(path, &fs) < 0) { 41 | warn("statvfs '%s':", path); 42 | return NULL; 43 | } 44 | 45 | return fmt_human(fs.f_frsize * fs.f_blocks, 1024); 46 | } 47 | 48 | const char * 49 | disk_used(const char *path) 50 | { 51 | struct statvfs fs; 52 | 53 | if (statvfs(path, &fs) < 0) { 54 | warn("statvfs '%s':", path); 55 | return NULL; 56 | } 57 | 58 | return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); 59 | } 60 | -------------------------------------------------------------------------------- /slstatus/components/entropy.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include "../slstatus.h" 3 | #if defined(__linux__) 4 | #include 5 | #include 6 | 7 | #include "../util.h" 8 | 9 | #define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" 10 | 11 | const char * 12 | entropy(const char *unused) 13 | { 14 | uintmax_t num; 15 | 16 | if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) 17 | return NULL; 18 | 19 | return bprintf("%ju", num); 20 | } 21 | #elif defined(__OpenBSD__) | defined(__FreeBSD__) 22 | const char * 23 | entropy(const char *unused) 24 | { 25 | // https://www.unicode.org/charts/PDF/U2200.pdf 26 | /* Unicode Character 'INFINITY' (U+221E) */ 27 | return "\u221E"; 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /slstatus/components/hostname.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | hostname(const char *unused) 10 | { 11 | if (gethostname(buf, sizeof(buf)) < 0) { 12 | warn("gethostbyname:"); 13 | return NULL; 14 | } 15 | 16 | return buf; 17 | } 18 | -------------------------------------------------------------------------------- /slstatus/components/ip.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #if defined(__OpenBSD__) 7 | #include 8 | #include 9 | #elif defined(__FreeBSD__) 10 | #include 11 | #include 12 | #endif 13 | 14 | #include "../slstatus.h" 15 | #include "../util.h" 16 | 17 | static const char * 18 | ip(const char *interface, unsigned short sa_family) 19 | { 20 | struct ifaddrs *ifaddr, *ifa; 21 | int s; 22 | char host[NI_MAXHOST]; 23 | 24 | if (getifaddrs(&ifaddr) < 0) { 25 | warn("getifaddrs:"); 26 | return NULL; 27 | } 28 | 29 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { 30 | if (!ifa->ifa_addr) 31 | continue; 32 | 33 | s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), 34 | host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); 35 | if (!strcmp(ifa->ifa_name, interface) && 36 | (ifa->ifa_addr->sa_family == sa_family)) { 37 | freeifaddrs(ifaddr); 38 | if (s != 0) { 39 | warn("getnameinfo: %s", gai_strerror(s)); 40 | return NULL; 41 | } 42 | return bprintf("%s", host); 43 | } 44 | } 45 | 46 | freeifaddrs(ifaddr); 47 | 48 | return NULL; 49 | } 50 | 51 | const char * 52 | ipv4(const char *interface) 53 | { 54 | return ip(interface, AF_INET); 55 | } 56 | 57 | const char * 58 | ipv6(const char *interface) 59 | { 60 | return ip(interface, AF_INET6); 61 | } 62 | -------------------------------------------------------------------------------- /slstatus/components/kernel_release.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | kernel_release(const char *unused) 10 | { 11 | struct utsname udata; 12 | 13 | if (uname(&udata) < 0) { 14 | warn("uname:"); 15 | return NULL; 16 | } 17 | 18 | return bprintf("%s", udata.release); 19 | } 20 | -------------------------------------------------------------------------------- /slstatus/components/keyboard_indicators.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../slstatus.h" 8 | #include "../util.h" 9 | 10 | /* 11 | * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num 12 | * lock, each optionally followed by '?', in the order of indicators desired. 13 | * If followed by '?', the letter with case preserved is included in the output 14 | * if the corresponding indicator is on. Otherwise, the letter is always 15 | * included, lowercase when off and uppercase when on. 16 | */ 17 | const char * 18 | keyboard_indicators(const char *fmt) 19 | { 20 | Display *dpy; 21 | XKeyboardState state; 22 | size_t fmtlen, i, n; 23 | int togglecase, isset; 24 | char key; 25 | 26 | if (!(dpy = XOpenDisplay(NULL))) { 27 | warn("XOpenDisplay: Failed to open display"); 28 | return NULL; 29 | } 30 | XGetKeyboardControl(dpy, &state); 31 | XCloseDisplay(dpy); 32 | 33 | fmtlen = strnlen(fmt, 4); 34 | for (i = n = 0; i < fmtlen; i++) { 35 | key = tolower(fmt[i]); 36 | if (key != 'c' && key != 'n') 37 | continue; 38 | 39 | togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); 40 | isset = (state.led_mask & (1 << (key == 'n'))); 41 | 42 | if (togglecase) 43 | buf[n++] = isset ? toupper(key) : key; 44 | else if (isset) 45 | buf[n++] = fmt[i]; 46 | } 47 | 48 | buf[n] = 0; 49 | return buf; 50 | } 51 | -------------------------------------------------------------------------------- /slstatus/components/keymap.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../slstatus.h" 9 | #include "../util.h" 10 | 11 | static int 12 | valid_layout_or_variant(char *sym) 13 | { 14 | size_t i; 15 | /* invalid symbols from xkb rules config */ 16 | static const char *invalid[] = { "evdev", "inet", "pc", "base" }; 17 | 18 | for (i = 0; i < LEN(invalid); i++) 19 | if (!strncmp(sym, invalid[i], strlen(invalid[i]))) 20 | return 0; 21 | 22 | return 1; 23 | } 24 | 25 | static char * 26 | get_layout(char *syms, int grp_num) 27 | { 28 | char *tok, *layout; 29 | int grp; 30 | 31 | layout = NULL; 32 | tok = strtok(syms, "+:"); 33 | for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) { 34 | if (!valid_layout_or_variant(tok)) { 35 | continue; 36 | } else if (strlen(tok) == 1 && isdigit(tok[0])) { 37 | /* ignore :2, :3, :4 (additional layout groups) */ 38 | continue; 39 | } 40 | layout = tok; 41 | grp++; 42 | } 43 | 44 | return layout; 45 | } 46 | 47 | const char * 48 | keymap(const char *unused) 49 | { 50 | Display *dpy; 51 | XkbDescRec *desc; 52 | XkbStateRec state; 53 | char *symbols; 54 | const char *layout; 55 | 56 | layout = NULL; 57 | 58 | if (!(dpy = XOpenDisplay(NULL))) { 59 | warn("XOpenDisplay: Failed to open display"); 60 | return NULL; 61 | } 62 | if (!(desc = XkbAllocKeyboard())) { 63 | warn("XkbAllocKeyboard: Failed to allocate keyboard"); 64 | goto end; 65 | } 66 | if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { 67 | warn("XkbGetNames: Failed to retrieve key symbols"); 68 | goto end; 69 | } 70 | if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { 71 | warn("XkbGetState: Failed to retrieve keyboard state"); 72 | goto end; 73 | } 74 | if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { 75 | warn("XGetAtomName: Failed to get atom name"); 76 | goto end; 77 | } 78 | layout = bprintf("%s", get_layout(symbols, state.group)); 79 | XFree(symbols); 80 | end: 81 | XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); 82 | if (XCloseDisplay(dpy)) 83 | warn("XCloseDisplay: Failed to close display"); 84 | 85 | return layout; 86 | } 87 | -------------------------------------------------------------------------------- /slstatus/components/load_avg.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | load_avg(const char *unused) 10 | { 11 | double avgs[3]; 12 | 13 | if (getloadavg(avgs, 3) < 0) { 14 | warn("getloadavg: Failed to obtain load average"); 15 | return NULL; 16 | } 17 | 18 | return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); 19 | } 20 | -------------------------------------------------------------------------------- /slstatus/components/netspeeds.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | #if defined(__linux__) 9 | #include 10 | 11 | #define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" 12 | #define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" 13 | 14 | const char * 15 | netspeed_rx(const char *interface) 16 | { 17 | uintmax_t oldrxbytes; 18 | static uintmax_t rxbytes; 19 | extern const unsigned int interval; 20 | char path[PATH_MAX]; 21 | 22 | oldrxbytes = rxbytes; 23 | 24 | if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) 25 | return NULL; 26 | if (pscanf(path, "%ju", &rxbytes) != 1) 27 | return NULL; 28 | if (oldrxbytes == 0) 29 | return NULL; 30 | 31 | return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, 32 | 1024); 33 | } 34 | 35 | const char * 36 | netspeed_tx(const char *interface) 37 | { 38 | uintmax_t oldtxbytes; 39 | static uintmax_t txbytes; 40 | extern const unsigned int interval; 41 | char path[PATH_MAX]; 42 | 43 | oldtxbytes = txbytes; 44 | 45 | if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) 46 | return NULL; 47 | if (pscanf(path, "%ju", &txbytes) != 1) 48 | return NULL; 49 | if (oldtxbytes == 0) 50 | return NULL; 51 | 52 | return fmt_human((txbytes - oldtxbytes) * 1000 / interval, 53 | 1024); 54 | } 55 | #elif defined(__OpenBSD__) | defined(__FreeBSD__) 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | 62 | const char * 63 | netspeed_rx(const char *interface) 64 | { 65 | struct ifaddrs *ifal, *ifa; 66 | struct if_data *ifd; 67 | uintmax_t oldrxbytes; 68 | static uintmax_t rxbytes; 69 | extern const unsigned int interval; 70 | int if_ok = 0; 71 | 72 | oldrxbytes = rxbytes; 73 | 74 | if (getifaddrs(&ifal) < 0) { 75 | warn("getifaddrs failed"); 76 | return NULL; 77 | } 78 | rxbytes = 0; 79 | for (ifa = ifal; ifa; ifa = ifa->ifa_next) 80 | if (!strcmp(ifa->ifa_name, interface) && 81 | (ifd = (struct if_data *)ifa->ifa_data)) 82 | rxbytes += ifd->ifi_ibytes, if_ok = 1; 83 | 84 | freeifaddrs(ifal); 85 | if (!if_ok) { 86 | warn("reading 'if_data' failed"); 87 | return NULL; 88 | } 89 | if (oldrxbytes == 0) 90 | return NULL; 91 | 92 | return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, 93 | 1024); 94 | } 95 | 96 | const char * 97 | netspeed_tx(const char *interface) 98 | { 99 | struct ifaddrs *ifal, *ifa; 100 | struct if_data *ifd; 101 | uintmax_t oldtxbytes; 102 | static uintmax_t txbytes; 103 | extern const unsigned int interval; 104 | int if_ok = 0; 105 | 106 | oldtxbytes = txbytes; 107 | 108 | if (getifaddrs(&ifal) < 0) { 109 | warn("getifaddrs failed"); 110 | return NULL; 111 | } 112 | txbytes = 0; 113 | for (ifa = ifal; ifa; ifa = ifa->ifa_next) 114 | if (!strcmp(ifa->ifa_name, interface) && 115 | (ifd = (struct if_data *)ifa->ifa_data)) 116 | txbytes += ifd->ifi_obytes, if_ok = 1; 117 | 118 | freeifaddrs(ifal); 119 | if (!if_ok) { 120 | warn("reading 'if_data' failed"); 121 | return NULL; 122 | } 123 | if (oldtxbytes == 0) 124 | return NULL; 125 | 126 | return fmt_human((txbytes - oldtxbytes) * 1000 / interval, 127 | 1024); 128 | } 129 | #endif 130 | -------------------------------------------------------------------------------- /slstatus/components/num_files.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../slstatus.h" 7 | #include "../util.h" 8 | 9 | const char * 10 | num_files(const char *path) 11 | { 12 | struct dirent *dp; 13 | DIR *dir; 14 | int num; 15 | 16 | if (!(dir = opendir(path))) { 17 | warn("opendir '%s':", path); 18 | return NULL; 19 | } 20 | 21 | num = 0; 22 | while ((dp = readdir(dir))) { 23 | if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 24 | continue; /* skip self and parent */ 25 | 26 | num++; 27 | } 28 | 29 | closedir(dir); 30 | 31 | return bprintf("%d", num); 32 | } 33 | -------------------------------------------------------------------------------- /slstatus/components/pixVol.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | volume=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -n 1 | tr -d '%') 4 | muted=$(pactl get-sink-mute @DEFAULT_SINK@ | awk '{print $2}') 5 | 6 | if [ "$muted" = "yes" ]; then 7 | echo "Muted" 8 | else 9 | echo "${volume}" 10 | fi 11 | -------------------------------------------------------------------------------- /slstatus/components/ram.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../slstatus.h" 5 | #include "../util.h" 6 | 7 | #if defined(__linux__) 8 | #include 9 | 10 | const char * 11 | ram_free(const char *unused) 12 | { 13 | uintmax_t free; 14 | 15 | if (pscanf("/proc/meminfo", 16 | "MemTotal: %ju kB\n" 17 | "MemFree: %ju kB\n" 18 | "MemAvailable: %ju kB\n", 19 | &free, &free, &free) != 3) 20 | return NULL; 21 | 22 | return fmt_human(free * 1024, 1024); 23 | } 24 | 25 | const char * 26 | ram_perc(const char *unused) 27 | { 28 | uintmax_t total, free, buffers, cached; 29 | int percent; 30 | 31 | if (pscanf("/proc/meminfo", 32 | "MemTotal: %ju kB\n" 33 | "MemFree: %ju kB\n" 34 | "MemAvailable: %ju kB\n" 35 | "Buffers: %ju kB\n" 36 | "Cached: %ju kB\n", 37 | &total, &free, &buffers, &buffers, &cached) != 5) 38 | return NULL; 39 | 40 | if (total == 0) 41 | return NULL; 42 | 43 | percent = 100 * ((total - free) - (buffers + cached)) / total; 44 | return bprintf("%d", percent); 45 | } 46 | 47 | const char * 48 | ram_total(const char *unused) 49 | { 50 | uintmax_t total; 51 | 52 | if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) 53 | != 1) 54 | return NULL; 55 | 56 | return fmt_human(total * 1024, 1024); 57 | } 58 | 59 | const char * 60 | ram_used(const char *unused) 61 | { 62 | uintmax_t total, free, buffers, cached, used; 63 | 64 | if (pscanf("/proc/meminfo", 65 | "MemTotal: %ju kB\n" 66 | "MemFree: %ju kB\n" 67 | "MemAvailable: %ju kB\n" 68 | "Buffers: %ju kB\n" 69 | "Cached: %ju kB\n", 70 | &total, &free, &buffers, &buffers, &cached) != 5) 71 | return NULL; 72 | 73 | used = (total - free - buffers - cached); 74 | return fmt_human(used * 1024, 1024); 75 | } 76 | #elif defined(__OpenBSD__) 77 | #include 78 | #include 79 | #include 80 | #include 81 | 82 | #define LOG1024 10 83 | #define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024)) 84 | 85 | inline int 86 | load_uvmexp(struct uvmexp *uvmexp) 87 | { 88 | int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; 89 | size_t size; 90 | 91 | size = sizeof(*uvmexp); 92 | 93 | if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0) 94 | return 1; 95 | 96 | return 0; 97 | } 98 | 99 | const char * 100 | ram_free(const char *unused) 101 | { 102 | struct uvmexp uvmexp; 103 | int free_pages; 104 | 105 | if (!load_uvmexp(&uvmexp)) 106 | return NULL; 107 | 108 | free_pages = uvmexp.npages - uvmexp.active; 109 | return fmt_human(pagetok(free_pages, uvmexp.pageshift) * 110 | 1024, 1024); 111 | } 112 | 113 | const char * 114 | ram_perc(const char *unused) 115 | { 116 | struct uvmexp uvmexp; 117 | int percent; 118 | 119 | if (!load_uvmexp(&uvmexp)) 120 | return NULL; 121 | 122 | percent = uvmexp.active * 100 / uvmexp.npages; 123 | return bprintf("%d", percent); 124 | } 125 | 126 | const char * 127 | ram_total(const char *unused) 128 | { 129 | struct uvmexp uvmexp; 130 | 131 | if (!load_uvmexp(&uvmexp)) 132 | return NULL; 133 | 134 | return fmt_human(pagetok(uvmexp.npages, 135 | uvmexp.pageshift) * 1024, 1024); 136 | } 137 | 138 | const char * 139 | ram_used(const char *unused) 140 | { 141 | struct uvmexp uvmexp; 142 | 143 | if (!load_uvmexp(&uvmexp)) 144 | return NULL; 145 | 146 | return fmt_human(pagetok(uvmexp.active, 147 | uvmexp.pageshift) * 1024, 1024); 148 | } 149 | #elif defined(__FreeBSD__) 150 | #include 151 | #include 152 | #include 153 | #include 154 | 155 | const char * 156 | ram_free(const char *unused) { 157 | struct vmtotal vm_stats; 158 | int mib[] = {CTL_VM, VM_TOTAL}; 159 | size_t len; 160 | 161 | len = sizeof(struct vmtotal); 162 | if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 163 | || !len) 164 | return NULL; 165 | 166 | return fmt_human(vm_stats.t_free * getpagesize(), 1024); 167 | } 168 | 169 | const char * 170 | ram_total(const char *unused) { 171 | unsigned int npages; 172 | size_t len; 173 | 174 | len = sizeof(npages); 175 | if (sysctlbyname("vm.stats.vm.v_page_count", 176 | &npages, &len, NULL, 0) < 0 || !len) 177 | return NULL; 178 | 179 | return fmt_human(npages * getpagesize(), 1024); 180 | } 181 | 182 | const char * 183 | ram_perc(const char *unused) { 184 | unsigned int npages; 185 | unsigned int active; 186 | size_t len; 187 | 188 | len = sizeof(npages); 189 | if (sysctlbyname("vm.stats.vm.v_page_count", 190 | &npages, &len, NULL, 0) < 0 || !len) 191 | return NULL; 192 | 193 | if (sysctlbyname("vm.stats.vm.v_active_count", 194 | &active, &len, NULL, 0) < 0 || !len) 195 | return NULL; 196 | 197 | return bprintf("%d", active * 100 / npages); 198 | } 199 | 200 | const char * 201 | ram_used(const char *unused) { 202 | unsigned int active; 203 | size_t len; 204 | 205 | len = sizeof(active); 206 | if (sysctlbyname("vm.stats.vm.v_active_count", 207 | &active, &len, NULL, 0) < 0 || !len) 208 | return NULL; 209 | 210 | return fmt_human(active * getpagesize(), 1024); 211 | } 212 | #endif 213 | -------------------------------------------------------------------------------- /slstatus/components/run_command.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../slstatus.h" 6 | #include "../util.h" 7 | 8 | const char * 9 | run_command(const char *cmd) 10 | { 11 | char *p; 12 | FILE *fp; 13 | 14 | if (!(fp = popen(cmd, "r"))) { 15 | warn("popen '%s':", cmd); 16 | return NULL; 17 | } 18 | 19 | p = fgets(buf, sizeof(buf) - 1, fp); 20 | if (pclose(fp) < 0) { 21 | warn("pclose '%s':", cmd); 22 | return NULL; 23 | } 24 | if (!p) 25 | return NULL; 26 | 27 | if ((p = strrchr(buf, '\n'))) 28 | p[0] = '\0'; 29 | 30 | return buf[0] ? buf : NULL; 31 | } 32 | -------------------------------------------------------------------------------- /slstatus/components/swap.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../slstatus.h" 8 | #include "../util.h" 9 | 10 | #if defined(__linux__) 11 | static int 12 | get_swap_info(long *s_total, long *s_free, long *s_cached) 13 | { 14 | FILE *fp; 15 | struct { 16 | const char *name; 17 | const size_t len; 18 | long *var; 19 | } ent[] = { 20 | { "SwapTotal", sizeof("SwapTotal") - 1, s_total }, 21 | { "SwapFree", sizeof("SwapFree") - 1, s_free }, 22 | { "SwapCached", sizeof("SwapCached") - 1, s_cached }, 23 | }; 24 | size_t line_len = 0, i, left; 25 | char *line = NULL; 26 | 27 | /* get number of fields we want to extract */ 28 | for (i = 0, left = 0; i < LEN(ent); i++) 29 | if (ent[i].var) 30 | left++; 31 | 32 | if (!(fp = fopen("/proc/meminfo", "r"))) { 33 | warn("fopen '/proc/meminfo':"); 34 | return 1; 35 | } 36 | 37 | /* read file line by line and extract field information */ 38 | while (left > 0 && getline(&line, &line_len, fp) >= 0) { 39 | for (i = 0; i < LEN(ent); i++) { 40 | if (ent[i].var && 41 | !strncmp(line, ent[i].name, ent[i].len)) { 42 | sscanf(line + ent[i].len + 1, 43 | "%ld kB\n", ent[i].var); 44 | left--; 45 | break; 46 | } 47 | } 48 | } 49 | free(line); 50 | if (ferror(fp)) { 51 | warn("getline '/proc/meminfo':"); 52 | return 1; 53 | } 54 | 55 | fclose(fp); 56 | return 0; 57 | } 58 | 59 | const char * 60 | swap_free(const char *unused) 61 | { 62 | long free; 63 | 64 | if (get_swap_info(NULL, &free, NULL)) 65 | return NULL; 66 | 67 | return fmt_human(free * 1024, 1024); 68 | } 69 | 70 | const char * 71 | swap_perc(const char *unused) 72 | { 73 | long total, free, cached; 74 | 75 | if (get_swap_info(&total, &free, &cached) || total == 0) 76 | return NULL; 77 | 78 | return bprintf("%d", 100 * (total - free - cached) / total); 79 | } 80 | 81 | const char * 82 | swap_total(const char *unused) 83 | { 84 | long total; 85 | 86 | if (get_swap_info(&total, NULL, NULL)) 87 | return NULL; 88 | 89 | return fmt_human(total * 1024, 1024); 90 | } 91 | 92 | const char * 93 | swap_used(const char *unused) 94 | { 95 | long total, free, cached; 96 | 97 | if (get_swap_info(&total, &free, &cached)) 98 | return NULL; 99 | 100 | return fmt_human((total - free - cached) * 1024, 1024); 101 | } 102 | #elif defined(__OpenBSD__) 103 | #include 104 | #include 105 | #include 106 | #include 107 | 108 | static int 109 | getstats(int *total, int *used) 110 | { 111 | struct swapent *sep, *fsep; 112 | int rnswap, nswap, i; 113 | 114 | if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) { 115 | warn("swaptctl 'SWAP_NSWAP':"); 116 | return 1; 117 | } 118 | if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) { 119 | warn("calloc 'nswap':"); 120 | return 1; 121 | } 122 | if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) { 123 | warn("swapctl 'SWAP_STATA':"); 124 | return 1; 125 | } 126 | if (nswap != rnswap) { 127 | warn("getstats: SWAP_STATS != SWAP_NSWAP"); 128 | return 1; 129 | } 130 | 131 | *total = 0; 132 | *used = 0; 133 | 134 | for (i = 0; i < rnswap; i++) { 135 | *total += sep->se_nblks >> 1; 136 | *used += sep->se_inuse >> 1; 137 | } 138 | 139 | free(fsep); 140 | 141 | return 0; 142 | } 143 | 144 | const char * 145 | swap_free(const char *unused) 146 | { 147 | int total, used; 148 | 149 | if (getstats(&total, &used)) 150 | return NULL; 151 | 152 | return fmt_human((total - used) * 1024, 1024); 153 | } 154 | 155 | const char * 156 | swap_perc(const char *unused) 157 | { 158 | int total, used; 159 | 160 | if (getstats(&total, &used)) 161 | return NULL; 162 | 163 | if (total == 0) 164 | return NULL; 165 | 166 | return bprintf("%d", 100 * used / total); 167 | } 168 | 169 | const char * 170 | swap_total(const char *unused) 171 | { 172 | int total, used; 173 | 174 | if (getstats(&total, &used)) 175 | return NULL; 176 | 177 | return fmt_human(total * 1024, 1024); 178 | } 179 | 180 | const char * 181 | swap_used(const char *unused) 182 | { 183 | int total, used; 184 | 185 | if (getstats(&total, &used)) 186 | return NULL; 187 | 188 | return fmt_human(used * 1024, 1024); 189 | } 190 | #elif defined(__FreeBSD__) 191 | #include 192 | #include 193 | #include 194 | #include 195 | #include 196 | 197 | static int getswapinfo(struct kvm_swap *swap_info, size_t size) 198 | { 199 | kvm_t *kd; 200 | 201 | kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL); 202 | if (kd == NULL) { 203 | warn("kvm_openfiles '/dev/null':"); 204 | return 0; 205 | } 206 | 207 | if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) { 208 | warn("kvm_getswapinfo:"); 209 | kvm_close(kd); 210 | return 0; 211 | } 212 | 213 | kvm_close(kd); 214 | return 1; 215 | } 216 | 217 | const char * 218 | swap_free(const char *unused) 219 | { 220 | struct kvm_swap swap_info[1]; 221 | long used, total; 222 | 223 | if (!getswapinfo(swap_info, 1)) 224 | return NULL; 225 | 226 | total = swap_info[0].ksw_total; 227 | used = swap_info[0].ksw_used; 228 | 229 | return fmt_human((total - used) * getpagesize(), 1024); 230 | } 231 | 232 | const char * 233 | swap_perc(const char *unused) 234 | { 235 | struct kvm_swap swap_info[1]; 236 | long used, total; 237 | 238 | if (!getswapinfo(swap_info, 1)) 239 | return NULL; 240 | 241 | total = swap_info[0].ksw_total; 242 | used = swap_info[0].ksw_used; 243 | 244 | return bprintf("%d", used * 100 / total); 245 | } 246 | 247 | const char * 248 | swap_total(const char *unused) 249 | { 250 | struct kvm_swap swap_info[1]; 251 | long total; 252 | 253 | if (!getswapinfo(swap_info, 1)) 254 | return NULL; 255 | 256 | total = swap_info[0].ksw_total; 257 | 258 | return fmt_human(total * getpagesize(), 1024); 259 | } 260 | 261 | const char * 262 | swap_used(const char *unused) 263 | { 264 | struct kvm_swap swap_info[1]; 265 | long used; 266 | 267 | if (!getswapinfo(swap_info, 1)) 268 | return NULL; 269 | 270 | used = swap_info[0].ksw_used; 271 | 272 | return fmt_human(used * getpagesize(), 1024); 273 | } 274 | #endif 275 | -------------------------------------------------------------------------------- /slstatus/components/temperature.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../slstatus.h" 5 | #include "../util.h" 6 | 7 | 8 | #if defined(__linux__) 9 | #include 10 | 11 | const char * 12 | temp(const char *file) 13 | { 14 | uintmax_t temp; 15 | 16 | if (pscanf(file, "%ju", &temp) != 1) 17 | return NULL; 18 | 19 | return bprintf("%ju", temp / 1000); 20 | } 21 | #elif defined(__OpenBSD__) 22 | #include 23 | #include /* before for struct timeval */ 24 | #include 25 | #include 26 | 27 | const char * 28 | temp(const char *unused) 29 | { 30 | int mib[5]; 31 | size_t size; 32 | struct sensor temp; 33 | 34 | mib[0] = CTL_HW; 35 | mib[1] = HW_SENSORS; 36 | mib[2] = 0; /* cpu0 */ 37 | mib[3] = SENSOR_TEMP; 38 | mib[4] = 0; /* temp0 */ 39 | 40 | size = sizeof(temp); 41 | 42 | if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) { 43 | warn("sysctl 'SENSOR_TEMP':"); 44 | return NULL; 45 | } 46 | 47 | /* kelvin to celsius */ 48 | return bprintf("%d", (int)((float)(temp.value-273150000) / 1E6)); 49 | } 50 | #elif defined(__FreeBSD__) 51 | #include 52 | #include 53 | #include 54 | 55 | #define ACPI_TEMP "hw.acpi.thermal.%s.temperature" 56 | 57 | const char * 58 | temp(const char *zone) 59 | { 60 | char buf[256]; 61 | int temp; 62 | size_t len; 63 | 64 | len = sizeof(temp); 65 | snprintf(buf, sizeof(buf), ACPI_TEMP, zone); 66 | if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 67 | || !len) 68 | return NULL; 69 | 70 | /* kelvin to decimal celcius */ 71 | return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); 72 | } 73 | #endif 74 | -------------------------------------------------------------------------------- /slstatus/components/uptime.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../slstatus.h" 7 | #include "../util.h" 8 | 9 | #if defined(CLOCK_BOOTTIME) 10 | #define UPTIME_FLAG CLOCK_BOOTTIME 11 | #elif defined(CLOCK_UPTIME) 12 | #define UPTIME_FLAG CLOCK_UPTIME 13 | #else 14 | #define UPTIME_FLAG CLOCK_MONOTONIC 15 | #endif 16 | 17 | const char * 18 | uptime(const char *unused) 19 | { 20 | char warn_buf[256]; 21 | uintmax_t h, m; 22 | struct timespec uptime; 23 | 24 | if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { 25 | snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); 26 | warn(warn_buf); 27 | return NULL; 28 | } 29 | 30 | h = uptime.tv_sec / 3600; 31 | m = uptime.tv_sec % 3600 / 60; 32 | 33 | return bprintf("%juh %jum", h, m); 34 | } 35 | -------------------------------------------------------------------------------- /slstatus/components/user.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../slstatus.h" 8 | #include "../util.h" 9 | 10 | const char * 11 | gid(const char *unused) 12 | { 13 | return bprintf("%d", getgid()); 14 | } 15 | 16 | const char * 17 | username(const char *unused) 18 | { 19 | struct passwd *pw; 20 | 21 | if (!(pw = getpwuid(geteuid()))) { 22 | warn("getpwuid '%d':", geteuid()); 23 | return NULL; 24 | } 25 | 26 | return bprintf("%s", pw->pw_name); 27 | } 28 | 29 | const char * 30 | uid(const char *unused) 31 | { 32 | return bprintf("%d", geteuid()); 33 | } 34 | -------------------------------------------------------------------------------- /slstatus/components/volume.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../slstatus.h" 9 | #include "../util.h" 10 | 11 | #if defined(__OpenBSD__) | defined(__FreeBSD__) 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct control { 18 | LIST_ENTRY(control) next; 19 | unsigned int addr; 20 | #define CTRL_NONE 0 21 | #define CTRL_LEVEL 1 22 | #define CTRL_MUTE 2 23 | unsigned int type; 24 | unsigned int maxval; 25 | unsigned int val; 26 | }; 27 | 28 | static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls); 29 | static struct pollfd *pfds; 30 | static struct sioctl_hdl *hdl; 31 | static int initialized; 32 | 33 | /* 34 | * Call-back to obtain the description of all audio controls. 35 | */ 36 | static void 37 | ondesc(void *unused, struct sioctl_desc *desc, int val) 38 | { 39 | struct control *c, *ctmp; 40 | unsigned int type = CTRL_NONE; 41 | 42 | if (desc == NULL) 43 | return; 44 | 45 | /* Delete existing audio control with the same address. */ 46 | LIST_FOREACH_SAFE(c, &controls, next, ctmp) { 47 | if (desc->addr == c->addr) { 48 | LIST_REMOVE(c, next); 49 | free(c); 50 | break; 51 | } 52 | } 53 | 54 | /* Only match output.level and output.mute audio controls. */ 55 | if (desc->group[0] != 0 || 56 | strcmp(desc->node0.name, "output") != 0) 57 | return; 58 | if (desc->type == SIOCTL_NUM && 59 | strcmp(desc->func, "level") == 0) 60 | type = CTRL_LEVEL; 61 | else if (desc->type == SIOCTL_SW && 62 | strcmp(desc->func, "mute") == 0) 63 | type = CTRL_MUTE; 64 | else 65 | return; 66 | 67 | c = malloc(sizeof(struct control)); 68 | if (c == NULL) { 69 | warn("sndio: failed to allocate audio control\n"); 70 | return; 71 | } 72 | 73 | c->addr = desc->addr; 74 | c->type = type; 75 | c->maxval = desc->maxval; 76 | c->val = val; 77 | LIST_INSERT_HEAD(&controls, c, next); 78 | } 79 | 80 | /* 81 | * Call-back invoked whenever an audio control changes. 82 | */ 83 | static void 84 | onval(void *unused, unsigned int addr, unsigned int val) 85 | { 86 | struct control *c; 87 | 88 | LIST_FOREACH(c, &controls, next) { 89 | if (c->addr == addr) 90 | break; 91 | } 92 | c->val = val; 93 | } 94 | 95 | static void 96 | cleanup(void) 97 | { 98 | struct control *c; 99 | 100 | if (hdl) { 101 | sioctl_close(hdl); 102 | hdl = NULL; 103 | } 104 | 105 | free(pfds); 106 | pfds = NULL; 107 | 108 | while (!LIST_EMPTY(&controls)) { 109 | c = LIST_FIRST(&controls); 110 | LIST_REMOVE(c, next); 111 | free(c); 112 | } 113 | } 114 | 115 | static int 116 | init(void) 117 | { 118 | hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); 119 | if (hdl == NULL) { 120 | warn("sndio: cannot open device"); 121 | goto failed; 122 | } 123 | 124 | if (!sioctl_ondesc(hdl, ondesc, NULL)) { 125 | warn("sndio: cannot set control description call-back"); 126 | goto failed; 127 | } 128 | 129 | if (!sioctl_onval(hdl, onval, NULL)) { 130 | warn("sndio: cannot set control values call-back"); 131 | goto failed; 132 | } 133 | 134 | pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd)); 135 | if (pfds == NULL) { 136 | warn("sndio: cannot allocate pollfd structures"); 137 | goto failed; 138 | } 139 | 140 | return 1; 141 | failed: 142 | cleanup(); 143 | return 0; 144 | } 145 | 146 | const char * 147 | vol_perc(const char *unused) 148 | { 149 | struct control *c; 150 | int n, v, value; 151 | 152 | if (!initialized) 153 | initialized = init(); 154 | 155 | if (hdl == NULL) 156 | return NULL; 157 | 158 | n = sioctl_pollfd(hdl, pfds, POLLIN); 159 | if (n > 0) { 160 | n = poll(pfds, n, 0); 161 | if (n > 0) { 162 | if (sioctl_revents(hdl, pfds) & POLLHUP) { 163 | warn("sndio: disconnected"); 164 | cleanup(); 165 | initialized = 0; 166 | return NULL; 167 | } 168 | } 169 | } 170 | 171 | value = 100; 172 | LIST_FOREACH(c, &controls, next) { 173 | if (c->type == CTRL_MUTE && c->val == 1) 174 | value = 0; 175 | else if (c->type == CTRL_LEVEL) { 176 | v = (c->val * 100 + c->maxval / 2) / c->maxval; 177 | /* For multiple channels return the minimum. */ 178 | if (v < value) 179 | value = v; 180 | } 181 | } 182 | 183 | return bprintf("%d", value); 184 | } 185 | #else 186 | #include 187 | 188 | const char * 189 | vol_perc(const char *card) 190 | { 191 | size_t i; 192 | int v, afd, devmask; 193 | char *vnames[] = SOUND_DEVICE_NAMES; 194 | 195 | if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { 196 | warn("open '%s':", card); 197 | return NULL; 198 | } 199 | 200 | if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { 201 | warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); 202 | close(afd); 203 | return NULL; 204 | } 205 | for (i = 0; i < LEN(vnames); i++) { 206 | if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { 207 | if (ioctl(afd, MIXER_READ(i), &v) < 0) { 208 | warn("ioctl 'MIXER_READ(%ld)':", i); 209 | close(afd); 210 | return NULL; 211 | } 212 | } 213 | } 214 | 215 | close(afd); 216 | 217 | return bprintf("%d", v & 0xff); 218 | } 219 | #endif 220 | -------------------------------------------------------------------------------- /slstatus/components/wifi.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../slstatus.h" 10 | #include "../util.h" 11 | 12 | #define RSSI_TO_PERC(rssi) \ 13 | rssi >= -50 ? 100 : \ 14 | (rssi <= -100 ? 0 : \ 15 | (2 * (rssi + 100))) 16 | 17 | #if defined(__linux__) 18 | #include 19 | #include 20 | 21 | #define NET_OPERSTATE "/sys/class/net/%s/operstate" 22 | 23 | const char * 24 | wifi_perc(const char *interface) 25 | { 26 | int cur; 27 | size_t i; 28 | char *p, *datastart; 29 | char path[PATH_MAX]; 30 | char status[5]; 31 | FILE *fp; 32 | 33 | if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) 34 | return NULL; 35 | if (!(fp = fopen(path, "r"))) { 36 | warn("fopen '%s':", path); 37 | return NULL; 38 | } 39 | p = fgets(status, 5, fp); 40 | fclose(fp); 41 | if (!p || strcmp(status, "up\n") != 0) 42 | return NULL; 43 | 44 | if (!(fp = fopen("/proc/net/wireless", "r"))) { 45 | warn("fopen '/proc/net/wireless':"); 46 | return NULL; 47 | } 48 | 49 | for (i = 0; i < 3; i++) 50 | if (!(p = fgets(buf, sizeof(buf) - 1, fp))) 51 | break; 52 | 53 | fclose(fp); 54 | if (i < 2 || !p) 55 | return NULL; 56 | 57 | if (!(datastart = strstr(buf, interface))) 58 | return NULL; 59 | 60 | datastart = (datastart+(strlen(interface)+1)); 61 | sscanf(datastart + 1, " %*d %d %*d %*d\t\t %*d\t " 62 | "%*d\t\t%*d\t\t %*d\t %*d\t\t %*d", &cur); 63 | 64 | /* 70 is the max of /proc/net/wireless */ 65 | return bprintf("%d", (int)((float)cur / 70 * 100)); 66 | } 67 | 68 | const char * 69 | wifi_essid(const char *interface) 70 | { 71 | static char id[IW_ESSID_MAX_SIZE+1]; 72 | int sockfd; 73 | struct iwreq wreq; 74 | 75 | memset(&wreq, 0, sizeof(struct iwreq)); 76 | wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; 77 | if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", 78 | interface) < 0) 79 | return NULL; 80 | 81 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 82 | warn("socket 'AF_INET':"); 83 | return NULL; 84 | } 85 | wreq.u.essid.pointer = id; 86 | if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { 87 | warn("ioctl 'SIOCGIWESSID':"); 88 | close(sockfd); 89 | return NULL; 90 | } 91 | 92 | close(sockfd); 93 | 94 | if (!strcmp(id, "")) 95 | return NULL; 96 | 97 | return id; 98 | } 99 | #elif defined(__OpenBSD__) 100 | #include 101 | #include 102 | #include 103 | #include /* before for NBBY */ 104 | #include 105 | #include 106 | #include 107 | 108 | static int 109 | load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr) 110 | { 111 | struct ieee80211_bssid bssid; 112 | int sockfd; 113 | uint8_t zero_bssid[IEEE80211_ADDR_LEN]; 114 | 115 | memset(&bssid, 0, sizeof(bssid)); 116 | memset(nr, 0, sizeof(struct ieee80211_nodereq)); 117 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 118 | warn("socket 'AF_INET':"); 119 | return 0; 120 | } 121 | strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); 122 | if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) { 123 | warn("ioctl 'SIOCG80211BSSID':"); 124 | close(sockfd); 125 | return 0; 126 | } 127 | memset(&zero_bssid, 0, sizeof(zero_bssid)); 128 | if (memcmp(bssid.i_bssid, zero_bssid, 129 | IEEE80211_ADDR_LEN) == 0) { 130 | close(sockfd); 131 | return 0; 132 | } 133 | strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname)); 134 | memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr)); 135 | if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) { 136 | warn("ioctl 'SIOCG80211NODE':"); 137 | close(sockfd); 138 | return 0; 139 | } 140 | 141 | return close(sockfd), 1; 142 | } 143 | 144 | const char * 145 | wifi_perc(const char *interface) 146 | { 147 | struct ieee80211_nodereq nr; 148 | int q; 149 | 150 | if (load_ieee80211_nodereq(interface, &nr)) { 151 | if (nr.nr_max_rssi) 152 | q = IEEE80211_NODEREQ_RSSI(&nr); 153 | else 154 | q = RSSI_TO_PERC(nr.nr_rssi); 155 | 156 | return bprintf("%d", q); 157 | } 158 | 159 | return NULL; 160 | } 161 | 162 | const char * 163 | wifi_essid(const char *interface) 164 | { 165 | struct ieee80211_nodereq nr; 166 | 167 | if (load_ieee80211_nodereq(interface, &nr)) 168 | return bprintf("%s", nr.nr_nwid); 169 | 170 | return NULL; 171 | } 172 | #elif defined(__FreeBSD__) 173 | #include 174 | #include 175 | 176 | int 177 | load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len) 178 | { 179 | char warn_buf[256]; 180 | struct ieee80211req ireq; 181 | memset(&ireq, 0, sizeof(ireq)); 182 | ireq.i_type = type; 183 | ireq.i_data = (caddr_t) data; 184 | ireq.i_len = *len; 185 | 186 | strlcpy(ireq.i_name, interface, sizeof(ireq.i_name)); 187 | if (ioctl(sock, SIOCG80211, &ireq) < 0) { 188 | snprintf(warn_buf, sizeof(warn_buf), 189 | "ioctl: 'SIOCG80211': %d", type); 190 | warn(warn_buf); 191 | return 0; 192 | } 193 | 194 | *len = ireq.i_len; 195 | return 1; 196 | } 197 | 198 | const char * 199 | wifi_perc(const char *interface) 200 | { 201 | union { 202 | struct ieee80211req_sta_req sta; 203 | uint8_t buf[24 * 1024]; 204 | } info; 205 | uint8_t bssid[IEEE80211_ADDR_LEN]; 206 | int rssi_dbm; 207 | int sockfd; 208 | size_t len; 209 | const char *fmt; 210 | 211 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 212 | warn("socket 'AF_INET':"); 213 | return NULL; 214 | } 215 | 216 | /* Retreive MAC address of interface */ 217 | len = IEEE80211_ADDR_LEN; 218 | fmt = NULL; 219 | if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len)) 220 | { 221 | /* Retrieve info on station with above BSSID */ 222 | memset(&info, 0, sizeof(info)); 223 | memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid)); 224 | 225 | len = sizeof(info); 226 | if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) { 227 | rssi_dbm = info.sta.info[0].isi_noise + 228 | info.sta.info[0].isi_rssi / 2; 229 | 230 | fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm)); 231 | } 232 | } 233 | 234 | close(sockfd); 235 | return fmt; 236 | } 237 | 238 | const char * 239 | wifi_essid(const char *interface) 240 | { 241 | char ssid[IEEE80211_NWID_LEN + 1]; 242 | size_t len; 243 | int sockfd; 244 | const char *fmt; 245 | 246 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 247 | warn("socket 'AF_INET':"); 248 | return NULL; 249 | } 250 | 251 | fmt = NULL; 252 | len = sizeof(ssid); 253 | memset(&ssid, 0, len); 254 | if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) { 255 | if (len < sizeof(ssid)) 256 | len += 1; 257 | else 258 | len = sizeof(ssid); 259 | 260 | ssid[len - 1] = '\0'; 261 | fmt = bprintf("%s", ssid); 262 | } 263 | 264 | close(sockfd); 265 | return fmt; 266 | } 267 | #endif 268 | -------------------------------------------------------------------------------- /slstatus/config.def.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | /* interval between updates (in ms) */ 4 | const unsigned int interval = 200; 5 | 6 | /* text to show if no value can be retrieved */ 7 | static const char unknown_str[] = "n/a"; 8 | 9 | /* maximum output string length */ 10 | #define MAXLEN 2048 11 | 12 | /* 13 | * function description argument (example) 14 | * 15 | * battery_perc battery percentage battery name (BAT0) 16 | * NULL on OpenBSD/FreeBSD 17 | * battery_remaining battery remaining HH:MM battery name (BAT0) 18 | * NULL on OpenBSD/FreeBSD 19 | * battery_state battery charging state battery name (BAT0) 20 | * NULL on OpenBSD/FreeBSD 21 | * cat read arbitrary file path 22 | * cpu_freq cpu frequency in MHz NULL 23 | * cpu_perc cpu usage in percent NULL 24 | * datetime date and time format string (%F %T) 25 | * disk_free free disk space in GB mountpoint path (/) 26 | * disk_perc disk usage in percent mountpoint path (/) 27 | * disk_total total disk space in GB mountpoint path (/) 28 | * disk_used used disk space in GB mountpoint path (/) 29 | * entropy available entropy NULL 30 | * gid GID of current user NULL 31 | * hostname hostname NULL 32 | * ipv4 IPv4 address interface name (eth0) 33 | * ipv6 IPv6 address interface name (eth0) 34 | * kernel_release `uname -r` NULL 35 | * keyboard_indicators caps/num lock indicators format string (c?n?) 36 | * see keyboard_indicators.c 37 | * keymap layout (variant) of current NULL 38 | * keymap 39 | * load_avg load average NULL 40 | * netspeed_rx receive network speed interface name (wlan0) 41 | * netspeed_tx transfer network speed interface name (wlan0) 42 | * num_files number of files in a directory path 43 | * (/home/foo/Inbox/cur) 44 | * ram_free free memory in GB NULL 45 | * ram_perc memory usage in percent NULL 46 | * ram_total total memory size in GB NULL 47 | * ram_used used memory in GB NULL 48 | * run_command custom shell command command (echo foo) 49 | * swap_free free swap in GB NULL 50 | * swap_perc swap usage in percent NULL 51 | * swap_total total swap size in GB NULL 52 | * swap_used used swap in GB NULL 53 | * temp temperature in degree celsius sensor file 54 | * (/sys/class/thermal/...) 55 | * NULL on OpenBSD 56 | * thermal zone on FreeBSD 57 | * (tz0, tz1, etc.) 58 | * uid UID of current user NULL 59 | * uptime system uptime NULL 60 | * username username of current user NULL 61 | * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) 62 | * NULL on OpenBSD/FreeBSD 63 | * wifi_essid WiFi ESSID interface name (wlan0) 64 | * wifi_perc WiFi signal in percent interface name (wlan0) 65 | */ 66 | static const struct arg args[] = { 67 | /* function format argument */ 68 | {run_command, " %s ", "date +%H:%M"}, 69 | {run_command, " %s ", "date +'%b %d'"}, 70 | {battery_state, " %s ", "BAT1"}, 71 | {battery_perc, "  %s% |", "BAT1"}, 72 | {run_command, "  %s% |", "light -G | awk '{print int($1)}'"}, 73 | {run_command, "  %s% |", "pamixer --get-volume"}, 74 | // {cpu_perc, "  %s% /", NULL}, 75 | // {temp, "  %s󰔄 |", "/sys/class/thermal/thermal_zone3/temp"}, 76 | // {ram_used, "  %s |", NULL}, 77 | {disk_perc, "  %s% |", "/home"}, 78 | {wifi_essid, "  %s ", "wlp2s0"}, 79 | // {keymap, "  %s ", NULL}, 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /slstatus/config.mk: -------------------------------------------------------------------------------- 1 | # slstatus version 2 | VERSION = 1.0 3 | 4 | # customize below to fit your system 5 | 6 | # paths 7 | PREFIX = /usr/local 8 | MANPREFIX = $(PREFIX)/share/man 9 | 10 | X11INC = /usr/X11R6/include 11 | X11LIB = /usr/X11R6/lib 12 | 13 | # flags 14 | CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" 15 | CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os 16 | LDFLAGS = -L$(X11LIB) -s 17 | # OpenBSD: add -lsndio 18 | # FreeBSD: add -lkvm -lsndio 19 | LDLIBS = -lX11 20 | 21 | # compiler and linker 22 | CC = cc 23 | -------------------------------------------------------------------------------- /slstatus/slstatus.1: -------------------------------------------------------------------------------- 1 | .Dd 2023-04-23 2 | .Dt SLSTATUS 1 3 | .Os 4 | .Sh NAME 5 | .Nm slstatus 6 | .Nd suckless status 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl s 10 | .Op Fl 1 11 | .Sh DESCRIPTION 12 | .Nm 13 | is a small tool for providing system status information to other programs 14 | over the EWMH 15 | .Em WM_NAME 16 | property of the root window (used by 17 | .Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by 18 | only issuing the minimum of system calls required. 19 | .P 20 | By default, 21 | .Nm 22 | outputs to WM_NAME. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl v 26 | Print version information to stderr, then exit. 27 | .It Fl s 28 | Write to stdout instead of WM_NAME. 29 | .It Fl 1 30 | Write once to stdout and quit. 31 | .El 32 | .Sh CUSTOMIZATION 33 | .Nm 34 | can be customized by creating a custom config.h and (re)compiling the source 35 | code. This keeps it fast, secure and simple. 36 | .Sh SIGNALS 37 | .Nm 38 | responds to the following signals: 39 | .Pp 40 | .Bl -tag -width TERM -compact 41 | .It USR1 42 | Triggers an instant redraw. 43 | .El 44 | .Sh AUTHORS 45 | See the LICENSE file for the authors. 46 | .Sh SEE ALSO 47 | .Xr dwm 1 48 | -------------------------------------------------------------------------------- /slstatus/slstatus.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "arg.h" 11 | #include "slstatus.h" 12 | #include "util.h" 13 | 14 | struct arg { 15 | const char *(*func)(const char *); 16 | const char *fmt; 17 | const char *args; 18 | }; 19 | 20 | char buf[1024]; 21 | static volatile sig_atomic_t done; 22 | static Display *dpy; 23 | 24 | #include "config.h" 25 | 26 | static void 27 | terminate(const int signo) 28 | { 29 | if (signo != SIGUSR1) 30 | done = 1; 31 | } 32 | 33 | static void 34 | difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) 35 | { 36 | res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); 37 | res->tv_nsec = a->tv_nsec - b->tv_nsec + 38 | (a->tv_nsec < b->tv_nsec) * 1E9; 39 | } 40 | 41 | static void 42 | usage(void) 43 | { 44 | die("usage: %s [-v] [-s] [-1]", argv0); 45 | } 46 | 47 | int 48 | main(int argc, char *argv[]) 49 | { 50 | struct sigaction act; 51 | struct timespec start, current, diff, intspec, wait; 52 | size_t i, len; 53 | int sflag, ret; 54 | char status[MAXLEN]; 55 | const char *res; 56 | 57 | sflag = 0; 58 | ARGBEGIN { 59 | case 'v': 60 | die("slstatus-"VERSION); 61 | case '1': 62 | done = 1; 63 | /* FALLTHROUGH */ 64 | case 's': 65 | sflag = 1; 66 | break; 67 | default: 68 | usage(); 69 | } ARGEND 70 | 71 | if (argc) 72 | usage(); 73 | 74 | memset(&act, 0, sizeof(act)); 75 | act.sa_handler = terminate; 76 | sigaction(SIGINT, &act, NULL); 77 | sigaction(SIGTERM, &act, NULL); 78 | act.sa_flags |= SA_RESTART; 79 | sigaction(SIGUSR1, &act, NULL); 80 | 81 | if (!sflag && !(dpy = XOpenDisplay(NULL))) 82 | die("XOpenDisplay: Failed to open display"); 83 | 84 | do { 85 | if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) 86 | die("clock_gettime:"); 87 | 88 | status[0] = '\0'; 89 | for (i = len = 0; i < LEN(args); i++) { 90 | if (!(res = args[i].func(args[i].args))) 91 | res = unknown_str; 92 | 93 | if ((ret = esnprintf(status + len, sizeof(status) - len, 94 | args[i].fmt, res)) < 0) 95 | break; 96 | 97 | len += ret; 98 | } 99 | 100 | if (sflag) { 101 | puts(status); 102 | fflush(stdout); 103 | if (ferror(stdout)) 104 | die("puts:"); 105 | } else { 106 | if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) 107 | die("XStoreName: Allocation failed"); 108 | XFlush(dpy); 109 | } 110 | 111 | if (!done) { 112 | if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) 113 | die("clock_gettime:"); 114 | difftimespec(&diff, ¤t, &start); 115 | 116 | intspec.tv_sec = interval / 1000; 117 | intspec.tv_nsec = (interval % 1000) * 1E6; 118 | difftimespec(&wait, &intspec, &diff); 119 | 120 | if (wait.tv_sec >= 0 && 121 | nanosleep(&wait, NULL) < 0 && 122 | errno != EINTR) 123 | die("nanosleep:"); 124 | } 125 | } while (!done); 126 | 127 | if (!sflag) { 128 | XStoreName(dpy, DefaultRootWindow(dpy), NULL); 129 | if (XCloseDisplay(dpy) < 0) 130 | die("XCloseDisplay: Failed to close display"); 131 | } 132 | 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /slstatus/slstatus.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | /* battery */ 4 | const char *battery_perc(const char *); 5 | const char *battery_remaining(const char *); 6 | const char *battery_state(const char *); 7 | 8 | /* cat */ 9 | const char *cat(const char *path); 10 | 11 | /* cpu */ 12 | const char *cpu_freq(const char *unused); 13 | const char *cpu_perc(const char *unused); 14 | 15 | /* datetime */ 16 | const char *datetime(const char *fmt); 17 | 18 | /* disk */ 19 | const char *disk_free(const char *path); 20 | const char *disk_perc(const char *path); 21 | const char *disk_total(const char *path); 22 | const char *disk_used(const char *path); 23 | 24 | /* entropy */ 25 | const char *entropy(const char *unused); 26 | 27 | /* hostname */ 28 | const char *hostname(const char *unused); 29 | 30 | /* ip */ 31 | const char *ipv4(const char *interface); 32 | const char *ipv6(const char *interface); 33 | 34 | /* kernel_release */ 35 | const char *kernel_release(const char *unused); 36 | 37 | /* keyboard_indicators */ 38 | const char *keyboard_indicators(const char *fmt); 39 | 40 | /* keymap */ 41 | const char *keymap(const char *unused); 42 | 43 | /* load_avg */ 44 | const char *load_avg(const char *unused); 45 | 46 | /* netspeeds */ 47 | const char *netspeed_rx(const char *interface); 48 | const char *netspeed_tx(const char *interface); 49 | 50 | /* num_files */ 51 | const char *num_files(const char *path); 52 | 53 | /* ram */ 54 | const char *ram_free(const char *unused); 55 | const char *ram_perc(const char *unused); 56 | const char *ram_total(const char *unused); 57 | const char *ram_used(const char *unused); 58 | 59 | /* run_command */ 60 | const char *run_command(const char *cmd); 61 | 62 | /* swap */ 63 | const char *swap_free(const char *unused); 64 | const char *swap_perc(const char *unused); 65 | const char *swap_total(const char *unused); 66 | const char *swap_used(const char *unused); 67 | 68 | /* temperature */ 69 | const char *temp(const char *); 70 | 71 | /* uptime */ 72 | const char *uptime(const char *unused); 73 | 74 | /* user */ 75 | const char *gid(const char *unused); 76 | const char *uid(const char *unused); 77 | const char *username(const char *unused); 78 | 79 | /* volume */ 80 | const char *vol_perc(const char *card); 81 | 82 | /* wifi */ 83 | const char *wifi_essid(const char *interface); 84 | const char *wifi_perc(const char *interface); 85 | -------------------------------------------------------------------------------- /slstatus/util.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "util.h" 10 | 11 | char *argv0; 12 | 13 | static void 14 | verr(const char *fmt, va_list ap) 15 | { 16 | vfprintf(stderr, fmt, ap); 17 | 18 | if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { 19 | fputc(' ', stderr); 20 | perror(NULL); 21 | } else { 22 | fputc('\n', stderr); 23 | } 24 | } 25 | 26 | void 27 | warn(const char *fmt, ...) 28 | { 29 | va_list ap; 30 | 31 | va_start(ap, fmt); 32 | verr(fmt, ap); 33 | va_end(ap); 34 | } 35 | 36 | void 37 | die(const char *fmt, ...) 38 | { 39 | va_list ap; 40 | 41 | va_start(ap, fmt); 42 | verr(fmt, ap); 43 | va_end(ap); 44 | 45 | exit(1); 46 | } 47 | 48 | static int 49 | evsnprintf(char *str, size_t size, const char *fmt, va_list ap) 50 | { 51 | int ret; 52 | 53 | ret = vsnprintf(str, size, fmt, ap); 54 | 55 | if (ret < 0) { 56 | warn("vsnprintf:"); 57 | return -1; 58 | } else if ((size_t)ret >= size) { 59 | warn("vsnprintf: Output truncated"); 60 | return -1; 61 | } 62 | 63 | return ret; 64 | } 65 | 66 | int 67 | esnprintf(char *str, size_t size, const char *fmt, ...) 68 | { 69 | va_list ap; 70 | int ret; 71 | 72 | va_start(ap, fmt); 73 | ret = evsnprintf(str, size, fmt, ap); 74 | va_end(ap); 75 | 76 | return ret; 77 | } 78 | 79 | const char * 80 | bprintf(const char *fmt, ...) 81 | { 82 | va_list ap; 83 | int ret; 84 | 85 | va_start(ap, fmt); 86 | ret = evsnprintf(buf, sizeof(buf), fmt, ap); 87 | va_end(ap); 88 | 89 | return (ret < 0) ? NULL : buf; 90 | } 91 | 92 | const char * 93 | fmt_human(uintmax_t num, int base) 94 | { 95 | double scaled; 96 | size_t i, prefixlen; 97 | const char **prefix; 98 | const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", 99 | "Y" }; 100 | const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", 101 | "Zi", "Yi" }; 102 | 103 | switch (base) { 104 | case 1000: 105 | prefix = prefix_1000; 106 | prefixlen = LEN(prefix_1000); 107 | break; 108 | case 1024: 109 | prefix = prefix_1024; 110 | prefixlen = LEN(prefix_1024); 111 | break; 112 | default: 113 | warn("fmt_human: Invalid base"); 114 | return NULL; 115 | } 116 | 117 | scaled = num; 118 | for (i = 0; i < prefixlen && scaled >= base; i++) 119 | scaled /= base; 120 | 121 | return bprintf("%.1f %s", scaled, prefix[i]); 122 | } 123 | 124 | int 125 | pscanf(const char *path, const char *fmt, ...) 126 | { 127 | FILE *fp; 128 | va_list ap; 129 | int n; 130 | 131 | if (!(fp = fopen(path, "r"))) { 132 | warn("fopen '%s':", path); 133 | return -1; 134 | } 135 | va_start(ap, fmt); 136 | n = vfscanf(fp, fmt, ap); 137 | va_end(ap); 138 | fclose(fp); 139 | 140 | return (n == EOF) ? -1 : n; 141 | } 142 | -------------------------------------------------------------------------------- /slstatus/util.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | extern char buf[1024]; 5 | 6 | #define LEN(x) (sizeof(x) / sizeof((x)[0])) 7 | 8 | extern char *argv0; 9 | 10 | void warn(const char *, ...); 11 | void die(const char *, ...); 12 | 13 | int esnprintf(char *str, size_t size, const char *fmt, ...); 14 | const char *bprintf(const char *fmt, ...); 15 | const char *fmt_human(uintmax_t num, int base); 16 | int pscanf(const char *path, const char *fmt, ...); 17 | -------------------------------------------------------------------------------- /st/LEGACY: -------------------------------------------------------------------------------- 1 | A STATEMENT ON LEGACY SUPPORT 2 | 3 | In the terminal world there is much cruft that comes from old and unsup‐ 4 | ported terminals that inherit incompatible modes and escape sequences 5 | which noone is able to know, except when he/she comes from that time and 6 | developed a graphical vt100 emulator at that time. 7 | 8 | One goal of st is to only support what is really needed. When you en‐ 9 | counter a sequence which you really need, implement it. But while you 10 | are at it, do not add the other cruft you might encounter while sneek‐ 11 | ing at other terminal emulators. History has bloated them and there is 12 | no real evidence that most of the sequences are used today. 13 | 14 | 15 | Christoph Lohmann <20h@r-36.net> 16 | 2012-09-13T07:00:36.081271045+02:00 17 | 18 | -------------------------------------------------------------------------------- /st/LICENSE: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | © 2014-2022 Hiltjo Posthuma 4 | © 2018 Devin J. Pohly 5 | © 2014-2017 Quentin Rameau 6 | © 2009-2012 Aurélien APTEL 7 | © 2008-2017 Anselm R Garbe 8 | © 2012-2017 Roberto E. Vargas Caballero 9 | © 2012-2016 Christoph Lohmann <20h at r-36 dot net> 10 | © 2013 Eon S. Jeon 11 | © 2013 Alexander Sedov 12 | © 2013 Mark Edgar 13 | © 2013-2014 Eric Pruitt 14 | © 2013 Michael Forney 15 | © 2013-2014 Markus Teich 16 | © 2014-2015 Laslo Hunhold 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a 19 | copy of this software and associated documentation files (the "Software"), 20 | to deal in the Software without restriction, including without limitation 21 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 | and/or sell copies of the Software, and to permit persons to whom the 23 | Software is furnished to do so, subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in 26 | all copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 31 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 34 | DEALINGS IN THE SOFTWARE. 35 | -------------------------------------------------------------------------------- /st/Makefile: -------------------------------------------------------------------------------- 1 | # st - simple terminal 2 | # See LICENSE file for copyright and license details. 3 | .POSIX: 4 | 5 | include config.mk 6 | 7 | SRC = st.c x.c boxdraw.c rowcolumn_diacritics_helpers.c graphics.c 8 | OBJ = $(SRC:.c=.o) 9 | 10 | all: st 11 | 12 | config.h: 13 | cp config.def.h config.h 14 | 15 | .c.o: 16 | $(CC) $(STCFLAGS) -c $< 17 | 18 | st.o: config.h st.h win.h 19 | x.o: arg.h config.h st.h win.h graphics.h 20 | boxdraw.o: config.h st.h boxdraw_data.h 21 | 22 | $(OBJ): config.h config.mk 23 | 24 | st: $(OBJ) 25 | $(CC) -o $@ $(OBJ) $(STLDFLAGS) 26 | 27 | clean: 28 | rm -f st $(OBJ) st-$(VERSION).tar.gz 29 | 30 | dist: clean 31 | mkdir -p st-$(VERSION) 32 | cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ 33 | config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ 34 | st-$(VERSION) 35 | tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz 36 | rm -rf st-$(VERSION) 37 | 38 | install: st 39 | mkdir -p $(DESTDIR)$(PREFIX)/bin 40 | cp -f st $(DESTDIR)$(PREFIX)/bin 41 | chmod 755 $(DESTDIR)$(PREFIX)/bin/st 42 | mkdir -p $(DESTDIR)$(MANPREFIX)/man1 43 | sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 44 | chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 45 | tic -sx st.info 46 | @echo Please see the README file regarding the terminfo entry of st. 47 | 48 | uninstall: 49 | rm -f $(DESTDIR)$(PREFIX)/bin/st 50 | rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 51 | 52 | .PHONY: all clean dist install uninstall 53 | -------------------------------------------------------------------------------- /st/README: -------------------------------------------------------------------------------- 1 | st - simple terminal 2 | -------------------- 3 | st is a simple terminal emulator for X which sucks less. 4 | 5 | 6 | Requirements 7 | ------------ 8 | In order to build st you need the Xlib header files. 9 | 10 | 11 | Installation 12 | ------------ 13 | Edit config.mk to match your local setup (st is installed into 14 | the /usr/local namespace by default). 15 | 16 | Afterwards enter the following command to build and install st (if 17 | necessary as root): 18 | 19 | make clean install 20 | 21 | 22 | Running st 23 | ---------- 24 | If you did not install st with make clean install, you must compile 25 | the st terminfo entry with the following command: 26 | 27 | tic -sx st.info 28 | 29 | See the man page for additional details. 30 | 31 | Credits 32 | ------- 33 | Based on Aurélien APTEL bt source code. 34 | 35 | -------------------------------------------------------------------------------- /st/TODO: -------------------------------------------------------------------------------- 1 | vt emulation 2 | ------------ 3 | 4 | * double-height support 5 | 6 | code & interface 7 | ---------------- 8 | 9 | * add a simple way to do multiplexing 10 | 11 | drawing 12 | ------- 13 | * add diacritics support to xdraws() 14 | * switch to a suckless font drawing library 15 | * make the font cache simpler 16 | * add better support for brightening of the upper colors 17 | 18 | bugs 19 | ---- 20 | 21 | * fix shift up/down (shift selection in emacs) 22 | * remove DEC test sequence when appropriate 23 | 24 | misc 25 | ---- 26 | 27 | $ grep -nE 'XXX|TODO' st.c 28 | 29 | -------------------------------------------------------------------------------- /st/arg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copy me if you can. 3 | * by 20h 4 | */ 5 | 6 | #ifndef ARG_H__ 7 | #define ARG_H__ 8 | 9 | extern char *argv0; 10 | 11 | /* use main(int argc, char *argv[]) */ 12 | #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ 13 | argv[0] && argv[0][0] == '-'\ 14 | && argv[0][1];\ 15 | argc--, argv++) {\ 16 | char argc_;\ 17 | char **argv_;\ 18 | int brk_;\ 19 | if (argv[0][1] == '-' && argv[0][2] == '\0') {\ 20 | argv++;\ 21 | argc--;\ 22 | break;\ 23 | }\ 24 | int i_;\ 25 | for (i_ = 1, brk_ = 0, argv_ = argv;\ 26 | argv[0][i_] && !brk_;\ 27 | i_++) {\ 28 | if (argv_ != argv)\ 29 | break;\ 30 | argc_ = argv[0][i_];\ 31 | switch (argc_) 32 | 33 | #define ARGEND }\ 34 | } 35 | 36 | #define ARGC() argc_ 37 | 38 | #define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ 39 | ((x), abort(), (char *)0) :\ 40 | (brk_ = 1, (argv[0][i_+1] != '\0')?\ 41 | (&argv[0][i_+1]) :\ 42 | (argc--, argv++, argv[0]))) 43 | 44 | #define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ 45 | (char *)0 :\ 46 | (brk_ = 1, (argv[0][i_+1] != '\0')?\ 47 | (&argv[0][i_+1]) :\ 48 | (argc--, argv++, argv[0]))) 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /st/boxdraw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih 3 | * MIT/X Consortium License 4 | */ 5 | 6 | #include 7 | #include "st.h" 8 | #include "boxdraw_data.h" 9 | 10 | /* Rounded non-negative integers division of n / d */ 11 | #define DIV(n, d) (((n) + (d) / 2) / (d)) 12 | 13 | static Display *xdpy; 14 | static Colormap xcmap; 15 | static XftDraw *xd; 16 | static Visual *xvis; 17 | 18 | static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); 19 | static void drawboxlines(int, int, int, int, XftColor *, ushort); 20 | 21 | /* public API */ 22 | 23 | void 24 | boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) 25 | { 26 | xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; 27 | } 28 | 29 | int 30 | isboxdraw(Rune u) 31 | { 32 | Rune block = u & ~0xff; 33 | return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || 34 | (boxdraw_braille && block == 0x2800); 35 | } 36 | 37 | /* the "index" is actually the entire shape data encoded as ushort */ 38 | ushort 39 | boxdrawindex(const Glyph *g) 40 | { 41 | if (boxdraw_braille && (g->u & ~0xff) == 0x2800) 42 | return BRL | (uint8_t)g->u; 43 | if (boxdraw_bold && (g->mode & ATTR_BOLD)) 44 | return BDB | boxdata[(uint8_t)g->u]; 45 | return boxdata[(uint8_t)g->u]; 46 | } 47 | 48 | void 49 | drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, 50 | const XftGlyphFontSpec *specs, int len) 51 | { 52 | for ( ; len-- > 0; x += cw, specs++) 53 | drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); 54 | } 55 | 56 | /* implementation */ 57 | 58 | void 59 | drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) 60 | { 61 | ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ 62 | if (bd & (BDL | BDA)) { 63 | /* lines (light/double/heavy/arcs) */ 64 | drawboxlines(x, y, w, h, fg, bd); 65 | 66 | } else if (cat == BBD) { 67 | /* lower (8-X)/8 block */ 68 | int d = DIV((uint8_t)bd * h, 8); 69 | XftDrawRect(xd, fg, x, y + d, w, h - d); 70 | 71 | } else if (cat == BBU) { 72 | /* upper X/8 block */ 73 | XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); 74 | 75 | } else if (cat == BBL) { 76 | /* left X/8 block */ 77 | XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); 78 | 79 | } else if (cat == BBR) { 80 | /* right (8-X)/8 block */ 81 | int d = DIV((uint8_t)bd * w, 8); 82 | XftDrawRect(xd, fg, x + d, y, w - d, h); 83 | 84 | } else if (cat == BBQ) { 85 | /* Quadrants */ 86 | int w2 = DIV(w, 2), h2 = DIV(h, 2); 87 | if (bd & TL) 88 | XftDrawRect(xd, fg, x, y, w2, h2); 89 | if (bd & TR) 90 | XftDrawRect(xd, fg, x + w2, y, w - w2, h2); 91 | if (bd & BL) 92 | XftDrawRect(xd, fg, x, y + h2, w2, h - h2); 93 | if (bd & BR) 94 | XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); 95 | 96 | } else if (bd & BBS) { 97 | /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ 98 | int d = (uint8_t)bd; 99 | XftColor xfc; 100 | XRenderColor xrc = { .alpha = 0xffff }; 101 | 102 | xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); 103 | xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); 104 | xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); 105 | 106 | XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); 107 | XftDrawRect(xd, &xfc, x, y, w, h); 108 | XftColorFree(xdpy, xvis, xcmap, &xfc); 109 | 110 | } else if (cat == BRL) { 111 | /* braille, each data bit corresponds to one dot at 2x4 grid */ 112 | int w1 = DIV(w, 2); 113 | int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); 114 | 115 | if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); 116 | if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); 117 | if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); 118 | if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); 119 | if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); 120 | if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); 121 | if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); 122 | if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); 123 | 124 | } 125 | } 126 | 127 | void 128 | drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) 129 | { 130 | /* s: stem thickness. width/8 roughly matches underscore thickness. */ 131 | /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ 132 | /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ 133 | int mwh = MIN(w, h); 134 | int base_s = MAX(1, DIV(mwh, 8)); 135 | int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ 136 | int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; 137 | int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); 138 | /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ 139 | /* The base length (per direction till edge) includes this square. */ 140 | 141 | int light = bd & (LL | LU | LR | LD); 142 | int double_ = bd & (DL | DU | DR | DD); 143 | 144 | if (light) { 145 | /* d: additional (negative) length to not-draw the center */ 146 | /* texel - at arcs and avoid drawing inside (some) doubles */ 147 | int arc = bd & BDA; 148 | int multi_light = light & (light - 1); 149 | int multi_double = double_ & (double_ - 1); 150 | /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ 151 | int d = arc || (multi_double && !multi_light) ? -s : 0; 152 | 153 | if (bd & LL) 154 | XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); 155 | if (bd & LU) 156 | XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); 157 | if (bd & LR) 158 | XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); 159 | if (bd & LD) 160 | XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); 161 | } 162 | 163 | /* double lines - also align with light to form heavy when combined */ 164 | if (double_) { 165 | /* 166 | * going clockwise, for each double-ray: p is additional length 167 | * to the single-ray nearer to the previous direction, and n to 168 | * the next. p and n adjust from the base length to lengths 169 | * which consider other doubles - shorter to avoid intersections 170 | * (p, n), or longer to draw the far-corner texel (n). 171 | */ 172 | int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; 173 | if (dl) { 174 | int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; 175 | XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); 176 | XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); 177 | } 178 | if (du) { 179 | int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; 180 | XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); 181 | XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); 182 | } 183 | if (dr) { 184 | int p = du ? -s : 0, n = dd ? -s : du ? s : 0; 185 | XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); 186 | XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); 187 | } 188 | if (dd) { 189 | int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; 190 | XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); 191 | XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /st/boxdraw_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih 3 | * MIT/X Consortium License 4 | */ 5 | 6 | /* 7 | * U+25XX codepoints data 8 | * 9 | * References: 10 | * http://www.unicode.org/charts/PDF/U2500.pdf 11 | * http://www.unicode.org/charts/PDF/U2580.pdf 12 | * 13 | * Test page: 14 | * https://github.com/GNOME/vte/blob/master/doc/boxes.txt 15 | */ 16 | 17 | /* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ 18 | /* Categories (mutually exclusive except BDB): */ 19 | /* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ 20 | #define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ 21 | #define BDA (1<<9) /* Box Draw Arc (light) */ 22 | 23 | #define BBD (1<<10) /* Box Block Down (lower) X/8 */ 24 | #define BBL (2<<10) /* Box Block Left X/8 */ 25 | #define BBU (3<<10) /* Box Block Upper X/8 */ 26 | #define BBR (4<<10) /* Box Block Right X/8 */ 27 | #define BBQ (5<<10) /* Box Block Quadrants */ 28 | #define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ 29 | 30 | #define BBS (1<<14) /* Box Block Shades */ 31 | #define BDB (1<<15) /* Box Draw is Bold */ 32 | 33 | /* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ 34 | /* Heavy is light+double (literally drawing light+double align to form heavy) */ 35 | #define LL (1<<0) 36 | #define LU (1<<1) 37 | #define LR (1<<2) 38 | #define LD (1<<3) 39 | #define LH (LL+LR) 40 | #define LV (LU+LD) 41 | 42 | #define DL (1<<4) 43 | #define DU (1<<5) 44 | #define DR (1<<6) 45 | #define DD (1<<7) 46 | #define DH (DL+DR) 47 | #define DV (DU+DD) 48 | 49 | #define HL (LL+DL) 50 | #define HU (LU+DU) 51 | #define HR (LR+DR) 52 | #define HD (LD+DD) 53 | #define HH (HL+HR) 54 | #define HV (HU+HD) 55 | 56 | /* (BBQ) Quadrants Top/Bottom x Left/Right */ 57 | #define TL (1<<0) 58 | #define TR (1<<1) 59 | #define BL (1<<2) 60 | #define BR (1<<3) 61 | 62 | /* Data for U+2500 - U+259F except dashes/diagonals */ 63 | static const unsigned short boxdata[256] = { 64 | /* light lines */ 65 | [0x00] = BDL + LH, /* light horizontal */ 66 | [0x02] = BDL + LV, /* light vertical */ 67 | [0x0c] = BDL + LD + LR, /* light down and right */ 68 | [0x10] = BDL + LD + LL, /* light down and left */ 69 | [0x14] = BDL + LU + LR, /* light up and right */ 70 | [0x18] = BDL + LU + LL, /* light up and left */ 71 | [0x1c] = BDL + LV + LR, /* light vertical and right */ 72 | [0x24] = BDL + LV + LL, /* light vertical and left */ 73 | [0x2c] = BDL + LH + LD, /* light horizontal and down */ 74 | [0x34] = BDL + LH + LU, /* light horizontal and up */ 75 | [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ 76 | [0x74] = BDL + LL, /* light left */ 77 | [0x75] = BDL + LU, /* light up */ 78 | [0x76] = BDL + LR, /* light right */ 79 | [0x77] = BDL + LD, /* light down */ 80 | 81 | /* heavy [+light] lines */ 82 | [0x01] = BDL + HH, 83 | [0x03] = BDL + HV, 84 | [0x0d] = BDL + HR + LD, 85 | [0x0e] = BDL + HD + LR, 86 | [0x0f] = BDL + HD + HR, 87 | [0x11] = BDL + HL + LD, 88 | [0x12] = BDL + HD + LL, 89 | [0x13] = BDL + HD + HL, 90 | [0x15] = BDL + HR + LU, 91 | [0x16] = BDL + HU + LR, 92 | [0x17] = BDL + HU + HR, 93 | [0x19] = BDL + HL + LU, 94 | [0x1a] = BDL + HU + LL, 95 | [0x1b] = BDL + HU + HL, 96 | [0x1d] = BDL + HR + LV, 97 | [0x1e] = BDL + HU + LD + LR, 98 | [0x1f] = BDL + HD + LR + LU, 99 | [0x20] = BDL + HV + LR, 100 | [0x21] = BDL + HU + HR + LD, 101 | [0x22] = BDL + HD + HR + LU, 102 | [0x23] = BDL + HV + HR, 103 | [0x25] = BDL + HL + LV, 104 | [0x26] = BDL + HU + LD + LL, 105 | [0x27] = BDL + HD + LU + LL, 106 | [0x28] = BDL + HV + LL, 107 | [0x29] = BDL + HU + HL + LD, 108 | [0x2a] = BDL + HD + HL + LU, 109 | [0x2b] = BDL + HV + HL, 110 | [0x2d] = BDL + HL + LD + LR, 111 | [0x2e] = BDL + HR + LL + LD, 112 | [0x2f] = BDL + HH + LD, 113 | [0x30] = BDL + HD + LH, 114 | [0x31] = BDL + HD + HL + LR, 115 | [0x32] = BDL + HR + HD + LL, 116 | [0x33] = BDL + HH + HD, 117 | [0x35] = BDL + HL + LU + LR, 118 | [0x36] = BDL + HR + LU + LL, 119 | [0x37] = BDL + HH + LU, 120 | [0x38] = BDL + HU + LH, 121 | [0x39] = BDL + HU + HL + LR, 122 | [0x3a] = BDL + HU + HR + LL, 123 | [0x3b] = BDL + HH + HU, 124 | [0x3d] = BDL + HL + LV + LR, 125 | [0x3e] = BDL + HR + LV + LL, 126 | [0x3f] = BDL + HH + LV, 127 | [0x40] = BDL + HU + LH + LD, 128 | [0x41] = BDL + HD + LH + LU, 129 | [0x42] = BDL + HV + LH, 130 | [0x43] = BDL + HU + HL + LD + LR, 131 | [0x44] = BDL + HU + HR + LD + LL, 132 | [0x45] = BDL + HD + HL + LU + LR, 133 | [0x46] = BDL + HD + HR + LU + LL, 134 | [0x47] = BDL + HH + HU + LD, 135 | [0x48] = BDL + HH + HD + LU, 136 | [0x49] = BDL + HV + HL + LR, 137 | [0x4a] = BDL + HV + HR + LL, 138 | [0x4b] = BDL + HV + HH, 139 | [0x78] = BDL + HL, 140 | [0x79] = BDL + HU, 141 | [0x7a] = BDL + HR, 142 | [0x7b] = BDL + HD, 143 | [0x7c] = BDL + HR + LL, 144 | [0x7d] = BDL + HD + LU, 145 | [0x7e] = BDL + HL + LR, 146 | [0x7f] = BDL + HU + LD, 147 | 148 | /* double [+light] lines */ 149 | [0x50] = BDL + DH, 150 | [0x51] = BDL + DV, 151 | [0x52] = BDL + DR + LD, 152 | [0x53] = BDL + DD + LR, 153 | [0x54] = BDL + DR + DD, 154 | [0x55] = BDL + DL + LD, 155 | [0x56] = BDL + DD + LL, 156 | [0x57] = BDL + DL + DD, 157 | [0x58] = BDL + DR + LU, 158 | [0x59] = BDL + DU + LR, 159 | [0x5a] = BDL + DU + DR, 160 | [0x5b] = BDL + DL + LU, 161 | [0x5c] = BDL + DU + LL, 162 | [0x5d] = BDL + DL + DU, 163 | [0x5e] = BDL + DR + LV, 164 | [0x5f] = BDL + DV + LR, 165 | [0x60] = BDL + DV + DR, 166 | [0x61] = BDL + DL + LV, 167 | [0x62] = BDL + DV + LL, 168 | [0x63] = BDL + DV + DL, 169 | [0x64] = BDL + DH + LD, 170 | [0x65] = BDL + DD + LH, 171 | [0x66] = BDL + DD + DH, 172 | [0x67] = BDL + DH + LU, 173 | [0x68] = BDL + DU + LH, 174 | [0x69] = BDL + DH + DU, 175 | [0x6a] = BDL + DH + LV, 176 | [0x6b] = BDL + DV + LH, 177 | [0x6c] = BDL + DH + DV, 178 | 179 | /* (light) arcs */ 180 | [0x6d] = BDA + LD + LR, 181 | [0x6e] = BDA + LD + LL, 182 | [0x6f] = BDA + LU + LL, 183 | [0x70] = BDA + LU + LR, 184 | 185 | /* Lower (Down) X/8 block (data is 8 - X) */ 186 | [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, 187 | [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, 188 | 189 | /* Left X/8 block (data is X) */ 190 | [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, 191 | [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, 192 | 193 | /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ 194 | [0x80] = BBU + 4, [0x94] = BBU + 1, 195 | [0x90] = BBR + 4, [0x95] = BBR + 7, 196 | 197 | /* Quadrants */ 198 | [0x96] = BBQ + BL, 199 | [0x97] = BBQ + BR, 200 | [0x98] = BBQ + TL, 201 | [0x99] = BBQ + TL + BL + BR, 202 | [0x9a] = BBQ + TL + BR, 203 | [0x9b] = BBQ + TL + TR + BL, 204 | [0x9c] = BBQ + TL + TR + BR, 205 | [0x9d] = BBQ + TR, 206 | [0x9e] = BBQ + BL + TR, 207 | [0x9f] = BBQ + BL + TR + BR, 208 | 209 | /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ 210 | [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, 211 | 212 | /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ 213 | /* U+2571 - U+2573: unsupported (diagonals) */ 214 | }; 215 | -------------------------------------------------------------------------------- /st/config.mk: -------------------------------------------------------------------------------- 1 | # st version 2 | VERSION = 0.9.2 3 | 4 | # Customize below to fit your system 5 | 6 | # paths 7 | PREFIX = /usr/local 8 | MANPREFIX = $(PREFIX)/share/man 9 | 10 | X11INC = /usr/X11R6/include 11 | X11LIB = /usr/X11R6/lib 12 | 13 | PKG_CONFIG = pkg-config 14 | 15 | # includes and libs 16 | INCS = -I$(X11INC) \ 17 | `$(PKG_CONFIG) --cflags imlib2` \ 18 | `$(PKG_CONFIG) --cflags fontconfig` \ 19 | `$(PKG_CONFIG) --cflags freetype2` 20 | LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender \ 21 | `$(PKG_CONFIG) --libs imlib2` \ 22 | `$(PKG_CONFIG) --libs zlib` \ 23 | `$(PKG_CONFIG) --libs fontconfig` \ 24 | `$(PKG_CONFIG) --libs freetype2` 25 | 26 | # flags 27 | STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 28 | STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) 29 | STLDFLAGS = $(LIBS) $(LDFLAGS) 30 | 31 | # OpenBSD: 32 | #CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE 33 | #LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ 34 | # `$(PKG_CONFIG) --libs fontconfig` \ 35 | # `$(PKG_CONFIG) --libs freetype2` 36 | #MANPREFIX = ${PREFIX}/man 37 | 38 | # compiler and linker 39 | # CC = c99 40 | -------------------------------------------------------------------------------- /st/graphics.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | /// Initialize the graphics module. 7 | void gr_init(Display *disp, Visual *vis, Colormap cm); 8 | /// Deinitialize the graphics module. 9 | void gr_deinit(); 10 | 11 | /// Add an image rectangle to a list if rectangles to draw. This function may 12 | /// actually draw some rectangles, or it may wait till more rectangles are 13 | /// appended. Must be called between `gr_start_drawing` and `gr_finish_drawing`. 14 | /// - `img_start_col..img_end_col` and `img_start_row..img_end_row` define the 15 | /// part of the image to draw (row/col indices are zero-based, ends are 16 | /// excluded). 17 | /// - `x_col` and `y_row` are the coordinates of the top-left corner of the 18 | /// image in the terminal grid. 19 | /// - `x_pix` and `y_pix` are the same but in pixels. 20 | /// - `reverse` indicates whether colors should be inverted. 21 | void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id, 22 | int img_start_col, int img_end_col, int img_start_row, 23 | int img_end_row, int x_col, int y_row, int x_pix, 24 | int y_pix, int cw, int ch, int reverse); 25 | /// Prepare for image drawing. `cw` and `ch` are dimensions of the cell. 26 | void gr_start_drawing(Drawable buf, int cw, int ch); 27 | /// Finish image drawing. This functions will draw all the rectangles left to 28 | /// draw. 29 | void gr_finish_drawing(Drawable buf); 30 | /// Mark rows containing animations as dirty if it's time to redraw them. Must 31 | /// be called right after `gr_start_drawing`. 32 | void gr_mark_dirty_animations(int *dirty, int rows); 33 | 34 | /// Parse and execute a graphics command. `buf` must start with 'G' and contain 35 | /// at least `len + 1` characters (including '\0'). Returns 1 on success. 36 | /// Additional informations is returned through `graphics_command_result`. 37 | int gr_parse_command(char *buf, size_t len); 38 | 39 | /// Executes `command` with the name of the file corresponding to `image_id` as 40 | /// the argument. Executes xmessage with an error message on failure. 41 | void gr_preview_image(uint32_t image_id, const char *command); 42 | 43 | /// Executes ` -e less ` where is the name of a temporary file 44 | /// containing the information about an image and placement, and is 45 | /// specified with `st_executable`. 46 | void gr_show_image_info(uint32_t image_id, uint32_t placement_id, 47 | uint32_t imgcol, uint32_t imgrow, 48 | char is_classic_placeholder, int32_t diacritic_count, 49 | char *st_executable); 50 | 51 | /// Dumps the internal state (images and placements) to stderr. 52 | void gr_dump_state(); 53 | 54 | /// Unloads images to reduce RAM usage. 55 | void gr_unload_images_to_reduce_ram(); 56 | 57 | /// Executes `callback` for each image cell. `callback` may return 1 to erase 58 | /// the cell or 0 to keep it. This function is implemented in `st.c`. 59 | void gr_for_each_image_cell(int (*callback)(void *data, uint32_t image_id, 60 | uint32_t placement_id, int col, 61 | int row, char is_classic), 62 | void *data); 63 | 64 | /// Marks all the rows containing the image with `image_id` as dirty. 65 | void gr_schedule_image_redraw_by_id(uint32_t image_id); 66 | 67 | typedef enum { 68 | GRAPHICS_DEBUG_NONE = 0, 69 | GRAPHICS_DEBUG_LOG = 1, 70 | GRAPHICS_DEBUG_LOG_AND_BOXES = 2, 71 | } GraphicsDebugMode; 72 | 73 | /// Print additional information, draw bounding bounding boxes, etc. 74 | extern GraphicsDebugMode graphics_debug_mode; 75 | 76 | /// Whether to display images or just draw bounding boxes. 77 | extern char graphics_display_images; 78 | 79 | /// The time in milliseconds until the next redraw to update animations. 80 | /// INT_MAX means no redraw is needed. Populated by `gr_finish_drawing`. 81 | extern int graphics_next_redraw_delay; 82 | 83 | #define MAX_GRAPHICS_RESPONSE_LEN 256 84 | 85 | /// A structure representing the result of a graphics command. 86 | typedef struct { 87 | /// Indicates if the terminal needs to be redrawn. 88 | char redraw; 89 | /// The response of the command that should be sent back to the client 90 | /// (may be empty if the quiet flag is set). 91 | char response[MAX_GRAPHICS_RESPONSE_LEN]; 92 | /// Whether there was an error executing this command (not very useful, 93 | /// the response must be sent back anyway). 94 | char error; 95 | /// Whether the terminal has to create a placeholder for a non-virtual 96 | /// placement. 97 | char create_placeholder; 98 | /// The placeholder that needs to be created. 99 | struct { 100 | uint32_t rows, columns; 101 | uint32_t image_id, placement_id; 102 | char do_not_move_cursor; 103 | } placeholder; 104 | } GraphicsCommandResult; 105 | 106 | /// The result of a graphics command. 107 | extern GraphicsCommandResult graphics_command_result; 108 | -------------------------------------------------------------------------------- /st/kvec.h: -------------------------------------------------------------------------------- 1 | /* The MIT License 2 | 3 | Copyright (c) 2008, by Attractive Chaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | /* 27 | An example: 28 | 29 | #include "kvec.h" 30 | int main() { 31 | kvec_t(int) array; 32 | kv_init(array); 33 | kv_push(int, array, 10); // append 34 | kv_a(int, array, 20) = 5; // dynamic 35 | kv_A(array, 20) = 4; // static 36 | kv_destroy(array); 37 | return 0; 38 | } 39 | */ 40 | 41 | /* 42 | 2008-09-22 (0.1.0): 43 | 44 | * The initial version. 45 | 46 | */ 47 | 48 | #ifndef AC_KVEC_H 49 | #define AC_KVEC_H 50 | 51 | #include 52 | 53 | #define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 54 | 55 | #define kvec_t(type) struct { size_t n, m; type *a; } 56 | #define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) 57 | #define kv_destroy(v) free((v).a) 58 | #define kv_A(v, i) ((v).a[(i)]) 59 | #define kv_pop(v) ((v).a[--(v).n]) 60 | #define kv_size(v) ((v).n) 61 | #define kv_max(v) ((v).m) 62 | 63 | #define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) 64 | 65 | #define kv_copy(type, v1, v0) do { \ 66 | if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ 67 | (v1).n = (v0).n; \ 68 | memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ 69 | } while (0) \ 70 | 71 | #define kv_push(type, v, x) do { \ 72 | if ((v).n == (v).m) { \ 73 | (v).m = (v).m? (v).m<<1 : 2; \ 74 | (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ 75 | } \ 76 | (v).a[(v).n++] = (x); \ 77 | } while (0) 78 | 79 | #define kv_pushp(type, v) ((((v).n == (v).m)? \ 80 | ((v).m = ((v).m? (v).m<<1 : 2), \ 81 | (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ 82 | : 0), ((v).a + ((v).n++))) 83 | 84 | #define kv_a(type, v, i) (((v).m <= (size_t)(i)? \ 85 | ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ 86 | (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ 87 | : (v).n <= (size_t)(i)? (v).n = (i) + 1 \ 88 | : 0), (v).a[(i)]) 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /st/rowcolumn_diacritics_helpers.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint16_t diacritic_to_num(uint32_t code) 4 | { 5 | switch (code) { 6 | case 0x305: 7 | return code - 0x305 + 1; 8 | case 0x30d: 9 | case 0x30e: 10 | return code - 0x30d + 2; 11 | case 0x310: 12 | return code - 0x310 + 4; 13 | case 0x312: 14 | return code - 0x312 + 5; 15 | case 0x33d: 16 | case 0x33e: 17 | case 0x33f: 18 | return code - 0x33d + 6; 19 | case 0x346: 20 | return code - 0x346 + 9; 21 | case 0x34a: 22 | case 0x34b: 23 | case 0x34c: 24 | return code - 0x34a + 10; 25 | case 0x350: 26 | case 0x351: 27 | case 0x352: 28 | return code - 0x350 + 13; 29 | case 0x357: 30 | return code - 0x357 + 16; 31 | case 0x35b: 32 | return code - 0x35b + 17; 33 | case 0x363: 34 | case 0x364: 35 | case 0x365: 36 | case 0x366: 37 | case 0x367: 38 | case 0x368: 39 | case 0x369: 40 | case 0x36a: 41 | case 0x36b: 42 | case 0x36c: 43 | case 0x36d: 44 | case 0x36e: 45 | case 0x36f: 46 | return code - 0x363 + 18; 47 | case 0x483: 48 | case 0x484: 49 | case 0x485: 50 | case 0x486: 51 | case 0x487: 52 | return code - 0x483 + 31; 53 | case 0x592: 54 | case 0x593: 55 | case 0x594: 56 | case 0x595: 57 | return code - 0x592 + 36; 58 | case 0x597: 59 | case 0x598: 60 | case 0x599: 61 | return code - 0x597 + 40; 62 | case 0x59c: 63 | case 0x59d: 64 | case 0x59e: 65 | case 0x59f: 66 | case 0x5a0: 67 | case 0x5a1: 68 | return code - 0x59c + 43; 69 | case 0x5a8: 70 | case 0x5a9: 71 | return code - 0x5a8 + 49; 72 | case 0x5ab: 73 | case 0x5ac: 74 | return code - 0x5ab + 51; 75 | case 0x5af: 76 | return code - 0x5af + 53; 77 | case 0x5c4: 78 | return code - 0x5c4 + 54; 79 | case 0x610: 80 | case 0x611: 81 | case 0x612: 82 | case 0x613: 83 | case 0x614: 84 | case 0x615: 85 | case 0x616: 86 | case 0x617: 87 | return code - 0x610 + 55; 88 | case 0x657: 89 | case 0x658: 90 | case 0x659: 91 | case 0x65a: 92 | case 0x65b: 93 | return code - 0x657 + 63; 94 | case 0x65d: 95 | case 0x65e: 96 | return code - 0x65d + 68; 97 | case 0x6d6: 98 | case 0x6d7: 99 | case 0x6d8: 100 | case 0x6d9: 101 | case 0x6da: 102 | case 0x6db: 103 | case 0x6dc: 104 | return code - 0x6d6 + 70; 105 | case 0x6df: 106 | case 0x6e0: 107 | case 0x6e1: 108 | case 0x6e2: 109 | return code - 0x6df + 77; 110 | case 0x6e4: 111 | return code - 0x6e4 + 81; 112 | case 0x6e7: 113 | case 0x6e8: 114 | return code - 0x6e7 + 82; 115 | case 0x6eb: 116 | case 0x6ec: 117 | return code - 0x6eb + 84; 118 | case 0x730: 119 | return code - 0x730 + 86; 120 | case 0x732: 121 | case 0x733: 122 | return code - 0x732 + 87; 123 | case 0x735: 124 | case 0x736: 125 | return code - 0x735 + 89; 126 | case 0x73a: 127 | return code - 0x73a + 91; 128 | case 0x73d: 129 | return code - 0x73d + 92; 130 | case 0x73f: 131 | case 0x740: 132 | case 0x741: 133 | return code - 0x73f + 93; 134 | case 0x743: 135 | return code - 0x743 + 96; 136 | case 0x745: 137 | return code - 0x745 + 97; 138 | case 0x747: 139 | return code - 0x747 + 98; 140 | case 0x749: 141 | case 0x74a: 142 | return code - 0x749 + 99; 143 | case 0x7eb: 144 | case 0x7ec: 145 | case 0x7ed: 146 | case 0x7ee: 147 | case 0x7ef: 148 | case 0x7f0: 149 | case 0x7f1: 150 | return code - 0x7eb + 101; 151 | case 0x7f3: 152 | return code - 0x7f3 + 108; 153 | case 0x816: 154 | case 0x817: 155 | case 0x818: 156 | case 0x819: 157 | return code - 0x816 + 109; 158 | case 0x81b: 159 | case 0x81c: 160 | case 0x81d: 161 | case 0x81e: 162 | case 0x81f: 163 | case 0x820: 164 | case 0x821: 165 | case 0x822: 166 | case 0x823: 167 | return code - 0x81b + 113; 168 | case 0x825: 169 | case 0x826: 170 | case 0x827: 171 | return code - 0x825 + 122; 172 | case 0x829: 173 | case 0x82a: 174 | case 0x82b: 175 | case 0x82c: 176 | case 0x82d: 177 | return code - 0x829 + 125; 178 | case 0x951: 179 | return code - 0x951 + 130; 180 | case 0x953: 181 | case 0x954: 182 | return code - 0x953 + 131; 183 | case 0xf82: 184 | case 0xf83: 185 | return code - 0xf82 + 133; 186 | case 0xf86: 187 | case 0xf87: 188 | return code - 0xf86 + 135; 189 | case 0x135d: 190 | case 0x135e: 191 | case 0x135f: 192 | return code - 0x135d + 137; 193 | case 0x17dd: 194 | return code - 0x17dd + 140; 195 | case 0x193a: 196 | return code - 0x193a + 141; 197 | case 0x1a17: 198 | return code - 0x1a17 + 142; 199 | case 0x1a75: 200 | case 0x1a76: 201 | case 0x1a77: 202 | case 0x1a78: 203 | case 0x1a79: 204 | case 0x1a7a: 205 | case 0x1a7b: 206 | case 0x1a7c: 207 | return code - 0x1a75 + 143; 208 | case 0x1b6b: 209 | return code - 0x1b6b + 151; 210 | case 0x1b6d: 211 | case 0x1b6e: 212 | case 0x1b6f: 213 | case 0x1b70: 214 | case 0x1b71: 215 | case 0x1b72: 216 | case 0x1b73: 217 | return code - 0x1b6d + 152; 218 | case 0x1cd0: 219 | case 0x1cd1: 220 | case 0x1cd2: 221 | return code - 0x1cd0 + 159; 222 | case 0x1cda: 223 | case 0x1cdb: 224 | return code - 0x1cda + 162; 225 | case 0x1ce0: 226 | return code - 0x1ce0 + 164; 227 | case 0x1dc0: 228 | case 0x1dc1: 229 | return code - 0x1dc0 + 165; 230 | case 0x1dc3: 231 | case 0x1dc4: 232 | case 0x1dc5: 233 | case 0x1dc6: 234 | case 0x1dc7: 235 | case 0x1dc8: 236 | case 0x1dc9: 237 | return code - 0x1dc3 + 167; 238 | case 0x1dcb: 239 | case 0x1dcc: 240 | return code - 0x1dcb + 174; 241 | case 0x1dd1: 242 | case 0x1dd2: 243 | case 0x1dd3: 244 | case 0x1dd4: 245 | case 0x1dd5: 246 | case 0x1dd6: 247 | case 0x1dd7: 248 | case 0x1dd8: 249 | case 0x1dd9: 250 | case 0x1dda: 251 | case 0x1ddb: 252 | case 0x1ddc: 253 | case 0x1ddd: 254 | case 0x1dde: 255 | case 0x1ddf: 256 | case 0x1de0: 257 | case 0x1de1: 258 | case 0x1de2: 259 | case 0x1de3: 260 | case 0x1de4: 261 | case 0x1de5: 262 | case 0x1de6: 263 | return code - 0x1dd1 + 176; 264 | case 0x1dfe: 265 | return code - 0x1dfe + 198; 266 | case 0x20d0: 267 | case 0x20d1: 268 | return code - 0x20d0 + 199; 269 | case 0x20d4: 270 | case 0x20d5: 271 | case 0x20d6: 272 | case 0x20d7: 273 | return code - 0x20d4 + 201; 274 | case 0x20db: 275 | case 0x20dc: 276 | return code - 0x20db + 205; 277 | case 0x20e1: 278 | return code - 0x20e1 + 207; 279 | case 0x20e7: 280 | return code - 0x20e7 + 208; 281 | case 0x20e9: 282 | return code - 0x20e9 + 209; 283 | case 0x20f0: 284 | return code - 0x20f0 + 210; 285 | case 0x2cef: 286 | case 0x2cf0: 287 | case 0x2cf1: 288 | return code - 0x2cef + 211; 289 | case 0x2de0: 290 | case 0x2de1: 291 | case 0x2de2: 292 | case 0x2de3: 293 | case 0x2de4: 294 | case 0x2de5: 295 | case 0x2de6: 296 | case 0x2de7: 297 | case 0x2de8: 298 | case 0x2de9: 299 | case 0x2dea: 300 | case 0x2deb: 301 | case 0x2dec: 302 | case 0x2ded: 303 | case 0x2dee: 304 | case 0x2def: 305 | case 0x2df0: 306 | case 0x2df1: 307 | case 0x2df2: 308 | case 0x2df3: 309 | case 0x2df4: 310 | case 0x2df5: 311 | case 0x2df6: 312 | case 0x2df7: 313 | case 0x2df8: 314 | case 0x2df9: 315 | case 0x2dfa: 316 | case 0x2dfb: 317 | case 0x2dfc: 318 | case 0x2dfd: 319 | case 0x2dfe: 320 | case 0x2dff: 321 | return code - 0x2de0 + 214; 322 | case 0xa66f: 323 | return code - 0xa66f + 246; 324 | case 0xa67c: 325 | case 0xa67d: 326 | return code - 0xa67c + 247; 327 | case 0xa6f0: 328 | case 0xa6f1: 329 | return code - 0xa6f0 + 249; 330 | case 0xa8e0: 331 | case 0xa8e1: 332 | case 0xa8e2: 333 | case 0xa8e3: 334 | case 0xa8e4: 335 | case 0xa8e5: 336 | case 0xa8e6: 337 | case 0xa8e7: 338 | case 0xa8e8: 339 | case 0xa8e9: 340 | case 0xa8ea: 341 | case 0xa8eb: 342 | case 0xa8ec: 343 | case 0xa8ed: 344 | case 0xa8ee: 345 | case 0xa8ef: 346 | case 0xa8f0: 347 | case 0xa8f1: 348 | return code - 0xa8e0 + 251; 349 | case 0xaab0: 350 | return code - 0xaab0 + 269; 351 | case 0xaab2: 352 | case 0xaab3: 353 | return code - 0xaab2 + 270; 354 | case 0xaab7: 355 | case 0xaab8: 356 | return code - 0xaab7 + 272; 357 | case 0xaabe: 358 | case 0xaabf: 359 | return code - 0xaabe + 274; 360 | case 0xaac1: 361 | return code - 0xaac1 + 276; 362 | case 0xfe20: 363 | case 0xfe21: 364 | case 0xfe22: 365 | case 0xfe23: 366 | case 0xfe24: 367 | case 0xfe25: 368 | case 0xfe26: 369 | return code - 0xfe20 + 277; 370 | case 0x10a0f: 371 | return code - 0x10a0f + 284; 372 | case 0x10a38: 373 | return code - 0x10a38 + 285; 374 | case 0x1d185: 375 | case 0x1d186: 376 | case 0x1d187: 377 | case 0x1d188: 378 | case 0x1d189: 379 | return code - 0x1d185 + 286; 380 | case 0x1d1aa: 381 | case 0x1d1ab: 382 | case 0x1d1ac: 383 | case 0x1d1ad: 384 | return code - 0x1d1aa + 291; 385 | case 0x1d242: 386 | case 0x1d243: 387 | case 0x1d244: 388 | return code - 0x1d242 + 295; 389 | } 390 | return 0; 391 | } 392 | -------------------------------------------------------------------------------- /st/st.1: -------------------------------------------------------------------------------- 1 | .TH ST 1 st\-VERSION 2 | .SH NAME 3 | st \- simple terminal 4 | .SH SYNOPSIS 5 | .B st 6 | .RB [ \-aiv ] 7 | .RB [ \-c 8 | .IR class ] 9 | .RB [ \-f 10 | .IR font ] 11 | .RB [ \-g 12 | .IR geometry ] 13 | .RB [ \-n 14 | .IR name ] 15 | .RB [ \-o 16 | .IR iofile ] 17 | .RB [ \-T 18 | .IR title ] 19 | .RB [ \-t 20 | .IR title ] 21 | .RB [ \-l 22 | .IR line ] 23 | .RB [ \-w 24 | .IR windowid ] 25 | .RB [[ \-e ] 26 | .IR command 27 | .RI [ arguments ...]] 28 | .PP 29 | .B st 30 | .RB [ \-aiv ] 31 | .RB [ \-c 32 | .IR class ] 33 | .RB [ \-f 34 | .IR font ] 35 | .RB [ \-g 36 | .IR geometry ] 37 | .RB [ \-n 38 | .IR name ] 39 | .RB [ \-o 40 | .IR iofile ] 41 | .RB [ \-T 42 | .IR title ] 43 | .RB [ \-t 44 | .IR title ] 45 | .RB [ \-w 46 | .IR windowid ] 47 | .RB \-l 48 | .IR line 49 | .RI [ stty_args ...] 50 | .SH DESCRIPTION 51 | .B st 52 | is a simple terminal emulator. 53 | .SH OPTIONS 54 | .TP 55 | .B \-a 56 | disable alternate screens in terminal 57 | .TP 58 | .BI \-c " class" 59 | defines the window class (default $TERM). 60 | .TP 61 | .BI \-f " font" 62 | defines the 63 | .I font 64 | to use when st is run. 65 | .TP 66 | .BI \-g " geometry" 67 | defines the X11 geometry string. 68 | The form is [=][{xX}][{+-}{+-}]. See 69 | .BR XParseGeometry (3) 70 | for further details. 71 | .TP 72 | .B \-i 73 | will fixate the position given with the -g option. 74 | .TP 75 | .BI \-n " name" 76 | defines the window instance name (default $TERM). 77 | .TP 78 | .BI \-o " iofile" 79 | writes all the I/O to 80 | .I iofile. 81 | This feature is useful when recording st sessions. A value of "-" means 82 | standard output. 83 | .TP 84 | .BI \-T " title" 85 | defines the window title (default 'st'). 86 | .TP 87 | .BI \-t " title" 88 | defines the window title (default 'st'). 89 | .TP 90 | .BI \-w " windowid" 91 | embeds st within the window identified by 92 | .I windowid 93 | .TP 94 | .BI \-l " line" 95 | use a tty 96 | .I line 97 | instead of a pseudo terminal. 98 | .I line 99 | should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port 100 | 0). 101 | When this flag is given 102 | remaining arguments are used as flags for 103 | .BR stty(1). 104 | By default st initializes the serial line to 8 bits, no parity, 1 stop bit 105 | and a 38400 baud rate. The speed is set by appending it as last argument 106 | (e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are 107 | .BR stty(1) 108 | flags. If you want to set odd parity on 115200 baud use for example 'st -l 109 | /dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for 110 | example 'st -l /dev/ttyS0 cs7 115200'. See 111 | .BR stty(1) 112 | for more arguments and cases. 113 | .TP 114 | .B \-v 115 | prints version information to stderr, then exits. 116 | .TP 117 | .BI \-e " command " [ " arguments " "... ]" 118 | st executes 119 | .I command 120 | instead of the shell. If this is used it 121 | .B must be the last option 122 | on the command line, as in xterm / rxvt. 123 | This option is only intended for compatibility, 124 | and all the remaining arguments are used as a command 125 | even without it. 126 | .SH SHORTCUTS 127 | .TP 128 | .B Break 129 | Send a break in the serial line. 130 | Break key is obtained in PC keyboards 131 | pressing at the same time control and pause. 132 | .TP 133 | .B Ctrl-Print Screen 134 | Toggle if st should print to the 135 | .I iofile. 136 | .TP 137 | .B Shift-Print Screen 138 | Print the full screen to the 139 | .I iofile. 140 | .TP 141 | .B Print Screen 142 | Print the selection to the 143 | .I iofile. 144 | .TP 145 | .B Ctrl-Shift-Page Up 146 | Increase font size. 147 | .TP 148 | .B Ctrl-Shift-Page Down 149 | Decrease font size. 150 | .TP 151 | .B Ctrl-Shift-Home 152 | Reset to default font size. 153 | .TP 154 | .B Ctrl-Shift-y 155 | Paste from primary selection (middle mouse button). 156 | .TP 157 | .B Ctrl-Shift-c 158 | Copy the selected text to the clipboard selection. 159 | .TP 160 | .B Ctrl-Shift-v 161 | Paste from the clipboard selection. 162 | .SH CUSTOMIZATION 163 | .B st 164 | can be customized by creating a custom config.h and (re)compiling the source 165 | code. This keeps it fast, secure and simple. 166 | .SH AUTHORS 167 | See the LICENSE file for the authors. 168 | .SH LICENSE 169 | See the LICENSE file for the terms of redistribution. 170 | .SH SEE ALSO 171 | .BR tabbed (1), 172 | .BR utmp (1), 173 | .BR stty (1), 174 | .BR scroll (1) 175 | .SH BUGS 176 | See the TODO file in the distribution. 177 | 178 | -------------------------------------------------------------------------------- /st/st.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE for license details. */ 2 | 3 | #include 4 | #include 5 | 6 | /* macros */ 7 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 8 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) 9 | #define LEN(a) (sizeof(a) / sizeof(a)[0]) 10 | #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) 11 | #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) 12 | #define DEFAULT(a, b) (a) = (a) ? (a) : (b) 13 | #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) 14 | #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ 15 | (a).bg != (b).bg || (a).decor != (b).decor) 16 | #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ 17 | (t1.tv_nsec-t2.tv_nsec)/1E6) 18 | #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) 19 | 20 | #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) 21 | #define IS_TRUECOL(x) (1 << 24 & (x)) 22 | 23 | // This decor color indicates that the fg color should be used. Note that it's 24 | // not a 24-bit color because the 25-th bit is not set. 25 | #define DECOR_DEFAULT_COLOR 0x0ffffff 26 | 27 | enum glyph_attribute { 28 | ATTR_NULL = 0, 29 | ATTR_BOLD = 1 << 0, 30 | ATTR_FAINT = 1 << 1, 31 | ATTR_ITALIC = 1 << 2, 32 | ATTR_UNDERLINE = 1 << 3, 33 | ATTR_BLINK = 1 << 4, 34 | ATTR_REVERSE = 1 << 5, 35 | ATTR_INVISIBLE = 1 << 6, 36 | ATTR_STRUCK = 1 << 7, 37 | ATTR_WRAP = 1 << 8, 38 | ATTR_WIDE = 1 << 9, 39 | ATTR_WDUMMY = 1 << 10, 40 | ATTR_BOXDRAW = 1 << 11, 41 | ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, 42 | ATTR_IMAGE = 1 << 14, 43 | }; 44 | 45 | enum selection_mode { 46 | SEL_IDLE = 0, 47 | SEL_EMPTY = 1, 48 | SEL_READY = 2 49 | }; 50 | 51 | enum selection_type { 52 | SEL_REGULAR = 1, 53 | SEL_RECTANGULAR = 2 54 | }; 55 | 56 | enum selection_snap { 57 | SNAP_WORD = 1, 58 | SNAP_LINE = 2 59 | }; 60 | 61 | enum underline_style { 62 | UNDERLINE_STRAIGHT = 1, 63 | UNDERLINE_DOUBLE = 2, 64 | UNDERLINE_CURLY = 3, 65 | UNDERLINE_DOTTED = 4, 66 | UNDERLINE_DASHED = 5, 67 | }; 68 | 69 | typedef unsigned char uchar; 70 | typedef unsigned int uint; 71 | typedef unsigned long ulong; 72 | typedef unsigned short ushort; 73 | 74 | typedef uint_least32_t Rune; 75 | 76 | #define Glyph Glyph_ 77 | typedef struct { 78 | Rune u; /* character code */ 79 | ushort mode; /* attribute flags */ 80 | uint32_t fg; /* foreground */ 81 | uint32_t bg; /* background */ 82 | uint32_t decor; /* decoration (like underline) */ 83 | } Glyph; 84 | 85 | typedef Glyph *Line; 86 | 87 | typedef union { 88 | int i; 89 | uint ui; 90 | float f; 91 | const void *v; 92 | const char *s; 93 | } Arg; 94 | 95 | void die(const char *, ...); 96 | void redraw(void); 97 | void draw(void); 98 | 99 | void kscrolldown(const Arg *); 100 | void kscrollup(const Arg *); 101 | void printscreen(const Arg *); 102 | void printsel(const Arg *); 103 | void sendbreak(const Arg *); 104 | void toggleprinter(const Arg *); 105 | 106 | int tattrset(int); 107 | void tnew(int, int); 108 | void tresize(int, int); 109 | void tsetdirtattr(int); 110 | void ttyhangup(void); 111 | int ttynew(const char *, char *, const char *, char **); 112 | size_t ttyread(void); 113 | void ttyresize(int, int); 114 | void ttywrite(const char *, size_t, int); 115 | 116 | void resettitle(void); 117 | 118 | void selclear(void); 119 | void selinit(void); 120 | void selstart(int, int, int); 121 | void selextend(int, int, int, int); 122 | int selected(int, int); 123 | char *getsel(void); 124 | 125 | Glyph getglyphat(int, int); 126 | 127 | size_t utf8encode(Rune, char *); 128 | 129 | void *xmalloc(size_t); 130 | void *xrealloc(void *, size_t); 131 | char *xstrdup(const char *); 132 | 133 | int isboxdraw(Rune); 134 | ushort boxdrawindex(const Glyph *); 135 | #ifdef XFT_VERSION 136 | /* only exposed to x.c, otherwise we'll need Xft.h for the types */ 137 | void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *); 138 | void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int); 139 | #endif 140 | 141 | /* config.h globals */ 142 | extern char *utmp; 143 | extern char *scroll; 144 | extern char *stty_args; 145 | extern char *vtiden; 146 | extern wchar_t *worddelimiters; 147 | extern int allowaltscreen; 148 | extern int allowwindowops; 149 | extern char *termname; 150 | extern unsigned int tabspaces; 151 | extern unsigned int defaultfg; 152 | extern unsigned int defaultbg; 153 | extern unsigned int defaultcs; 154 | extern const int boxdraw, boxdraw_bold, boxdraw_braille; 155 | 156 | // Accessors to decoration properties stored in `decor`. 157 | // The 25-th bit is used to indicate if it's a 24-bit color. 158 | static inline uint32_t tgetdecorcolor(Glyph *g) { return g->decor & 0x1ffffff; } 159 | static inline uint32_t tgetdecorstyle(Glyph *g) { return (g->decor >> 25) & 0x7; } 160 | static inline void tsetdecorcolor(Glyph *g, uint32_t color) { 161 | g->decor = (g->decor & ~0x1ffffff) | (color & 0x1ffffff); 162 | } 163 | static inline void tsetdecorstyle(Glyph *g, uint32_t style) { 164 | g->decor = (g->decor & ~(0x7 << 25)) | ((style & 0x7) << 25); 165 | } 166 | 167 | 168 | // Some accessors to image placeholder properties stored in `u`: 169 | // - row (1-base) - 9 bits 170 | // - column (1-base) - 9 bits 171 | // - most significant byte of the image id plus 1 - 9 bits (0 means unspecified, 172 | // don't forget to subtract 1). 173 | // - the original number of diacritics (0, 1, 2, or 3) - 2 bits 174 | // - whether this is a classic (1) or Unicode (0) placeholder - 1 bit 175 | static inline uint32_t tgetimgrow(Glyph *g) { return g->u & 0x1ff; } 176 | static inline uint32_t tgetimgcol(Glyph *g) { return (g->u >> 9) & 0x1ff; } 177 | static inline uint32_t tgetimgid4thbyteplus1(Glyph *g) { return (g->u >> 18) & 0x1ff; } 178 | static inline uint32_t tgetimgdiacriticcount(Glyph *g) { return (g->u >> 27) & 0x3; } 179 | static inline uint32_t tgetisclassicplaceholder(Glyph *g) { return (g->u >> 29) & 0x1; } 180 | static inline void tsetimgrow(Glyph *g, uint32_t row) { 181 | g->u = (g->u & ~0x1ff) | (row & 0x1ff); 182 | } 183 | static inline void tsetimgcol(Glyph *g, uint32_t col) { 184 | g->u = (g->u & ~(0x1ff << 9)) | ((col & 0x1ff) << 9); 185 | } 186 | static inline void tsetimg4thbyteplus1(Glyph *g, uint32_t byteplus1) { 187 | g->u = (g->u & ~(0x1ff << 18)) | ((byteplus1 & 0x1ff) << 18); 188 | } 189 | static inline void tsetimgdiacriticcount(Glyph *g, uint32_t count) { 190 | g->u = (g->u & ~(0x3 << 27)) | ((count & 0x3) << 27); 191 | } 192 | static inline void tsetisclassicplaceholder(Glyph *g, uint32_t isclassic) { 193 | g->u = (g->u & ~(0x1 << 29)) | ((isclassic & 0x1) << 29); 194 | } 195 | 196 | /// Returns the full image id. This is a naive implementation, if the most 197 | /// significant byte is not specified, it's assumed to be 0 instead of inferring 198 | /// it from the cells to the left. 199 | static inline uint32_t tgetimgid(Glyph *g) { 200 | uint32_t msb = tgetimgid4thbyteplus1(g); 201 | if (msb != 0) 202 | --msb; 203 | return (msb << 24) | (g->fg & 0xFFFFFF); 204 | } 205 | 206 | /// Sets the full image id. 207 | static inline void tsetimgid(Glyph *g, uint32_t id) { 208 | g->fg = (id & 0xFFFFFF) | (1 << 24); 209 | tsetimg4thbyteplus1(g, ((id >> 24) & 0xFF) + 1); 210 | } 211 | 212 | static inline uint32_t tgetimgplacementid(Glyph *g) { 213 | if (tgetdecorcolor(g) == DECOR_DEFAULT_COLOR) 214 | return 0; 215 | return g->decor & 0xFFFFFF; 216 | } 217 | 218 | static inline void tsetimgplacementid(Glyph *g, uint32_t id) { 219 | g->decor = (id & 0xFFFFFF) | (1 << 24); 220 | } 221 | -------------------------------------------------------------------------------- /st/st.info: -------------------------------------------------------------------------------- 1 | st-mono| simpleterm monocolor, 2 | acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, 3 | am, 4 | bce, 5 | bel=^G, 6 | blink=\E[5m, 7 | bold=\E[1m, 8 | cbt=\E[Z, 9 | cvvis=\E[?25h, 10 | civis=\E[?25l, 11 | clear=\E[H\E[2J, 12 | cnorm=\E[?12l\E[?25h, 13 | colors#2, 14 | cols#80, 15 | cr=^M, 16 | csr=\E[%i%p1%d;%p2%dr, 17 | cub=\E[%p1%dD, 18 | cub1=^H, 19 | cud1=^J, 20 | cud=\E[%p1%dB, 21 | cuf1=\E[C, 22 | cuf=\E[%p1%dC, 23 | cup=\E[%i%p1%d;%p2%dH, 24 | cuu1=\E[A, 25 | cuu=\E[%p1%dA, 26 | dch=\E[%p1%dP, 27 | dch1=\E[P, 28 | dim=\E[2m, 29 | dl=\E[%p1%dM, 30 | dl1=\E[M, 31 | ech=\E[%p1%dX, 32 | ed=\E[J, 33 | el=\E[K, 34 | el1=\E[1K, 35 | enacs=\E)0, 36 | flash=\E[?5h$<80/>\E[?5l, 37 | fsl=^G, 38 | home=\E[H, 39 | hpa=\E[%i%p1%dG, 40 | hs, 41 | ht=^I, 42 | hts=\EH, 43 | ich=\E[%p1%d@, 44 | il1=\E[L, 45 | il=\E[%p1%dL, 46 | ind=^J, 47 | indn=\E[%p1%dS, 48 | invis=\E[8m, 49 | is2=\E[4l\E>\E[?1034l, 50 | it#8, 51 | kel=\E[1;2F, 52 | ked=\E[1;5F, 53 | ka1=\E[1~, 54 | ka3=\E[5~, 55 | kc1=\E[4~, 56 | kc3=\E[6~, 57 | kbs=\177, 58 | kcbt=\E[Z, 59 | kb2=\EOu, 60 | kcub1=\EOD, 61 | kcud1=\EOB, 62 | kcuf1=\EOC, 63 | kcuu1=\EOA, 64 | kDC=\E[3;2~, 65 | kent=\EOM, 66 | kEND=\E[1;2F, 67 | kIC=\E[2;2~, 68 | kNXT=\E[6;2~, 69 | kPRV=\E[5;2~, 70 | kHOM=\E[1;2H, 71 | kLFT=\E[1;2D, 72 | kRIT=\E[1;2C, 73 | kind=\E[1;2B, 74 | kri=\E[1;2A, 75 | kclr=\E[3;5~, 76 | kdl1=\E[3;2~, 77 | kdch1=\E[3~, 78 | kich1=\E[2~, 79 | kend=\E[4~, 80 | kf1=\EOP, 81 | kf2=\EOQ, 82 | kf3=\EOR, 83 | kf4=\EOS, 84 | kf5=\E[15~, 85 | kf6=\E[17~, 86 | kf7=\E[18~, 87 | kf8=\E[19~, 88 | kf9=\E[20~, 89 | kf10=\E[21~, 90 | kf11=\E[23~, 91 | kf12=\E[24~, 92 | kf13=\E[1;2P, 93 | kf14=\E[1;2Q, 94 | kf15=\E[1;2R, 95 | kf16=\E[1;2S, 96 | kf17=\E[15;2~, 97 | kf18=\E[17;2~, 98 | kf19=\E[18;2~, 99 | kf20=\E[19;2~, 100 | kf21=\E[20;2~, 101 | kf22=\E[21;2~, 102 | kf23=\E[23;2~, 103 | kf24=\E[24;2~, 104 | kf25=\E[1;5P, 105 | kf26=\E[1;5Q, 106 | kf27=\E[1;5R, 107 | kf28=\E[1;5S, 108 | kf29=\E[15;5~, 109 | kf30=\E[17;5~, 110 | kf31=\E[18;5~, 111 | kf32=\E[19;5~, 112 | kf33=\E[20;5~, 113 | kf34=\E[21;5~, 114 | kf35=\E[23;5~, 115 | kf36=\E[24;5~, 116 | kf37=\E[1;6P, 117 | kf38=\E[1;6Q, 118 | kf39=\E[1;6R, 119 | kf40=\E[1;6S, 120 | kf41=\E[15;6~, 121 | kf42=\E[17;6~, 122 | kf43=\E[18;6~, 123 | kf44=\E[19;6~, 124 | kf45=\E[20;6~, 125 | kf46=\E[21;6~, 126 | kf47=\E[23;6~, 127 | kf48=\E[24;6~, 128 | kf49=\E[1;3P, 129 | kf50=\E[1;3Q, 130 | kf51=\E[1;3R, 131 | kf52=\E[1;3S, 132 | kf53=\E[15;3~, 133 | kf54=\E[17;3~, 134 | kf55=\E[18;3~, 135 | kf56=\E[19;3~, 136 | kf57=\E[20;3~, 137 | kf58=\E[21;3~, 138 | kf59=\E[23;3~, 139 | kf60=\E[24;3~, 140 | kf61=\E[1;4P, 141 | kf62=\E[1;4Q, 142 | kf63=\E[1;4R, 143 | khome=\E[1~, 144 | kil1=\E[2;5~, 145 | krmir=\E[2;2~, 146 | knp=\E[6~, 147 | kmous=\E[M, 148 | kpp=\E[5~, 149 | lines#24, 150 | mir, 151 | msgr, 152 | npc, 153 | op=\E[39;49m, 154 | pairs#64, 155 | mc0=\E[i, 156 | mc4=\E[4i, 157 | mc5=\E[5i, 158 | rc=\E8, 159 | rev=\E[7m, 160 | ri=\EM, 161 | rin=\E[%p1%dT, 162 | ritm=\E[23m, 163 | rmacs=\E(B, 164 | rmcup=\E[?1049l, 165 | rmir=\E[4l, 166 | rmkx=\E[?1l\E>, 167 | rmso=\E[27m, 168 | rmul=\E[24m, 169 | rs1=\Ec, 170 | rs2=\E[4l\E>\E[?1034l, 171 | sc=\E7, 172 | sitm=\E[3m, 173 | sgr0=\E[0m, 174 | smacs=\E(0, 175 | smcup=\E[?1049h, 176 | smir=\E[4h, 177 | smkx=\E[?1h\E=, 178 | smso=\E[7m, 179 | smul=\E[4m, 180 | tbc=\E[3g, 181 | tsl=\E]0;, 182 | xenl, 183 | vpa=\E[%i%p1%dd, 184 | # XTerm extensions 185 | rmxx=\E[29m, 186 | smxx=\E[9m, 187 | BE=\E[?2004h, 188 | BD=\E[?2004l, 189 | PS=\E[200~, 190 | PE=\E[201~, 191 | # disabled rep for now: causes some issues with older ncurses versions. 192 | # rep=%p1%c\E[%p2%{1}%-%db, 193 | # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) 194 | Tc, 195 | Ms=\E]52;%p1%s;%p2%s\007, 196 | Se=\E[2 q, 197 | Ss=\E[%p1%d q, 198 | Smulx=\E[4:%p1%dm, 199 | 200 | st| simpleterm, 201 | use=st-mono, 202 | colors#8, 203 | setab=\E[4%p1%dm, 204 | setaf=\E[3%p1%dm, 205 | setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, 206 | setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, 207 | 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, 208 | 209 | st-256color| simpleterm with 256 colors, 210 | use=st, 211 | ccc, 212 | colors#256, 213 | oc=\E]104\007, 214 | pairs#32767, 215 | # Nicked from xterm-256color 216 | initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, 217 | setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, 218 | setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, 219 | # Underline colors 220 | Su, 221 | Setulc=\E[58:2:%p1%{65536}%/%d:%p1%{256}%/%{255}%&%d:%p1%{255}%&%d%;m, 222 | Setulc1=\E[58:5:%p1%dm, 223 | ol=\E[59m, 224 | 225 | st-meta| simpleterm with meta key, 226 | use=st, 227 | km, 228 | rmm=\E[?1034l, 229 | smm=\E[?1034h, 230 | rs2=\E[4l\E>\E[?1034h, 231 | is2=\E[4l\E>\E[?1034h, 232 | 233 | st-meta-256color| simpleterm with meta key and 256 colors, 234 | use=st-256color, 235 | km, 236 | rmm=\E[?1034l, 237 | smm=\E[?1034h, 238 | rs2=\E[4l\E>\E[?1034h, 239 | is2=\E[4l\E>\E[?1034h, 240 | 241 | st-bs| simpleterm with backspace as backspace, 242 | use=st, 243 | kbs=\010, 244 | kdch1=\177, 245 | 246 | st-bs-256color| simpleterm with backspace as backspace and 256colors, 247 | use=st-256color, 248 | kbs=\010, 249 | kdch1=\177, 250 | -------------------------------------------------------------------------------- /st/win.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE for license details. */ 2 | 3 | enum win_mode { 4 | MODE_VISIBLE = 1 << 0, 5 | MODE_FOCUSED = 1 << 1, 6 | MODE_APPKEYPAD = 1 << 2, 7 | MODE_MOUSEBTN = 1 << 3, 8 | MODE_MOUSEMOTION = 1 << 4, 9 | MODE_REVERSE = 1 << 5, 10 | MODE_KBDLOCK = 1 << 6, 11 | MODE_HIDE = 1 << 7, 12 | MODE_APPCURSOR = 1 << 8, 13 | MODE_MOUSESGR = 1 << 9, 14 | MODE_8BIT = 1 << 10, 15 | MODE_BLINK = 1 << 11, 16 | MODE_FBLINK = 1 << 12, 17 | MODE_FOCUS = 1 << 13, 18 | MODE_MOUSEX10 = 1 << 14, 19 | MODE_MOUSEMANY = 1 << 15, 20 | MODE_BRCKTPASTE = 1 << 16, 21 | MODE_NUMLOCK = 1 << 17, 22 | MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ 23 | |MODE_MOUSEMANY, 24 | }; 25 | 26 | void xbell(void); 27 | void xclipcopy(void); 28 | void xdrawcursor(int, int, Glyph, int, int, Glyph); 29 | void xdrawline(Line, int, int, int); 30 | void xfinishdraw(void); 31 | void xloadcols(void); 32 | int xsetcolorname(int, const char *); 33 | int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); 34 | void xseticontitle(char *); 35 | void xsettitle(char *); 36 | int xsetcursor(int); 37 | void xsetmode(int, unsigned int); 38 | void xsetpointermotion(int); 39 | void xsetsel(char *); 40 | int xstartdraw(void); 41 | void xximspot(int, int); 42 | 43 | void xstartimagedraw(int *dirty, int rows); 44 | void xfinishimagedraw(); 45 | --------------------------------------------------------------------------------