init
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| *.o | ||||
							
								
								
									
										38
									
								
								dwm/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								dwm/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| MIT/X Consortium License | ||||
|  | ||||
| © 2006-2019 Anselm R Garbe <anselm@garbe.ca> | ||||
| © 2006-2009 Jukka Salmi <jukka at salmi dot ch> | ||||
| © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> | ||||
| © 2007-2011 Peter Hartlich <sgkkr at hartlich dot com> | ||||
| © 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com> | ||||
| © 2007-2009 Christof Musik <christof at sendfax dot de> | ||||
| © 2007-2009 Premysl Hruby <dfenze at gmail dot com> | ||||
| © 2007-2008 Enno Gottox Boland <gottox at s01 dot de> | ||||
| © 2008 Martin Hurton <martin dot hurton at gmail dot com> | ||||
| © 2008 Neale Pickett <neale dot woozle dot org> | ||||
| © 2009 Mate Nagy <mnagy at port70 dot net> | ||||
| © 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org> | ||||
| © 2010-2012 Connor Lane Smith <cls@lubutu.com> | ||||
| © 2011 Christoph Lohmann <20h@r-36.net> | ||||
| © 2015-2016 Quentin Rameau <quinq@fifth.space> | ||||
| © 2015-2016 Eric Pruitt <eric.pruitt@gmail.com> | ||||
| © 2016-2017 Markus Teich <markus.teich@stusta.mhn.de> | ||||
| © 2020-2022 Chris Down <chris@chrisdown.name> | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a | ||||
| copy of this software and associated documentation files (the "Software"), | ||||
| to deal in the Software without restriction, including without limitation | ||||
| the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
| and/or sell copies of the Software, and to permit persons to whom the | ||||
| Software is furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | ||||
| THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
| DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										45
									
								
								dwm/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								dwm/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| # dwm - dynamic window manager | ||||
| # See LICENSE file for copyright and license details. | ||||
|  | ||||
| include config.mk | ||||
|  | ||||
| SRC = drw.c dwm.c util.c | ||||
| OBJ = ${SRC:.c=.o} | ||||
|  | ||||
| all: dwm | ||||
|  | ||||
| .c.o: | ||||
| 	${CC} -c ${CFLAGS} $< | ||||
|  | ||||
| ${OBJ}: config.h config.mk | ||||
|  | ||||
| config.h: | ||||
| 	cp config.def.h $@ | ||||
|  | ||||
| dwm: ${OBJ} | ||||
| 	${CC} -o $@ ${OBJ} ${LDFLAGS} | ||||
|  | ||||
| clean: | ||||
| 	rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz | ||||
|  | ||||
| dist: clean | ||||
| 	mkdir -p dwm-${VERSION} | ||||
| 	cp -R LICENSE Makefile README config.def.h config.mk\ | ||||
| 		dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} | ||||
| 	tar -cf dwm-${VERSION}.tar dwm-${VERSION} | ||||
| 	gzip dwm-${VERSION}.tar | ||||
| 	rm -rf dwm-${VERSION} | ||||
|  | ||||
| install: all | ||||
| 	mkdir -p ${DESTDIR}${PREFIX}/bin | ||||
| 	cp -f dwm ${DESTDIR}${PREFIX}/bin | ||||
| 	chmod 755 ${DESTDIR}${PREFIX}/bin/dwm | ||||
| 	mkdir -p ${DESTDIR}${MANPREFIX}/man1 | ||||
| 	sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 | ||||
| 	chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 | ||||
|  | ||||
| uninstall: | ||||
| 	rm -f ${DESTDIR}${PREFIX}/bin/dwm\ | ||||
| 		${DESTDIR}${MANPREFIX}/man1/dwm.1 | ||||
|  | ||||
| .PHONY: all clean dist install uninstall | ||||
							
								
								
									
										48
									
								
								dwm/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								dwm/README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| dwm - dynamic window manager | ||||
| ============================ | ||||
| dwm is an extremely fast, small, and dynamic window manager for X. | ||||
|  | ||||
|  | ||||
| Requirements | ||||
| ------------ | ||||
| In order to build dwm you need the Xlib header files. | ||||
|  | ||||
|  | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup (dwm is installed into | ||||
| the /usr/local namespace by default). | ||||
|  | ||||
| Afterwards enter the following command to build and install dwm (if | ||||
| necessary as root): | ||||
|  | ||||
|     make clean install | ||||
|  | ||||
|  | ||||
| Running dwm | ||||
| ----------- | ||||
| Add the following line to your .xinitrc to start dwm using startx: | ||||
|  | ||||
|     exec dwm | ||||
|  | ||||
| In order to connect dwm to a specific display, make sure that | ||||
| the DISPLAY environment variable is set correctly, e.g.: | ||||
|  | ||||
|     DISPLAY=foo.bar:1 exec dwm | ||||
|  | ||||
| (This will start dwm on display :1 of the host foo.bar.) | ||||
|  | ||||
| In order to display status info in the bar, you can do something | ||||
| like this in your .xinitrc: | ||||
|  | ||||
|     while xsetroot -name "`date` `uptime | sed 's/.*,//'`" | ||||
|     do | ||||
|     	sleep 1 | ||||
|     done & | ||||
|     exec dwm | ||||
|  | ||||
|  | ||||
| Configuration | ||||
| ------------- | ||||
| The configuration of dwm is done by creating a custom config.h | ||||
| and (re)compiling the source code. | ||||
							
								
								
									
										116
									
								
								dwm/config.def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								dwm/config.def.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* appearance */ | ||||
| static const unsigned int borderpx  = 1;        /* border pixel of windows */ | ||||
| static const unsigned int snap      = 32;       /* snap pixel */ | ||||
| static const int showbar            = 1;        /* 0 means no bar */ | ||||
| static const int topbar             = 1;        /* 0 means bottom bar */ | ||||
| static const char *fonts[]          = { "monospace:size=10" }; | ||||
| static const char dmenufont[]       = "monospace:size=10"; | ||||
| static const char col_gray1[]       = "#222222"; | ||||
| static const char col_gray2[]       = "#444444"; | ||||
| static const char col_gray3[]       = "#bbbbbb"; | ||||
| static const char col_gray4[]       = "#eeeeee"; | ||||
| static const char col_cyan[]        = "#005577"; | ||||
| static const char *colors[][3]      = { | ||||
| 	/*               fg         bg         border   */ | ||||
| 	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, | ||||
| 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, | ||||
| }; | ||||
|  | ||||
| /* tagging */ | ||||
| static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; | ||||
|  | ||||
| static const Rule rules[] = { | ||||
| 	/* xprop(1): | ||||
| 	 *	WM_CLASS(STRING) = instance, class | ||||
| 	 *	WM_NAME(STRING) = title | ||||
| 	 */ | ||||
| 	/* class      instance    title       tags mask     isfloating   monitor */ | ||||
| 	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, | ||||
| 	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, | ||||
| }; | ||||
|  | ||||
| /* layout(s) */ | ||||
| static const float mfact     = 0.55; /* factor of master area size [0.05..0.95] */ | ||||
| static const int nmaster     = 1;    /* number of clients in master area */ | ||||
| static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ | ||||
| static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ | ||||
|  | ||||
| static const Layout layouts[] = { | ||||
| 	/* symbol     arrange function */ | ||||
| 	{ "[]=",      tile },    /* first entry is default */ | ||||
| 	{ "><>",      NULL },    /* no layout function means floating behavior */ | ||||
| 	{ "[M]",      monocle }, | ||||
| }; | ||||
|  | ||||
| /* key definitions */ | ||||
| #define MODKEY Mod1Mask | ||||
| #define TAGKEYS(KEY,TAG) \ | ||||
| 	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} }, | ||||
|  | ||||
| /* helper for spawning shell commands in the pre dwm-5.0 fashion */ | ||||
| #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } | ||||
|  | ||||
| /* commands */ | ||||
| static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ | ||||
| static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; | ||||
| static const char *termcmd[]  = { "st", NULL }; | ||||
|  | ||||
| static const Key keys[] = { | ||||
| 	/* modifier                     key        function        argument */ | ||||
| 	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } }, | ||||
| 	{ MODKEY,                       XK_b,      togglebar,      {0} }, | ||||
| 	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } }, | ||||
| 	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_i,      incnmaster,     {.i = +1 } }, | ||||
| 	{ MODKEY,                       XK_d,      incnmaster,     {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} }, | ||||
| 	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} }, | ||||
| 	{ MODKEY,                       XK_Return, zoom,           {0} }, | ||||
| 	{ MODKEY,                       XK_Tab,    view,           {0} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} }, | ||||
| 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} }, | ||||
| 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, | ||||
| 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, | ||||
| 	{ MODKEY,                       XK_space,  setlayout,      {0} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, | ||||
| 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } }, | ||||
| 	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } }, | ||||
| 	TAGKEYS(                        XK_1,                      0) | ||||
| 	TAGKEYS(                        XK_2,                      1) | ||||
| 	TAGKEYS(                        XK_3,                      2) | ||||
| 	TAGKEYS(                        XK_4,                      3) | ||||
| 	TAGKEYS(                        XK_5,                      4) | ||||
| 	TAGKEYS(                        XK_6,                      5) | ||||
| 	TAGKEYS(                        XK_7,                      6) | ||||
| 	TAGKEYS(                        XK_8,                      7) | ||||
| 	TAGKEYS(                        XK_9,                      8) | ||||
| 	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} }, | ||||
| }; | ||||
|  | ||||
| /* button definitions */ | ||||
| /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ | ||||
| static const Button buttons[] = { | ||||
| 	/* click                event mask      button          function        argument */ | ||||
| 	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} }, | ||||
| 	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} }, | ||||
| 	{ ClkWinTitle,          0,              Button2,        zoom,           {0} }, | ||||
| 	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} }, | ||||
| 	{ ClkTagBar,            0,              Button1,        view,           {0} }, | ||||
| 	{ ClkTagBar,            0,              Button3,        toggleview,     {0} }, | ||||
| 	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, | ||||
| 	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, | ||||
| }; | ||||
|  | ||||
							
								
								
									
										116
									
								
								dwm/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								dwm/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* appearance */ | ||||
| static const unsigned int borderpx  = 1;        /* border pixel of windows */ | ||||
| static const unsigned int snap      = 32;       /* snap pixel */ | ||||
| static const int showbar            = 1;        /* 0 means no bar */ | ||||
| static const int topbar             = 1;        /* 0 means bottom bar */ | ||||
| static const char *fonts[]          = { "monospace:size=10" }; | ||||
| static const char dmenufont[]       = "monospace:size=10"; | ||||
| static const char col_gray1[]       = "#222222"; | ||||
| static const char col_gray2[]       = "#444444"; | ||||
| static const char col_gray3[]       = "#bbbbbb"; | ||||
| static const char col_gray4[]       = "#eeeeee"; | ||||
| static const char col_cyan[]        = "#005577"; | ||||
| static const char *colors[][3]      = { | ||||
| 	/*               fg         bg         border   */ | ||||
| 	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, | ||||
| 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, | ||||
| }; | ||||
|  | ||||
| /* tagging */ | ||||
| static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; | ||||
|  | ||||
| static const Rule rules[] = { | ||||
| 	/* xprop(1): | ||||
| 	 *	WM_CLASS(STRING) = instance, class | ||||
| 	 *	WM_NAME(STRING) = title | ||||
| 	 */ | ||||
| 	/* class      instance    title       tags mask     isfloating   monitor */ | ||||
| 	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, | ||||
| 	//{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, | ||||
| }; | ||||
|  | ||||
| /* layout(s) */ | ||||
| static const float mfact     = 0.55; /* factor of master area size [0.05..0.95] */ | ||||
| static const int nmaster     = 1;    /* number of clients in master area */ | ||||
| static const int resizehints = 0;    /* 1 means respect size hints in tiled resizals */ | ||||
| static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ | ||||
|  | ||||
| static const Layout layouts[] = { | ||||
| 	/* symbol     arrange function */ | ||||
| 	{ "[]=",      tile },    /* first entry is default */ | ||||
| 	{ "><>",      NULL },    /* no layout function means floating behavior */ | ||||
| 	{ "[M]",      monocle }, | ||||
| }; | ||||
|  | ||||
| /* key definitions */ | ||||
| #define MODKEY Mod4Mask | ||||
| #define TAGKEYS(KEY,TAG) \ | ||||
| 	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} }, | ||||
|  | ||||
| /* helper for spawning shell commands in the pre dwm-5.0 fashion */ | ||||
| #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } | ||||
|  | ||||
| /* commands */ | ||||
| static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ | ||||
| static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; | ||||
| static const char *termcmd[]  = { "st", NULL }; | ||||
|  | ||||
| static const Key keys[] = { | ||||
| 	/* modifier                     key        function        argument */ | ||||
| 	{ MODKEY,                       XK_d,      spawn,          {.v = dmenucmd } }, | ||||
| 	{ MODKEY,                       XK_Return, spawn,          {.v = termcmd } }, | ||||
| 	{ MODKEY,                       XK_b,      togglebar,      {0} }, | ||||
| 	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } }, | ||||
| 	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_i,      incnmaster,     {.i = +1 } }, | ||||
| 	{ MODKEY,                       XK_o,      incnmaster,     {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} }, | ||||
| 	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_Return, zoom,           {0} }, | ||||
| 	{ MODKEY,                       XK_Tab,    view,           {0} }, | ||||
| 	{ MODKEY,                       XK_q,      killclient,     {0} }, | ||||
| 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} }, | ||||
| 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, | ||||
| 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, | ||||
| 	{ MODKEY,                       XK_space,  setlayout,      {0} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, | ||||
| 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } }, | ||||
| 	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } }, | ||||
| 	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } }, | ||||
| 	TAGKEYS(                        XK_1,                      0) | ||||
| 	TAGKEYS(                        XK_2,                      1) | ||||
| 	TAGKEYS(                        XK_3,                      2) | ||||
| 	TAGKEYS(                        XK_4,                      3) | ||||
| 	TAGKEYS(                        XK_5,                      4) | ||||
| 	TAGKEYS(                        XK_6,                      5) | ||||
| 	TAGKEYS(                        XK_7,                      6) | ||||
| 	TAGKEYS(                        XK_8,                      7) | ||||
| 	TAGKEYS(                        XK_9,                      8) | ||||
| 	{ MODKEY|ShiftMask,             XK_e,      quit,           {0} }, | ||||
| }; | ||||
|  | ||||
| /* button definitions */ | ||||
| /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ | ||||
| static const Button buttons[] = { | ||||
| 	/* click                event mask      button          function        argument */ | ||||
| 	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} }, | ||||
| 	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} }, | ||||
| 	{ ClkWinTitle,          0,              Button2,        zoom,           {0} }, | ||||
| 	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} }, | ||||
| 	{ ClkTagBar,            0,              Button1,        view,           {0} }, | ||||
| 	{ ClkTagBar,            0,              Button3,        toggleview,     {0} }, | ||||
| 	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, | ||||
| 	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, | ||||
| }; | ||||
|  | ||||
							
								
								
									
										39
									
								
								dwm/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								dwm/config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| # dwm version | ||||
| VERSION = 6.4 | ||||
|  | ||||
| # Customize below to fit your system | ||||
|  | ||||
| # paths | ||||
| PREFIX = /usr/local | ||||
| MANPREFIX = ${PREFIX}/share/man | ||||
|  | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
|  | ||||
| # Xinerama, comment if you don't want it | ||||
| XINERAMALIBS  = -lXinerama | ||||
| XINERAMAFLAGS = -DXINERAMA | ||||
|  | ||||
| # freetype | ||||
| FREETYPELIBS = -lfontconfig -lXft | ||||
| FREETYPEINC = /usr/include/freetype2 | ||||
| # OpenBSD (uncomment) | ||||
| FREETYPEINC = ${X11INC}/freetype2 | ||||
| MANPREFIX = ${PREFIX}/man | ||||
|  | ||||
| # includes and libs | ||||
| INCS = -I${X11INC} -I${FREETYPEINC} | ||||
| LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} | ||||
|  | ||||
| # flags | ||||
| CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} | ||||
| #CFLAGS   = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} | ||||
| CFLAGS   = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} | ||||
| LDFLAGS  = ${LIBS} | ||||
|  | ||||
| # Solaris | ||||
| #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" | ||||
| #LDFLAGS = ${LIBS} | ||||
|  | ||||
| # compiler and linker | ||||
| CC = cc | ||||
							
								
								
									
										450
									
								
								dwm/drw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										450
									
								
								dwm/drw.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,450 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xft/Xft.h> | ||||
|  | ||||
| #include "drw.h" | ||||
| #include "util.h" | ||||
|  | ||||
| #define UTF_INVALID 0xFFFD | ||||
| #define UTF_SIZ     4 | ||||
|  | ||||
| static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0}; | ||||
| static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; | ||||
| static const long utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000}; | ||||
| static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; | ||||
|  | ||||
| static long | ||||
| utf8decodebyte(const char c, size_t *i) | ||||
| { | ||||
| 	for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) | ||||
| 		if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) | ||||
| 			return (unsigned char)c & ~utfmask[*i]; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static size_t | ||||
| utf8validate(long *u, size_t i) | ||||
| { | ||||
| 	if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) | ||||
| 		*u = UTF_INVALID; | ||||
| 	for (i = 1; *u > utfmax[i]; ++i) | ||||
| 		; | ||||
| 	return i; | ||||
| } | ||||
|  | ||||
| static size_t | ||||
| utf8decode(const char *c, long *u, size_t clen) | ||||
| { | ||||
| 	size_t i, j, len, type; | ||||
| 	long udecoded; | ||||
|  | ||||
| 	*u = UTF_INVALID; | ||||
| 	if (!clen) | ||||
| 		return 0; | ||||
| 	udecoded = utf8decodebyte(c[0], &len); | ||||
| 	if (!BETWEEN(len, 1, UTF_SIZ)) | ||||
| 		return 1; | ||||
| 	for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { | ||||
| 		udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); | ||||
| 		if (type) | ||||
| 			return j; | ||||
| 	} | ||||
| 	if (j < len) | ||||
| 		return 0; | ||||
| 	*u = udecoded; | ||||
| 	utf8validate(u, len); | ||||
|  | ||||
| 	return len; | ||||
| } | ||||
|  | ||||
| Drw * | ||||
| drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	Drw *drw = ecalloc(1, sizeof(Drw)); | ||||
|  | ||||
| 	drw->dpy = dpy; | ||||
| 	drw->screen = screen; | ||||
| 	drw->root = root; | ||||
| 	drw->w = w; | ||||
| 	drw->h = h; | ||||
| 	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); | ||||
| 	drw->gc = XCreateGC(dpy, root, 0, NULL); | ||||
| 	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); | ||||
|  | ||||
| 	return drw; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_resize(Drw *drw, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	if (!drw) | ||||
| 		return; | ||||
|  | ||||
| 	drw->w = w; | ||||
| 	drw->h = h; | ||||
| 	if (drw->drawable) | ||||
| 		XFreePixmap(drw->dpy, drw->drawable); | ||||
| 	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_free(Drw *drw) | ||||
| { | ||||
| 	XFreePixmap(drw->dpy, drw->drawable); | ||||
| 	XFreeGC(drw->dpy, drw->gc); | ||||
| 	drw_fontset_free(drw->fonts); | ||||
| 	free(drw); | ||||
| } | ||||
|  | ||||
| /* This function is an implementation detail. Library users should use | ||||
|  * drw_fontset_create instead. | ||||
|  */ | ||||
| static Fnt * | ||||
| xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) | ||||
| { | ||||
| 	Fnt *font; | ||||
| 	XftFont *xfont = NULL; | ||||
| 	FcPattern *pattern = NULL; | ||||
|  | ||||
| 	if (fontname) { | ||||
| 		/* Using the pattern found at font->xfont->pattern does not yield the | ||||
| 		 * same substitution results as using the pattern returned by | ||||
| 		 * FcNameParse; using the latter results in the desired fallback | ||||
| 		 * behaviour whereas the former just results in missing-character | ||||
| 		 * rectangles being drawn, at least with some fonts. */ | ||||
| 		if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { | ||||
| 			fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (!(pattern = FcNameParse((FcChar8 *) fontname))) { | ||||
| 			fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); | ||||
| 			XftFontClose(drw->dpy, xfont); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} else if (fontpattern) { | ||||
| 		if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { | ||||
| 			fprintf(stderr, "error, cannot load font from pattern.\n"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} else { | ||||
| 		die("no font specified."); | ||||
| 	} | ||||
|  | ||||
| 	font = ecalloc(1, sizeof(Fnt)); | ||||
| 	font->xfont = xfont; | ||||
| 	font->pattern = pattern; | ||||
| 	font->h = xfont->ascent + xfont->descent; | ||||
| 	font->dpy = drw->dpy; | ||||
|  | ||||
| 	return font; | ||||
| } | ||||
|  | ||||
| static void | ||||
| xfont_free(Fnt *font) | ||||
| { | ||||
| 	if (!font) | ||||
| 		return; | ||||
| 	if (font->pattern) | ||||
| 		FcPatternDestroy(font->pattern); | ||||
| 	XftFontClose(font->dpy, font->xfont); | ||||
| 	free(font); | ||||
| } | ||||
|  | ||||
| Fnt* | ||||
| drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) | ||||
| { | ||||
| 	Fnt *cur, *ret = NULL; | ||||
| 	size_t i; | ||||
|  | ||||
| 	if (!drw || !fonts) | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 1; i <= fontcount; i++) { | ||||
| 		if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { | ||||
| 			cur->next = ret; | ||||
| 			ret = cur; | ||||
| 		} | ||||
| 	} | ||||
| 	return (drw->fonts = ret); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_fontset_free(Fnt *font) | ||||
| { | ||||
| 	if (font) { | ||||
| 		drw_fontset_free(font->next); | ||||
| 		xfont_free(font); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_clr_create(Drw *drw, Clr *dest, const char *clrname) | ||||
| { | ||||
| 	if (!drw || !dest || !clrname) | ||||
| 		return; | ||||
|  | ||||
| 	if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), | ||||
| 	                       DefaultColormap(drw->dpy, drw->screen), | ||||
| 	                       clrname, dest)) | ||||
| 		die("error, cannot allocate color '%s'", clrname); | ||||
| } | ||||
|  | ||||
| /* Wrapper to create color schemes. The caller has to call free(3) on the | ||||
|  * returned color scheme when done using it. */ | ||||
| Clr * | ||||
| drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) | ||||
| { | ||||
| 	size_t i; | ||||
| 	Clr *ret; | ||||
|  | ||||
| 	/* need at least two colors for a scheme */ | ||||
| 	if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 0; i < clrcount; i++) | ||||
| 		drw_clr_create(drw, &ret[i], clrnames[i]); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_setfontset(Drw *drw, Fnt *set) | ||||
| { | ||||
| 	if (drw) | ||||
| 		drw->fonts = set; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_setscheme(Drw *drw, Clr *scm) | ||||
| { | ||||
| 	if (drw) | ||||
| 		drw->scheme = scm; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) | ||||
| { | ||||
| 	if (!drw || !drw->scheme) | ||||
| 		return; | ||||
| 	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); | ||||
| 	if (filled) | ||||
| 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | ||||
| 	else | ||||
| 		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); | ||||
| } | ||||
|  | ||||
| int | ||||
| drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) | ||||
| { | ||||
| 	int i, ty, ellipsis_x = 0; | ||||
| 	unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; | ||||
| 	XftDraw *d = NULL; | ||||
| 	Fnt *usedfont, *curfont, *nextfont; | ||||
| 	int utf8strlen, utf8charlen, render = x || y || w || h; | ||||
| 	long utf8codepoint = 0; | ||||
| 	const char *utf8str; | ||||
| 	FcCharSet *fccharset; | ||||
| 	FcPattern *fcpattern; | ||||
| 	FcPattern *match; | ||||
| 	XftResult result; | ||||
| 	int charexists = 0, overflow = 0; | ||||
| 	/* keep track of a couple codepoints for which we have no match. */ | ||||
| 	enum { nomatches_len = 64 }; | ||||
| 	static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; | ||||
| 	static unsigned int ellipsis_width = 0; | ||||
|  | ||||
| 	if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!render) { | ||||
| 		w = invert ? invert : ~invert; | ||||
| 	} else { | ||||
| 		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); | ||||
| 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | ||||
| 		d = XftDrawCreate(drw->dpy, drw->drawable, | ||||
| 		                  DefaultVisual(drw->dpy, drw->screen), | ||||
| 		                  DefaultColormap(drw->dpy, drw->screen)); | ||||
| 		x += lpad; | ||||
| 		w -= lpad; | ||||
| 	} | ||||
|  | ||||
| 	usedfont = drw->fonts; | ||||
| 	if (!ellipsis_width && render) | ||||
| 		ellipsis_width = drw_fontset_getwidth(drw, "..."); | ||||
| 	while (1) { | ||||
| 		ew = ellipsis_len = utf8strlen = 0; | ||||
| 		utf8str = text; | ||||
| 		nextfont = NULL; | ||||
| 		while (*text) { | ||||
| 			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); | ||||
| 			for (curfont = drw->fonts; curfont; curfont = curfont->next) { | ||||
| 				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); | ||||
| 				if (charexists) { | ||||
| 					drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); | ||||
| 					if (ew + ellipsis_width <= w) { | ||||
| 						/* keep track where the ellipsis still fits */ | ||||
| 						ellipsis_x = x + ew; | ||||
| 						ellipsis_w = w - ew; | ||||
| 						ellipsis_len = utf8strlen; | ||||
| 					} | ||||
|  | ||||
| 					if (ew + tmpw > w) { | ||||
| 						overflow = 1; | ||||
| 						/* called from drw_fontset_getwidth_clamp(): | ||||
| 						 * it wants the width AFTER the overflow | ||||
| 						 */ | ||||
| 						if (!render) | ||||
| 							x += tmpw; | ||||
| 						else | ||||
| 							utf8strlen = ellipsis_len; | ||||
| 					} else if (curfont == usedfont) { | ||||
| 						utf8strlen += utf8charlen; | ||||
| 						text += utf8charlen; | ||||
| 						ew += tmpw; | ||||
| 					} else { | ||||
| 						nextfont = curfont; | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (overflow || !charexists || nextfont) | ||||
| 				break; | ||||
| 			else | ||||
| 				charexists = 0; | ||||
| 		} | ||||
|  | ||||
| 		if (utf8strlen) { | ||||
| 			if (render) { | ||||
| 				ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; | ||||
| 				XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], | ||||
| 				                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); | ||||
| 			} | ||||
| 			x += ew; | ||||
| 			w -= ew; | ||||
| 		} | ||||
| 		if (render && overflow) | ||||
| 			drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); | ||||
|  | ||||
| 		if (!*text || overflow) { | ||||
| 			break; | ||||
| 		} else if (nextfont) { | ||||
| 			charexists = 0; | ||||
| 			usedfont = nextfont; | ||||
| 		} else { | ||||
| 			/* Regardless of whether or not a fallback font is found, the | ||||
| 			 * character must be drawn. */ | ||||
| 			charexists = 1; | ||||
|  | ||||
| 			for (i = 0; i < nomatches_len; ++i) { | ||||
| 				/* avoid calling XftFontMatch if we know we won't find a match */ | ||||
| 				if (utf8codepoint == nomatches.codepoint[i]) | ||||
| 					goto no_match; | ||||
| 			} | ||||
|  | ||||
| 			fccharset = FcCharSetCreate(); | ||||
| 			FcCharSetAddChar(fccharset, utf8codepoint); | ||||
|  | ||||
| 			if (!drw->fonts->pattern) { | ||||
| 				/* Refer to the comment in xfont_create for more information. */ | ||||
| 				die("the first font in the cache must be loaded from a font string."); | ||||
| 			} | ||||
|  | ||||
| 			fcpattern = FcPatternDuplicate(drw->fonts->pattern); | ||||
| 			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); | ||||
| 			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); | ||||
|  | ||||
| 			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); | ||||
| 			FcDefaultSubstitute(fcpattern); | ||||
| 			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); | ||||
|  | ||||
| 			FcCharSetDestroy(fccharset); | ||||
| 			FcPatternDestroy(fcpattern); | ||||
|  | ||||
| 			if (match) { | ||||
| 				usedfont = xfont_create(drw, NULL, match); | ||||
| 				if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { | ||||
| 					for (curfont = drw->fonts; curfont->next; curfont = curfont->next) | ||||
| 						; /* NOP */ | ||||
| 					curfont->next = usedfont; | ||||
| 				} else { | ||||
| 					xfont_free(usedfont); | ||||
| 					nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; | ||||
| no_match: | ||||
| 					usedfont = drw->fonts; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if (d) | ||||
| 		XftDrawDestroy(d); | ||||
|  | ||||
| 	return x + (render ? w : 0); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	if (!drw) | ||||
| 		return; | ||||
|  | ||||
| 	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); | ||||
| 	XSync(drw->dpy, False); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| drw_fontset_getwidth(Drw *drw, const char *text) | ||||
| { | ||||
| 	if (!drw || !drw->fonts || !text) | ||||
| 		return 0; | ||||
| 	return drw_text(drw, 0, 0, 0, 0, 0, text, 0); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) | ||||
| { | ||||
| 	unsigned int tmp = 0; | ||||
| 	if (drw && drw->fonts && text && n) | ||||
| 		tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); | ||||
| 	return MIN(n, tmp); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) | ||||
| { | ||||
| 	XGlyphInfo ext; | ||||
|  | ||||
| 	if (!font || !text) | ||||
| 		return; | ||||
|  | ||||
| 	XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); | ||||
| 	if (w) | ||||
| 		*w = ext.xOff; | ||||
| 	if (h) | ||||
| 		*h = font->h; | ||||
| } | ||||
|  | ||||
| Cur * | ||||
| drw_cur_create(Drw *drw, int shape) | ||||
| { | ||||
| 	Cur *cur; | ||||
|  | ||||
| 	if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	cur->cursor = XCreateFontCursor(drw->dpy, shape); | ||||
|  | ||||
| 	return cur; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_cur_free(Drw *drw, Cur *cursor) | ||||
| { | ||||
| 	if (!cursor) | ||||
| 		return; | ||||
|  | ||||
| 	XFreeCursor(drw->dpy, cursor->cursor); | ||||
| 	free(cursor); | ||||
| } | ||||
							
								
								
									
										58
									
								
								dwm/drw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								dwm/drw.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| typedef struct { | ||||
| 	Cursor cursor; | ||||
| } Cur; | ||||
|  | ||||
| typedef struct Fnt { | ||||
| 	Display *dpy; | ||||
| 	unsigned int h; | ||||
| 	XftFont *xfont; | ||||
| 	FcPattern *pattern; | ||||
| 	struct Fnt *next; | ||||
| } Fnt; | ||||
|  | ||||
| enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ | ||||
| typedef XftColor Clr; | ||||
|  | ||||
| typedef struct { | ||||
| 	unsigned int w, h; | ||||
| 	Display *dpy; | ||||
| 	int screen; | ||||
| 	Window root; | ||||
| 	Drawable drawable; | ||||
| 	GC gc; | ||||
| 	Clr *scheme; | ||||
| 	Fnt *fonts; | ||||
| } Drw; | ||||
|  | ||||
| /* Drawable abstraction */ | ||||
| Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); | ||||
| void drw_resize(Drw *drw, unsigned int w, unsigned int h); | ||||
| void drw_free(Drw *drw); | ||||
|  | ||||
| /* Fnt abstraction */ | ||||
| Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); | ||||
| void drw_fontset_free(Fnt* set); | ||||
| unsigned int drw_fontset_getwidth(Drw *drw, const char *text); | ||||
| unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); | ||||
| void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); | ||||
|  | ||||
| /* Colorscheme abstraction */ | ||||
| void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); | ||||
| Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); | ||||
|  | ||||
| /* Cursor abstraction */ | ||||
| Cur *drw_cur_create(Drw *drw, int shape); | ||||
| void drw_cur_free(Drw *drw, Cur *cursor); | ||||
|  | ||||
| /* Drawing context manipulation */ | ||||
| void drw_setfontset(Drw *drw, Fnt *set); | ||||
| void drw_setscheme(Drw *drw, Clr *scm); | ||||
|  | ||||
| /* Drawing functions */ | ||||
| void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); | ||||
| int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); | ||||
|  | ||||
| /* Map functions */ | ||||
| void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); | ||||
							
								
								
									
										215
									
								
								dwm/dwm-pertag_with_sel-20231003-9f88553.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								dwm/dwm-pertag_with_sel-20231003-9f88553.diff
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| From b47a32da69a1bb6f60b9c81619f3e504278cc780 Mon Sep 17 00:00:00 2001 | ||||
| From: Leonardo-Boss <70913810+Leonardo-Boss@users.noreply.github.com> | ||||
| Date: Tue, 3 Oct 2023 12:33:58 -0300 | ||||
| Subject: [PATCH] pertag with last selection | ||||
|  | ||||
| --- | ||||
|  dwm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- | ||||
|  1 file changed, 90 insertions(+), 7 deletions(-) | ||||
|  | ||||
| diff --git a/dwm.c b/dwm.c | ||||
| index f1d86b2..0e4d444 100644 | ||||
| --- a/dwm.c | ||||
| +++ b/dwm.c | ||||
| @@ -111,6 +111,7 @@ typedef struct { | ||||
|  	void (*arrange)(Monitor *); | ||||
|  } Layout; | ||||
|   | ||||
| +typedef struct Pertag Pertag; | ||||
|  struct Monitor { | ||||
|  	char ltsymbol[16]; | ||||
|  	float mfact; | ||||
| @@ -130,6 +131,7 @@ struct Monitor { | ||||
|  	Monitor *next; | ||||
|  	Window barwin; | ||||
|  	const Layout *lt[2]; | ||||
| +	Pertag *pertag; | ||||
|  }; | ||||
|   | ||||
|  typedef struct { | ||||
| @@ -271,6 +273,16 @@ static Window root, wmcheckwin; | ||||
|  /* configuration, allows nested code to access above variables */ | ||||
|  #include "config.h" | ||||
|   | ||||
| +struct Pertag { | ||||
| +	unsigned int curtag, prevtag; /* current and previous tag */ | ||||
| +	int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ | ||||
| +	float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ | ||||
| +	unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ | ||||
| +	const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes  */ | ||||
| +	int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ | ||||
| +	Client *sel[LENGTH(tags) + 1]; /* selected client */ | ||||
| +}; | ||||
| + | ||||
|  /* compile-time check if all tags fit into an unsigned int bit array. */ | ||||
|  struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; | ||||
|   | ||||
| @@ -634,6 +646,7 @@ Monitor * | ||||
|  createmon(void) | ||||
|  { | ||||
|  	Monitor *m; | ||||
| +	unsigned int i; | ||||
|   | ||||
|  	m = ecalloc(1, sizeof(Monitor)); | ||||
|  	m->tagset[0] = m->tagset[1] = 1; | ||||
| @@ -644,6 +657,20 @@ createmon(void) | ||||
|  	m->lt[0] = &layouts[0]; | ||||
|  	m->lt[1] = &layouts[1 % LENGTH(layouts)]; | ||||
|  	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | ||||
| +	m->pertag = ecalloc(1, sizeof(Pertag)); | ||||
| +	m->pertag->curtag = m->pertag->prevtag = 1; | ||||
| + | ||||
| +	for (i = 0; i <= LENGTH(tags); i++) { | ||||
| +		m->pertag->nmasters[i] = m->nmaster; | ||||
| +		m->pertag->mfacts[i] = m->mfact; | ||||
| + | ||||
| +		m->pertag->ltidxs[i][0] = m->lt[0]; | ||||
| +		m->pertag->ltidxs[i][1] = m->lt[1]; | ||||
| +		m->pertag->sellts[i] = m->sellt; | ||||
| + | ||||
| +		m->pertag->showbars[i] = m->showbar; | ||||
| +	} | ||||
| + | ||||
|  	return m; | ||||
|  } | ||||
|   | ||||
| @@ -808,6 +835,7 @@ focus(Client *c) | ||||
|  		XDeleteProperty(dpy, root, netatom[NetActiveWindow]); | ||||
|  	} | ||||
|  	selmon->sel = c; | ||||
| +	selmon->pertag->sel[selmon->pertag->curtag] = c; | ||||
|  	drawbars(); | ||||
|  } | ||||
|   | ||||
| @@ -980,7 +1008,7 @@ grabkeys(void) | ||||
|  void | ||||
|  incnmaster(const Arg *arg) | ||||
|  { | ||||
| -	selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); | ||||
| +	selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); | ||||
|  	arrange(selmon); | ||||
|  } | ||||
|   | ||||
| @@ -1511,9 +1539,9 @@ void | ||||
|  setlayout(const Arg *arg) | ||||
|  { | ||||
|  	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) | ||||
| -		selmon->sellt ^= 1; | ||||
| +		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; | ||||
|  	if (arg && arg->v) | ||||
| -		selmon->lt[selmon->sellt] = (Layout *)arg->v; | ||||
| +		selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; | ||||
|  	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); | ||||
|  	if (selmon->sel) | ||||
|  		arrange(selmon); | ||||
| @@ -1532,7 +1560,7 @@ setmfact(const Arg *arg) | ||||
|  	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; | ||||
|  	if (f < 0.05 || f > 0.95) | ||||
|  		return; | ||||
| -	selmon->mfact = f; | ||||
| +	selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; | ||||
|  	arrange(selmon); | ||||
|  } | ||||
|   | ||||
| @@ -1715,7 +1743,7 @@ tile(Monitor *m) | ||||
|  void | ||||
|  togglebar(const Arg *arg) | ||||
|  { | ||||
| -	selmon->showbar = !selmon->showbar; | ||||
| +	selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; | ||||
|  	updatebarpos(selmon); | ||||
|  	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); | ||||
|  	arrange(selmon); | ||||
| @@ -1754,9 +1782,33 @@ void | ||||
|  toggleview(const Arg *arg) | ||||
|  { | ||||
|  	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); | ||||
| +	int i; | ||||
|   | ||||
|  	if (newtagset) { | ||||
|  		selmon->tagset[selmon->seltags] = newtagset; | ||||
| + | ||||
| +		if (newtagset == ~0) { | ||||
| +			selmon->pertag->prevtag = selmon->pertag->curtag; | ||||
| +			selmon->pertag->curtag = 0; | ||||
| +		} | ||||
| + | ||||
| +		/* test if the user did not select the same tag */ | ||||
| +		if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { | ||||
| +			selmon->pertag->prevtag = selmon->pertag->curtag; | ||||
| +			for (i = 0; !(newtagset & 1 << i); i++) ; | ||||
| +			selmon->pertag->curtag = i + 1; | ||||
| +		} | ||||
| + | ||||
| +		/* apply settings for this view */ | ||||
| +		selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; | ||||
| +		selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; | ||||
| +		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; | ||||
| +		selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; | ||||
| +		selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; | ||||
| + | ||||
| +		if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) | ||||
| +			togglebar(NULL); | ||||
| + | ||||
|  		focus(NULL); | ||||
|  		arrange(selmon); | ||||
|  	} | ||||
| @@ -1778,9 +1830,14 @@ unfocus(Client *c, int setfocus) | ||||
|  void | ||||
|  unmanage(Client *c, int destroyed) | ||||
|  { | ||||
| +	int i; | ||||
|  	Monitor *m = c->mon; | ||||
|  	XWindowChanges wc; | ||||
|   | ||||
| +	for (i = 0; i < LENGTH(tags) + 1; i++) | ||||
| +		if (c->mon->pertag->sel[i] == c) | ||||
| +			c->mon->pertag->sel[i] = NULL; | ||||
| + | ||||
|  	detach(c); | ||||
|  	detachstack(c); | ||||
|  	if (!destroyed) { | ||||
| @@ -2053,12 +2110,38 @@ updatewmhints(Client *c) | ||||
|  void | ||||
|  view(const Arg *arg) | ||||
|  { | ||||
| +	int i; | ||||
| +	unsigned int tmptag; | ||||
| + | ||||
|  	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) | ||||
|  		return; | ||||
|  	selmon->seltags ^= 1; /* toggle sel tagset */ | ||||
| -	if (arg->ui & TAGMASK) | ||||
| +	if (arg->ui & TAGMASK) { | ||||
|  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; | ||||
| -	focus(NULL); | ||||
| +		selmon->pertag->prevtag = selmon->pertag->curtag; | ||||
| + | ||||
| +		if (arg->ui == ~0) | ||||
| +			selmon->pertag->curtag = 0; | ||||
| +		else { | ||||
| +			for (i = 0; !(arg->ui & 1 << i); i++) ; | ||||
| +			selmon->pertag->curtag = i + 1; | ||||
| +		} | ||||
| +	} else { | ||||
| +		tmptag = selmon->pertag->prevtag; | ||||
| +		selmon->pertag->prevtag = selmon->pertag->curtag; | ||||
| +		selmon->pertag->curtag = tmptag; | ||||
| +	} | ||||
| + | ||||
| +	selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; | ||||
| +	selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; | ||||
| +	selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; | ||||
| +	selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; | ||||
| +	selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; | ||||
| + | ||||
| +	if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) | ||||
| +		togglebar(NULL); | ||||
| + | ||||
| +	focus(selmon->pertag->sel[selmon->pertag->curtag]); | ||||
|  	arrange(selmon); | ||||
|  } | ||||
|   | ||||
| --  | ||||
| 2.41.0 | ||||
|  | ||||
							
								
								
									
										176
									
								
								dwm/dwm.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								dwm/dwm.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| .TH DWM 1 dwm\-VERSION | ||||
| .SH NAME | ||||
| dwm \- dynamic window manager | ||||
| .SH SYNOPSIS | ||||
| .B dwm | ||||
| .RB [ \-v ] | ||||
| .SH DESCRIPTION | ||||
| dwm is a dynamic window manager for X. It manages windows in tiled, monocle | ||||
| and floating layouts. Either layout can be applied dynamically, optimising the | ||||
| environment for the application in use and the task performed. | ||||
| .P | ||||
| In tiled layouts windows are managed in a master and stacking area. The master | ||||
| area on the left contains one window by default, and the stacking area on the | ||||
| right contains all other windows. The number of master area windows can be | ||||
| adjusted from zero to an arbitrary number. In monocle layout all windows are | ||||
| maximised to the screen size. In floating layout windows can be resized and | ||||
| moved freely. Dialog windows are always managed floating, regardless of the | ||||
| layout applied. | ||||
| .P | ||||
| Windows are grouped by tags. Each window can be tagged with one or multiple | ||||
| tags. Selecting certain tags displays all windows with these tags. | ||||
| .P | ||||
| Each screen contains a small status bar which displays all available tags, the | ||||
| layout, the title of the focused window, and the text read from the root window | ||||
| name property, if the screen is focused. A floating window is indicated with an | ||||
| empty square and a maximised floating window is indicated with a filled square | ||||
| before the windows title.  The selected tags are indicated with a different | ||||
| color. The tags of the focused window are indicated with a filled square in the | ||||
| top left corner.  The tags which are applied to one or more windows are | ||||
| indicated with an empty square in the top left corner. | ||||
| .P | ||||
| dwm draws a small border around windows to indicate the focus state. | ||||
| .SH OPTIONS | ||||
| .TP | ||||
| .B \-v | ||||
| prints version information to stderr, then exits. | ||||
| .SH USAGE | ||||
| .SS Status bar | ||||
| .TP | ||||
| .B X root window name | ||||
| is read and displayed in the status text area. It can be set with the | ||||
| .BR xsetroot (1) | ||||
| command. | ||||
| .TP | ||||
| .B Button1 | ||||
| click on a tag label to display all windows with that tag, click on the layout | ||||
| label toggles between tiled and floating layout. | ||||
| .TP | ||||
| .B Button3 | ||||
| click on a tag label adds/removes all windows with that tag to/from the view. | ||||
| .TP | ||||
| .B Mod1\-Button1 | ||||
| click on a tag label applies that tag to the focused window. | ||||
| .TP | ||||
| .B Mod1\-Button3 | ||||
| click on a tag label adds/removes that tag to/from the focused window. | ||||
| .SS Keyboard commands | ||||
| .TP | ||||
| .B Mod1\-Shift\-Return | ||||
| Start | ||||
| .BR st(1). | ||||
| .TP | ||||
| .B Mod1\-p | ||||
| Spawn | ||||
| .BR dmenu(1) | ||||
| for launching other programs. | ||||
| .TP | ||||
| .B Mod1\-, | ||||
| Focus previous screen, if any. | ||||
| .TP | ||||
| .B Mod1\-. | ||||
| Focus next screen, if any. | ||||
| .TP | ||||
| .B Mod1\-Shift\-, | ||||
| Send focused window to previous screen, if any. | ||||
| .TP | ||||
| .B Mod1\-Shift\-. | ||||
| Send focused window to next screen, if any. | ||||
| .TP | ||||
| .B Mod1\-b | ||||
| Toggles bar on and off. | ||||
| .TP | ||||
| .B Mod1\-t | ||||
| Sets tiled layout. | ||||
| .TP | ||||
| .B Mod1\-f | ||||
| Sets floating layout. | ||||
| .TP | ||||
| .B Mod1\-m | ||||
| Sets monocle layout. | ||||
| .TP | ||||
| .B Mod1\-space | ||||
| Toggles between current and previous layout. | ||||
| .TP | ||||
| .B Mod1\-j | ||||
| Focus next window. | ||||
| .TP | ||||
| .B Mod1\-k | ||||
| Focus previous window. | ||||
| .TP | ||||
| .B Mod1\-i | ||||
| Increase number of windows in master area. | ||||
| .TP | ||||
| .B Mod1\-d | ||||
| Decrease number of windows in master area. | ||||
| .TP | ||||
| .B Mod1\-l | ||||
| Increase master area size. | ||||
| .TP | ||||
| .B Mod1\-h | ||||
| Decrease master area size. | ||||
| .TP | ||||
| .B Mod1\-Return | ||||
| Zooms/cycles focused window to/from master area (tiled layouts only). | ||||
| .TP | ||||
| .B Mod1\-Shift\-c | ||||
| Close focused window. | ||||
| .TP | ||||
| .B Mod1\-Shift\-space | ||||
| Toggle focused window between tiled and floating state. | ||||
| .TP | ||||
| .B Mod1\-Tab | ||||
| Toggles to the previously selected tags. | ||||
| .TP | ||||
| .B Mod1\-Shift\-[1..n] | ||||
| Apply nth tag to focused window. | ||||
| .TP | ||||
| .B Mod1\-Shift\-0 | ||||
| Apply all tags to focused window. | ||||
| .TP | ||||
| .B Mod1\-Control\-Shift\-[1..n] | ||||
| Add/remove nth tag to/from focused window. | ||||
| .TP | ||||
| .B Mod1\-[1..n] | ||||
| View all windows with nth tag. | ||||
| .TP | ||||
| .B Mod1\-0 | ||||
| View all windows with any tag. | ||||
| .TP | ||||
| .B Mod1\-Control\-[1..n] | ||||
| Add/remove all windows with nth tag to/from the view. | ||||
| .TP | ||||
| .B Mod1\-Shift\-q | ||||
| Quit dwm. | ||||
| .SS Mouse commands | ||||
| .TP | ||||
| .B Mod1\-Button1 | ||||
| Move focused window while dragging. Tiled windows will be toggled to the floating state. | ||||
| .TP | ||||
| .B Mod1\-Button2 | ||||
| Toggles focused window between floating and tiled state. | ||||
| .TP | ||||
| .B Mod1\-Button3 | ||||
| Resize focused window while dragging. Tiled windows will be toggled to the floating state. | ||||
| .SH CUSTOMIZATION | ||||
| dwm is customized by creating a custom config.h and (re)compiling the source | ||||
| code. This keeps it fast, secure and simple. | ||||
| .SH SEE ALSO | ||||
| .BR dmenu (1), | ||||
| .BR st (1) | ||||
| .SH ISSUES | ||||
| Java applications which use the XToolkit/XAWT backend may draw grey windows | ||||
| only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early | ||||
| JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds | ||||
| are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the | ||||
| environment variable | ||||
| .BR AWT_TOOLKIT=MToolkit | ||||
| (to use the older Motif backend instead) or running | ||||
| .B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D | ||||
| or | ||||
| .B wmname LG3D | ||||
| (to pretend that a non-reparenting window manager is running that the | ||||
| XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable | ||||
| .BR _JAVA_AWT_WM_NONREPARENTING=1 . | ||||
| .SH BUGS | ||||
| Send all bug reports with a patch to hackers@suckless.org. | ||||
							
								
								
									
										
											BIN
										
									
								
								dwm/dwm.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								dwm/dwm.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 373 B | 
							
								
								
									
										42
									
								
								dwm/transient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								dwm/transient.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* cc transient.c -o transient -lX11 */ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xutil.h> | ||||
|  | ||||
| int main(void) { | ||||
| 	Display *d; | ||||
| 	Window r, f, t = None; | ||||
| 	XSizeHints h; | ||||
| 	XEvent e; | ||||
|  | ||||
| 	d = XOpenDisplay(NULL); | ||||
| 	if (!d) | ||||
| 		exit(1); | ||||
| 	r = DefaultRootWindow(d); | ||||
|  | ||||
| 	f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); | ||||
| 	h.min_width = h.max_width = h.min_height = h.max_height = 400; | ||||
| 	h.flags = PMinSize | PMaxSize; | ||||
| 	XSetWMNormalHints(d, f, &h); | ||||
| 	XStoreName(d, f, "floating"); | ||||
| 	XMapWindow(d, f); | ||||
|  | ||||
| 	XSelectInput(d, f, ExposureMask); | ||||
| 	while (1) { | ||||
| 		XNextEvent(d, &e); | ||||
|  | ||||
| 		if (t == None) { | ||||
| 			sleep(5); | ||||
| 			t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); | ||||
| 			XSetTransientForHint(d, t, f); | ||||
| 			XStoreName(d, t, "transient"); | ||||
| 			XMapWindow(d, t); | ||||
| 			XSelectInput(d, t, ExposureMask); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	XCloseDisplay(d); | ||||
| 	exit(0); | ||||
| } | ||||
							
								
								
									
										36
									
								
								dwm/util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								dwm/util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "util.h" | ||||
|  | ||||
| void | ||||
| die(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	vfprintf(stderr, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	if (fmt[0] && fmt[strlen(fmt)-1] == ':') { | ||||
| 		fputc(' ', stderr); | ||||
| 		perror(NULL); | ||||
| 	} else { | ||||
| 		fputc('\n', stderr); | ||||
| 	} | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| void * | ||||
| ecalloc(size_t nmemb, size_t size) | ||||
| { | ||||
| 	void *p; | ||||
|  | ||||
| 	if (!(p = calloc(nmemb, size))) | ||||
| 		die("calloc:"); | ||||
| 	return p; | ||||
| } | ||||
							
								
								
									
										8
									
								
								dwm/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								dwm/util.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| #define MAX(A, B)               ((A) > (B) ? (A) : (B)) | ||||
| #define MIN(A, B)               ((A) < (B) ? (A) : (B)) | ||||
| #define BETWEEN(X, A, B)        ((A) <= (X) && (X) <= (B)) | ||||
|  | ||||
| void die(const char *fmt, ...); | ||||
| void *ecalloc(size_t nmemb, size_t size); | ||||
							
								
								
									
										43
									
								
								slstatus/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								slstatus/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| ISC License | ||||
|  | ||||
| Copyright 2016-2022 Aaron Marcher <me@drkhsh.at> | ||||
|  | ||||
| Copyright 2016 Roy Freytag <rfreytag@hs-mittweida.de> | ||||
| Copyright 2016 Vincent Loupmon <vincentloupmon@gmail.com> | ||||
| Copyright 2016 Daniel Walter <d.walter@0x90.at> | ||||
| Copyright 2016-2018 Ali H. Fardan <raiz@firemail.cc> | ||||
| Copyright 2016 Jody Leonard <me@jodyleonard.com> | ||||
| Copyright 2016-2018 Quentin Rameau <quinq@fifth.space> | ||||
| Copyright 2016 Mike Coddington <mike@coddington.us> | ||||
| Copyright 2016-2018 Ivan J. <parazyd@dyne.org> | ||||
| Copyright 2017 Tobias Stoeckmann <tobias@stoeckmann.org> | ||||
| Copyright 2017-2018 Laslo Hunhold <dev@frign.de> | ||||
| Copyright 2018 Darron Anderson <darronanderson@protonmail.com> | ||||
| Copyright 2018 Josuah Demangeon <mail@josuah.net> | ||||
| Copyright 2018 Tobias Tschinkowitz <tobias@he4d.net> | ||||
| Copyright 2018 David Demelier <markand@malikania.fr> | ||||
| Copyright 2018-2012 Michael Buch <michaelbuch12@gmail.com> | ||||
| Copyright 2018 Ian Remmler <ian@remmler.org> | ||||
| Copyright 2016-2019 Joerg Jung <jung@openbsd.org> | ||||
| Copyright 2019 Ryan Kes <alrayyes@gmail.com> | ||||
| Copyright 2019 Cem Keylan <cem@ckyln.com> | ||||
| Copyright 2019 Dimitris Papastamos <dsp@2f30.org> | ||||
| Copyright 2019-2022 Ingo Feinerer <feinerer@logic.at> | ||||
| Copyright 2020 Alexandre Ratchov <alex@caoua.org> | ||||
| Copyright 2020 Mart Lubbers <mart@martlubbers.net> | ||||
| Copyright 2020 Daniel Moch <daniel@danielmoch.com> | ||||
| Copyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org> | ||||
| Copyright 2022 Patrick Iacob <iacobp@oregonstate.edu> | ||||
| Copyright 2021-2022 Steven Ward <planet36@gmail.com> | ||||
|  | ||||
| Permission to use, copy, modify, and/or distribute this software for any | ||||
| purpose with or without fee is hereby granted, provided that the above | ||||
| copyright notice and this permission notice appear in all copies. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
| WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
| MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
| ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
| OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
							
								
								
									
										69
									
								
								slstatus/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| # See LICENSE file for copyright and license details | ||||
| # slstatus - suckless status monitor | ||||
| .POSIX: | ||||
|  | ||||
| include config.mk | ||||
|  | ||||
| REQ = util | ||||
| COM =\ | ||||
| 	components/battery\ | ||||
| 	components/cat\ | ||||
| 	components/cpu\ | ||||
| 	components/datetime\ | ||||
| 	components/disk\ | ||||
| 	components/entropy\ | ||||
| 	components/hostname\ | ||||
| 	components/ip\ | ||||
| 	components/kernel_release\ | ||||
| 	components/keyboard_indicators\ | ||||
| 	components/keymap\ | ||||
| 	components/load_avg\ | ||||
| 	components/netspeeds\ | ||||
| 	components/num_files\ | ||||
| 	components/ram\ | ||||
| 	components/run_command\ | ||||
| 	components/swap\ | ||||
| 	components/temperature\ | ||||
| 	components/uptime\ | ||||
| 	components/user\ | ||||
| 	components/volume\ | ||||
| 	components/wifi | ||||
|  | ||||
| all: slstatus | ||||
|  | ||||
| $(COM:=.o): config.mk $(REQ:=.h) slstatus.h | ||||
| slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) | ||||
|  | ||||
| .c.o: | ||||
| 	$(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< | ||||
|  | ||||
| config.h: | ||||
| 	cp config.def.h $@ | ||||
|  | ||||
| slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) | ||||
| 	$(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) | ||||
|  | ||||
| clean: | ||||
| 	rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz | ||||
|  | ||||
| dist: | ||||
| 	rm -rf "slstatus-$(VERSION)" | ||||
| 	mkdir -p "slstatus-$(VERSION)/components" | ||||
| 	cp -R LICENSE Makefile README config.mk config.def.h \ | ||||
| 	      arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ | ||||
| 	      slstatus.1 "slstatus-$(VERSION)" | ||||
| 	cp -R $(COM:=.c) "slstatus-$(VERSION)/components" | ||||
| 	tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" | ||||
| 	rm -rf "slstatus-$(VERSION)" | ||||
|  | ||||
| install: all | ||||
| 	mkdir -p "$(DESTDIR)$(PREFIX)/bin" | ||||
| 	cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" | ||||
| 	chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" | ||||
| 	mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" | ||||
| 	cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" | ||||
| 	chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" | ||||
|  | ||||
| uninstall: | ||||
| 	rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" | ||||
| 	rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" | ||||
							
								
								
									
										65
									
								
								slstatus/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								slstatus/README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| slstatus - suckless status | ||||
| ========================== | ||||
| slstatus is a small tool for providing system status information to other | ||||
| programs over the EWMH property of the root window (used by dwm(1)) or | ||||
| standard input/output. It is designed to be as efficient as possible by | ||||
| only issuing the minimum of system calls required. | ||||
|  | ||||
|  | ||||
| Features | ||||
| -------- | ||||
| - Battery percentage/state/time left | ||||
| - Cat (read file) | ||||
| - CPU usage | ||||
| - CPU frequency | ||||
| - Custom shell commands | ||||
| - Date and time | ||||
| - Disk status (free storage, percentage, total storage and used storage) | ||||
| - Available entropy | ||||
| - Username/GID/UID | ||||
| - Hostname | ||||
| - IP address (IPv4 and IPv6) | ||||
| - Kernel version | ||||
| - Keyboard indicators | ||||
| - Keymap | ||||
| - Load average | ||||
| - Network speeds (RX and TX) | ||||
| - Number of files in a directory (hint: Maildir) | ||||
| - Memory status (free memory, percentage, total memory and used memory) | ||||
| - Swap status (free swap, percentage, total swap and used swap) | ||||
| - Temperature | ||||
| - Uptime | ||||
| - Volume percentage | ||||
| - WiFi signal percentage and ESSID | ||||
|  | ||||
|  | ||||
| Requirements | ||||
| ------------ | ||||
| Currently slstatus works on FreeBSD, Linux and OpenBSD. | ||||
| In order to build slstatus you need the Xlib header files. | ||||
|  | ||||
| - For volume percentage on Linux the kernel module `snd-mixer-oss` must be | ||||
|   loaded. | ||||
| - For volume percentage on FreeBSD, `sndio` must be installed. | ||||
|  | ||||
|  | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup (slstatus is installed into the | ||||
| /usr/local namespace by default). | ||||
|  | ||||
| Afterwards enter the following command to build and install slstatus (if | ||||
| necessary as root): | ||||
|  | ||||
|     make clean install | ||||
|  | ||||
|  | ||||
| Running slstatus | ||||
| ---------------- | ||||
| See the man page for details. | ||||
|  | ||||
|  | ||||
| Configuration | ||||
| ------------- | ||||
| slstatus can be customized by creating a custom config.h and (re)compiling the | ||||
| source code. This keeps it fast, secure and simple. | ||||
							
								
								
									
										33
									
								
								slstatus/arg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								slstatus/arg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #ifndef ARG_H | ||||
| #define ARG_H | ||||
|  | ||||
| extern char *argv0; | ||||
|  | ||||
| /* int main(int argc, char *argv[]) */ | ||||
| #define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0);      \ | ||||
|                       *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ | ||||
|                  	int i_, argused_;                                         \ | ||||
|                  	if ((*argv)[1] == '-' && !(*argv)[2]) {                   \ | ||||
|                  		argc--, argv++;                                   \ | ||||
|                  		break;                                            \ | ||||
|                  	}                                                         \ | ||||
|                  	for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) {           \ | ||||
| 				switch ((*argv)[i_]) | ||||
| #define ARGEND   		if (argused_) {                                   \ | ||||
|                  			if ((*argv)[i_ + 1]) {                    \ | ||||
|                  				break;                            \ | ||||
|                  			} else {                                  \ | ||||
|                  				argc--, argv++;                   \ | ||||
|                  				break;                            \ | ||||
|                  			}                                         \ | ||||
|                  		}                                                 \ | ||||
|                  	}                                                         \ | ||||
|                  } | ||||
| #define ARGC()    ((*argv)[i_]) | ||||
| #define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) :        \ | ||||
|                   (*(argv + 1))     ? (argused_ = 1, *(argv + 1))        : (x)) | ||||
| #define EARGF(x) ARGF_(((x), exit(1), (char *)0)) | ||||
| #define ARGF()   ARGF_((char *)0) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										247
									
								
								slstatus/components/battery.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								slstatus/components/battery.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| /* | ||||
|  * https://www.kernel.org/doc/html/latest/power/power_supply_class.html | ||||
|  */ | ||||
| 	#include <limits.h> | ||||
| 	#include <stdint.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	#define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" | ||||
| 	#define POWER_SUPPLY_STATUS   "/sys/class/power_supply/%s/status" | ||||
| 	#define POWER_SUPPLY_CHARGE   "/sys/class/power_supply/%s/charge_now" | ||||
| 	#define POWER_SUPPLY_ENERGY   "/sys/class/power_supply/%s/energy_now" | ||||
| 	#define POWER_SUPPLY_CURRENT  "/sys/class/power_supply/%s/current_now" | ||||
| 	#define POWER_SUPPLY_POWER    "/sys/class/power_supply/%s/power_now" | ||||
|  | ||||
| 	static const char * | ||||
| 	pick(const char *bat, const char *f1, const char *f2, char *path, | ||||
| 	     size_t length) | ||||
| 	{ | ||||
| 		if (esnprintf(path, length, f1, bat) > 0 && | ||||
| 		    access(path, R_OK) == 0) | ||||
| 			return f1; | ||||
|  | ||||
| 		if (esnprintf(path, length, f2, bat) > 0 && | ||||
| 		    access(path, R_OK) == 0) | ||||
| 			return f2; | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *bat) | ||||
| 	{ | ||||
| 		int cap_perc; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%d", &cap_perc) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", cap_perc); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *bat) | ||||
| 	{ | ||||
| 		static struct { | ||||
| 			char *state; | ||||
| 			char *symbol; | ||||
| 		} map[] = { | ||||
| 			{ "Charging",    "+" }, | ||||
| 			{ "Discharging", "-" }, | ||||
| 			{ "Full",        "o" }, | ||||
| 			{ "Not charging", "o" }, | ||||
| 		}; | ||||
| 		size_t i; | ||||
| 		char path[PATH_MAX], state[12]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%12[a-zA-Z ]", state) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		for (i = 0; i < LEN(map); i++) | ||||
| 			if (!strcmp(map[i].state, state)) | ||||
| 				break; | ||||
|  | ||||
| 		return (i == LEN(map)) ? "?" : map[i].symbol; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *bat) | ||||
| 	{ | ||||
| 		uintmax_t charge_now, current_now, m, h; | ||||
| 		double timeleft; | ||||
| 		char path[PATH_MAX], state[12]; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%12[a-zA-Z ]", state) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, | ||||
| 		          sizeof(path)) || | ||||
| 		    pscanf(path, "%ju", &charge_now) < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!strcmp(state, "Discharging")) { | ||||
| 			if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, | ||||
| 			          sizeof(path)) || | ||||
| 			    pscanf(path, "%ju", ¤t_now) < 0) | ||||
| 				return NULL; | ||||
|  | ||||
| 			if (current_now == 0) | ||||
| 				return NULL; | ||||
|  | ||||
| 			timeleft = (double)charge_now / (double)current_now; | ||||
| 			h = timeleft; | ||||
| 			m = (timeleft - (double)h) * 60; | ||||
|  | ||||
| 			return bprintf("%juh %jum", h, m); | ||||
| 		} | ||||
|  | ||||
| 		return ""; | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <fcntl.h> | ||||
| 	#include <machine/apmvar.h> | ||||
| 	#include <sys/ioctl.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int | ||||
| 	load_apm_power_info(struct apm_power_info *apm_info) | ||||
| 	{ | ||||
| 		int fd; | ||||
|  | ||||
| 		fd = open("/dev/apm", O_RDONLY); | ||||
| 		if (fd < 0) { | ||||
| 			warn("open '/dev/apm':"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		memset(apm_info, 0, sizeof(struct apm_power_info)); | ||||
| 		if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { | ||||
| 			warn("ioctl 'APM_IOC_GETPOWER':"); | ||||
| 			close(fd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		return close(fd), 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct apm_power_info apm_info; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) | ||||
| 			return bprintf("%d", apm_info.battery_life); | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *unused) | ||||
| 	{ | ||||
| 		struct { | ||||
| 			unsigned int state; | ||||
| 			char *symbol; | ||||
| 		} map[] = { | ||||
| 			{ APM_AC_ON,      "+" }, | ||||
| 			{ APM_AC_OFF,     "-" }, | ||||
| 		}; | ||||
| 		struct apm_power_info apm_info; | ||||
| 		size_t i; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) { | ||||
| 			for (i = 0; i < LEN(map); i++) | ||||
| 				if (map[i].state == apm_info.ac_state) | ||||
| 					break; | ||||
|  | ||||
| 			return (i == LEN(map)) ? "?" : map[i].symbol; | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *unused) | ||||
| 	{ | ||||
| 		struct apm_power_info apm_info; | ||||
| 		unsigned int h, m; | ||||
|  | ||||
| 		if (load_apm_power_info(&apm_info)) { | ||||
| 			if (apm_info.ac_state != APM_AC_ON) { | ||||
| 				h = apm_info.minutes_left / 60; | ||||
| 				m = apm_info.minutes_left % 60; | ||||
| 				return bprintf("%uh %02um", h, m); | ||||
| 			} else { | ||||
| 				return ""; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	#define BATTERY_LIFE  "hw.acpi.battery.life" | ||||
| 	#define BATTERY_STATE "hw.acpi.battery.state" | ||||
| 	#define BATTERY_TIME  "hw.acpi.battery.time" | ||||
|  | ||||
| 	const char * | ||||
| 	battery_perc(const char *unused) | ||||
| 	{ | ||||
| 		int cap_perc; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(cap_perc); | ||||
| 		if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", cap_perc); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_state(const char *unused) | ||||
| 	{ | ||||
| 		int state; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(state); | ||||
| 		if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		switch (state) { | ||||
| 		case 0: /* FALLTHROUGH */ | ||||
| 		case 2: | ||||
| 			return "+"; | ||||
| 		case 1: | ||||
| 			return "-"; | ||||
| 		default: | ||||
| 			return "?"; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	battery_remaining(const char *unused) | ||||
| 	{ | ||||
| 		int rem; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(rem); | ||||
| 		if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len | ||||
| 		    || rem < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%uh %02um", rem / 60, rem % 60); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										32
									
								
								slstatus/components/cat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								slstatus/components/cat.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| cat(const char *path) | ||||
| { | ||||
|         char *f; | ||||
|         FILE *fp; | ||||
|  | ||||
|         if (!(fp = fopen(path, "r"))) { | ||||
|                 warn("fopen '%s':", path); | ||||
|                 return NULL; | ||||
|         } | ||||
|  | ||||
|         f = fgets(buf, sizeof(buf) - 1, fp); | ||||
|         if (fclose(fp) < 0) { | ||||
|                 warn("fclose '%s':", path); | ||||
|                 return NULL; | ||||
|         } | ||||
|         if (!f) | ||||
|                 return NULL; | ||||
|  | ||||
|         if ((f = strrchr(buf, '\n'))) | ||||
|                 f[0] = '\0'; | ||||
|  | ||||
|         return buf[0] ? buf : NULL; | ||||
| } | ||||
|  | ||||
							
								
								
									
										157
									
								
								slstatus/components/cpu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								slstatus/components/cpu.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t freq; | ||||
|  | ||||
| 		/* in kHz */ | ||||
| 		if (pscanf(CPU_FREQ, "%ju", &freq) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(freq * 1000, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		static long double a[7]; | ||||
| 		long double b[7], sum; | ||||
|  | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		/* cpu user nice system idle iowait irq softirq */ | ||||
| 		if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", | ||||
| 		           &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) | ||||
| 		    != 7) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - | ||||
| 		      (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", (int)(100 * | ||||
| 		               ((b[0] + b[1] + b[2] + b[5] + b[6]) - | ||||
| 		                (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <sys/param.h> | ||||
| 	#include <sys/sched.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		int freq, mib[2]; | ||||
| 		size_t size; | ||||
|  | ||||
| 		mib[0] = CTL_HW; | ||||
| 		mib[1] = HW_CPUSPEED; | ||||
|  | ||||
| 		size = sizeof(freq); | ||||
|  | ||||
| 		/* in MHz */ | ||||
| 		if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'HW_CPUSPEED':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		return fmt_human(freq * 1E6, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		int mib[2]; | ||||
| 		static uintmax_t a[CPUSTATES]; | ||||
| 		uintmax_t b[CPUSTATES], sum; | ||||
| 		size_t size; | ||||
|  | ||||
| 		mib[0] = CTL_KERN; | ||||
| 		mib[1] = KERN_CPTIME; | ||||
|  | ||||
| 		size = sizeof(a); | ||||
|  | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'KERN_CPTIME':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - | ||||
| 		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * | ||||
| 		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + | ||||
| 		                 a[CP_INTR]) - | ||||
| 		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + | ||||
| 		                 b[CP_INTR])) / sum); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <devstat.h> | ||||
| 	#include <sys/param.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_freq(const char *unused) | ||||
| 	{ | ||||
| 		int freq; | ||||
| 		size_t size; | ||||
|  | ||||
| 		size = sizeof(freq); | ||||
| 		/* in MHz */ | ||||
| 		if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { | ||||
| 			warn("sysctlbyname 'hw.clockrate':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		return fmt_human(freq * 1E6, 1000); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	cpu_perc(const char *unused) | ||||
| 	{ | ||||
| 		size_t size; | ||||
| 		static long a[CPUSTATES]; | ||||
| 		long b[CPUSTATES], sum; | ||||
|  | ||||
| 		size = sizeof(a); | ||||
| 		memcpy(b, a, sizeof(b)); | ||||
| 		if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { | ||||
| 			warn("sysctlbyname 'kern.cp_time':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (b[0] == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - | ||||
| 		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); | ||||
|  | ||||
| 		if (sum == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * | ||||
| 		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + | ||||
| 		                 a[CP_INTR]) - | ||||
| 		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + | ||||
| 		                 b[CP_INTR])) / sum); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										20
									
								
								slstatus/components/datetime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								slstatus/components/datetime.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| datetime(const char *fmt) | ||||
| { | ||||
| 	time_t t; | ||||
|  | ||||
| 	t = time(NULL); | ||||
| 	if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { | ||||
| 		warn("strftime: Result string exceeds buffer size"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										59
									
								
								slstatus/components/disk.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								slstatus/components/disk.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <sys/statvfs.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| disk_free(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * fs.f_bavail, 1024); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_perc(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%d", (int)(100 * | ||||
| 	               (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_total(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * fs.f_blocks, 1024); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| disk_used(const char *path) | ||||
| { | ||||
| 	struct statvfs fs; | ||||
|  | ||||
| 	if (statvfs(path, &fs) < 0) { | ||||
| 		warn("statvfs '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); | ||||
| } | ||||
							
								
								
									
										29
									
								
								slstatus/components/entropy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								slstatus/components/entropy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include "../slstatus.h" | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
| 	#include <stdio.h> | ||||
|  | ||||
| 	#include "../util.h" | ||||
|  | ||||
| 	#define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" | ||||
|  | ||||
| 	const char * | ||||
| 	entropy(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t num; | ||||
|  | ||||
| 		if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%ju", num); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	const char * | ||||
| 	entropy(const char *unused) | ||||
| 	{ | ||||
| 		// https://www.unicode.org/charts/PDF/U2200.pdf | ||||
| 		/* Unicode Character 'INFINITY' (U+221E) */ | ||||
| 		return "\u221E"; | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										17
									
								
								slstatus/components/hostname.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								slstatus/components/hostname.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| hostname(const char *unused) | ||||
| { | ||||
| 	if (gethostname(buf, sizeof(buf)) < 0) { | ||||
| 		warn("gethostbyname:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										61
									
								
								slstatus/components/ip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								slstatus/components/ip.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ifaddrs.h> | ||||
| #include <netdb.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #if defined(__OpenBSD__) | ||||
| 	#include <sys/socket.h> | ||||
| 	#include <sys/types.h> | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <netinet/in.h> | ||||
| 	#include <sys/socket.h> | ||||
| #endif | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| static const char * | ||||
| ip(const char *interface, unsigned short sa_family) | ||||
| { | ||||
| 	struct ifaddrs *ifaddr, *ifa; | ||||
| 	int s; | ||||
| 	char host[NI_MAXHOST]; | ||||
|  | ||||
| 	if (getifaddrs(&ifaddr) < 0) { | ||||
| 		warn("getifaddrs:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||||
| 		if (!ifa->ifa_addr) | ||||
| 			continue; | ||||
|  | ||||
| 		s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), | ||||
| 		                host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); | ||||
| 		if (!strcmp(ifa->ifa_name, interface) && | ||||
| 		    (ifa->ifa_addr->sa_family == sa_family)) { | ||||
| 			freeifaddrs(ifaddr); | ||||
| 			if (s != 0) { | ||||
| 				warn("getnameinfo: %s", gai_strerror(s)); | ||||
| 				return NULL; | ||||
| 			} | ||||
| 			return bprintf("%s", host); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	freeifaddrs(ifaddr); | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| ipv4(const char *interface) | ||||
| { | ||||
| 	return ip(interface, AF_INET); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| ipv6(const char *interface) | ||||
| { | ||||
| 	return ip(interface, AF_INET6); | ||||
| } | ||||
							
								
								
									
										19
									
								
								slstatus/components/kernel_release.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								slstatus/components/kernel_release.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <sys/utsname.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| kernel_release(const char *unused) | ||||
| { | ||||
| 	struct utsname udata; | ||||
|  | ||||
| 	if (uname(&udata) < 0) { | ||||
| 		warn("uname:"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%s", udata.release); | ||||
| } | ||||
							
								
								
									
										50
									
								
								slstatus/components/keyboard_indicators.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								slstatus/components/keyboard_indicators.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| /* | ||||
|  * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num | ||||
|  * lock, each optionally followed by '?', in the order of indicators desired. | ||||
|  * If followed by '?', the letter with case preserved is included in the output | ||||
|  * if the corresponding indicator is on.  Otherwise, the letter is always | ||||
|  * included, lowercase when off and uppercase when on. | ||||
|  */ | ||||
| const char * | ||||
| keyboard_indicators(const char *fmt) | ||||
| { | ||||
| 	Display *dpy; | ||||
| 	XKeyboardState state; | ||||
| 	size_t fmtlen, i, n; | ||||
| 	int togglecase, isset; | ||||
| 	char key; | ||||
|  | ||||
| 	if (!(dpy = XOpenDisplay(NULL))) { | ||||
| 		warn("XOpenDisplay: Failed to open display"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	XGetKeyboardControl(dpy, &state); | ||||
| 	XCloseDisplay(dpy); | ||||
|  | ||||
| 	fmtlen = strnlen(fmt, 4); | ||||
| 	for (i = n = 0; i < fmtlen; i++) { | ||||
| 		key = tolower(fmt[i]); | ||||
| 		if (key != 'c' && key != 'n') | ||||
| 			continue; | ||||
|  | ||||
| 		togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); | ||||
| 		isset = (state.led_mask & (1 << (key == 'n'))); | ||||
|  | ||||
| 		if (togglecase) | ||||
| 			buf[n++] = isset ? toupper(key) : key; | ||||
| 		else if (isset) | ||||
| 			buf[n++] = fmt[i]; | ||||
| 	} | ||||
|  | ||||
| 	buf[n] = 0; | ||||
| 	return buf; | ||||
| } | ||||
							
								
								
									
										86
									
								
								slstatus/components/keymap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								slstatus/components/keymap.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ctype.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <X11/XKBlib.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| static int | ||||
| valid_layout_or_variant(char *sym) | ||||
| { | ||||
| 	size_t i; | ||||
| 	/* invalid symbols from xkb rules config */ | ||||
| 	static const char *invalid[] = { "evdev", "inet", "pc", "base" }; | ||||
|  | ||||
| 	for (i = 0; i < LEN(invalid); i++) | ||||
| 		if (!strncmp(sym, invalid[i], strlen(invalid[i]))) | ||||
| 			return 0; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| get_layout(char *syms, int grp_num) | ||||
| { | ||||
| 	char *tok, *layout; | ||||
| 	int grp; | ||||
|  | ||||
| 	layout = NULL; | ||||
| 	tok = strtok(syms, "+:"); | ||||
| 	for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) { | ||||
| 		if (!valid_layout_or_variant(tok)) { | ||||
| 			continue; | ||||
| 		} else if (strlen(tok) == 1 && isdigit(tok[0])) { | ||||
| 			/* ignore :2, :3, :4 (additional layout groups) */ | ||||
| 			continue; | ||||
| 		} | ||||
| 		layout = tok; | ||||
| 		grp++; | ||||
| 	} | ||||
|  | ||||
| 	return layout; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| keymap(const char *unused) | ||||
| { | ||||
| 	Display *dpy; | ||||
| 	XkbDescRec *desc; | ||||
| 	XkbStateRec state; | ||||
| 	char *symbols; | ||||
| 	const char *layout; | ||||
|  | ||||
| 	layout = NULL; | ||||
|  | ||||
| 	if (!(dpy = XOpenDisplay(NULL))) { | ||||
| 		warn("XOpenDisplay: Failed to open display"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (!(desc = XkbAllocKeyboard())) { | ||||
| 		warn("XkbAllocKeyboard: Failed to allocate keyboard"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { | ||||
| 		warn("XkbGetNames: Failed to retrieve key symbols"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { | ||||
| 		warn("XkbGetState: Failed to retrieve keyboard state"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { | ||||
| 		warn("XGetAtomName: Failed to get atom name"); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	layout = bprintf("%s", get_layout(symbols, state.group)); | ||||
| 	XFree(symbols); | ||||
| end: | ||||
| 	XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); | ||||
| 	if (XCloseDisplay(dpy)) | ||||
| 		warn("XCloseDisplay: Failed to close display"); | ||||
|  | ||||
| 	return layout; | ||||
| } | ||||
							
								
								
									
										19
									
								
								slstatus/components/load_avg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								slstatus/components/load_avg.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| load_avg(const char *unused) | ||||
| { | ||||
| 	double avgs[3]; | ||||
|  | ||||
| 	if (getloadavg(avgs, 3) < 0) { | ||||
| 		warn("getloadavg: Failed to obtain load average"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); | ||||
| } | ||||
							
								
								
									
										129
									
								
								slstatus/components/netspeeds.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								slstatus/components/netspeeds.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	#define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" | ||||
| 	#define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_rx(const char *interface) | ||||
| 	{ | ||||
| 		uintmax_t oldrxbytes; | ||||
| 		static uintmax_t rxbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		oldrxbytes = rxbytes; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%ju", &rxbytes) != 1) | ||||
| 			return NULL; | ||||
| 		if (oldrxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_tx(const char *interface) | ||||
| 	{ | ||||
| 		uintmax_t oldtxbytes; | ||||
| 		static uintmax_t txbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		char path[PATH_MAX]; | ||||
|  | ||||
| 		oldtxbytes = txbytes; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (pscanf(path, "%ju", &txbytes) != 1) | ||||
| 			return NULL; | ||||
| 		if (oldtxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((txbytes - oldtxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	#include <ifaddrs.h> | ||||
| 	#include <net/if.h> | ||||
| 	#include <string.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <sys/socket.h> | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_rx(const char *interface) | ||||
| 	{ | ||||
| 		struct ifaddrs *ifal, *ifa; | ||||
| 		struct if_data *ifd; | ||||
| 		uintmax_t oldrxbytes; | ||||
| 		static uintmax_t rxbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		int if_ok = 0; | ||||
|  | ||||
| 		oldrxbytes = rxbytes; | ||||
|  | ||||
| 		if (getifaddrs(&ifal) < 0) { | ||||
| 			warn("getifaddrs failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		rxbytes = 0; | ||||
| 		for (ifa = ifal; ifa; ifa = ifa->ifa_next) | ||||
| 			if (!strcmp(ifa->ifa_name, interface) && | ||||
| 			   (ifd = (struct if_data *)ifa->ifa_data)) | ||||
| 				rxbytes += ifd->ifi_ibytes, if_ok = 1; | ||||
|  | ||||
| 		freeifaddrs(ifal); | ||||
| 		if (!if_ok) { | ||||
| 			warn("reading 'if_data' failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (oldrxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	netspeed_tx(const char *interface) | ||||
| 	{ | ||||
| 		struct ifaddrs *ifal, *ifa; | ||||
| 		struct if_data *ifd; | ||||
| 		uintmax_t oldtxbytes; | ||||
| 		static uintmax_t txbytes; | ||||
| 		extern const unsigned int interval; | ||||
| 		int if_ok = 0; | ||||
|  | ||||
| 		oldtxbytes = txbytes; | ||||
|  | ||||
| 		if (getifaddrs(&ifal) < 0) { | ||||
| 			warn("getifaddrs failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		txbytes = 0; | ||||
| 		for (ifa = ifal; ifa; ifa = ifa->ifa_next) | ||||
| 			if (!strcmp(ifa->ifa_name, interface) && | ||||
| 			   (ifd = (struct if_data *)ifa->ifa_data)) | ||||
| 				txbytes += ifd->ifi_obytes, if_ok = 1; | ||||
|  | ||||
| 		freeifaddrs(ifal); | ||||
| 		if (!if_ok) { | ||||
| 			warn("reading 'if_data' failed"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (oldtxbytes == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((txbytes - oldtxbytes) * 1000 / interval, | ||||
| 		                 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										32
									
								
								slstatus/components/num_files.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								slstatus/components/num_files.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <dirent.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| num_files(const char *path) | ||||
| { | ||||
| 	struct dirent *dp; | ||||
| 	DIR *dir; | ||||
| 	int num; | ||||
|  | ||||
| 	if (!(dir = opendir(path))) { | ||||
| 		warn("opendir '%s':", path); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	num = 0; | ||||
| 	while ((dp = readdir(dir))) { | ||||
| 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) | ||||
| 			continue; /* skip self and parent */ | ||||
|  | ||||
| 		num++; | ||||
| 	} | ||||
|  | ||||
| 	closedir(dir); | ||||
|  | ||||
| 	return bprintf("%d", num); | ||||
| } | ||||
							
								
								
									
										212
									
								
								slstatus/components/ram.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								slstatus/components/ram.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,212 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t free; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n", | ||||
| 		           &free, &free, &free) != 3) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(free * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total, free, buffers, cached; | ||||
| 		int percent; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n" | ||||
| 		           "Buffers: %ju kB\n" | ||||
| 		           "Cached: %ju kB\n", | ||||
| 		           &total, &free, &buffers, &buffers, &cached) != 5) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		percent = 100 * ((total - free) - (buffers + cached)) / total; | ||||
| 		return bprintf("%d", percent); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) | ||||
| 		    != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) | ||||
| 	{ | ||||
| 		uintmax_t total, free, buffers, cached, used; | ||||
|  | ||||
| 		if (pscanf("/proc/meminfo", | ||||
| 		           "MemTotal: %ju kB\n" | ||||
| 		           "MemFree: %ju kB\n" | ||||
| 		           "MemAvailable: %ju kB\n" | ||||
| 		           "Buffers: %ju kB\n" | ||||
| 		           "Cached: %ju kB\n", | ||||
| 		           &total, &free, &buffers, &buffers, &cached) != 5) | ||||
| 			return NULL; | ||||
|  | ||||
| 		used = (total - free - buffers - cached); | ||||
| 		return fmt_human(used * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/sysctl.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	#define LOG1024 10 | ||||
| 	#define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024)) | ||||
|  | ||||
| 	inline int | ||||
| 	load_uvmexp(struct uvmexp *uvmexp) | ||||
| 	{ | ||||
| 		int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; | ||||
| 		size_t size; | ||||
|  | ||||
| 		size = sizeof(*uvmexp); | ||||
|  | ||||
| 		if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0) | ||||
| 			return 1; | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
| 		int free_pages; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		free_pages = uvmexp.npages - uvmexp.active; | ||||
| 		return fmt_human(pagetok(free_pages, uvmexp.pageshift) * | ||||
| 				 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
| 		int percent; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		percent = uvmexp.active * 100 / uvmexp.npages; | ||||
| 		return bprintf("%d", percent); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(pagetok(uvmexp.npages, | ||||
| 					 uvmexp.pageshift) * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) | ||||
| 	{ | ||||
| 		struct uvmexp uvmexp; | ||||
|  | ||||
| 		if (!load_uvmexp(&uvmexp)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(pagetok(uvmexp.active, | ||||
| 					 uvmexp.pageshift) * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <sys/sysctl.h> | ||||
| 	#include <sys/vmmeter.h> | ||||
| 	#include <unistd.h> | ||||
| 	#include <vm/vm_param.h> | ||||
|  | ||||
| 	const char * | ||||
| 	ram_free(const char *unused) { | ||||
| 		struct vmtotal vm_stats; | ||||
| 		int mib[] = {CTL_VM, VM_TOTAL}; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(struct vmtotal); | ||||
| 		if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 | ||||
| 		    || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(vm_stats.t_free * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_total(const char *unused) { | ||||
| 		unsigned int npages; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(npages); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_page_count", | ||||
| 		                 &npages, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(npages * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_perc(const char *unused) { | ||||
| 		unsigned int npages; | ||||
| 		unsigned int active; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(npages); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_page_count", | ||||
| 		                 &npages, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (sysctlbyname("vm.stats.vm.v_active_count", | ||||
| 		                 &active, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", active * 100 / npages); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	ram_used(const char *unused) { | ||||
| 		unsigned int active; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(active); | ||||
| 		if (sysctlbyname("vm.stats.vm.v_active_count", | ||||
| 		                 &active, &len, NULL, 0) < 0 || !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(active * getpagesize(), 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										31
									
								
								slstatus/components/run_command.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								slstatus/components/run_command.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| run_command(const char *cmd) | ||||
| { | ||||
| 	char *p; | ||||
| 	FILE *fp; | ||||
|  | ||||
| 	if (!(fp = popen(cmd, "r"))) { | ||||
| 		warn("popen '%s':", cmd); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	p = fgets(buf, sizeof(buf) - 1, fp); | ||||
| 	if (pclose(fp) < 0) { | ||||
| 		warn("pclose '%s':", cmd); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if (!p) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if ((p = strrchr(buf, '\n'))) | ||||
| 		p[0] = '\0'; | ||||
|  | ||||
| 	return buf[0] ? buf : NULL; | ||||
| } | ||||
							
								
								
									
										274
									
								
								slstatus/components/swap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								slstatus/components/swap.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	static int | ||||
| 	get_swap_info(long *s_total, long *s_free, long *s_cached) | ||||
| 	{ | ||||
| 		FILE *fp; | ||||
| 		struct { | ||||
| 			const char *name; | ||||
| 			const size_t len; | ||||
| 			long *var; | ||||
| 		} ent[] = { | ||||
| 			{ "SwapTotal",  sizeof("SwapTotal") - 1,  s_total  }, | ||||
| 			{ "SwapFree",   sizeof("SwapFree") - 1,   s_free   }, | ||||
| 			{ "SwapCached", sizeof("SwapCached") - 1, s_cached }, | ||||
| 		}; | ||||
| 		size_t line_len = 0, i, left; | ||||
| 		char *line = NULL; | ||||
|  | ||||
| 		/* get number of fields we want to extract */ | ||||
| 		for (i = 0, left = 0; i < LEN(ent); i++) | ||||
| 			if (ent[i].var) | ||||
| 				left++; | ||||
|  | ||||
| 		if (!(fp = fopen("/proc/meminfo", "r"))) { | ||||
| 			warn("fopen '/proc/meminfo':"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		/* read file line by line and extract field information */ | ||||
| 		while (left > 0 && getline(&line, &line_len, fp) >= 0) { | ||||
| 			for (i = 0; i < LEN(ent); i++) { | ||||
| 				if (ent[i].var && | ||||
| 				    !strncmp(line, ent[i].name, ent[i].len)) { | ||||
| 					sscanf(line + ent[i].len + 1, | ||||
| 					       "%ld kB\n", ent[i].var); | ||||
| 					left--; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		free(line); | ||||
| 		if (ferror(fp)) { | ||||
| 			warn("getline '/proc/meminfo':"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		fclose(fp); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		long free; | ||||
|  | ||||
| 		if (get_swap_info(NULL, &free, NULL)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(free * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		long total, free, cached; | ||||
|  | ||||
| 		if (get_swap_info(&total, &free, &cached) || total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * (total - free - cached) / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		long total; | ||||
|  | ||||
| 		if (get_swap_info(&total, NULL, NULL)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		long total, free, cached; | ||||
|  | ||||
| 		if (get_swap_info(&total, &free, &cached)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((total - free - cached) * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/swap.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int | ||||
| 	getstats(int *total, int *used) | ||||
| 	{ | ||||
| 		struct swapent *sep, *fsep; | ||||
| 		int rnswap, nswap, i; | ||||
|  | ||||
| 		if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) { | ||||
| 			warn("swaptctl 'SWAP_NSWAP':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) { | ||||
| 			warn("calloc 'nswap':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) { | ||||
| 			warn("swapctl 'SWAP_STATA':"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if (nswap != rnswap) { | ||||
| 			warn("getstats: SWAP_STATS != SWAP_NSWAP"); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		*total = 0; | ||||
| 		*used = 0; | ||||
|  | ||||
| 		for (i = 0; i < rnswap; i++) { | ||||
| 			*total += sep->se_nblks >> 1; | ||||
| 			*used += sep->se_inuse >> 1; | ||||
| 		} | ||||
|  | ||||
| 		free(fsep); | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human((total - used) * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (total == 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%d", 100 * used / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(total * 1024, 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		int total, used; | ||||
|  | ||||
| 		if (getstats(&total, &used)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return fmt_human(used * 1024, 1024); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <fcntl.h> | ||||
| 	#include <kvm.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/types.h> | ||||
| 	#include <unistd.h> | ||||
|  | ||||
| 	static int getswapinfo(struct kvm_swap *swap_info, size_t size) | ||||
| 	{ | ||||
| 		kvm_t *kd; | ||||
|  | ||||
| 		kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL); | ||||
| 		if (kd == NULL) { | ||||
| 			warn("kvm_openfiles '/dev/null':"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) { | ||||
| 			warn("kvm_getswapinfo:"); | ||||
| 			kvm_close(kd); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		kvm_close(kd); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_free(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used, total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return fmt_human((total - used) * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used, total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return bprintf("%d", used * 100 / total); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_total(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long total; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		total = swap_info[0].ksw_total; | ||||
|  | ||||
| 		return fmt_human(total * getpagesize(), 1024); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	swap_used(const char *unused) | ||||
| 	{ | ||||
| 		struct kvm_swap swap_info[1]; | ||||
| 		long used; | ||||
|  | ||||
| 		if (!getswapinfo(swap_info, 1)) | ||||
| 			return NULL; | ||||
|  | ||||
| 		used = swap_info[0].ksw_used; | ||||
|  | ||||
| 		return fmt_human(used * getpagesize(), 1024); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										73
									
								
								slstatus/components/temperature.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								slstatus/components/temperature.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stddef.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <stdint.h> | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *file) | ||||
| 	{ | ||||
| 		uintmax_t temp; | ||||
|  | ||||
| 		if (pscanf(file, "%ju", &temp) != 1) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return bprintf("%ju", temp / 1000); | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <stdio.h> | ||||
| 	#include <sys/time.h> /* before <sys/sensors.h> for struct timeval */ | ||||
| 	#include <sys/sensors.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *unused) | ||||
| 	{ | ||||
| 		int mib[5]; | ||||
| 		size_t size; | ||||
| 		struct sensor temp; | ||||
|  | ||||
| 		mib[0] = CTL_HW; | ||||
| 		mib[1] = HW_SENSORS; | ||||
| 		mib[2] = 0; /* cpu0 */ | ||||
| 		mib[3] = SENSOR_TEMP; | ||||
| 		mib[4] = 0; /* temp0 */ | ||||
|  | ||||
| 		size = sizeof(temp); | ||||
|  | ||||
| 		if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) { | ||||
| 			warn("sysctl 'SENSOR_TEMP':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		/* kelvin to celsius */ | ||||
| 		return bprintf("%d", (int)((float)(temp.value-273150000) / 1E6)); | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <stdio.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/sysctl.h> | ||||
|  | ||||
| 	#define ACPI_TEMP "hw.acpi.thermal.%s.temperature" | ||||
|  | ||||
| 	const char * | ||||
| 	temp(const char *zone) | ||||
| 	{ | ||||
| 		char buf[256]; | ||||
| 		int temp; | ||||
| 		size_t len; | ||||
|  | ||||
| 		len = sizeof(temp); | ||||
| 		snprintf(buf, sizeof(buf), ACPI_TEMP, zone); | ||||
| 		if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 | ||||
| 				|| !len) | ||||
| 			return NULL; | ||||
|  | ||||
| 		/* kelvin to decimal celcius */ | ||||
| 		return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										34
									
								
								slstatus/components/uptime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								slstatus/components/uptime.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(CLOCK_BOOTTIME) | ||||
| 	#define UPTIME_FLAG CLOCK_BOOTTIME | ||||
| #elif defined(CLOCK_UPTIME) | ||||
| 	#define UPTIME_FLAG CLOCK_UPTIME | ||||
| #else | ||||
| 	#define UPTIME_FLAG CLOCK_MONOTONIC | ||||
| #endif | ||||
|  | ||||
| const char * | ||||
| uptime(const char *unused) | ||||
| { | ||||
| 	char warn_buf[256]; | ||||
| 	uintmax_t h, m; | ||||
| 	struct timespec uptime; | ||||
|  | ||||
| 	if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { | ||||
| 		snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); | ||||
| 		warn(warn_buf); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	h = uptime.tv_sec / 3600; | ||||
| 	m = uptime.tv_sec % 3600 / 60; | ||||
|  | ||||
| 	return bprintf("%juh %jum", h, m); | ||||
| } | ||||
							
								
								
									
										33
									
								
								slstatus/components/user.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								slstatus/components/user.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <pwd.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| const char * | ||||
| gid(const char *unused) | ||||
| { | ||||
| 	return bprintf("%d", getgid()); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| username(const char *unused) | ||||
| { | ||||
| 	struct passwd *pw; | ||||
|  | ||||
| 	if (!(pw = getpwuid(geteuid()))) { | ||||
| 		warn("getpwuid '%d':", geteuid()); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bprintf("%s", pw->pw_name); | ||||
| } | ||||
|  | ||||
| const char * | ||||
| uid(const char *unused) | ||||
| { | ||||
| 	return bprintf("%d", geteuid()); | ||||
| } | ||||
							
								
								
									
										219
									
								
								slstatus/components/volume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								slstatus/components/volume.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #if defined(__OpenBSD__) | defined(__FreeBSD__) | ||||
| 	#include <poll.h> | ||||
| 	#include <sndio.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/queue.h> | ||||
|  | ||||
| 	struct control { | ||||
| 		LIST_ENTRY(control)	next; | ||||
| 		unsigned int		addr; | ||||
| 	#define CTRL_NONE	0 | ||||
| 	#define CTRL_LEVEL	1 | ||||
| 	#define CTRL_MUTE	2 | ||||
| 		unsigned int		type; | ||||
| 		unsigned int		maxval; | ||||
| 		unsigned int		val; | ||||
| 	}; | ||||
|  | ||||
| 	static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls); | ||||
| 	static struct pollfd *pfds; | ||||
| 	static struct sioctl_hdl *hdl; | ||||
| 	static int initialized; | ||||
|  | ||||
| 	/* | ||||
| 	 * Call-back to obtain the description of all audio controls. | ||||
| 	 */ | ||||
| 	static void | ||||
| 	ondesc(void *unused, struct sioctl_desc *desc, int val) | ||||
| 	{ | ||||
| 		struct control *c, *ctmp; | ||||
| 		unsigned int type = CTRL_NONE; | ||||
|  | ||||
| 		if (desc == NULL) | ||||
| 			return; | ||||
|  | ||||
| 		/* Delete existing audio control with the same address. */ | ||||
| 		LIST_FOREACH_SAFE(c, &controls, next, ctmp) { | ||||
| 			if (desc->addr == c->addr) { | ||||
| 				LIST_REMOVE(c, next); | ||||
| 				free(c); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* Only match output.level and output.mute audio controls. */ | ||||
| 		if (desc->group[0] != 0 || | ||||
| 		    strcmp(desc->node0.name, "output") != 0) | ||||
| 			return; | ||||
| 		if (desc->type == SIOCTL_NUM && | ||||
| 		    strcmp(desc->func, "level") == 0) | ||||
| 			type = CTRL_LEVEL; | ||||
| 		else if (desc->type == SIOCTL_SW && | ||||
| 			 strcmp(desc->func, "mute") == 0) | ||||
| 			type = CTRL_MUTE; | ||||
| 		else | ||||
| 			return; | ||||
|  | ||||
| 		c = malloc(sizeof(struct control)); | ||||
| 		if (c == NULL) { | ||||
| 			warn("sndio: failed to allocate audio control\n"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		c->addr = desc->addr; | ||||
| 		c->type = type; | ||||
| 		c->maxval = desc->maxval; | ||||
| 		c->val = val; | ||||
| 		LIST_INSERT_HEAD(&controls, c, next); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Call-back invoked whenever an audio control changes. | ||||
| 	 */ | ||||
| 	static void | ||||
| 	onval(void *unused, unsigned int addr, unsigned int val) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
|  | ||||
| 		LIST_FOREACH(c, &controls, next) { | ||||
| 			if (c->addr == addr) | ||||
| 				break; | ||||
| 		} | ||||
| 		c->val = val; | ||||
| 	} | ||||
|  | ||||
| 	static void | ||||
| 	cleanup(void) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
|  | ||||
| 		if (hdl) { | ||||
| 			sioctl_close(hdl); | ||||
| 			hdl = NULL; | ||||
| 		} | ||||
|  | ||||
| 		free(pfds); | ||||
| 		pfds = NULL; | ||||
|  | ||||
| 		while (!LIST_EMPTY(&controls)) { | ||||
| 			c = LIST_FIRST(&controls); | ||||
| 			LIST_REMOVE(c, next); | ||||
| 			free(c); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static int | ||||
| 	init(void) | ||||
| 	{ | ||||
| 		hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); | ||||
| 		if (hdl == NULL) { | ||||
| 			warn("sndio: cannot open device"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		if (!sioctl_ondesc(hdl, ondesc, NULL)) { | ||||
| 			warn("sndio: cannot set control description call-back"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		if (!sioctl_onval(hdl, onval, NULL)) { | ||||
| 			warn("sndio: cannot set control values call-back"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd)); | ||||
| 		if (pfds == NULL) { | ||||
| 			warn("sndio: cannot allocate pollfd structures"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		return 1; | ||||
| 	failed: | ||||
| 		cleanup(); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	vol_perc(const char *unused) | ||||
| 	{ | ||||
| 		struct control *c; | ||||
| 		int n, v, value; | ||||
|  | ||||
| 		if (!initialized) | ||||
| 			initialized = init(); | ||||
|  | ||||
| 		if (hdl == NULL) | ||||
| 			return NULL; | ||||
|  | ||||
| 		n = sioctl_pollfd(hdl, pfds, POLLIN); | ||||
| 		if (n > 0) { | ||||
| 			n = poll(pfds, n, 0); | ||||
| 			if (n > 0) { | ||||
| 				if (sioctl_revents(hdl, pfds) & POLLHUP) { | ||||
| 					warn("sndio: disconnected"); | ||||
| 					cleanup(); | ||||
| 					initialized = 0; | ||||
| 					return NULL; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		value = 100; | ||||
| 		LIST_FOREACH(c, &controls, next) { | ||||
| 			if (c->type == CTRL_MUTE && c->val == 1) | ||||
| 				value = 0; | ||||
| 			else if (c->type == CTRL_LEVEL) { | ||||
| 				v = (c->val * 100 + c->maxval / 2) / c->maxval; | ||||
| 				/* For multiple channels return the minimum. */ | ||||
| 				if (v < value) | ||||
| 					value = v; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return bprintf("%d", value); | ||||
| 	} | ||||
| #else | ||||
| 	#include <sys/soundcard.h> | ||||
|  | ||||
| 	const char * | ||||
| 	vol_perc(const char *card) | ||||
| 	{ | ||||
| 		size_t i; | ||||
| 		int v, afd, devmask; | ||||
| 		char *vnames[] = SOUND_DEVICE_NAMES; | ||||
|  | ||||
| 		if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { | ||||
| 			warn("open '%s':", card); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { | ||||
| 			warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); | ||||
| 			close(afd); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		for (i = 0; i < LEN(vnames); i++) { | ||||
| 			if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { | ||||
| 				if (ioctl(afd, MIXER_READ(i), &v) < 0) { | ||||
| 					warn("ioctl 'MIXER_READ(%ld)':", i); | ||||
| 					close(afd); | ||||
| 					return NULL; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		close(afd); | ||||
|  | ||||
| 		return bprintf("%d", v & 0xff); | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										267
									
								
								slstatus/components/wifi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								slstatus/components/wifi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ifaddrs.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/socket.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "../slstatus.h" | ||||
| #include "../util.h" | ||||
|  | ||||
| #define RSSI_TO_PERC(rssi) \ | ||||
| 			rssi >= -50 ? 100 : \ | ||||
| 			(rssi <= -100 ? 0 : \ | ||||
| 			(2 * (rssi + 100))) | ||||
|  | ||||
| #if defined(__linux__) | ||||
| 	#include <limits.h> | ||||
| 	#include <linux/wireless.h> | ||||
|  | ||||
| 	#define NET_OPERSTATE "/sys/class/net/%s/operstate" | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		int cur; | ||||
| 		size_t i; | ||||
| 		char *p, *datastart; | ||||
| 		char path[PATH_MAX]; | ||||
| 		char status[5]; | ||||
| 		FILE *fp; | ||||
|  | ||||
| 		if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) | ||||
| 			return NULL; | ||||
| 		if (!(fp = fopen(path, "r"))) { | ||||
| 			warn("fopen '%s':", path); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		p = fgets(status, 5, fp); | ||||
| 		fclose(fp); | ||||
| 		if (!p || strcmp(status, "up\n") != 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!(fp = fopen("/proc/net/wireless", "r"))) { | ||||
| 			warn("fopen '/proc/net/wireless':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		for (i = 0; i < 3; i++) | ||||
| 			if (!(p = fgets(buf, sizeof(buf) - 1, fp))) | ||||
| 				break; | ||||
|  | ||||
| 		fclose(fp); | ||||
| 		if (i < 2 || !p) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if (!(datastart = strstr(buf, interface))) | ||||
| 			return NULL; | ||||
|  | ||||
| 		datastart = (datastart+(strlen(interface)+1)); | ||||
| 		sscanf(datastart + 1, " %*d   %d  %*d  %*d\t\t  %*d\t   " | ||||
| 		       "%*d\t\t%*d\t\t %*d\t  %*d\t\t %*d", &cur); | ||||
|  | ||||
| 		/* 70 is the max of /proc/net/wireless */ | ||||
| 		return bprintf("%d", (int)((float)cur / 70 * 100)); | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		static char id[IW_ESSID_MAX_SIZE+1]; | ||||
| 		int sockfd; | ||||
| 		struct iwreq wreq; | ||||
|  | ||||
| 		memset(&wreq, 0, sizeof(struct iwreq)); | ||||
| 		wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; | ||||
| 		if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", | ||||
| 		              interface) < 0) | ||||
| 			return NULL; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		wreq.u.essid.pointer = id; | ||||
| 		if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { | ||||
| 			warn("ioctl 'SIOCGIWESSID':"); | ||||
| 			close(sockfd); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
|  | ||||
| 		if (!strcmp(id, "")) | ||||
| 			return NULL; | ||||
|  | ||||
| 		return id; | ||||
| 	} | ||||
| #elif defined(__OpenBSD__) | ||||
| 	#include <net/if.h> | ||||
| 	#include <net/if_media.h> | ||||
| 	#include <net80211/ieee80211.h> | ||||
| 	#include <sys/select.h> /* before <sys/ieee80211_ioctl.h> for NBBY */ | ||||
| 	#include <net80211/ieee80211_ioctl.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <sys/types.h> | ||||
|  | ||||
| 	static int | ||||
| 	load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr) | ||||
| 	{ | ||||
| 		struct ieee80211_bssid bssid; | ||||
| 		int sockfd; | ||||
| 		uint8_t zero_bssid[IEEE80211_ADDR_LEN]; | ||||
|  | ||||
| 		memset(&bssid, 0, sizeof(bssid)); | ||||
| 		memset(nr, 0, sizeof(struct ieee80211_nodereq)); | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); | ||||
| 		if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) { | ||||
| 			warn("ioctl 'SIOCG80211BSSID':"); | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		memset(&zero_bssid, 0, sizeof(zero_bssid)); | ||||
| 		if (memcmp(bssid.i_bssid, zero_bssid, | ||||
| 		    IEEE80211_ADDR_LEN) == 0) { | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname)); | ||||
| 		memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr)); | ||||
| 		if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) { | ||||
| 			warn("ioctl 'SIOCG80211NODE':"); | ||||
| 			close(sockfd); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		return close(sockfd), 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		struct ieee80211_nodereq nr; | ||||
| 		int q; | ||||
|  | ||||
| 		if (load_ieee80211_nodereq(interface, &nr)) { | ||||
| 			if (nr.nr_max_rssi) | ||||
| 				q = IEEE80211_NODEREQ_RSSI(&nr); | ||||
| 			else | ||||
| 				q = RSSI_TO_PERC(nr.nr_rssi); | ||||
|  | ||||
| 			return bprintf("%d", q); | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		struct ieee80211_nodereq nr; | ||||
|  | ||||
| 		if (load_ieee80211_nodereq(interface, &nr)) | ||||
| 			return bprintf("%s", nr.nr_nwid); | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
| #elif defined(__FreeBSD__) | ||||
| 	#include <net/if.h> | ||||
| 	#include <net80211/ieee80211_ioctl.h> | ||||
|  | ||||
| 	int | ||||
| 	load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len) | ||||
| 	{ | ||||
| 		char warn_buf[256]; | ||||
| 		struct ieee80211req ireq; | ||||
| 		memset(&ireq, 0, sizeof(ireq)); | ||||
| 		ireq.i_type = type; | ||||
| 		ireq.i_data = (caddr_t) data; | ||||
| 		ireq.i_len = *len; | ||||
|  | ||||
| 		strlcpy(ireq.i_name, interface, sizeof(ireq.i_name)); | ||||
| 		if (ioctl(sock, SIOCG80211, &ireq) < 0) { | ||||
| 			snprintf(warn_buf,  sizeof(warn_buf), | ||||
| 					"ioctl: 'SIOCG80211': %d", type); | ||||
| 			warn(warn_buf); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		*len = ireq.i_len; | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_perc(const char *interface) | ||||
| 	{ | ||||
| 		union { | ||||
| 			struct ieee80211req_sta_req sta; | ||||
| 			uint8_t buf[24 * 1024]; | ||||
| 		} info; | ||||
| 		uint8_t bssid[IEEE80211_ADDR_LEN]; | ||||
| 		int rssi_dbm; | ||||
| 		int sockfd; | ||||
| 		size_t len; | ||||
| 		const char *fmt; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		/* Retreive MAC address of interface */ | ||||
| 		len = IEEE80211_ADDR_LEN; | ||||
| 		fmt = NULL; | ||||
| 		if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len)) | ||||
| 		{ | ||||
| 			/* Retrieve info on station with above BSSID */ | ||||
| 			memset(&info, 0, sizeof(info)); | ||||
| 			memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid)); | ||||
|  | ||||
| 			len = sizeof(info); | ||||
| 			if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) { | ||||
| 				rssi_dbm = info.sta.info[0].isi_noise + | ||||
|  					         info.sta.info[0].isi_rssi / 2; | ||||
|  | ||||
| 				fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
| 		return fmt; | ||||
| 	} | ||||
|  | ||||
| 	const char * | ||||
| 	wifi_essid(const char *interface) | ||||
| 	{ | ||||
| 		char ssid[IEEE80211_NWID_LEN + 1]; | ||||
| 		size_t len; | ||||
| 		int sockfd; | ||||
| 		const char *fmt; | ||||
|  | ||||
| 		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||||
| 			warn("socket 'AF_INET':"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		fmt = NULL; | ||||
| 		len = sizeof(ssid); | ||||
| 		memset(&ssid, 0, len); | ||||
| 		if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) { | ||||
| 			if (len < sizeof(ssid)) | ||||
| 				len += 1; | ||||
| 			else | ||||
| 				len = sizeof(ssid); | ||||
|  | ||||
| 			ssid[len - 1] = '\0'; | ||||
| 			fmt = bprintf("%s", ssid); | ||||
| 		} | ||||
|  | ||||
| 		close(sockfd); | ||||
| 		return fmt; | ||||
| 	} | ||||
| #endif | ||||
							
								
								
									
										69
									
								
								slstatus/config.def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/config.def.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* interval between updates (in ms) */ | ||||
| const unsigned int interval = 1000; | ||||
|  | ||||
| /* text to show if no value can be retrieved */ | ||||
| static const char unknown_str[] = "n/a"; | ||||
|  | ||||
| /* maximum output string length */ | ||||
| #define MAXLEN 2048 | ||||
|  | ||||
| /* | ||||
|  * function            description                     argument (example) | ||||
|  * | ||||
|  * battery_perc        battery percentage              battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_remaining   battery remaining HH:MM         battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_state       battery charging state          battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * cat                 read arbitrary file             path | ||||
|  * cpu_freq            cpu frequency in MHz            NULL | ||||
|  * cpu_perc            cpu usage in percent            NULL | ||||
|  * datetime            date and time                   format string (%F %T) | ||||
|  * disk_free           free disk space in GB           mountpoint path (/) | ||||
|  * disk_perc           disk usage in percent           mountpoint path (/) | ||||
|  * disk_total          total disk space in GB          mountpoint path (/) | ||||
|  * disk_used           used disk space in GB           mountpoint path (/) | ||||
|  * entropy             available entropy               NULL | ||||
|  * gid                 GID of current user             NULL | ||||
|  * hostname            hostname                        NULL | ||||
|  * ipv4                IPv4 address                    interface name (eth0) | ||||
|  * ipv6                IPv6 address                    interface name (eth0) | ||||
|  * kernel_release      `uname -r`                      NULL | ||||
|  * keyboard_indicators caps/num lock indicators        format string (c?n?) | ||||
|  *                                                     see keyboard_indicators.c | ||||
|  * keymap              layout (variant) of current     NULL | ||||
|  *                     keymap | ||||
|  * load_avg            load average                    NULL | ||||
|  * netspeed_rx         receive network speed           interface name (wlan0) | ||||
|  * netspeed_tx         transfer network speed          interface name (wlan0) | ||||
|  * num_files           number of files in a directory  path | ||||
|  *                                                     (/home/foo/Inbox/cur) | ||||
|  * ram_free            free memory in GB               NULL | ||||
|  * ram_perc            memory usage in percent         NULL | ||||
|  * ram_total           total memory size in GB         NULL | ||||
|  * ram_used            used memory in GB               NULL | ||||
|  * run_command         custom shell command            command (echo foo) | ||||
|  * swap_free           free swap in GB                 NULL | ||||
|  * swap_perc           swap usage in percent           NULL | ||||
|  * swap_total          total swap size in GB           NULL | ||||
|  * swap_used           used swap in GB                 NULL | ||||
|  * temp                temperature in degree celsius   sensor file | ||||
|  *                                                     (/sys/class/thermal/...) | ||||
|  *                                                     NULL on OpenBSD | ||||
|  *                                                     thermal zone on FreeBSD | ||||
|  *                                                     (tz0, tz1, etc.) | ||||
|  * uid                 UID of current user             NULL | ||||
|  * uptime              system uptime                   NULL | ||||
|  * username            username of current user        NULL | ||||
|  * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * wifi_essid          WiFi ESSID                      interface name (wlan0) | ||||
|  * wifi_perc           WiFi signal in percent          interface name (wlan0) | ||||
|  */ | ||||
| static const struct arg args[] = { | ||||
| 	/* function format          argument */ | ||||
| 	{ datetime, "%s",           "%F %T" }, | ||||
| }; | ||||
							
								
								
									
										69
									
								
								slstatus/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								slstatus/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* interval between updates (in ms) */ | ||||
| const unsigned int interval = 1000; | ||||
|  | ||||
| /* text to show if no value can be retrieved */ | ||||
| static const char unknown_str[] = "n/a"; | ||||
|  | ||||
| /* maximum output string length */ | ||||
| #define MAXLEN 2048 | ||||
|  | ||||
| /* | ||||
|  * function            description                     argument (example) | ||||
|  * | ||||
|  * battery_perc        battery percentage              battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_remaining   battery remaining HH:MM         battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * battery_state       battery charging state          battery name (BAT0) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * cat                 read arbitrary file             path | ||||
|  * cpu_freq            cpu frequency in MHz            NULL | ||||
|  * cpu_perc            cpu usage in percent            NULL | ||||
|  * datetime            date and time                   format string (%F %T) | ||||
|  * disk_free           free disk space in GB           mountpoint path (/) | ||||
|  * disk_perc           disk usage in percent           mountpoint path (/) | ||||
|  * disk_total          total disk space in GB          mountpoint path (/) | ||||
|  * disk_used           used disk space in GB           mountpoint path (/) | ||||
|  * entropy             available entropy               NULL | ||||
|  * gid                 GID of current user             NULL | ||||
|  * hostname            hostname                        NULL | ||||
|  * ipv4                IPv4 address                    interface name (eth0) | ||||
|  * ipv6                IPv6 address                    interface name (eth0) | ||||
|  * kernel_release      `uname -r`                      NULL | ||||
|  * keyboard_indicators caps/num lock indicators        format string (c?n?) | ||||
|  *                                                     see keyboard_indicators.c | ||||
|  * keymap              layout (variant) of current     NULL | ||||
|  *                     keymap | ||||
|  * load_avg            load average                    NULL | ||||
|  * netspeed_rx         receive network speed           interface name (wlan0) | ||||
|  * netspeed_tx         transfer network speed          interface name (wlan0) | ||||
|  * num_files           number of files in a directory  path | ||||
|  *                                                     (/home/foo/Inbox/cur) | ||||
|  * ram_free            free memory in GB               NULL | ||||
|  * ram_perc            memory usage in percent         NULL | ||||
|  * ram_total           total memory size in GB         NULL | ||||
|  * ram_used            used memory in GB               NULL | ||||
|  * run_command         custom shell command            command (echo foo) | ||||
|  * swap_free           free swap in GB                 NULL | ||||
|  * swap_perc           swap usage in percent           NULL | ||||
|  * swap_total          total swap size in GB           NULL | ||||
|  * swap_used           used swap in GB                 NULL | ||||
|  * temp                temperature in degree celsius   sensor file | ||||
|  *                                                     (/sys/class/thermal/...) | ||||
|  *                                                     NULL on OpenBSD | ||||
|  *                                                     thermal zone on FreeBSD | ||||
|  *                                                     (tz0, tz1, etc.) | ||||
|  * uid                 UID of current user             NULL | ||||
|  * uptime              system uptime                   NULL | ||||
|  * username            username of current user        NULL | ||||
|  * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer) | ||||
|  *                                                     NULL on OpenBSD/FreeBSD | ||||
|  * wifi_essid          WiFi ESSID                      interface name (wlan0) | ||||
|  * wifi_perc           WiFi signal in percent          interface name (wlan0) | ||||
|  */ | ||||
| static const struct arg args[] = { | ||||
| 	/* function format          argument */ | ||||
| 	{ datetime, "%s",           "%F %T" }, | ||||
| }; | ||||
							
								
								
									
										22
									
								
								slstatus/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								slstatus/config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| # slstatus version | ||||
| VERSION = 1.0 | ||||
|  | ||||
| # customize below to fit your system | ||||
|  | ||||
| # paths | ||||
| PREFIX = /usr/local | ||||
| MANPREFIX = $(PREFIX)/share/man | ||||
|  | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
|  | ||||
| # flags | ||||
| CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" | ||||
| CFLAGS   = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os | ||||
| LDFLAGS  = -L$(X11LIB) -s | ||||
| # OpenBSD: add -lsndio | ||||
| # FreeBSD: add -lkvm -lsndio | ||||
| LDLIBS   = -lX11 -lsndio | ||||
|  | ||||
| # compiler and linker | ||||
| CC = cc | ||||
							
								
								
									
										
											BIN
										
									
								
								slstatus/slstatus
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								slstatus/slstatus
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										47
									
								
								slstatus/slstatus.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								slstatus/slstatus.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| .Dd 2023-04-23 | ||||
| .Dt SLSTATUS 1 | ||||
| .Os | ||||
| .Sh NAME | ||||
| .Nm slstatus | ||||
| .Nd suckless status | ||||
| .Sh SYNOPSIS | ||||
| .Nm | ||||
| .Op Fl s | ||||
| .Op Fl 1 | ||||
| .Sh DESCRIPTION | ||||
| .Nm | ||||
| is a small tool for providing system status information to other programs | ||||
| over the EWMH | ||||
| .Em WM_NAME | ||||
| property of the root window (used by | ||||
| .Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by | ||||
| only issuing the minimum of system calls required. | ||||
| .P | ||||
| By default, | ||||
| .Nm | ||||
| outputs to WM_NAME. | ||||
| .Sh OPTIONS | ||||
| .Bl -tag -width Ds | ||||
| .It Fl v | ||||
| Print version information to stderr, then exit. | ||||
| .It Fl s | ||||
| Write to stdout instead of WM_NAME. | ||||
| .It Fl 1 | ||||
| Write once to stdout and quit. | ||||
| .El | ||||
| .Sh CUSTOMIZATION | ||||
| .Nm | ||||
| can be customized by creating a custom config.h and (re)compiling the source | ||||
| code. This keeps it fast, secure and simple. | ||||
| .Sh SIGNALS | ||||
| .Nm | ||||
| responds to the following signals: | ||||
| .Pp | ||||
| .Bl -tag -width TERM -compact | ||||
| .It USR1 | ||||
| Triggers an instant redraw. | ||||
| .El | ||||
| .Sh AUTHORS | ||||
| See the LICENSE file for the authors. | ||||
| .Sh SEE ALSO | ||||
| .Xr dwm 1 | ||||
							
								
								
									
										134
									
								
								slstatus/slstatus.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								slstatus/slstatus.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #include "arg.h" | ||||
| #include "slstatus.h" | ||||
| #include "util.h" | ||||
|  | ||||
| struct arg { | ||||
| 	const char *(*func)(const char *); | ||||
| 	const char *fmt; | ||||
| 	const char *args; | ||||
| }; | ||||
|  | ||||
| char buf[1024]; | ||||
| static volatile sig_atomic_t done; | ||||
| static Display *dpy; | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| static void | ||||
| terminate(const int signo) | ||||
| { | ||||
| 	if (signo != SIGUSR1) | ||||
| 		done = 1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) | ||||
| { | ||||
| 	res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); | ||||
| 	res->tv_nsec = a->tv_nsec - b->tv_nsec + | ||||
| 	               (a->tv_nsec < b->tv_nsec) * 1E9; | ||||
| } | ||||
|  | ||||
| static void | ||||
| usage(void) | ||||
| { | ||||
| 	die("usage: %s [-v] [-s] [-1]", argv0); | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	struct sigaction act; | ||||
| 	struct timespec start, current, diff, intspec, wait; | ||||
| 	size_t i, len; | ||||
| 	int sflag, ret; | ||||
| 	char status[MAXLEN]; | ||||
| 	const char *res; | ||||
|  | ||||
| 	sflag = 0; | ||||
| 	ARGBEGIN { | ||||
| 	case 'v': | ||||
| 		die("slstatus-"VERSION); | ||||
| 	case '1': | ||||
| 		done = 1; | ||||
| 		/* FALLTHROUGH */ | ||||
| 	case 's': | ||||
| 		sflag = 1; | ||||
| 		break; | ||||
| 	default: | ||||
| 		usage(); | ||||
| 	} ARGEND | ||||
|  | ||||
| 	if (argc) | ||||
| 		usage(); | ||||
|  | ||||
| 	memset(&act, 0, sizeof(act)); | ||||
| 	act.sa_handler = terminate; | ||||
| 	sigaction(SIGINT,  &act, NULL); | ||||
| 	sigaction(SIGTERM, &act, NULL); | ||||
| 	act.sa_flags |= SA_RESTART; | ||||
| 	sigaction(SIGUSR1, &act, NULL); | ||||
|  | ||||
| 	if (!sflag && !(dpy = XOpenDisplay(NULL))) | ||||
| 		die("XOpenDisplay: Failed to open display"); | ||||
|  | ||||
| 	do { | ||||
| 		if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) | ||||
| 			die("clock_gettime:"); | ||||
|  | ||||
| 		status[0] = '\0'; | ||||
| 		for (i = len = 0; i < LEN(args); i++) { | ||||
| 			if (!(res = args[i].func(args[i].args))) | ||||
| 				res = unknown_str; | ||||
|  | ||||
| 			if ((ret = esnprintf(status + len, sizeof(status) - len, | ||||
| 			                     args[i].fmt, res)) < 0) | ||||
| 				break; | ||||
|  | ||||
| 			len += ret; | ||||
| 		} | ||||
|  | ||||
| 		if (sflag) { | ||||
| 			puts(status); | ||||
| 			fflush(stdout); | ||||
| 			if (ferror(stdout)) | ||||
| 				die("puts:"); | ||||
| 		} else { | ||||
| 			if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) | ||||
| 				die("XStoreName: Allocation failed"); | ||||
| 			XFlush(dpy); | ||||
| 		} | ||||
|  | ||||
| 		if (!done) { | ||||
| 			if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) | ||||
| 				die("clock_gettime:"); | ||||
| 			difftimespec(&diff, ¤t, &start); | ||||
|  | ||||
| 			intspec.tv_sec = interval / 1000; | ||||
| 			intspec.tv_nsec = (interval % 1000) * 1E6; | ||||
| 			difftimespec(&wait, &intspec, &diff); | ||||
|  | ||||
| 			if (wait.tv_sec >= 0 && | ||||
| 			    nanosleep(&wait, NULL) < 0 && | ||||
| 			    errno != EINTR) | ||||
| 					die("nanosleep:"); | ||||
| 		} | ||||
| 	} while (!done); | ||||
|  | ||||
| 	if (!sflag) { | ||||
| 		XStoreName(dpy, DefaultRootWindow(dpy), NULL); | ||||
| 		if (XCloseDisplay(dpy) < 0) | ||||
| 			die("XCloseDisplay: Failed to close display"); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										84
									
								
								slstatus/slstatus.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								slstatus/slstatus.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* battery */ | ||||
| const char *battery_perc(const char *); | ||||
| const char *battery_remaining(const char *); | ||||
| const char *battery_state(const char *); | ||||
|  | ||||
| /* cat */ | ||||
| const char *cat(const char *path); | ||||
|  | ||||
| /* cpu */ | ||||
| const char *cpu_freq(const char *unused); | ||||
| const char *cpu_perc(const char *unused); | ||||
|  | ||||
| /* datetime */ | ||||
| const char *datetime(const char *fmt); | ||||
|  | ||||
| /* disk */ | ||||
| const char *disk_free(const char *path); | ||||
| const char *disk_perc(const char *path); | ||||
| const char *disk_total(const char *path); | ||||
| const char *disk_used(const char *path); | ||||
|  | ||||
| /* entropy */ | ||||
| const char *entropy(const char *unused); | ||||
|  | ||||
| /* hostname */ | ||||
| const char *hostname(const char *unused); | ||||
|  | ||||
| /* ip */ | ||||
| const char *ipv4(const char *interface); | ||||
| const char *ipv6(const char *interface); | ||||
|  | ||||
| /* kernel_release */ | ||||
| const char *kernel_release(const char *unused); | ||||
|  | ||||
| /* keyboard_indicators */ | ||||
| const char *keyboard_indicators(const char *fmt); | ||||
|  | ||||
| /* keymap */ | ||||
| const char *keymap(const char *unused); | ||||
|  | ||||
| /* load_avg */ | ||||
| const char *load_avg(const char *unused); | ||||
|  | ||||
| /* netspeeds */ | ||||
| const char *netspeed_rx(const char *interface); | ||||
| const char *netspeed_tx(const char *interface); | ||||
|  | ||||
| /* num_files */ | ||||
| const char *num_files(const char *path); | ||||
|  | ||||
| /* ram */ | ||||
| const char *ram_free(const char *unused); | ||||
| const char *ram_perc(const char *unused); | ||||
| const char *ram_total(const char *unused); | ||||
| const char *ram_used(const char *unused); | ||||
|  | ||||
| /* run_command */ | ||||
| const char *run_command(const char *cmd); | ||||
|  | ||||
| /* swap */ | ||||
| const char *swap_free(const char *unused); | ||||
| const char *swap_perc(const char *unused); | ||||
| const char *swap_total(const char *unused); | ||||
| const char *swap_used(const char *unused); | ||||
|  | ||||
| /* temperature */ | ||||
| const char *temp(const char *); | ||||
|  | ||||
| /* uptime */ | ||||
| const char *uptime(const char *unused); | ||||
|  | ||||
| /* user */ | ||||
| const char *gid(const char *unused); | ||||
| const char *uid(const char *unused); | ||||
| const char *username(const char *unused); | ||||
|  | ||||
| /* volume */ | ||||
| const char *vol_perc(const char *card); | ||||
|  | ||||
| /* wifi */ | ||||
| const char *wifi_essid(const char *interface); | ||||
| const char *wifi_perc(const char *interface); | ||||
							
								
								
									
										141
									
								
								slstatus/util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								slstatus/util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <errno.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "util.h" | ||||
|  | ||||
| char *argv0; | ||||
|  | ||||
| static void | ||||
| verr(const char *fmt, va_list ap) | ||||
| { | ||||
| 	vfprintf(stderr, fmt, ap); | ||||
|  | ||||
| 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { | ||||
| 		fputc(' ', stderr); | ||||
| 		perror(NULL); | ||||
| 	} else { | ||||
| 		fputc('\n', stderr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| warn(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	verr(fmt, ap); | ||||
| 	va_end(ap); | ||||
| } | ||||
|  | ||||
| void | ||||
| die(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	verr(fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| static int | ||||
| evsnprintf(char *str, size_t size, const char *fmt, va_list ap) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = vsnprintf(str, size, fmt, ap); | ||||
|  | ||||
| 	if (ret < 0) { | ||||
| 		warn("vsnprintf:"); | ||||
| 		return -1; | ||||
| 	} else if ((size_t)ret >= size) { | ||||
| 		warn("vsnprintf: Output truncated"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| esnprintf(char *str, size_t size, const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int ret; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	ret = evsnprintf(str, size, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| bprintf(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int ret; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	ret = evsnprintf(buf, sizeof(buf), fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	return (ret < 0) ? NULL : buf; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| fmt_human(uintmax_t num, int base) | ||||
| { | ||||
| 	double scaled; | ||||
| 	size_t i, prefixlen; | ||||
| 	const char **prefix; | ||||
| 	const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", | ||||
| 	                              "Y" }; | ||||
| 	const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", | ||||
| 	                              "Zi", "Yi" }; | ||||
|  | ||||
| 	switch (base) { | ||||
| 	case 1000: | ||||
| 		prefix = prefix_1000; | ||||
| 		prefixlen = LEN(prefix_1000); | ||||
| 		break; | ||||
| 	case 1024: | ||||
| 		prefix = prefix_1024; | ||||
| 		prefixlen = LEN(prefix_1024); | ||||
| 		break; | ||||
| 	default: | ||||
| 		warn("fmt_human: Invalid base"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	scaled = num; | ||||
| 	for (i = 0; i < prefixlen && scaled >= base; i++) | ||||
| 		scaled /= base; | ||||
|  | ||||
| 	return bprintf("%.1f %s", scaled, prefix[i]); | ||||
| } | ||||
|  | ||||
| int | ||||
| pscanf(const char *path, const char *fmt, ...) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	va_list ap; | ||||
| 	int n; | ||||
|  | ||||
| 	if (!(fp = fopen(path, "r"))) { | ||||
| 		warn("fopen '%s':", path); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	va_start(ap, fmt); | ||||
| 	n = vfscanf(fp, fmt, ap); | ||||
| 	va_end(ap); | ||||
| 	fclose(fp); | ||||
|  | ||||
| 	return (n == EOF) ? -1 : n; | ||||
| } | ||||
							
								
								
									
										16
									
								
								slstatus/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								slstatus/util.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <stdint.h> | ||||
|  | ||||
| extern char buf[1024]; | ||||
|  | ||||
| #define LEN(x) (sizeof(x) / sizeof((x)[0])) | ||||
|  | ||||
| extern char *argv0; | ||||
|  | ||||
| void warn(const char *, ...); | ||||
| void die(const char *, ...); | ||||
|  | ||||
| int esnprintf(char *str, size_t size, const char *fmt, ...); | ||||
| const char *bprintf(const char *fmt, ...); | ||||
| const char *fmt_human(uintmax_t num, int base); | ||||
| int pscanf(const char *path, const char *fmt, ...); | ||||
							
								
								
									
										253
									
								
								st/FAQ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								st/FAQ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,253 @@ | ||||
| ## Why does st not handle utmp entries? | ||||
|  | ||||
| Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. | ||||
|  | ||||
|  | ||||
| ## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! | ||||
|  | ||||
| It means that st doesn’t have any terminfo entry on your system. Chances are | ||||
| you did not `make install`. If you just want to test it without installing it, | ||||
| you can manually run `tic -sx st.info`. | ||||
|  | ||||
|  | ||||
| ## Nothing works, and nothing is said about an unknown terminal! | ||||
|  | ||||
| * Some programs just assume they’re running in xterm i.e. they don’t rely on | ||||
|   terminfo. What you see is the current state of the “xterm compliance”. | ||||
| * Some programs don’t complain about the lacking st description and default to | ||||
|   another terminal. In that case see the question about terminfo. | ||||
|  | ||||
|  | ||||
| ## How do I scroll back up? | ||||
|  | ||||
| * Using a terminal multiplexer. | ||||
| 	* `st -e tmux` using C-b [ | ||||
| 	* `st -e screen` using C-a ESC | ||||
| * Using the excellent tool of [scroll](https://git.suckless.org/scroll/). | ||||
| * Using the scrollback [patch](https://st.suckless.org/patches/scrollback/). | ||||
|  | ||||
|  | ||||
| ## I would like to have utmp and/or scroll functionality by default | ||||
|  | ||||
| You can add the absolute path of both programs in your config.h file. You only | ||||
| have to modify the value of utmp and scroll variables. | ||||
|  | ||||
|  | ||||
| ## Why doesn't the Del key work in some programs? | ||||
|  | ||||
| Taken from the terminfo manpage: | ||||
|  | ||||
| 	If the terminal has a keypad that transmits codes when the keys | ||||
| 	are pressed, this information can be given. Note that it is not | ||||
| 	possible to handle terminals where the keypad only works in | ||||
| 	local (this applies, for example, to the unshifted HP 2621 keys). | ||||
| 	If the keypad can be set to transmit or not transmit, give these | ||||
| 	codes as smkx and rmkx. Otherwise the keypad is assumed to | ||||
| 	always transmit. | ||||
|  | ||||
| In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that | ||||
| applications which want to test against keypad keys send these | ||||
| sequences. | ||||
|  | ||||
| But buggy applications (like bash and irssi, for example) don't do this. A fast | ||||
| solution for them is to use the following command: | ||||
|  | ||||
| 	$ printf '\033[?1h\033=' >/dev/tty | ||||
|  | ||||
| or | ||||
| 	$ tput smkx | ||||
|  | ||||
| In the case of bash, readline is used. Readline has a different note in its | ||||
| manpage about this issue: | ||||
|  | ||||
| 	enable-keypad (Off) | ||||
| 		When set to On, readline will try to enable the | ||||
| 		application keypad when it is called. Some systems | ||||
| 		need this to enable arrow keys. | ||||
|  | ||||
| Adding this option to your .inputrc will fix the keypad problem for all | ||||
| applications using readline. | ||||
|  | ||||
| If you are using zsh, then read the zsh FAQ | ||||
| <http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25>: | ||||
|  | ||||
| 	It should be noted that the O / [ confusion can occur with other keys | ||||
| 	such as Home and End. Some systems let you query the key sequences | ||||
| 	sent by these keys from the system's terminal database, terminfo. | ||||
| 	Unfortunately, the key sequences given there typically apply to the | ||||
| 	mode that is not the one zsh uses by default (it's the "application" | ||||
| 	mode rather than the "raw" mode). Explaining the use of terminfo is | ||||
| 	outside of the scope of this FAQ, but if you wish to use the key | ||||
| 	sequences given there you can tell the line editor to turn on | ||||
| 	"application" mode when it starts and turn it off when it stops: | ||||
|  | ||||
| 		function zle-line-init () { echoti smkx } | ||||
| 		function zle-line-finish () { echoti rmkx } | ||||
| 		zle -N zle-line-init | ||||
| 		zle -N zle-line-finish | ||||
|  | ||||
| Putting these lines into your .zshrc will fix the problems. | ||||
|  | ||||
|  | ||||
| ## How can I use meta in 8bit mode? | ||||
|  | ||||
| St supports meta in 8bit mode, but the default terminfo entry doesn't | ||||
| use this capability. If you want it, you have to use the 'st-meta' value | ||||
| in TERM. | ||||
|  | ||||
|  | ||||
| ## I cannot compile st in OpenBSD | ||||
|  | ||||
| OpenBSD lacks librt, despite it being mandatory in POSIX | ||||
| <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_13>. | ||||
| If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and | ||||
| st will compile without any loss of functionality, because all the functions are | ||||
| included in libc on this platform. | ||||
|  | ||||
|  | ||||
| ## The Backspace Case | ||||
|  | ||||
| St is emulating the Linux way of handling backspace being delete and delete being | ||||
| backspace. | ||||
|  | ||||
| This is an issue that was discussed in suckless mailing list | ||||
| <https://lists.suckless.org/dev/1404/20697.html>. Here is why some old grumpy | ||||
| terminal users wants its backspace to be how he feels it: | ||||
|  | ||||
| 	Well, I am going to comment why I want to change the behaviour | ||||
| 	of this key. When ASCII was defined in 1968, communication | ||||
| 	with computers was done using punched cards, or hardcopy | ||||
| 	terminals (basically a typewriter machine connected with the | ||||
| 	computer using a serial port).  ASCII defines DELETE as 7F, | ||||
| 	because, in punched-card terms, it means all the holes of the | ||||
| 	card punched; it is thus a kind of 'physical delete'. In the | ||||
| 	same way, the BACKSPACE key was a non-destructive backspace, | ||||
| 	as on a typewriter.  So, if you wanted to delete a character, | ||||
| 	you had to BACKSPACE and then DELETE.  Another use of BACKSPACE | ||||
| 	was to type accented characters, for example 'a BACKSPACE `'. | ||||
| 	The VT100 had no BACKSPACE key; it was generated using the | ||||
| 	CONTROL key as another control character (CONTROL key sets to | ||||
| 	0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code | ||||
| 	0x08)), but it had a DELETE key in a similar position where | ||||
| 	the BACKSPACE key is located today on common PC keyboards. | ||||
| 	All the terminal emulators emulated the difference between | ||||
| 	these keys correctly: the backspace key generated a BACKSPACE | ||||
| 	(^H) and delete key generated a DELETE (^?). | ||||
|  | ||||
| 	But a problem arose when Linus Torvalds wrote Linux. Unlike | ||||
| 	earlier terminals, the Linux virtual terminal (the terminal | ||||
| 	emulator integrated in the kernel) returned a DELETE when | ||||
| 	backspace was pressed, due to the VT100 having a DELETE key in | ||||
| 	the same position.  This created a lot of problems (see [1] | ||||
| 	and [2]). Since Linux has become the king, a lot of terminal | ||||
| 	emulators today generate a DELETE when the backspace key is | ||||
| 	pressed in order to avoid problems with Linux. The result is | ||||
| 	that the only way of generating a BACKSPACE on these systems | ||||
| 	is by using CONTROL + H. (I also think that emacs had an | ||||
| 	important point here because the CONTROL + H prefix is used | ||||
| 	in emacs in some commands (help commands).) | ||||
|  | ||||
| 	From point of view of the kernel, you can change the key | ||||
| 	for deleting a previous character with stty erase. When you | ||||
| 	connect a real terminal into a machine you describe the type | ||||
| 	of terminal, so getty configures the correct value of stty | ||||
| 	erase for this terminal. In the case of terminal emulators, | ||||
| 	however, you don't have any getty that can set the correct | ||||
| 	value of stty erase, so you always get the default value. | ||||
| 	For this reason, it is necessary to add 'stty erase ^H' to your | ||||
| 	profile if you have changed the value of the backspace key. | ||||
| 	Of course, another solution is for st itself to modify the | ||||
| 	value of stty erase.  I usually have the inverse problem: | ||||
| 	when I connect to non-Unix machines, I have to press CONTROL + | ||||
| 	h to get a BACKSPACE. The inverse problem occurs when a user | ||||
| 	connects to my Unix machines from a different system with a | ||||
| 	correct backspace key. | ||||
|  | ||||
| 	[1] http://www.ibb.net/~anne/keyboard.html | ||||
| 	[2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html | ||||
|  | ||||
|  | ||||
| ## But I really want the old grumpy behaviour of my terminal | ||||
|  | ||||
| Apply [1]. | ||||
|  | ||||
| [1] https://st.suckless.org/patches/delkey | ||||
|  | ||||
|  | ||||
| ## Why do images not work in st using the w3m image hack? | ||||
|  | ||||
| w3mimg uses a hack that draws an image on top of the terminal emulator Drawable | ||||
| window. The hack relies on the terminal to use a single buffer to draw its | ||||
| contents directly. | ||||
|  | ||||
| st uses double-buffered drawing so the image is quickly replaced and may show a | ||||
| short flicker effect. | ||||
|  | ||||
| Below is a patch example to change st double-buffering to a single Drawable | ||||
| buffer. | ||||
|  | ||||
| diff --git a/x.c b/x.c | ||||
| --- a/x.c | ||||
| +++ b/x.c | ||||
| @@ -732,10 +732,6 @@ xresize(int col, int row) | ||||
|  	win.tw = col * win.cw; | ||||
|  	win.th = row * win.ch; | ||||
|   | ||||
| -	XFreePixmap(xw.dpy, xw.buf); | ||||
| -	xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, | ||||
| -			DefaultDepth(xw.dpy, xw.scr)); | ||||
| -	XftDrawChange(xw.draw, xw.buf); | ||||
|  	xclear(0, 0, win.w, win.h); | ||||
|   | ||||
|  	/* resize to new width */ | ||||
| @@ -1148,8 +1144,7 @@ xinit(int cols, int rows) | ||||
|  	gcvalues.graphics_exposures = False; | ||||
|  	dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, | ||||
|  			&gcvalues); | ||||
| -	xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, | ||||
| -			DefaultDepth(xw.dpy, xw.scr)); | ||||
| +	xw.buf = xw.win; | ||||
|  	XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); | ||||
|  	XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); | ||||
|   | ||||
| @@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2) | ||||
|  void | ||||
|  xfinishdraw(void) | ||||
|  { | ||||
| -	XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, | ||||
| -			win.h, 0, 0); | ||||
|  	XSetForeground(xw.dpy, dc.gc, | ||||
|  			dc.col[IS_SET(MODE_REVERSE)? | ||||
|  				defaultfg : defaultbg].pixel); | ||||
|  | ||||
|  | ||||
| ## BadLength X error in Xft when trying to render emoji | ||||
|  | ||||
| Xft makes st crash when rendering color emojis with the following error: | ||||
|  | ||||
| "X Error of failed request:  BadLength (poly request too large or internal Xlib length error)" | ||||
|   Major opcode of failed request:  139 (RENDER) | ||||
|   Minor opcode of failed request:  20 (RenderAddGlyphs) | ||||
|   Serial number of failed request: 1595 | ||||
|   Current serial number in output stream:  1818" | ||||
|  | ||||
| This is a known bug in Xft (not st) which happens on some platforms and | ||||
| combination of particular fonts and fontconfig settings. | ||||
|  | ||||
| See also: | ||||
| https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 | ||||
| https://bugs.freedesktop.org/show_bug.cgi?id=107534 | ||||
| https://bugzilla.redhat.com/show_bug.cgi?id=1498269 | ||||
|  | ||||
| The solution is to remove color emoji fonts or disable this in the fontconfig | ||||
| XML configuration.  As an ugly workaround (which may work only on newer | ||||
| fontconfig versions (FC_COLOR)), the following code can be used to mask color | ||||
| fonts: | ||||
|  | ||||
| 	FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); | ||||
|  | ||||
| Please don't bother reporting this bug to st, but notify the upstream Xft | ||||
| developers about fixing this bug. | ||||
|  | ||||
| As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5: | ||||
| https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS | ||||
							
								
								
									
										17
									
								
								st/LEGACY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								st/LEGACY
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| A STATEMENT ON LEGACY SUPPORT | ||||
|  | ||||
| In the terminal world there is much cruft that comes from old and unsup‐ | ||||
| ported terminals that inherit incompatible modes  and  escape  sequences | ||||
| which noone is able to know, except when he/she comes from that time and | ||||
| developed a graphical vt100 emulator at that time. | ||||
|  | ||||
| One  goal  of  st is to only support what is really needed. When you en‐ | ||||
| counter a sequence which you really need, implement it.  But  while  you | ||||
| are  at it,  do not add the other cruft you might encounter while sneek‐ | ||||
| ing at other terminal emulators. History has bloated them and  there  is | ||||
| no real evidence that most of the sequences are used today. | ||||
|  | ||||
|  | ||||
| Christoph Lohmann <20h@r-36.net> | ||||
| 2012-09-13T07:00:36.081271045+02:00 | ||||
|  | ||||
							
								
								
									
										34
									
								
								st/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								st/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| MIT/X Consortium License | ||||
|  | ||||
| © 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org> | ||||
| © 2018 Devin J. Pohly <djpohly at gmail dot com> | ||||
| © 2014-2017 Quentin Rameau <quinq at fifth dot space> | ||||
| © 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> | ||||
| © 2008-2017 Anselm R Garbe <garbeam at gmail dot com> | ||||
| © 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com> | ||||
| © 2012-2016 Christoph Lohmann <20h at r-36 dot net> | ||||
| © 2013 Eon S. Jeon <esjeon at hyunmu dot am> | ||||
| © 2013 Alexander Sedov <alex0player at gmail dot com> | ||||
| © 2013 Mark Edgar <medgar123 at gmail dot com> | ||||
| © 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com> | ||||
| © 2013 Michael Forney <mforney at mforney dot org> | ||||
| © 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de> | ||||
| © 2014-2015 Laslo Hunhold <dev at frign dot de> | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a | ||||
| copy of this software and associated documentation files (the "Software"), | ||||
| to deal in the Software without restriction, including without limitation | ||||
| the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
| and/or sell copies of the Software, and to permit persons to whom the | ||||
| Software is furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | ||||
| THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
| DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										51
									
								
								st/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								st/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| # st - simple terminal | ||||
| # See LICENSE file for copyright and license details. | ||||
| .POSIX: | ||||
|  | ||||
| include config.mk | ||||
|  | ||||
| SRC = st.c x.c | ||||
| OBJ = $(SRC:.c=.o) | ||||
|  | ||||
| all: st | ||||
|  | ||||
| config.h: | ||||
| 	cp config.def.h config.h | ||||
|  | ||||
| .c.o: | ||||
| 	$(CC) $(STCFLAGS) -c $< | ||||
|  | ||||
| st.o: config.h st.h win.h | ||||
| x.o: arg.h config.h st.h win.h | ||||
|  | ||||
| $(OBJ): config.h config.mk | ||||
|  | ||||
| st: $(OBJ) | ||||
| 	$(CC) -o $@ $(OBJ) $(STLDFLAGS) | ||||
|  | ||||
| clean: | ||||
| 	rm -f st $(OBJ) st-$(VERSION).tar.gz | ||||
|  | ||||
| dist: clean | ||||
| 	mkdir -p st-$(VERSION) | ||||
| 	cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ | ||||
| 		config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ | ||||
| 		st-$(VERSION) | ||||
| 	tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz | ||||
| 	rm -rf st-$(VERSION) | ||||
|  | ||||
| install: st | ||||
| 	mkdir -p $(DESTDIR)$(PREFIX)/bin | ||||
| 	cp -f st $(DESTDIR)$(PREFIX)/bin | ||||
| 	chmod 755 $(DESTDIR)$(PREFIX)/bin/st | ||||
| 	mkdir -p $(DESTDIR)$(MANPREFIX)/man1 | ||||
| 	sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 | ||||
| 	chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 | ||||
| 	tic -sx st.info | ||||
| 	@echo Please see the README file regarding the terminfo entry of st. | ||||
|  | ||||
| uninstall: | ||||
| 	rm -f $(DESTDIR)$(PREFIX)/bin/st | ||||
| 	rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 | ||||
|  | ||||
| .PHONY: all clean dist install uninstall | ||||
							
								
								
									
										34
									
								
								st/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								st/README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| st - simple terminal | ||||
| -------------------- | ||||
| st is a simple terminal emulator for X which sucks less. | ||||
|  | ||||
|  | ||||
| Requirements | ||||
| ------------ | ||||
| In order to build st you need the Xlib header files. | ||||
|  | ||||
|  | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup (st is installed into | ||||
| the /usr/local namespace by default). | ||||
|  | ||||
| Afterwards enter the following command to build and install st (if | ||||
| necessary as root): | ||||
|  | ||||
|     make clean install | ||||
|  | ||||
|  | ||||
| Running st | ||||
| ---------- | ||||
| If you did not install st with make clean install, you must compile | ||||
| the st terminfo entry with the following command: | ||||
|  | ||||
|     tic -sx st.info | ||||
|  | ||||
| See the man page for additional details. | ||||
|  | ||||
| Credits | ||||
| ------- | ||||
| Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code. | ||||
|  | ||||
							
								
								
									
										28
									
								
								st/TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								st/TODO
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| vt emulation | ||||
| ------------ | ||||
|  | ||||
| * double-height support | ||||
|  | ||||
| code & interface | ||||
| ---------------- | ||||
|  | ||||
| * add a simple way to do multiplexing | ||||
|  | ||||
| drawing | ||||
| ------- | ||||
| * add diacritics support to xdraws() | ||||
| 	* switch to a suckless font drawing library | ||||
| * make the font cache simpler | ||||
| * add better support for brightening of the upper colors | ||||
|  | ||||
| bugs | ||||
| ---- | ||||
|  | ||||
| * fix shift up/down (shift selection in emacs) | ||||
| * remove DEC test sequence when appropriate | ||||
|  | ||||
| misc | ||||
| ---- | ||||
|  | ||||
|     $ grep -nE 'XXX|TODO' st.c | ||||
|  | ||||
							
								
								
									
										50
									
								
								st/arg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								st/arg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|  * Copy me if you can. | ||||
|  * by 20h | ||||
|  */ | ||||
|  | ||||
| #ifndef ARG_H__ | ||||
| #define ARG_H__ | ||||
|  | ||||
| extern char *argv0; | ||||
|  | ||||
| /* use main(int argc, char *argv[]) */ | ||||
| #define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\ | ||||
| 					argv[0] && argv[0][0] == '-'\ | ||||
| 					&& argv[0][1];\ | ||||
| 					argc--, argv++) {\ | ||||
| 				char argc_;\ | ||||
| 				char **argv_;\ | ||||
| 				int brk_;\ | ||||
| 				if (argv[0][1] == '-' && argv[0][2] == '\0') {\ | ||||
| 					argv++;\ | ||||
| 					argc--;\ | ||||
| 					break;\ | ||||
| 				}\ | ||||
| 				int i_;\ | ||||
| 				for (i_ = 1, brk_ = 0, argv_ = argv;\ | ||||
| 						argv[0][i_] && !brk_;\ | ||||
| 						i_++) {\ | ||||
| 					if (argv_ != argv)\ | ||||
| 						break;\ | ||||
| 					argc_ = argv[0][i_];\ | ||||
| 					switch (argc_) | ||||
|  | ||||
| #define ARGEND			}\ | ||||
| 			} | ||||
|  | ||||
| #define ARGC()		argc_ | ||||
|  | ||||
| #define EARGF(x)	((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ | ||||
| 				((x), abort(), (char *)0) :\ | ||||
| 				(brk_ = 1, (argv[0][i_+1] != '\0')?\ | ||||
| 					(&argv[0][i_+1]) :\ | ||||
| 					(argc--, argv++, argv[0]))) | ||||
|  | ||||
| #define ARGF()		((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ | ||||
| 				(char *)0 :\ | ||||
| 				(brk_ = 1, (argv[0][i_+1] != '\0')?\ | ||||
| 					(&argv[0][i_+1]) :\ | ||||
| 					(argc--, argv++, argv[0]))) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										474
									
								
								st/config.def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								st/config.def.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,474 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* | ||||
|  * appearance | ||||
|  * | ||||
|  * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html | ||||
|  */ | ||||
| static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; | ||||
| static int borderpx = 2; | ||||
|  | ||||
| /* | ||||
|  * What program is execed by st depends of these precedence rules: | ||||
|  * 1: program passed with -e | ||||
|  * 2: scroll and/or utmp | ||||
|  * 3: SHELL environment variable | ||||
|  * 4: value of shell in /etc/passwd | ||||
|  * 5: value of shell in config.h | ||||
|  */ | ||||
| static char *shell = "/bin/sh"; | ||||
| char *utmp = NULL; | ||||
| /* scroll program: to enable use a string like "scroll" */ | ||||
| char *scroll = NULL; | ||||
| char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; | ||||
|  | ||||
| /* identification sequence returned in DA and DECID */ | ||||
| char *vtiden = "\033[?6c"; | ||||
|  | ||||
| /* Kerning / character bounding-box multipliers */ | ||||
| static float cwscale = 1.0; | ||||
| static float chscale = 1.0; | ||||
|  | ||||
| /* | ||||
|  * word delimiter string | ||||
|  * | ||||
|  * More advanced example: L" `'\"()[]{}" | ||||
|  */ | ||||
| wchar_t *worddelimiters = L" "; | ||||
|  | ||||
| /* selection timeouts (in milliseconds) */ | ||||
| static unsigned int doubleclicktimeout = 300; | ||||
| static unsigned int tripleclicktimeout = 600; | ||||
|  | ||||
| /* alt screens */ | ||||
| int allowaltscreen = 1; | ||||
|  | ||||
| /* allow certain non-interactive (insecure) window operations such as: | ||||
|    setting the clipboard text */ | ||||
| int allowwindowops = 0; | ||||
|  | ||||
| /* | ||||
|  * draw latency range in ms - from new content/keypress/etc until drawing. | ||||
|  * within this range, st draws when content stops arriving (idle). mostly it's | ||||
|  * near minlatency, but it waits longer for slow updates to avoid partial draw. | ||||
|  * low minlatency will tear/flicker more, as it can "detect" idle too early. | ||||
|  */ | ||||
| static double minlatency = 8; | ||||
| static double maxlatency = 33; | ||||
|  | ||||
| /* | ||||
|  * blinking timeout (set to 0 to disable blinking) for the terminal blinking | ||||
|  * attribute. | ||||
|  */ | ||||
| static unsigned int blinktimeout = 800; | ||||
|  | ||||
| /* | ||||
|  * thickness of underline and bar cursors | ||||
|  */ | ||||
| static unsigned int cursorthickness = 2; | ||||
|  | ||||
| /* | ||||
|  * bell volume. It must be a value between -100 and 100. Use 0 for disabling | ||||
|  * it | ||||
|  */ | ||||
| static int bellvolume = 0; | ||||
|  | ||||
| /* default TERM value */ | ||||
| char *termname = "st-256color"; | ||||
|  | ||||
| /* | ||||
|  * spaces per tab | ||||
|  * | ||||
|  * When you are changing this value, don't forget to adapt the »it« value in | ||||
|  * the st.info and appropriately install the st.info in the environment where | ||||
|  * you use this st version. | ||||
|  * | ||||
|  *	it#$tabspaces, | ||||
|  * | ||||
|  * Secondly make sure your kernel is not expanding tabs. When running `stty | ||||
|  * -a` »tab0« should appear. You can tell the terminal to not expand tabs by | ||||
|  *  running following command: | ||||
|  * | ||||
|  *	stty tabs | ||||
|  */ | ||||
| unsigned int tabspaces = 8; | ||||
|  | ||||
| /* Terminal colors (16 first used in escape sequence) */ | ||||
| static const char *colorname[] = { | ||||
| 	/* 8 normal colors */ | ||||
| 	"black", | ||||
| 	"red3", | ||||
| 	"green3", | ||||
| 	"yellow3", | ||||
| 	"blue2", | ||||
| 	"magenta3", | ||||
| 	"cyan3", | ||||
| 	"gray90", | ||||
|  | ||||
| 	/* 8 bright colors */ | ||||
| 	"gray50", | ||||
| 	"red", | ||||
| 	"green", | ||||
| 	"yellow", | ||||
| 	"#5c5cff", | ||||
| 	"magenta", | ||||
| 	"cyan", | ||||
| 	"white", | ||||
|  | ||||
| 	[255] = 0, | ||||
|  | ||||
| 	/* more colors can be added after 255 to use with DefaultXX */ | ||||
| 	"#cccccc", | ||||
| 	"#555555", | ||||
| 	"gray90", /* default foreground colour */ | ||||
| 	"black", /* default background colour */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Default colors (colorname index) | ||||
|  * foreground, background, cursor, reverse cursor | ||||
|  */ | ||||
| unsigned int defaultfg = 258; | ||||
| unsigned int defaultbg = 259; | ||||
| unsigned int defaultcs = 256; | ||||
| static unsigned int defaultrcs = 257; | ||||
|  | ||||
| /* | ||||
|  * Default shape of cursor | ||||
|  * 2: Block ("█") | ||||
|  * 4: Underline ("_") | ||||
|  * 6: Bar ("|") | ||||
|  * 7: Snowman ("☃") | ||||
|  */ | ||||
| static unsigned int cursorshape = 2; | ||||
|  | ||||
| /* | ||||
|  * Default columns and rows numbers | ||||
|  */ | ||||
|  | ||||
| static unsigned int cols = 80; | ||||
| static unsigned int rows = 24; | ||||
|  | ||||
| /* | ||||
|  * Default colour and shape of the mouse cursor | ||||
|  */ | ||||
| static unsigned int mouseshape = XC_xterm; | ||||
| static unsigned int mousefg = 7; | ||||
| static unsigned int mousebg = 0; | ||||
|  | ||||
| /* | ||||
|  * Color used to display font attributes when fontconfig selected a font which | ||||
|  * doesn't match the ones requested. | ||||
|  */ | ||||
| static unsigned int defaultattr = 11; | ||||
|  | ||||
| /* | ||||
|  * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). | ||||
|  * Note that if you want to use ShiftMask with selmasks, set this to an other | ||||
|  * modifier, set to 0 to not use it. | ||||
|  */ | ||||
| static uint forcemousemod = ShiftMask; | ||||
|  | ||||
| /* | ||||
|  * Internal mouse shortcuts. | ||||
|  * Beware that overloading Button1 will disable the selection. | ||||
|  */ | ||||
| static MouseShortcut mshortcuts[] = { | ||||
| 	/* mask                 button   function        argument       release */ | ||||
| 	{ XK_ANY_MOD,           Button2, selpaste,       {.i = 0},      1 }, | ||||
| 	{ ShiftMask,            Button4, ttysend,        {.s = "\033[5;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button4, ttysend,        {.s = "\031"} }, | ||||
| 	{ ShiftMask,            Button5, ttysend,        {.s = "\033[6;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button5, ttysend,        {.s = "\005"} }, | ||||
| }; | ||||
|  | ||||
| /* Internal keyboard shortcuts. */ | ||||
| #define MODKEY Mod1Mask | ||||
| #define TERMMOD (ControlMask|ShiftMask) | ||||
|  | ||||
| static Shortcut shortcuts[] = { | ||||
| 	/* mask                 keysym          function        argument */ | ||||
| 	{ XK_ANY_MOD,           XK_Break,       sendbreak,      {.i =  0} }, | ||||
| 	{ ControlMask,          XK_Print,       toggleprinter,  {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Print,       printscreen,    {.i =  0} }, | ||||
| 	{ XK_ANY_MOD,           XK_Print,       printsel,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Prior,       zoom,           {.f = +1} }, | ||||
| 	{ TERMMOD,              XK_Next,        zoom,           {.f = -1} }, | ||||
| 	{ TERMMOD,              XK_Home,        zoomreset,      {.f =  0} }, | ||||
| 	{ TERMMOD,              XK_C,           clipcopy,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_V,           clippaste,      {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Y,           selpaste,       {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} }, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Special keys (change & recompile st.info accordingly) | ||||
|  * | ||||
|  * Mask value: | ||||
|  * * Use XK_ANY_MOD to match the key no matter modifiers state | ||||
|  * * Use XK_NO_MOD to match the key alone (no modifiers) | ||||
|  * appkey value: | ||||
|  * * 0: no value | ||||
|  * * > 0: keypad application mode enabled | ||||
|  * *   = 2: term.numlock = 1 | ||||
|  * * < 0: keypad application mode disabled | ||||
|  * appcursor value: | ||||
|  * * 0: no value | ||||
|  * * > 0: cursor application mode enabled | ||||
|  * * < 0: cursor application mode disabled | ||||
|  * | ||||
|  * Be careful with the order of the definitions because st searches in | ||||
|  * this table sequentially, so any XK_ANY_MOD must be in the last | ||||
|  * position for a key. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) | ||||
|  * to be mapped below, add them to this array. | ||||
|  */ | ||||
| static KeySym mappedkeys[] = { -1 }; | ||||
|  | ||||
| /* | ||||
|  * State bits to ignore when matching key or button events.  By default, | ||||
|  * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. | ||||
|  */ | ||||
| static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; | ||||
|  | ||||
| /* | ||||
|  * This is the huge key array which defines all compatibility to the Linux | ||||
|  * world. Please decide about changes wisely. | ||||
|  */ | ||||
| static Key key[] = { | ||||
| 	/* keysym           mask            string      appkey appcursor */ | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033Ox",       +1,    0}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033Or",       +1,    0}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033Ot",       +1,    0}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033Ov",       +1,    0}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_KP_Prior,      XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_KP_Begin,      XK_ANY_MOD,     "\033[E",        0,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_KP_End,        XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_KP_Next,       XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_KP_Multiply,   XK_ANY_MOD,     "\033Oj",       +2,    0}, | ||||
| 	{ XK_KP_Add,        XK_ANY_MOD,     "\033Ok",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\033OM",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\r",           -1,    0}, | ||||
| 	{ XK_KP_Subtract,   XK_ANY_MOD,     "\033Om",       +2,    0}, | ||||
| 	{ XK_KP_Decimal,    XK_ANY_MOD,     "\033On",       +2,    0}, | ||||
| 	{ XK_KP_Divide,     XK_ANY_MOD,     "\033Oo",       +2,    0}, | ||||
| 	{ XK_KP_0,          XK_ANY_MOD,     "\033Op",       +2,    0}, | ||||
| 	{ XK_KP_1,          XK_ANY_MOD,     "\033Oq",       +2,    0}, | ||||
| 	{ XK_KP_2,          XK_ANY_MOD,     "\033Or",       +2,    0}, | ||||
| 	{ XK_KP_3,          XK_ANY_MOD,     "\033Os",       +2,    0}, | ||||
| 	{ XK_KP_4,          XK_ANY_MOD,     "\033Ot",       +2,    0}, | ||||
| 	{ XK_KP_5,          XK_ANY_MOD,     "\033Ou",       +2,    0}, | ||||
| 	{ XK_KP_6,          XK_ANY_MOD,     "\033Ov",       +2,    0}, | ||||
| 	{ XK_KP_7,          XK_ANY_MOD,     "\033Ow",       +2,    0}, | ||||
| 	{ XK_KP_8,          XK_ANY_MOD,     "\033Ox",       +2,    0}, | ||||
| 	{ XK_KP_9,          XK_ANY_MOD,     "\033Oy",       +2,    0}, | ||||
| 	{ XK_Up,            ShiftMask,      "\033[1;2A",     0,    0}, | ||||
| 	{ XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0}, | ||||
| 	{ XK_Up,         ShiftMask|Mod1Mask,"\033[1;4A",     0,    0}, | ||||
| 	{ XK_Up,            ControlMask,    "\033[1;5A",     0,    0}, | ||||
| 	{ XK_Up,      ShiftMask|ControlMask,"\033[1;6A",     0,    0}, | ||||
| 	{ XK_Up,       ControlMask|Mod1Mask,"\033[1;7A",     0,    0}, | ||||
| 	{ XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A",  0,    0}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_Down,          ShiftMask,      "\033[1;2B",     0,    0}, | ||||
| 	{ XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0}, | ||||
| 	{ XK_Down,       ShiftMask|Mod1Mask,"\033[1;4B",     0,    0}, | ||||
| 	{ XK_Down,          ControlMask,    "\033[1;5B",     0,    0}, | ||||
| 	{ XK_Down,    ShiftMask|ControlMask,"\033[1;6B",     0,    0}, | ||||
| 	{ XK_Down,     ControlMask|Mod1Mask,"\033[1;7B",     0,    0}, | ||||
| 	{ XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0,    0}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_Left,          ShiftMask,      "\033[1;2D",     0,    0}, | ||||
| 	{ XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0}, | ||||
| 	{ XK_Left,       ShiftMask|Mod1Mask,"\033[1;4D",     0,    0}, | ||||
| 	{ XK_Left,          ControlMask,    "\033[1;5D",     0,    0}, | ||||
| 	{ XK_Left,    ShiftMask|ControlMask,"\033[1;6D",     0,    0}, | ||||
| 	{ XK_Left,     ControlMask|Mod1Mask,"\033[1;7D",     0,    0}, | ||||
| 	{ XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0,    0}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0}, | ||||
| 	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0}, | ||||
| 	{ XK_Right,      ShiftMask|Mod1Mask,"\033[1;4C",     0,    0}, | ||||
| 	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0}, | ||||
| 	{ XK_Right,   ShiftMask|ControlMask,"\033[1;6C",     0,    0}, | ||||
| 	{ XK_Right,    ControlMask|Mod1Mask,"\033[1;7C",     0,    0}, | ||||
| 	{ XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0,   0}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_ISO_Left_Tab,  ShiftMask,      "\033[Z",        0,    0}, | ||||
| 	{ XK_Return,        Mod1Mask,       "\033\r",        0,    0}, | ||||
| 	{ XK_Return,        XK_ANY_MOD,     "\r",            0,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0}, | ||||
| 	{ XK_BackSpace,     Mod1Mask,       "\033\177",      0,    0}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_End,           ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_End,           ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_End,           XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_Prior,         ControlMask,    "\033[5;5~",     0,    0}, | ||||
| 	{ XK_Prior,         ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_Prior,         XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_Next,          ControlMask,    "\033[6;5~",     0,    0}, | ||||
| 	{ XK_Next,          ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_Next,          XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0}, | ||||
| 	{ XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F1, /* F37 */  Mod4Mask,       "\033[1;6P",     0,    0}, | ||||
| 	{ XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0}, | ||||
| 	{ XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0}, | ||||
| 	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0}, | ||||
| 	{ XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F2, /* F38 */  Mod4Mask,       "\033[1;6Q",     0,    0}, | ||||
| 	{ XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0}, | ||||
| 	{ XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0}, | ||||
| 	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0}, | ||||
| 	{ XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F3, /* F39 */  Mod4Mask,       "\033[1;6R",     0,    0}, | ||||
| 	{ XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0}, | ||||
| 	{ XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0}, | ||||
| 	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0}, | ||||
| 	{ XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F4, /* F28 */  ControlMask,    "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F4, /* F40 */  Mod4Mask,       "\033[1;6S",     0,    0}, | ||||
| 	{ XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0}, | ||||
| 	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0}, | ||||
| 	{ XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F5, /* F41 */  Mod4Mask,       "\033[15;6~",    0,    0}, | ||||
| 	{ XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0}, | ||||
| 	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0}, | ||||
| 	{ XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F6, /* F42 */  Mod4Mask,       "\033[17;6~",    0,    0}, | ||||
| 	{ XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0}, | ||||
| 	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0}, | ||||
| 	{ XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F7, /* F43 */  Mod4Mask,       "\033[18;6~",    0,    0}, | ||||
| 	{ XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0}, | ||||
| 	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0}, | ||||
| 	{ XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F8, /* F44 */  Mod4Mask,       "\033[19;6~",    0,    0}, | ||||
| 	{ XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0}, | ||||
| 	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0}, | ||||
| 	{ XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F9, /* F45 */  Mod4Mask,       "\033[20;6~",    0,    0}, | ||||
| 	{ XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0}, | ||||
| 	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0}, | ||||
| 	{ XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F10, /* F46 */ Mod4Mask,       "\033[21;6~",    0,    0}, | ||||
| 	{ XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0}, | ||||
| 	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0}, | ||||
| 	{ XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0}, | ||||
| 	{ XK_F11, /* F47 */ Mod4Mask,       "\033[23;6~",    0,    0}, | ||||
| 	{ XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0}, | ||||
| 	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0}, | ||||
| 	{ XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0}, | ||||
| 	{ XK_F12, /* F48 */ Mod4Mask,       "\033[24;6~",    0,    0}, | ||||
| 	{ XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0}, | ||||
| 	{ XK_F13,           XK_NO_MOD,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F14,           XK_NO_MOD,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F15,           XK_NO_MOD,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F16,           XK_NO_MOD,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F17,           XK_NO_MOD,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F18,           XK_NO_MOD,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F19,           XK_NO_MOD,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F20,           XK_NO_MOD,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F21,           XK_NO_MOD,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F22,           XK_NO_MOD,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F23,           XK_NO_MOD,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F24,           XK_NO_MOD,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F25,           XK_NO_MOD,      "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F26,           XK_NO_MOD,      "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F27,           XK_NO_MOD,      "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F28,           XK_NO_MOD,      "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F29,           XK_NO_MOD,      "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F30,           XK_NO_MOD,      "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F31,           XK_NO_MOD,      "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F32,           XK_NO_MOD,      "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F33,           XK_NO_MOD,      "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F34,           XK_NO_MOD,      "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0}, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Selection types' masks. | ||||
|  * Use the same masks as usual. | ||||
|  * Button1Mask is always unset, to make masks match between ButtonPress. | ||||
|  * ButtonRelease and MotionNotify. | ||||
|  * If no match is found, regular selection is used. | ||||
|  */ | ||||
| static uint selmasks[] = { | ||||
| 	[SEL_RECTANGULAR] = Mod1Mask, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Printable characters in ASCII, used to estimate the advance width | ||||
|  * of single wide characters. | ||||
|  */ | ||||
| static char ascii_printable[] = | ||||
| 	" !\"#$%&'()*+,-./0123456789:;<=>?" | ||||
| 	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | ||||
| 	"`abcdefghijklmnopqrstuvwxyz{|}~"; | ||||
							
								
								
									
										466
									
								
								st/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								st/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* | ||||
|  * appearance | ||||
|  * | ||||
|  * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html | ||||
|  */ | ||||
| static char *font = "Go Mono:size=10"; | ||||
| static int borderpx = 2; | ||||
|  | ||||
| /* | ||||
|  * What program is execed by st depends of these precedence rules: | ||||
|  * 1: program passed with -e | ||||
|  * 2: scroll and/or utmp | ||||
|  * 3: SHELL environment variable | ||||
|  * 4: value of shell in /etc/passwd | ||||
|  * 5: value of shell in config.h | ||||
|  */ | ||||
| static char *shell = "/bin/sh"; | ||||
| char *utmp = NULL; | ||||
| /* scroll program: to enable use a string like "scroll" */ | ||||
| char *scroll = NULL; | ||||
| char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; | ||||
|  | ||||
| /* identification sequence returned in DA and DECID */ | ||||
| char *vtiden = "\033[?6c"; | ||||
|  | ||||
| /* Kerning / character bounding-box multipliers */ | ||||
| static float cwscale = 1.0; | ||||
| static float chscale = 1.0; | ||||
|  | ||||
| /* | ||||
|  * word delimiter string | ||||
|  * | ||||
|  * More advanced example: L" `'\"()[]{}" | ||||
|  */ | ||||
| wchar_t *worddelimiters = L" "; | ||||
|  | ||||
| /* selection timeouts (in milliseconds) */ | ||||
| static unsigned int doubleclicktimeout = 300; | ||||
| static unsigned int tripleclicktimeout = 600; | ||||
|  | ||||
| /* alt screens */ | ||||
| int allowaltscreen = 1; | ||||
|  | ||||
| /* allow certain non-interactive (insecure) window operations such as: | ||||
|    setting the clipboard text */ | ||||
| int allowwindowops = 0; | ||||
|  | ||||
| /* | ||||
|  * draw latency range in ms - from new content/keypress/etc until drawing. | ||||
|  * within this range, st draws when content stops arriving (idle). mostly it's | ||||
|  * near minlatency, but it waits longer for slow updates to avoid partial draw. | ||||
|  * low minlatency will tear/flicker more, as it can "detect" idle too early. | ||||
|  */ | ||||
| static double minlatency = 8; | ||||
| static double maxlatency = 33; | ||||
|  | ||||
| /* | ||||
|  * blinking timeout (set to 0 to disable blinking) for the terminal blinking | ||||
|  * attribute. | ||||
|  */ | ||||
| static unsigned int blinktimeout = 800; | ||||
|  | ||||
| /* | ||||
|  * thickness of underline and bar cursors | ||||
|  */ | ||||
| static unsigned int cursorthickness = 2; | ||||
|  | ||||
| /* | ||||
|  * bell volume. It must be a value between -100 and 100. Use 0 for disabling | ||||
|  * it | ||||
|  */ | ||||
| static int bellvolume = 0; | ||||
|  | ||||
| /* default TERM value */ | ||||
| char *termname = "st-256color"; | ||||
|  | ||||
| /* | ||||
|  * spaces per tab | ||||
|  * | ||||
|  * When you are changing this value, don't forget to adapt the »it« value in | ||||
|  * the st.info and appropriately install the st.info in the environment where | ||||
|  * you use this st version. | ||||
|  * | ||||
|  *	it#$tabspaces, | ||||
|  * | ||||
|  * Secondly make sure your kernel is not expanding tabs. When running `stty | ||||
|  * -a` »tab0« should appear. You can tell the terminal to not expand tabs by | ||||
|  *  running following command: | ||||
|  * | ||||
|  *	stty tabs | ||||
|  */ | ||||
| unsigned int tabspaces = 8; | ||||
|  | ||||
| /* Terminal colors (16 first used in escape sequence) */ | ||||
| static const char *colorname[] = { | ||||
| 	/* 8 normal colors */ | ||||
| 	[0] = "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */ | ||||
| 	[1] = "#cc241d", /* red     */ | ||||
| 	[2] = "#98971a", /* green   */ | ||||
| 	[3] = "#d79921", /* yellow  */ | ||||
| 	[4] = "#458588", /* blue    */ | ||||
| 	[5] = "#b16286", /* magenta */ | ||||
| 	[6] = "#689d6a", /* cyan    */ | ||||
| 	[7] = "#a89984", /* white   */ | ||||
|  | ||||
| 	/* 8 bright colors */ | ||||
| 	[8]  = "#928374", /* black   */ | ||||
| 	[9]  = "#fb4934", /* red     */ | ||||
| 	[10] = "#b8bb26", /* green   */ | ||||
| 	[11] = "#fabd2f", /* yellow  */ | ||||
| 	[12] = "#83a598", /* blue    */ | ||||
| 	[13] = "#d3869b", /* magenta */ | ||||
| 	[14] = "#8ec07c", /* cyan    */ | ||||
| 	[15] = "#ebdbb2", /* white   */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Default colors (colorname index) | ||||
|  * foreground, background, cursor, reverse cursor | ||||
|  */ | ||||
| unsigned int defaultfg = 15; | ||||
| unsigned int defaultbg = 0; | ||||
| unsigned int defaultcs = 15; | ||||
| static unsigned int defaultrcs = 257; | ||||
|  | ||||
| /* | ||||
|  * Default shape of cursor | ||||
|  * 2: Block ("█") | ||||
|  * 4: Underline ("_") | ||||
|  * 6: Bar ("|") | ||||
|  * 7: Snowman ("☃") | ||||
|  */ | ||||
| static unsigned int cursorshape = 2; | ||||
|  | ||||
| /* | ||||
|  * Default columns and rows numbers | ||||
|  */ | ||||
|  | ||||
| static unsigned int cols = 80; | ||||
| static unsigned int rows = 24; | ||||
|  | ||||
| /* | ||||
|  * Default colour and shape of the mouse cursor | ||||
|  */ | ||||
| static unsigned int mouseshape = XC_xterm; | ||||
| static unsigned int mousefg = 7; | ||||
| static unsigned int mousebg = 0; | ||||
|  | ||||
| /* | ||||
|  * Color used to display font attributes when fontconfig selected a font which | ||||
|  * doesn't match the ones requested. | ||||
|  */ | ||||
| static unsigned int defaultattr = 11; | ||||
|  | ||||
| /* | ||||
|  * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). | ||||
|  * Note that if you want to use ShiftMask with selmasks, set this to an other | ||||
|  * modifier, set to 0 to not use it. | ||||
|  */ | ||||
| static uint forcemousemod = ShiftMask; | ||||
|  | ||||
| /* | ||||
|  * Internal mouse shortcuts. | ||||
|  * Beware that overloading Button1 will disable the selection. | ||||
|  */ | ||||
| static MouseShortcut mshortcuts[] = { | ||||
| 	/* mask                 button   function        argument       release */ | ||||
| 	{ XK_ANY_MOD,           Button2, selpaste,       {.i = 0},      1 }, | ||||
| 	{ ShiftMask,            Button4, ttysend,        {.s = "\033[5;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button4, ttysend,        {.s = "\031"} }, | ||||
| 	{ ShiftMask,            Button5, ttysend,        {.s = "\033[6;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button5, ttysend,        {.s = "\005"} }, | ||||
| }; | ||||
|  | ||||
| /* Internal keyboard shortcuts. */ | ||||
| #define MODKEY Mod1Mask | ||||
| #define TERMMOD (ControlMask|ShiftMask) | ||||
|  | ||||
| static Shortcut shortcuts[] = { | ||||
| 	/* mask                 keysym          function        argument */ | ||||
| 	{ XK_ANY_MOD,           XK_Break,       sendbreak,      {.i =  0} }, | ||||
| 	{ ControlMask,          XK_Print,       toggleprinter,  {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Print,       printscreen,    {.i =  0} }, | ||||
| 	{ XK_ANY_MOD,           XK_Print,       printsel,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Prior,       zoom,           {.f = +1} }, | ||||
| 	{ TERMMOD,              XK_Next,        zoom,           {.f = -1} }, | ||||
| 	{ TERMMOD,              XK_Home,        zoomreset,      {.f =  0} }, | ||||
| 	{ TERMMOD,              XK_C,           clipcopy,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_V,           clippaste,      {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Y,           selpaste,       {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} }, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Special keys (change & recompile st.info accordingly) | ||||
|  * | ||||
|  * Mask value: | ||||
|  * * Use XK_ANY_MOD to match the key no matter modifiers state | ||||
|  * * Use XK_NO_MOD to match the key alone (no modifiers) | ||||
|  * appkey value: | ||||
|  * * 0: no value | ||||
|  * * > 0: keypad application mode enabled | ||||
|  * *   = 2: term.numlock = 1 | ||||
|  * * < 0: keypad application mode disabled | ||||
|  * appcursor value: | ||||
|  * * 0: no value | ||||
|  * * > 0: cursor application mode enabled | ||||
|  * * < 0: cursor application mode disabled | ||||
|  * | ||||
|  * Be careful with the order of the definitions because st searches in | ||||
|  * this table sequentially, so any XK_ANY_MOD must be in the last | ||||
|  * position for a key. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) | ||||
|  * to be mapped below, add them to this array. | ||||
|  */ | ||||
| static KeySym mappedkeys[] = { -1 }; | ||||
|  | ||||
| /* | ||||
|  * State bits to ignore when matching key or button events.  By default, | ||||
|  * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. | ||||
|  */ | ||||
| static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; | ||||
|  | ||||
| /* | ||||
|  * This is the huge key array which defines all compatibility to the Linux | ||||
|  * world. Please decide about changes wisely. | ||||
|  */ | ||||
| static Key key[] = { | ||||
| 	/* keysym           mask            string      appkey appcursor */ | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033Ox",       +1,    0}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033Or",       +1,    0}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033Ot",       +1,    0}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033Ov",       +1,    0}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_KP_Prior,      XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_KP_Begin,      XK_ANY_MOD,     "\033[E",        0,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_KP_End,        XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_KP_Next,       XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_KP_Multiply,   XK_ANY_MOD,     "\033Oj",       +2,    0}, | ||||
| 	{ XK_KP_Add,        XK_ANY_MOD,     "\033Ok",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\033OM",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\r",           -1,    0}, | ||||
| 	{ XK_KP_Subtract,   XK_ANY_MOD,     "\033Om",       +2,    0}, | ||||
| 	{ XK_KP_Decimal,    XK_ANY_MOD,     "\033On",       +2,    0}, | ||||
| 	{ XK_KP_Divide,     XK_ANY_MOD,     "\033Oo",       +2,    0}, | ||||
| 	{ XK_KP_0,          XK_ANY_MOD,     "\033Op",       +2,    0}, | ||||
| 	{ XK_KP_1,          XK_ANY_MOD,     "\033Oq",       +2,    0}, | ||||
| 	{ XK_KP_2,          XK_ANY_MOD,     "\033Or",       +2,    0}, | ||||
| 	{ XK_KP_3,          XK_ANY_MOD,     "\033Os",       +2,    0}, | ||||
| 	{ XK_KP_4,          XK_ANY_MOD,     "\033Ot",       +2,    0}, | ||||
| 	{ XK_KP_5,          XK_ANY_MOD,     "\033Ou",       +2,    0}, | ||||
| 	{ XK_KP_6,          XK_ANY_MOD,     "\033Ov",       +2,    0}, | ||||
| 	{ XK_KP_7,          XK_ANY_MOD,     "\033Ow",       +2,    0}, | ||||
| 	{ XK_KP_8,          XK_ANY_MOD,     "\033Ox",       +2,    0}, | ||||
| 	{ XK_KP_9,          XK_ANY_MOD,     "\033Oy",       +2,    0}, | ||||
| 	{ XK_Up,            ShiftMask,      "\033[1;2A",     0,    0}, | ||||
| 	{ XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0}, | ||||
| 	{ XK_Up,         ShiftMask|Mod1Mask,"\033[1;4A",     0,    0}, | ||||
| 	{ XK_Up,            ControlMask,    "\033[1;5A",     0,    0}, | ||||
| 	{ XK_Up,      ShiftMask|ControlMask,"\033[1;6A",     0,    0}, | ||||
| 	{ XK_Up,       ControlMask|Mod1Mask,"\033[1;7A",     0,    0}, | ||||
| 	{ XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A",  0,    0}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_Down,          ShiftMask,      "\033[1;2B",     0,    0}, | ||||
| 	{ XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0}, | ||||
| 	{ XK_Down,       ShiftMask|Mod1Mask,"\033[1;4B",     0,    0}, | ||||
| 	{ XK_Down,          ControlMask,    "\033[1;5B",     0,    0}, | ||||
| 	{ XK_Down,    ShiftMask|ControlMask,"\033[1;6B",     0,    0}, | ||||
| 	{ XK_Down,     ControlMask|Mod1Mask,"\033[1;7B",     0,    0}, | ||||
| 	{ XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0,    0}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_Left,          ShiftMask,      "\033[1;2D",     0,    0}, | ||||
| 	{ XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0}, | ||||
| 	{ XK_Left,       ShiftMask|Mod1Mask,"\033[1;4D",     0,    0}, | ||||
| 	{ XK_Left,          ControlMask,    "\033[1;5D",     0,    0}, | ||||
| 	{ XK_Left,    ShiftMask|ControlMask,"\033[1;6D",     0,    0}, | ||||
| 	{ XK_Left,     ControlMask|Mod1Mask,"\033[1;7D",     0,    0}, | ||||
| 	{ XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0,    0}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0}, | ||||
| 	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0}, | ||||
| 	{ XK_Right,      ShiftMask|Mod1Mask,"\033[1;4C",     0,    0}, | ||||
| 	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0}, | ||||
| 	{ XK_Right,   ShiftMask|ControlMask,"\033[1;6C",     0,    0}, | ||||
| 	{ XK_Right,    ControlMask|Mod1Mask,"\033[1;7C",     0,    0}, | ||||
| 	{ XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0,   0}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_ISO_Left_Tab,  ShiftMask,      "\033[Z",        0,    0}, | ||||
| 	{ XK_Return,        Mod1Mask,       "\033\r",        0,    0}, | ||||
| 	{ XK_Return,        XK_ANY_MOD,     "\r",            0,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0}, | ||||
| 	{ XK_BackSpace,     Mod1Mask,       "\033\177",      0,    0}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_End,           ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_End,           ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_End,           XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_Prior,         ControlMask,    "\033[5;5~",     0,    0}, | ||||
| 	{ XK_Prior,         ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_Prior,         XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_Next,          ControlMask,    "\033[6;5~",     0,    0}, | ||||
| 	{ XK_Next,          ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_Next,          XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0}, | ||||
| 	{ XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F1, /* F37 */  Mod4Mask,       "\033[1;6P",     0,    0}, | ||||
| 	{ XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0}, | ||||
| 	{ XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0}, | ||||
| 	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0}, | ||||
| 	{ XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F2, /* F38 */  Mod4Mask,       "\033[1;6Q",     0,    0}, | ||||
| 	{ XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0}, | ||||
| 	{ XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0}, | ||||
| 	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0}, | ||||
| 	{ XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F3, /* F39 */  Mod4Mask,       "\033[1;6R",     0,    0}, | ||||
| 	{ XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0}, | ||||
| 	{ XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0}, | ||||
| 	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0}, | ||||
| 	{ XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F4, /* F28 */  ControlMask,    "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F4, /* F40 */  Mod4Mask,       "\033[1;6S",     0,    0}, | ||||
| 	{ XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0}, | ||||
| 	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0}, | ||||
| 	{ XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F5, /* F41 */  Mod4Mask,       "\033[15;6~",    0,    0}, | ||||
| 	{ XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0}, | ||||
| 	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0}, | ||||
| 	{ XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F6, /* F42 */  Mod4Mask,       "\033[17;6~",    0,    0}, | ||||
| 	{ XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0}, | ||||
| 	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0}, | ||||
| 	{ XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F7, /* F43 */  Mod4Mask,       "\033[18;6~",    0,    0}, | ||||
| 	{ XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0}, | ||||
| 	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0}, | ||||
| 	{ XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F8, /* F44 */  Mod4Mask,       "\033[19;6~",    0,    0}, | ||||
| 	{ XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0}, | ||||
| 	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0}, | ||||
| 	{ XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F9, /* F45 */  Mod4Mask,       "\033[20;6~",    0,    0}, | ||||
| 	{ XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0}, | ||||
| 	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0}, | ||||
| 	{ XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F10, /* F46 */ Mod4Mask,       "\033[21;6~",    0,    0}, | ||||
| 	{ XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0}, | ||||
| 	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0}, | ||||
| 	{ XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0}, | ||||
| 	{ XK_F11, /* F47 */ Mod4Mask,       "\033[23;6~",    0,    0}, | ||||
| 	{ XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0}, | ||||
| 	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0}, | ||||
| 	{ XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0}, | ||||
| 	{ XK_F12, /* F48 */ Mod4Mask,       "\033[24;6~",    0,    0}, | ||||
| 	{ XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0}, | ||||
| 	{ XK_F13,           XK_NO_MOD,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F14,           XK_NO_MOD,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F15,           XK_NO_MOD,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F16,           XK_NO_MOD,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F17,           XK_NO_MOD,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F18,           XK_NO_MOD,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F19,           XK_NO_MOD,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F20,           XK_NO_MOD,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F21,           XK_NO_MOD,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F22,           XK_NO_MOD,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F23,           XK_NO_MOD,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F24,           XK_NO_MOD,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F25,           XK_NO_MOD,      "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F26,           XK_NO_MOD,      "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F27,           XK_NO_MOD,      "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F28,           XK_NO_MOD,      "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F29,           XK_NO_MOD,      "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F30,           XK_NO_MOD,      "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F31,           XK_NO_MOD,      "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F32,           XK_NO_MOD,      "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F33,           XK_NO_MOD,      "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F34,           XK_NO_MOD,      "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0}, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Selection types' masks. | ||||
|  * Use the same masks as usual. | ||||
|  * Button1Mask is always unset, to make masks match between ButtonPress. | ||||
|  * ButtonRelease and MotionNotify. | ||||
|  * If no match is found, regular selection is used. | ||||
|  */ | ||||
| static uint selmasks[] = { | ||||
| 	[SEL_RECTANGULAR] = Mod1Mask, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Printable characters in ASCII, used to estimate the advance width | ||||
|  * of single wide characters. | ||||
|  */ | ||||
| static char ascii_printable[] = | ||||
| 	" !\"#$%&'()*+,-./0123456789:;<=>?" | ||||
| 	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | ||||
| 	"`abcdefghijklmnopqrstuvwxyz{|}~"; | ||||
							
								
								
									
										474
									
								
								st/config.h.orig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								st/config.h.orig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,474 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
|  | ||||
| /* | ||||
|  * appearance | ||||
|  * | ||||
|  * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html | ||||
|  */ | ||||
| static char *font = "Go Mono:size=10"; | ||||
| static int borderpx = 2; | ||||
|  | ||||
| /* | ||||
|  * What program is execed by st depends of these precedence rules: | ||||
|  * 1: program passed with -e | ||||
|  * 2: scroll and/or utmp | ||||
|  * 3: SHELL environment variable | ||||
|  * 4: value of shell in /etc/passwd | ||||
|  * 5: value of shell in config.h | ||||
|  */ | ||||
| static char *shell = "/bin/sh"; | ||||
| char *utmp = NULL; | ||||
| /* scroll program: to enable use a string like "scroll" */ | ||||
| char *scroll = NULL; | ||||
| char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; | ||||
|  | ||||
| /* identification sequence returned in DA and DECID */ | ||||
| char *vtiden = "\033[?6c"; | ||||
|  | ||||
| /* Kerning / character bounding-box multipliers */ | ||||
| static float cwscale = 1.0; | ||||
| static float chscale = 1.0; | ||||
|  | ||||
| /* | ||||
|  * word delimiter string | ||||
|  * | ||||
|  * More advanced example: L" `'\"()[]{}" | ||||
|  */ | ||||
| wchar_t *worddelimiters = L" "; | ||||
|  | ||||
| /* selection timeouts (in milliseconds) */ | ||||
| static unsigned int doubleclicktimeout = 300; | ||||
| static unsigned int tripleclicktimeout = 600; | ||||
|  | ||||
| /* alt screens */ | ||||
| int allowaltscreen = 1; | ||||
|  | ||||
| /* allow certain non-interactive (insecure) window operations such as: | ||||
|    setting the clipboard text */ | ||||
| int allowwindowops = 0; | ||||
|  | ||||
| /* | ||||
|  * draw latency range in ms - from new content/keypress/etc until drawing. | ||||
|  * within this range, st draws when content stops arriving (idle). mostly it's | ||||
|  * near minlatency, but it waits longer for slow updates to avoid partial draw. | ||||
|  * low minlatency will tear/flicker more, as it can "detect" idle too early. | ||||
|  */ | ||||
| static double minlatency = 8; | ||||
| static double maxlatency = 33; | ||||
|  | ||||
| /* | ||||
|  * blinking timeout (set to 0 to disable blinking) for the terminal blinking | ||||
|  * attribute. | ||||
|  */ | ||||
| static unsigned int blinktimeout = 800; | ||||
|  | ||||
| /* | ||||
|  * thickness of underline and bar cursors | ||||
|  */ | ||||
| static unsigned int cursorthickness = 2; | ||||
|  | ||||
| /* | ||||
|  * bell volume. It must be a value between -100 and 100. Use 0 for disabling | ||||
|  * it | ||||
|  */ | ||||
| static int bellvolume = 0; | ||||
|  | ||||
| /* default TERM value */ | ||||
| char *termname = "st-256color"; | ||||
|  | ||||
| /* | ||||
|  * spaces per tab | ||||
|  * | ||||
|  * When you are changing this value, don't forget to adapt the »it« value in | ||||
|  * the st.info and appropriately install the st.info in the environment where | ||||
|  * you use this st version. | ||||
|  * | ||||
|  *	it#$tabspaces, | ||||
|  * | ||||
|  * Secondly make sure your kernel is not expanding tabs. When running `stty | ||||
|  * -a` »tab0« should appear. You can tell the terminal to not expand tabs by | ||||
|  *  running following command: | ||||
|  * | ||||
|  *	stty tabs | ||||
|  */ | ||||
| unsigned int tabspaces = 8; | ||||
|  | ||||
| /* Terminal colors (16 first used in escape sequence) */ | ||||
| static const char *colorname[] = { | ||||
| 	/* 8 normal colors */ | ||||
| 	"black", | ||||
| 	"red3", | ||||
| 	"green3", | ||||
| 	"yellow3", | ||||
| 	"blue2", | ||||
| 	"magenta3", | ||||
| 	"cyan3", | ||||
| 	"gray90", | ||||
|  | ||||
| 	/* 8 bright colors */ | ||||
| 	"gray50", | ||||
| 	"red", | ||||
| 	"green", | ||||
| 	"yellow", | ||||
| 	"#5c5cff", | ||||
| 	"magenta", | ||||
| 	"cyan", | ||||
| 	"white", | ||||
|  | ||||
| 	[255] = 0, | ||||
|  | ||||
| 	/* more colors can be added after 255 to use with DefaultXX */ | ||||
| 	"#cccccc", | ||||
| 	"#555555", | ||||
| 	"gray90", /* default foreground colour */ | ||||
| 	"black", /* default background colour */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Default colors (colorname index) | ||||
|  * foreground, background, cursor, reverse cursor | ||||
|  */ | ||||
| unsigned int defaultfg = 258; | ||||
| unsigned int defaultbg = 259; | ||||
| unsigned int defaultcs = 256; | ||||
| static unsigned int defaultrcs = 257; | ||||
|  | ||||
| /* | ||||
|  * Default shape of cursor | ||||
|  * 2: Block ("█") | ||||
|  * 4: Underline ("_") | ||||
|  * 6: Bar ("|") | ||||
|  * 7: Snowman ("☃") | ||||
|  */ | ||||
| static unsigned int cursorshape = 2; | ||||
|  | ||||
| /* | ||||
|  * Default columns and rows numbers | ||||
|  */ | ||||
|  | ||||
| static unsigned int cols = 80; | ||||
| static unsigned int rows = 24; | ||||
|  | ||||
| /* | ||||
|  * Default colour and shape of the mouse cursor | ||||
|  */ | ||||
| static unsigned int mouseshape = XC_xterm; | ||||
| static unsigned int mousefg = 7; | ||||
| static unsigned int mousebg = 0; | ||||
|  | ||||
| /* | ||||
|  * Color used to display font attributes when fontconfig selected a font which | ||||
|  * doesn't match the ones requested. | ||||
|  */ | ||||
| static unsigned int defaultattr = 11; | ||||
|  | ||||
| /* | ||||
|  * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). | ||||
|  * Note that if you want to use ShiftMask with selmasks, set this to an other | ||||
|  * modifier, set to 0 to not use it. | ||||
|  */ | ||||
| static uint forcemousemod = ShiftMask; | ||||
|  | ||||
| /* | ||||
|  * Internal mouse shortcuts. | ||||
|  * Beware that overloading Button1 will disable the selection. | ||||
|  */ | ||||
| static MouseShortcut mshortcuts[] = { | ||||
| 	/* mask                 button   function        argument       release */ | ||||
| 	{ XK_ANY_MOD,           Button2, selpaste,       {.i = 0},      1 }, | ||||
| 	{ ShiftMask,            Button4, ttysend,        {.s = "\033[5;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button4, ttysend,        {.s = "\031"} }, | ||||
| 	{ ShiftMask,            Button5, ttysend,        {.s = "\033[6;2~"} }, | ||||
| 	{ XK_ANY_MOD,           Button5, ttysend,        {.s = "\005"} }, | ||||
| }; | ||||
|  | ||||
| /* Internal keyboard shortcuts. */ | ||||
| #define MODKEY Mod1Mask | ||||
| #define TERMMOD (ControlMask|ShiftMask) | ||||
|  | ||||
| static Shortcut shortcuts[] = { | ||||
| 	/* mask                 keysym          function        argument */ | ||||
| 	{ XK_ANY_MOD,           XK_Break,       sendbreak,      {.i =  0} }, | ||||
| 	{ ControlMask,          XK_Print,       toggleprinter,  {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Print,       printscreen,    {.i =  0} }, | ||||
| 	{ XK_ANY_MOD,           XK_Print,       printsel,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Prior,       zoom,           {.f = +1} }, | ||||
| 	{ TERMMOD,              XK_Next,        zoom,           {.f = -1} }, | ||||
| 	{ TERMMOD,              XK_Home,        zoomreset,      {.f =  0} }, | ||||
| 	{ TERMMOD,              XK_C,           clipcopy,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_V,           clippaste,      {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Y,           selpaste,       {.i =  0} }, | ||||
| 	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} }, | ||||
| 	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} }, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Special keys (change & recompile st.info accordingly) | ||||
|  * | ||||
|  * Mask value: | ||||
|  * * Use XK_ANY_MOD to match the key no matter modifiers state | ||||
|  * * Use XK_NO_MOD to match the key alone (no modifiers) | ||||
|  * appkey value: | ||||
|  * * 0: no value | ||||
|  * * > 0: keypad application mode enabled | ||||
|  * *   = 2: term.numlock = 1 | ||||
|  * * < 0: keypad application mode disabled | ||||
|  * appcursor value: | ||||
|  * * 0: no value | ||||
|  * * > 0: cursor application mode enabled | ||||
|  * * < 0: cursor application mode disabled | ||||
|  * | ||||
|  * Be careful with the order of the definitions because st searches in | ||||
|  * this table sequentially, so any XK_ANY_MOD must be in the last | ||||
|  * position for a key. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) | ||||
|  * to be mapped below, add them to this array. | ||||
|  */ | ||||
| static KeySym mappedkeys[] = { -1 }; | ||||
|  | ||||
| /* | ||||
|  * State bits to ignore when matching key or button events.  By default, | ||||
|  * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. | ||||
|  */ | ||||
| static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; | ||||
|  | ||||
| /* | ||||
|  * This is the huge key array which defines all compatibility to the Linux | ||||
|  * world. Please decide about changes wisely. | ||||
|  */ | ||||
| static Key key[] = { | ||||
| 	/* keysym           mask            string      appkey appcursor */ | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_KP_Home,       XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033Ox",       +1,    0}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_KP_Up,         XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033Or",       +1,    0}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_KP_Down,       XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033Ot",       +1,    0}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_KP_Left,       XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033Ov",       +1,    0}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_KP_Right,      XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_KP_Prior,      XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_KP_Begin,      XK_ANY_MOD,     "\033[E",        0,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_KP_End,        ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_KP_End,        ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_KP_End,        XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_KP_Next,       XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_KP_Insert,     ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_KP_Delete,     ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_KP_Multiply,   XK_ANY_MOD,     "\033Oj",       +2,    0}, | ||||
| 	{ XK_KP_Add,        XK_ANY_MOD,     "\033Ok",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\033OM",       +2,    0}, | ||||
| 	{ XK_KP_Enter,      XK_ANY_MOD,     "\r",           -1,    0}, | ||||
| 	{ XK_KP_Subtract,   XK_ANY_MOD,     "\033Om",       +2,    0}, | ||||
| 	{ XK_KP_Decimal,    XK_ANY_MOD,     "\033On",       +2,    0}, | ||||
| 	{ XK_KP_Divide,     XK_ANY_MOD,     "\033Oo",       +2,    0}, | ||||
| 	{ XK_KP_0,          XK_ANY_MOD,     "\033Op",       +2,    0}, | ||||
| 	{ XK_KP_1,          XK_ANY_MOD,     "\033Oq",       +2,    0}, | ||||
| 	{ XK_KP_2,          XK_ANY_MOD,     "\033Or",       +2,    0}, | ||||
| 	{ XK_KP_3,          XK_ANY_MOD,     "\033Os",       +2,    0}, | ||||
| 	{ XK_KP_4,          XK_ANY_MOD,     "\033Ot",       +2,    0}, | ||||
| 	{ XK_KP_5,          XK_ANY_MOD,     "\033Ou",       +2,    0}, | ||||
| 	{ XK_KP_6,          XK_ANY_MOD,     "\033Ov",       +2,    0}, | ||||
| 	{ XK_KP_7,          XK_ANY_MOD,     "\033Ow",       +2,    0}, | ||||
| 	{ XK_KP_8,          XK_ANY_MOD,     "\033Ox",       +2,    0}, | ||||
| 	{ XK_KP_9,          XK_ANY_MOD,     "\033Oy",       +2,    0}, | ||||
| 	{ XK_Up,            ShiftMask,      "\033[1;2A",     0,    0}, | ||||
| 	{ XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0}, | ||||
| 	{ XK_Up,         ShiftMask|Mod1Mask,"\033[1;4A",     0,    0}, | ||||
| 	{ XK_Up,            ControlMask,    "\033[1;5A",     0,    0}, | ||||
| 	{ XK_Up,      ShiftMask|ControlMask,"\033[1;6A",     0,    0}, | ||||
| 	{ XK_Up,       ControlMask|Mod1Mask,"\033[1;7A",     0,    0}, | ||||
| 	{ XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A",  0,    0}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033[A",        0,   -1}, | ||||
| 	{ XK_Up,            XK_ANY_MOD,     "\033OA",        0,   +1}, | ||||
| 	{ XK_Down,          ShiftMask,      "\033[1;2B",     0,    0}, | ||||
| 	{ XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0}, | ||||
| 	{ XK_Down,       ShiftMask|Mod1Mask,"\033[1;4B",     0,    0}, | ||||
| 	{ XK_Down,          ControlMask,    "\033[1;5B",     0,    0}, | ||||
| 	{ XK_Down,    ShiftMask|ControlMask,"\033[1;6B",     0,    0}, | ||||
| 	{ XK_Down,     ControlMask|Mod1Mask,"\033[1;7B",     0,    0}, | ||||
| 	{ XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0,    0}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033[B",        0,   -1}, | ||||
| 	{ XK_Down,          XK_ANY_MOD,     "\033OB",        0,   +1}, | ||||
| 	{ XK_Left,          ShiftMask,      "\033[1;2D",     0,    0}, | ||||
| 	{ XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0}, | ||||
| 	{ XK_Left,       ShiftMask|Mod1Mask,"\033[1;4D",     0,    0}, | ||||
| 	{ XK_Left,          ControlMask,    "\033[1;5D",     0,    0}, | ||||
| 	{ XK_Left,    ShiftMask|ControlMask,"\033[1;6D",     0,    0}, | ||||
| 	{ XK_Left,     ControlMask|Mod1Mask,"\033[1;7D",     0,    0}, | ||||
| 	{ XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0,    0}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033[D",        0,   -1}, | ||||
| 	{ XK_Left,          XK_ANY_MOD,     "\033OD",        0,   +1}, | ||||
| 	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0}, | ||||
| 	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0}, | ||||
| 	{ XK_Right,      ShiftMask|Mod1Mask,"\033[1;4C",     0,    0}, | ||||
| 	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0}, | ||||
| 	{ XK_Right,   ShiftMask|ControlMask,"\033[1;6C",     0,    0}, | ||||
| 	{ XK_Right,    ControlMask|Mod1Mask,"\033[1;7C",     0,    0}, | ||||
| 	{ XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0,   0}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033[C",        0,   -1}, | ||||
| 	{ XK_Right,         XK_ANY_MOD,     "\033OC",        0,   +1}, | ||||
| 	{ XK_ISO_Left_Tab,  ShiftMask,      "\033[Z",        0,    0}, | ||||
| 	{ XK_Return,        Mod1Mask,       "\033\r",        0,    0}, | ||||
| 	{ XK_Return,        XK_ANY_MOD,     "\r",            0,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[4l",      -1,    0}, | ||||
| 	{ XK_Insert,        ShiftMask,      "\033[2;2~",    +1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[L",       -1,    0}, | ||||
| 	{ XK_Insert,        ControlMask,    "\033[2;5~",    +1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[4h",      -1,    0}, | ||||
| 	{ XK_Insert,        XK_ANY_MOD,     "\033[2~",      +1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[M",       -1,    0}, | ||||
| 	{ XK_Delete,        ControlMask,    "\033[3;5~",    +1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[2K",      -1,    0}, | ||||
| 	{ XK_Delete,        ShiftMask,      "\033[3;2~",    +1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[P",       -1,    0}, | ||||
| 	{ XK_Delete,        XK_ANY_MOD,     "\033[3~",      +1,    0}, | ||||
| 	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0}, | ||||
| 	{ XK_BackSpace,     Mod1Mask,       "\033\177",      0,    0}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[2J",       0,   -1}, | ||||
| 	{ XK_Home,          ShiftMask,      "\033[1;2H",     0,   +1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[H",        0,   -1}, | ||||
| 	{ XK_Home,          XK_ANY_MOD,     "\033[1~",       0,   +1}, | ||||
| 	{ XK_End,           ControlMask,    "\033[J",       -1,    0}, | ||||
| 	{ XK_End,           ControlMask,    "\033[1;5F",    +1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[K",       -1,    0}, | ||||
| 	{ XK_End,           ShiftMask,      "\033[1;2F",    +1,    0}, | ||||
| 	{ XK_End,           XK_ANY_MOD,     "\033[4~",       0,    0}, | ||||
| 	{ XK_Prior,         ControlMask,    "\033[5;5~",     0,    0}, | ||||
| 	{ XK_Prior,         ShiftMask,      "\033[5;2~",     0,    0}, | ||||
| 	{ XK_Prior,         XK_ANY_MOD,     "\033[5~",       0,    0}, | ||||
| 	{ XK_Next,          ControlMask,    "\033[6;5~",     0,    0}, | ||||
| 	{ XK_Next,          ShiftMask,      "\033[6;2~",     0,    0}, | ||||
| 	{ XK_Next,          XK_ANY_MOD,     "\033[6~",       0,    0}, | ||||
| 	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0}, | ||||
| 	{ XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F1, /* F37 */  Mod4Mask,       "\033[1;6P",     0,    0}, | ||||
| 	{ XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0}, | ||||
| 	{ XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0}, | ||||
| 	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0}, | ||||
| 	{ XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F2, /* F38 */  Mod4Mask,       "\033[1;6Q",     0,    0}, | ||||
| 	{ XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0}, | ||||
| 	{ XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0}, | ||||
| 	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0}, | ||||
| 	{ XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F3, /* F39 */  Mod4Mask,       "\033[1;6R",     0,    0}, | ||||
| 	{ XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0}, | ||||
| 	{ XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0}, | ||||
| 	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0}, | ||||
| 	{ XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F4, /* F28 */  ControlMask,    "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F4, /* F40 */  Mod4Mask,       "\033[1;6S",     0,    0}, | ||||
| 	{ XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0}, | ||||
| 	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0}, | ||||
| 	{ XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F5, /* F41 */  Mod4Mask,       "\033[15;6~",    0,    0}, | ||||
| 	{ XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0}, | ||||
| 	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0}, | ||||
| 	{ XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F6, /* F42 */  Mod4Mask,       "\033[17;6~",    0,    0}, | ||||
| 	{ XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0}, | ||||
| 	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0}, | ||||
| 	{ XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F7, /* F43 */  Mod4Mask,       "\033[18;6~",    0,    0}, | ||||
| 	{ XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0}, | ||||
| 	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0}, | ||||
| 	{ XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F8, /* F44 */  Mod4Mask,       "\033[19;6~",    0,    0}, | ||||
| 	{ XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0}, | ||||
| 	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0}, | ||||
| 	{ XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F9, /* F45 */  Mod4Mask,       "\033[20;6~",    0,    0}, | ||||
| 	{ XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0}, | ||||
| 	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0}, | ||||
| 	{ XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F10, /* F46 */ Mod4Mask,       "\033[21;6~",    0,    0}, | ||||
| 	{ XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0}, | ||||
| 	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0}, | ||||
| 	{ XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0}, | ||||
| 	{ XK_F11, /* F47 */ Mod4Mask,       "\033[23;6~",    0,    0}, | ||||
| 	{ XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0}, | ||||
| 	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0}, | ||||
| 	{ XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0}, | ||||
| 	{ XK_F12, /* F48 */ Mod4Mask,       "\033[24;6~",    0,    0}, | ||||
| 	{ XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0}, | ||||
| 	{ XK_F13,           XK_NO_MOD,      "\033[1;2P",     0,    0}, | ||||
| 	{ XK_F14,           XK_NO_MOD,      "\033[1;2Q",     0,    0}, | ||||
| 	{ XK_F15,           XK_NO_MOD,      "\033[1;2R",     0,    0}, | ||||
| 	{ XK_F16,           XK_NO_MOD,      "\033[1;2S",     0,    0}, | ||||
| 	{ XK_F17,           XK_NO_MOD,      "\033[15;2~",    0,    0}, | ||||
| 	{ XK_F18,           XK_NO_MOD,      "\033[17;2~",    0,    0}, | ||||
| 	{ XK_F19,           XK_NO_MOD,      "\033[18;2~",    0,    0}, | ||||
| 	{ XK_F20,           XK_NO_MOD,      "\033[19;2~",    0,    0}, | ||||
| 	{ XK_F21,           XK_NO_MOD,      "\033[20;2~",    0,    0}, | ||||
| 	{ XK_F22,           XK_NO_MOD,      "\033[21;2~",    0,    0}, | ||||
| 	{ XK_F23,           XK_NO_MOD,      "\033[23;2~",    0,    0}, | ||||
| 	{ XK_F24,           XK_NO_MOD,      "\033[24;2~",    0,    0}, | ||||
| 	{ XK_F25,           XK_NO_MOD,      "\033[1;5P",     0,    0}, | ||||
| 	{ XK_F26,           XK_NO_MOD,      "\033[1;5Q",     0,    0}, | ||||
| 	{ XK_F27,           XK_NO_MOD,      "\033[1;5R",     0,    0}, | ||||
| 	{ XK_F28,           XK_NO_MOD,      "\033[1;5S",     0,    0}, | ||||
| 	{ XK_F29,           XK_NO_MOD,      "\033[15;5~",    0,    0}, | ||||
| 	{ XK_F30,           XK_NO_MOD,      "\033[17;5~",    0,    0}, | ||||
| 	{ XK_F31,           XK_NO_MOD,      "\033[18;5~",    0,    0}, | ||||
| 	{ XK_F32,           XK_NO_MOD,      "\033[19;5~",    0,    0}, | ||||
| 	{ XK_F33,           XK_NO_MOD,      "\033[20;5~",    0,    0}, | ||||
| 	{ XK_F34,           XK_NO_MOD,      "\033[21;5~",    0,    0}, | ||||
| 	{ XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0}, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Selection types' masks. | ||||
|  * Use the same masks as usual. | ||||
|  * Button1Mask is always unset, to make masks match between ButtonPress. | ||||
|  * ButtonRelease and MotionNotify. | ||||
|  * If no match is found, regular selection is used. | ||||
|  */ | ||||
| static uint selmasks[] = { | ||||
| 	[SEL_RECTANGULAR] = Mod1Mask, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Printable characters in ASCII, used to estimate the advance width | ||||
|  * of single wide characters. | ||||
|  */ | ||||
| static char ascii_printable[] = | ||||
| 	" !\"#$%&'()*+,-./0123456789:;<=>?" | ||||
| 	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | ||||
| 	"`abcdefghijklmnopqrstuvwxyz{|}~"; | ||||
							
								
								
									
										36
									
								
								st/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								st/config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| # st version | ||||
| VERSION = 0.9 | ||||
|  | ||||
| # Customize below to fit your system | ||||
|  | ||||
| # paths | ||||
| PREFIX = /usr/local | ||||
| MANPREFIX = $(PREFIX)/share/man | ||||
|  | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
|  | ||||
| PKG_CONFIG = pkg-config | ||||
|  | ||||
| # includes and libs | ||||
| INCS = -I$(X11INC) \ | ||||
|        `$(PKG_CONFIG) --cflags fontconfig` \ | ||||
|        `$(PKG_CONFIG) --cflags freetype2` | ||||
| LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ | ||||
|        `$(PKG_CONFIG) --libs fontconfig` \ | ||||
|        `$(PKG_CONFIG) --libs freetype2` | ||||
|  | ||||
| # flags | ||||
| STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 | ||||
| STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) | ||||
| STLDFLAGS = $(LIBS) $(LDFLAGS) | ||||
|  | ||||
| # OpenBSD: | ||||
| CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE | ||||
| LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ | ||||
|        `$(PKG_CONFIG) --libs fontconfig` \ | ||||
|        `$(PKG_CONFIG) --libs freetype2` | ||||
| MANPREFIX = ${PREFIX}/man | ||||
|  | ||||
| # compiler and linker | ||||
| # CC = c99 | ||||
							
								
								
									
										66
									
								
								st/st-gruvbox-dark-0.8.5.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								st/st-gruvbox-dark-0.8.5.diff
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| diff --git a/config.def.h b/config.def.h | ||||
| index 91ab8ca..a068694 100644 | ||||
| --- a/config.def.h | ||||
| +++ b/config.def.h | ||||
| @@ -96,32 +96,24 @@ unsigned int tabspaces = 8; | ||||
|  /* Terminal colors (16 first used in escape sequence) */ | ||||
|  static const char *colorname[] = { | ||||
|  	/* 8 normal colors */ | ||||
| -	"black", | ||||
| -	"red3", | ||||
| -	"green3", | ||||
| -	"yellow3", | ||||
| -	"blue2", | ||||
| -	"magenta3", | ||||
| -	"cyan3", | ||||
| -	"gray90", | ||||
| +	[0] = "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */ | ||||
| +	[1] = "#cc241d", /* red     */ | ||||
| +	[2] = "#98971a", /* green   */ | ||||
| +	[3] = "#d79921", /* yellow  */ | ||||
| +	[4] = "#458588", /* blue    */ | ||||
| +	[5] = "#b16286", /* magenta */ | ||||
| +	[6] = "#689d6a", /* cyan    */ | ||||
| +	[7] = "#a89984", /* white   */ | ||||
|   | ||||
|  	/* 8 bright colors */ | ||||
| -	"gray50", | ||||
| -	"red", | ||||
| -	"green", | ||||
| -	"yellow", | ||||
| -	"#5c5cff", | ||||
| -	"magenta", | ||||
| -	"cyan", | ||||
| -	"white", | ||||
| - | ||||
| -	[255] = 0, | ||||
| - | ||||
| -	/* more colors can be added after 255 to use with DefaultXX */ | ||||
| -	"#cccccc", | ||||
| -	"#555555", | ||||
| -	"gray90", /* default foreground colour */ | ||||
| -	"black", /* default background colour */ | ||||
| +	[8]  = "#928374", /* black   */ | ||||
| +	[9]  = "#fb4934", /* red     */ | ||||
| +	[10] = "#b8bb26", /* green   */ | ||||
| +	[11] = "#fabd2f", /* yellow  */ | ||||
| +	[12] = "#83a598", /* blue    */ | ||||
| +	[13] = "#d3869b", /* magenta */ | ||||
| +	[14] = "#8ec07c", /* cyan    */ | ||||
| +	[15] = "#ebdbb2", /* white   */ | ||||
|  }; | ||||
|   | ||||
|   | ||||
| @@ -129,9 +121,9 @@ static const char *colorname[] = { | ||||
|   * Default colors (colorname index) | ||||
|   * foreground, background, cursor, reverse cursor | ||||
|   */ | ||||
| -unsigned int defaultfg = 258; | ||||
| -unsigned int defaultbg = 259; | ||||
| -unsigned int defaultcs = 256; | ||||
| +unsigned int defaultfg = 15; | ||||
| +unsigned int defaultbg = 0; | ||||
| +unsigned int defaultcs = 15; | ||||
|  static unsigned int defaultrcs = 257; | ||||
|   | ||||
|  /* | ||||
							
								
								
									
										177
									
								
								st/st.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								st/st.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| .TH ST 1 st\-VERSION | ||||
| .SH NAME | ||||
| st \- simple terminal | ||||
| .SH SYNOPSIS | ||||
| .B st | ||||
| .RB [ \-aiv ] | ||||
| .RB [ \-c | ||||
| .IR class ] | ||||
| .RB [ \-f | ||||
| .IR font ] | ||||
| .RB [ \-g | ||||
| .IR geometry ] | ||||
| .RB [ \-n | ||||
| .IR name ] | ||||
| .RB [ \-o | ||||
| .IR iofile ] | ||||
| .RB [ \-T | ||||
| .IR title ] | ||||
| .RB [ \-t | ||||
| .IR title ] | ||||
| .RB [ \-l | ||||
| .IR line ] | ||||
| .RB [ \-w | ||||
| .IR windowid ] | ||||
| .RB [[ \-e ] | ||||
| .IR command | ||||
| .RI [ arguments ...]] | ||||
| .PP | ||||
| .B st | ||||
| .RB [ \-aiv ] | ||||
| .RB [ \-c | ||||
| .IR class ] | ||||
| .RB [ \-f | ||||
| .IR font ] | ||||
| .RB [ \-g | ||||
| .IR geometry ] | ||||
| .RB [ \-n | ||||
| .IR name ] | ||||
| .RB [ \-o | ||||
| .IR iofile ] | ||||
| .RB [ \-T | ||||
| .IR title ] | ||||
| .RB [ \-t | ||||
| .IR title ] | ||||
| .RB [ \-w | ||||
| .IR windowid ] | ||||
| .RB \-l | ||||
| .IR line | ||||
| .RI [ stty_args ...] | ||||
| .SH DESCRIPTION | ||||
| .B st | ||||
| is a simple terminal emulator. | ||||
| .SH OPTIONS | ||||
| .TP | ||||
| .B \-a | ||||
| disable alternate screens in terminal | ||||
| .TP | ||||
| .BI \-c " class" | ||||
| defines the window class (default $TERM). | ||||
| .TP | ||||
| .BI \-f " font" | ||||
| defines the | ||||
| .I font | ||||
| to use when st is run. | ||||
| .TP | ||||
| .BI \-g " geometry" | ||||
| defines the X11 geometry string. | ||||
| The form is [=][<cols>{xX}<rows>][{+-}<xoffset>{+-}<yoffset>]. See | ||||
| .BR XParseGeometry (3) | ||||
| for further details. | ||||
| .TP | ||||
| .B \-i | ||||
| will fixate the position given with the -g option. | ||||
| .TP | ||||
| .BI \-n " name" | ||||
| defines the window instance name (default $TERM). | ||||
| .TP | ||||
| .BI \-o " iofile" | ||||
| writes all the I/O to | ||||
| .I iofile. | ||||
| This feature is useful when recording st sessions. A value of "-" means | ||||
| standard output. | ||||
| .TP | ||||
| .BI \-T " title" | ||||
| defines the window title (default 'st'). | ||||
| .TP | ||||
| .BI \-t " title" | ||||
| defines the window title (default 'st'). | ||||
| .TP | ||||
| .BI \-w " windowid" | ||||
| embeds st within the window identified by | ||||
| .I windowid | ||||
| .TP | ||||
| .BI \-l " line" | ||||
| use a tty | ||||
| .I line | ||||
| instead of a pseudo terminal. | ||||
| .I line | ||||
| should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port | ||||
| 0). | ||||
| When this flag is given | ||||
| remaining arguments are used as flags for | ||||
| .BR stty(1). | ||||
| By default st initializes the serial line to 8 bits, no parity, 1 stop bit | ||||
| and a 38400 baud rate. The speed is set by appending it as last argument | ||||
| (e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are | ||||
| .BR stty(1) | ||||
| flags. If you want to set odd parity on 115200 baud use for example 'st -l | ||||
| /dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for | ||||
| example 'st -l /dev/ttyS0 cs7 115200'. See | ||||
| .BR stty(1) | ||||
| for more arguments and cases. | ||||
| .TP | ||||
| .B \-v | ||||
| prints version information to stderr, then exits. | ||||
| .TP | ||||
| .BI \-e " command " [ " arguments " "... ]" | ||||
| st executes | ||||
| .I command | ||||
| instead of the shell.  If this is used it | ||||
| .B must be the last option | ||||
| on the command line, as in xterm / rxvt. | ||||
| This option is only intended for compatibility, | ||||
| and all the remaining arguments are used as a command | ||||
| even without it. | ||||
| .SH SHORTCUTS | ||||
| .TP | ||||
| .B Break | ||||
| Send a break in the serial line. | ||||
| Break key is obtained in PC keyboards | ||||
| pressing at the same time control and pause. | ||||
| .TP | ||||
| .B Ctrl-Print Screen | ||||
| Toggle if st should print to the | ||||
| .I iofile. | ||||
| .TP | ||||
| .B Shift-Print Screen | ||||
| Print the full screen to the | ||||
| .I iofile. | ||||
| .TP | ||||
| .B Print Screen | ||||
| Print the selection to the | ||||
| .I iofile. | ||||
| .TP | ||||
| .B Ctrl-Shift-Page Up | ||||
| Increase font size. | ||||
| .TP | ||||
| .B Ctrl-Shift-Page Down | ||||
| Decrease font size. | ||||
| .TP | ||||
| .B Ctrl-Shift-Home | ||||
| Reset to default font size. | ||||
| .TP | ||||
| .B Ctrl-Shift-y | ||||
| Paste from primary selection (middle mouse button). | ||||
| .TP | ||||
| .B Ctrl-Shift-c | ||||
| Copy the selected text to the clipboard selection. | ||||
| .TP | ||||
| .B Ctrl-Shift-v | ||||
| Paste from the clipboard selection. | ||||
| .SH CUSTOMIZATION | ||||
| .B st | ||||
| can be customized by creating a custom config.h and (re)compiling the source | ||||
| code. This keeps it fast, secure and simple. | ||||
| .SH AUTHORS | ||||
| See the LICENSE file for the authors. | ||||
| .SH LICENSE | ||||
| See the LICENSE file for the terms of redistribution. | ||||
| .SH SEE ALSO | ||||
| .BR tabbed (1), | ||||
| .BR utmp (1), | ||||
| .BR stty (1), | ||||
| .BR scroll (1) | ||||
| .SH BUGS | ||||
| See the TODO file in the distribution. | ||||
|  | ||||
							
								
								
									
										126
									
								
								st/st.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								st/st.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | ||||
| /* See LICENSE for license details. */ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| /* macros */ | ||||
| #define MIN(a, b)		((a) < (b) ? (a) : (b)) | ||||
| #define MAX(a, b)		((a) < (b) ? (b) : (a)) | ||||
| #define LEN(a)			(sizeof(a) / sizeof(a)[0]) | ||||
| #define BETWEEN(x, a, b)	((a) <= (x) && (x) <= (b)) | ||||
| #define DIVCEIL(n, d)		(((n) + ((d) - 1)) / (d)) | ||||
| #define DEFAULT(a, b)		(a) = (a) ? (a) : (b) | ||||
| #define LIMIT(x, a, b)		(x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) | ||||
| #define ATTRCMP(a, b)		((a).mode != (b).mode || (a).fg != (b).fg || \ | ||||
| 				(a).bg != (b).bg) | ||||
| #define TIMEDIFF(t1, t2)	((t1.tv_sec-t2.tv_sec)*1000 + \ | ||||
| 				(t1.tv_nsec-t2.tv_nsec)/1E6) | ||||
| #define MODBIT(x, set, bit)	((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) | ||||
|  | ||||
| #define TRUECOLOR(r,g,b)	(1 << 24 | (r) << 16 | (g) << 8 | (b)) | ||||
| #define IS_TRUECOL(x)		(1 << 24 & (x)) | ||||
|  | ||||
| enum glyph_attribute { | ||||
| 	ATTR_NULL       = 0, | ||||
| 	ATTR_BOLD       = 1 << 0, | ||||
| 	ATTR_FAINT      = 1 << 1, | ||||
| 	ATTR_ITALIC     = 1 << 2, | ||||
| 	ATTR_UNDERLINE  = 1 << 3, | ||||
| 	ATTR_BLINK      = 1 << 4, | ||||
| 	ATTR_REVERSE    = 1 << 5, | ||||
| 	ATTR_INVISIBLE  = 1 << 6, | ||||
| 	ATTR_STRUCK     = 1 << 7, | ||||
| 	ATTR_WRAP       = 1 << 8, | ||||
| 	ATTR_WIDE       = 1 << 9, | ||||
| 	ATTR_WDUMMY     = 1 << 10, | ||||
| 	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, | ||||
| }; | ||||
|  | ||||
| enum selection_mode { | ||||
| 	SEL_IDLE = 0, | ||||
| 	SEL_EMPTY = 1, | ||||
| 	SEL_READY = 2 | ||||
| }; | ||||
|  | ||||
| enum selection_type { | ||||
| 	SEL_REGULAR = 1, | ||||
| 	SEL_RECTANGULAR = 2 | ||||
| }; | ||||
|  | ||||
| enum selection_snap { | ||||
| 	SNAP_WORD = 1, | ||||
| 	SNAP_LINE = 2 | ||||
| }; | ||||
|  | ||||
| typedef unsigned char uchar; | ||||
| typedef unsigned int uint; | ||||
| typedef unsigned long ulong; | ||||
| typedef unsigned short ushort; | ||||
|  | ||||
| typedef uint_least32_t Rune; | ||||
|  | ||||
| #define Glyph Glyph_ | ||||
| typedef struct { | ||||
| 	Rune u;           /* character code */ | ||||
| 	ushort mode;      /* attribute flags */ | ||||
| 	uint32_t fg;      /* foreground  */ | ||||
| 	uint32_t bg;      /* background  */ | ||||
| } Glyph; | ||||
|  | ||||
| typedef Glyph *Line; | ||||
|  | ||||
| typedef union { | ||||
| 	int i; | ||||
| 	uint ui; | ||||
| 	float f; | ||||
| 	const void *v; | ||||
| 	const char *s; | ||||
| } Arg; | ||||
|  | ||||
| void die(const char *, ...); | ||||
| void redraw(void); | ||||
| void draw(void); | ||||
|  | ||||
| void printscreen(const Arg *); | ||||
| void printsel(const Arg *); | ||||
| void sendbreak(const Arg *); | ||||
| void toggleprinter(const Arg *); | ||||
|  | ||||
| int tattrset(int); | ||||
| void tnew(int, int); | ||||
| void tresize(int, int); | ||||
| void tsetdirtattr(int); | ||||
| void ttyhangup(void); | ||||
| int ttynew(const char *, char *, const char *, char **); | ||||
| size_t ttyread(void); | ||||
| void ttyresize(int, int); | ||||
| void ttywrite(const char *, size_t, int); | ||||
|  | ||||
| void resettitle(void); | ||||
|  | ||||
| void selclear(void); | ||||
| void selinit(void); | ||||
| void selstart(int, int, int); | ||||
| void selextend(int, int, int, int); | ||||
| int selected(int, int); | ||||
| char *getsel(void); | ||||
|  | ||||
| size_t utf8encode(Rune, char *); | ||||
|  | ||||
| void *xmalloc(size_t); | ||||
| void *xrealloc(void *, size_t); | ||||
| char *xstrdup(const char *); | ||||
|  | ||||
| /* config.h globals */ | ||||
| extern char *utmp; | ||||
| extern char *scroll; | ||||
| extern char *stty_args; | ||||
| extern char *vtiden; | ||||
| extern wchar_t *worddelimiters; | ||||
| extern int allowaltscreen; | ||||
| extern int allowwindowops; | ||||
| extern char *termname; | ||||
| extern unsigned int tabspaces; | ||||
| extern unsigned int defaultfg; | ||||
| extern unsigned int defaultbg; | ||||
| extern unsigned int defaultcs; | ||||
							
								
								
									
										243
									
								
								st/st.info
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								st/st.info
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,243 @@ | ||||
| st-mono| simpleterm monocolor, | ||||
| 	acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, | ||||
| 	am, | ||||
| 	bce, | ||||
| 	bel=^G, | ||||
| 	blink=\E[5m, | ||||
| 	bold=\E[1m, | ||||
| 	cbt=\E[Z, | ||||
| 	cvvis=\E[?25h, | ||||
| 	civis=\E[?25l, | ||||
| 	clear=\E[H\E[2J, | ||||
| 	cnorm=\E[?12l\E[?25h, | ||||
| 	colors#2, | ||||
| 	cols#80, | ||||
| 	cr=^M, | ||||
| 	csr=\E[%i%p1%d;%p2%dr, | ||||
| 	cub=\E[%p1%dD, | ||||
| 	cub1=^H, | ||||
| 	cud1=^J, | ||||
| 	cud=\E[%p1%dB, | ||||
| 	cuf1=\E[C, | ||||
| 	cuf=\E[%p1%dC, | ||||
| 	cup=\E[%i%p1%d;%p2%dH, | ||||
| 	cuu1=\E[A, | ||||
| 	cuu=\E[%p1%dA, | ||||
| 	dch=\E[%p1%dP, | ||||
| 	dch1=\E[P, | ||||
| 	dim=\E[2m, | ||||
| 	dl=\E[%p1%dM, | ||||
| 	dl1=\E[M, | ||||
| 	ech=\E[%p1%dX, | ||||
| 	ed=\E[J, | ||||
| 	el=\E[K, | ||||
| 	el1=\E[1K, | ||||
| 	enacs=\E)0, | ||||
| 	flash=\E[?5h$<80/>\E[?5l, | ||||
| 	fsl=^G, | ||||
| 	home=\E[H, | ||||
| 	hpa=\E[%i%p1%dG, | ||||
| 	hs, | ||||
| 	ht=^I, | ||||
| 	hts=\EH, | ||||
| 	ich=\E[%p1%d@, | ||||
| 	il1=\E[L, | ||||
| 	il=\E[%p1%dL, | ||||
| 	ind=^J, | ||||
| 	indn=\E[%p1%dS, | ||||
| 	invis=\E[8m, | ||||
| 	is2=\E[4l\E>\E[?1034l, | ||||
| 	it#8, | ||||
| 	kel=\E[1;2F, | ||||
| 	ked=\E[1;5F, | ||||
| 	ka1=\E[1~, | ||||
| 	ka3=\E[5~, | ||||
| 	kc1=\E[4~, | ||||
| 	kc3=\E[6~, | ||||
| 	kbs=\177, | ||||
| 	kcbt=\E[Z, | ||||
| 	kb2=\EOu, | ||||
| 	kcub1=\EOD, | ||||
| 	kcud1=\EOB, | ||||
| 	kcuf1=\EOC, | ||||
| 	kcuu1=\EOA, | ||||
| 	kDC=\E[3;2~, | ||||
| 	kent=\EOM, | ||||
| 	kEND=\E[1;2F, | ||||
| 	kIC=\E[2;2~, | ||||
| 	kNXT=\E[6;2~, | ||||
| 	kPRV=\E[5;2~, | ||||
| 	kHOM=\E[1;2H, | ||||
| 	kLFT=\E[1;2D, | ||||
| 	kRIT=\E[1;2C, | ||||
| 	kind=\E[1;2B, | ||||
| 	kri=\E[1;2A, | ||||
| 	kclr=\E[3;5~, | ||||
| 	kdl1=\E[3;2~, | ||||
| 	kdch1=\E[3~, | ||||
| 	kich1=\E[2~, | ||||
| 	kend=\E[4~, | ||||
| 	kf1=\EOP, | ||||
| 	kf2=\EOQ, | ||||
| 	kf3=\EOR, | ||||
| 	kf4=\EOS, | ||||
| 	kf5=\E[15~, | ||||
| 	kf6=\E[17~, | ||||
| 	kf7=\E[18~, | ||||
| 	kf8=\E[19~, | ||||
| 	kf9=\E[20~, | ||||
| 	kf10=\E[21~, | ||||
| 	kf11=\E[23~, | ||||
| 	kf12=\E[24~, | ||||
| 	kf13=\E[1;2P, | ||||
| 	kf14=\E[1;2Q, | ||||
| 	kf15=\E[1;2R, | ||||
| 	kf16=\E[1;2S, | ||||
| 	kf17=\E[15;2~, | ||||
| 	kf18=\E[17;2~, | ||||
| 	kf19=\E[18;2~, | ||||
| 	kf20=\E[19;2~, | ||||
| 	kf21=\E[20;2~, | ||||
| 	kf22=\E[21;2~, | ||||
| 	kf23=\E[23;2~, | ||||
| 	kf24=\E[24;2~, | ||||
| 	kf25=\E[1;5P, | ||||
| 	kf26=\E[1;5Q, | ||||
| 	kf27=\E[1;5R, | ||||
| 	kf28=\E[1;5S, | ||||
| 	kf29=\E[15;5~, | ||||
| 	kf30=\E[17;5~, | ||||
| 	kf31=\E[18;5~, | ||||
| 	kf32=\E[19;5~, | ||||
| 	kf33=\E[20;5~, | ||||
| 	kf34=\E[21;5~, | ||||
| 	kf35=\E[23;5~, | ||||
| 	kf36=\E[24;5~, | ||||
| 	kf37=\E[1;6P, | ||||
| 	kf38=\E[1;6Q, | ||||
| 	kf39=\E[1;6R, | ||||
| 	kf40=\E[1;6S, | ||||
| 	kf41=\E[15;6~, | ||||
| 	kf42=\E[17;6~, | ||||
| 	kf43=\E[18;6~, | ||||
| 	kf44=\E[19;6~, | ||||
| 	kf45=\E[20;6~, | ||||
| 	kf46=\E[21;6~, | ||||
| 	kf47=\E[23;6~, | ||||
| 	kf48=\E[24;6~, | ||||
| 	kf49=\E[1;3P, | ||||
| 	kf50=\E[1;3Q, | ||||
| 	kf51=\E[1;3R, | ||||
| 	kf52=\E[1;3S, | ||||
| 	kf53=\E[15;3~, | ||||
| 	kf54=\E[17;3~, | ||||
| 	kf55=\E[18;3~, | ||||
| 	kf56=\E[19;3~, | ||||
| 	kf57=\E[20;3~, | ||||
| 	kf58=\E[21;3~, | ||||
| 	kf59=\E[23;3~, | ||||
| 	kf60=\E[24;3~, | ||||
| 	kf61=\E[1;4P, | ||||
| 	kf62=\E[1;4Q, | ||||
| 	kf63=\E[1;4R, | ||||
| 	khome=\E[1~, | ||||
| 	kil1=\E[2;5~, | ||||
| 	krmir=\E[2;2~, | ||||
| 	knp=\E[6~, | ||||
| 	kmous=\E[M, | ||||
| 	kpp=\E[5~, | ||||
| 	lines#24, | ||||
| 	mir, | ||||
| 	msgr, | ||||
| 	npc, | ||||
| 	op=\E[39;49m, | ||||
| 	pairs#64, | ||||
| 	mc0=\E[i, | ||||
| 	mc4=\E[4i, | ||||
| 	mc5=\E[5i, | ||||
| 	rc=\E8, | ||||
| 	rev=\E[7m, | ||||
| 	ri=\EM, | ||||
| 	rin=\E[%p1%dT, | ||||
| 	ritm=\E[23m, | ||||
| 	rmacs=\E(B, | ||||
| 	rmcup=\E[?1049l, | ||||
| 	rmir=\E[4l, | ||||
| 	rmkx=\E[?1l\E>, | ||||
| 	rmso=\E[27m, | ||||
| 	rmul=\E[24m, | ||||
| 	rs1=\Ec, | ||||
| 	rs2=\E[4l\E>\E[?1034l, | ||||
| 	sc=\E7, | ||||
| 	sitm=\E[3m, | ||||
| 	sgr0=\E[0m, | ||||
| 	smacs=\E(0, | ||||
| 	smcup=\E[?1049h, | ||||
| 	smir=\E[4h, | ||||
| 	smkx=\E[?1h\E=, | ||||
| 	smso=\E[7m, | ||||
| 	smul=\E[4m, | ||||
| 	tbc=\E[3g, | ||||
| 	tsl=\E]0;, | ||||
| 	xenl, | ||||
| 	vpa=\E[%i%p1%dd, | ||||
| # XTerm extensions | ||||
| 	rmxx=\E[29m, | ||||
| 	smxx=\E[9m, | ||||
| 	BE=\E[?2004h, | ||||
| 	BD=\E[?2004l, | ||||
| 	PS=\E[200~, | ||||
| 	PE=\E[201~, | ||||
| # disabled rep for now: causes some issues with older ncurses versions. | ||||
| #	rep=%p1%c\E[%p2%{1}%-%db, | ||||
| # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) | ||||
| 	Tc, | ||||
| 	Ms=\E]52;%p1%s;%p2%s\007, | ||||
| 	Se=\E[2 q, | ||||
| 	Ss=\E[%p1%d q, | ||||
|  | ||||
| st| simpleterm, | ||||
| 	use=st-mono, | ||||
| 	colors#8, | ||||
| 	setab=\E[4%p1%dm, | ||||
| 	setaf=\E[3%p1%dm, | ||||
| 	setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, | ||||
| 	setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, | ||||
| 	sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, | ||||
|  | ||||
| st-256color| simpleterm with 256 colors, | ||||
| 	use=st, | ||||
| 	ccc, | ||||
| 	colors#256, | ||||
| 	oc=\E]104\007, | ||||
| 	pairs#32767, | ||||
| #	Nicked from xterm-256color | ||||
| 	initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, | ||||
| 	setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, | ||||
| 	setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, | ||||
|  | ||||
| st-meta| simpleterm with meta key, | ||||
| 	use=st, | ||||
| 	km, | ||||
| 	rmm=\E[?1034l, | ||||
| 	smm=\E[?1034h, | ||||
| 	rs2=\E[4l\E>\E[?1034h, | ||||
| 	is2=\E[4l\E>\E[?1034h, | ||||
|  | ||||
| st-meta-256color| simpleterm with meta key and 256 colors, | ||||
| 	use=st-256color, | ||||
| 	km, | ||||
| 	rmm=\E[?1034l, | ||||
| 	smm=\E[?1034h, | ||||
| 	rs2=\E[4l\E>\E[?1034h, | ||||
| 	is2=\E[4l\E>\E[?1034h, | ||||
|  | ||||
| st-bs| simpleterm with backspace as backspace, | ||||
| 	use=st, | ||||
| 	kbs=\010, | ||||
| 	kdch1=\177, | ||||
|  | ||||
| st-bs-256color| simpleterm with backspace as backspace and 256colors, | ||||
| 	use=st-256color, | ||||
| 	kbs=\010, | ||||
| 	kdch1=\177, | ||||
							
								
								
									
										41
									
								
								st/win.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								st/win.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* See LICENSE for license details. */ | ||||
|  | ||||
| enum win_mode { | ||||
| 	MODE_VISIBLE     = 1 << 0, | ||||
| 	MODE_FOCUSED     = 1 << 1, | ||||
| 	MODE_APPKEYPAD   = 1 << 2, | ||||
| 	MODE_MOUSEBTN    = 1 << 3, | ||||
| 	MODE_MOUSEMOTION = 1 << 4, | ||||
| 	MODE_REVERSE     = 1 << 5, | ||||
| 	MODE_KBDLOCK     = 1 << 6, | ||||
| 	MODE_HIDE        = 1 << 7, | ||||
| 	MODE_APPCURSOR   = 1 << 8, | ||||
| 	MODE_MOUSESGR    = 1 << 9, | ||||
| 	MODE_8BIT        = 1 << 10, | ||||
| 	MODE_BLINK       = 1 << 11, | ||||
| 	MODE_FBLINK      = 1 << 12, | ||||
| 	MODE_FOCUS       = 1 << 13, | ||||
| 	MODE_MOUSEX10    = 1 << 14, | ||||
| 	MODE_MOUSEMANY   = 1 << 15, | ||||
| 	MODE_BRCKTPASTE  = 1 << 16, | ||||
| 	MODE_NUMLOCK     = 1 << 17, | ||||
| 	MODE_MOUSE       = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ | ||||
| 	                  |MODE_MOUSEMANY, | ||||
| }; | ||||
|  | ||||
| void xbell(void); | ||||
| void xclipcopy(void); | ||||
| void xdrawcursor(int, int, Glyph, int, int, Glyph); | ||||
| void xdrawline(Line, int, int, int); | ||||
| void xfinishdraw(void); | ||||
| void xloadcols(void); | ||||
| int xsetcolorname(int, const char *); | ||||
| int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); | ||||
| void xseticontitle(char *); | ||||
| void xsettitle(char *); | ||||
| int xsetcursor(int); | ||||
| void xsetmode(int, unsigned int); | ||||
| void xsetpointermotion(int); | ||||
| void xsetsel(char *); | ||||
| int xstartdraw(void); | ||||
| void xximspot(int, int); | ||||
		Reference in New Issue
	
	Block a user