From 4bdb58a9b2db64960f220233cc0ace3329c31bc4 Mon Sep 17 00:00:00 2001 From: crazzy_fingers Date: Mon, 16 May 2022 00:17:37 -0400 Subject: [PATCH] First update --- myports/dwm/Makefile | 88 + myports/dwm/distinfo | 13 + myports/dwm/files/dwm.desktop.in | 6 + .../dwm-centeredwindowname-20200723.diff | 30 + .../dwm/files/patches/dwm-fullscreen-6.2.diff | 56 + .../patches/dwm-noborderfloatingfix-6.2.diff | 31 + .../patches/dwm-rotatestack-20161021.diff | 102 + .../files/superasmodkey-patch-config.def.h | 11 + .../files/volumecontrol-patch-config.def.h | 23 + myports/dwm/pkg-descr | 9 + myports/dwm/work/.PLIST.flattened | 7 + myports/dwm/work/.PLIST.mktmp | 7 + myports/dwm/work/.PLIST.readelf | 142 + myports/dwm/work/.PLIST.setuid | 0 myports/dwm/work/.PLIST.writable | 0 myports/dwm/work/.build_done.dwm._usr_local | 0 .../dwm/work/.configure_done.dwm._usr_local | 0 myports/dwm/work/.extract_done.dwm._usr_local | 0 myports/dwm/work/.install_done.dwm._usr_local | 0 myports/dwm/work/.license-catalog.mk | 5 + myports/dwm/work/.license-report | 1 + myports/dwm/work/.license_done.dwm._usr_local | 0 myports/dwm/work/.patch_done.dwm._usr_local | 0 myports/dwm/work/.stage_done.dwm._usr_local | 0 myports/dwm/work/dwm-6.3/LICENSE | 37 + myports/dwm/work/dwm-6.3/Makefile | 51 + myports/dwm/work/dwm-6.3/README | 48 + myports/dwm/work/dwm-6.3/config.def.h | 125 + myports/dwm/work/dwm-6.3/config.def.h.orig | 119 + myports/dwm/work/dwm-6.3/config.h | 130 + myports/dwm/work/dwm-6.3/config.mk | 38 + myports/dwm/work/dwm-6.3/config.mk.bak | 38 + myports/dwm/work/dwm-6.3/drw.c | 436 +++ myports/dwm/work/dwm-6.3/drw.h | 57 + myports/dwm/work/dwm-6.3/drw.o | Bin 0 -> 10744 bytes myports/dwm/work/dwm-6.3/dwm | Bin 0 -> 69976 bytes myports/dwm/work/dwm-6.3/dwm.1 | 176 ++ myports/dwm/work/dwm-6.3/dwm.c | 2238 +++++++++++++ myports/dwm/work/dwm-6.3/dwm.c.orig | 2181 +++++++++++++ myports/dwm/work/dwm-6.3/dwm.o | Bin 0 -> 63152 bytes myports/dwm/work/dwm-6.3/dwm.png | Bin 0 -> 373 bytes myports/dwm/work/dwm-6.3/transient.c | 42 + myports/dwm/work/dwm-6.3/util.c | 35 + myports/dwm/work/dwm-6.3/util.h | 8 + myports/dwm/work/dwm-6.3/util.o | Bin 0 -> 2016 bytes myports/dwm/work/dwm.desktop | 6 + myports/dwm/work/stage/usr/local/bin/dwm | Bin 0 -> 50296 bytes .../work/stage/usr/local/share/doc/dwm/README | 48 + .../usr/local/share/licenses/dwm-6.3/LICENSE | 1 + .../usr/local/share/licenses/dwm-6.3/MIT | 37 + .../local/share/licenses/dwm-6.3/catalog.mk | 5 + .../stage/usr/local/share/man/man1/dwm.1.gz | Bin 0 -> 1868 bytes .../usr/local/share/xsessions/dwm.desktop | 6 + myports/sterm/Makefile | 72 + myports/sterm/Makefile.new | 70 + myports/sterm/distinfo | 11 + myports/sterm/pkg-descr | 6 + myports/sterm/work/.PLIST.flattened | 11 + myports/sterm/work/.PLIST.mktmp | 11 + myports/sterm/work/.PLIST.readelf | 180 ++ myports/sterm/work/.PLIST.setuid | 0 myports/sterm/work/.PLIST.writable | 0 myports/sterm/work/.bin/tic | Bin 0 -> 4952 bytes .../sterm/work/.build_done.sterm._usr_local | 0 .../work/.configure_done.sterm._usr_local | 0 .../sterm/work/.extract_done.sterm._usr_local | 0 .../sterm/work/.install_done.sterm._usr_local | 0 myports/sterm/work/.license-catalog.mk | 5 + myports/sterm/work/.license-report | 1 + .../sterm/work/.license_done.sterm._usr_local | 0 .../sterm/work/.patch_done.sterm._usr_local | 0 .../sterm/work/.stage_done.sterm._usr_local | 0 myports/sterm/work/st-0.8.5/FAQ | 250 ++ myports/sterm/work/st-0.8.5/LEGACY | 17 + myports/sterm/work/st-0.8.5/LICENSE | 34 + myports/sterm/work/st-0.8.5/Makefile | 57 + myports/sterm/work/st-0.8.5/README | 34 + myports/sterm/work/st-0.8.5/TODO | 28 + myports/sterm/work/st-0.8.5/arg.h | 50 + myports/sterm/work/st-0.8.5/config.def.h | 478 +++ myports/sterm/work/st-0.8.5/config.def.h.orig | 476 +++ myports/sterm/work/st-0.8.5/config.h | 479 +++ myports/sterm/work/st-0.8.5/config.mk | 35 + myports/sterm/work/st-0.8.5/config.mk.bak | 35 + myports/sterm/work/st-0.8.5/st | Bin 0 -> 116112 bytes myports/sterm/work/st-0.8.5/st.1 | 177 ++ myports/sterm/work/st-0.8.5/st.c | 2761 +++++++++++++++++ myports/sterm/work/st-0.8.5/st.c.orig | 2690 ++++++++++++++++ myports/sterm/work/st-0.8.5/st.h | 130 + myports/sterm/work/st-0.8.5/st.h.orig | 128 + myports/sterm/work/st-0.8.5/st.info | 239 ++ myports/sterm/work/st-0.8.5/st.o | Bin 0 -> 109488 bytes myports/sterm/work/st-0.8.5/win.h | 40 + myports/sterm/work/st-0.8.5/x.c | 2080 +++++++++++++ myports/sterm/work/st-0.8.5/x.o | Bin 0 -> 78256 bytes myports/sterm/work/stage/usr/local/bin/st | Bin 0 -> 94832 bytes .../work/stage/usr/local/man/man1/st.1.gz | Bin 0 -> 1523 bytes .../work/stage/usr/local/share/doc/sterm/FAQ | 250 ++ .../stage/usr/local/share/doc/sterm/LEGACY | 17 + .../stage/usr/local/share/doc/sterm/README | 34 + .../work/stage/usr/local/share/doc/sterm/TODO | 28 + .../local/share/licenses/sterm-0.8.5/LICENSE | 1 + .../usr/local/share/licenses/sterm-0.8.5/MIT | 34 + .../share/licenses/sterm-0.8.5/catalog.mk | 5 + .../stage/usr/local/share/sterm/config.def.h | 478 +++ .../work/stage/usr/local/share/sterm/st.info | 239 ++ suckless/dwm/config.def.h | 125 + suckless/dwm/config.h | 130 + suckless/st/config.def.h | 478 +++ suckless/st/config.h | 479 +++ 110 files changed, 19276 insertions(+) create mode 100644 myports/dwm/Makefile create mode 100644 myports/dwm/distinfo create mode 100644 myports/dwm/files/dwm.desktop.in create mode 100644 myports/dwm/files/patches/dwm-centeredwindowname-20200723.diff create mode 100644 myports/dwm/files/patches/dwm-fullscreen-6.2.diff create mode 100644 myports/dwm/files/patches/dwm-noborderfloatingfix-6.2.diff create mode 100644 myports/dwm/files/patches/dwm-rotatestack-20161021.diff create mode 100644 myports/dwm/files/superasmodkey-patch-config.def.h create mode 100644 myports/dwm/files/volumecontrol-patch-config.def.h create mode 100644 myports/dwm/pkg-descr create mode 100644 myports/dwm/work/.PLIST.flattened create mode 100644 myports/dwm/work/.PLIST.mktmp create mode 100644 myports/dwm/work/.PLIST.readelf create mode 100644 myports/dwm/work/.PLIST.setuid create mode 100644 myports/dwm/work/.PLIST.writable create mode 100644 myports/dwm/work/.build_done.dwm._usr_local create mode 100644 myports/dwm/work/.configure_done.dwm._usr_local create mode 100644 myports/dwm/work/.extract_done.dwm._usr_local create mode 100644 myports/dwm/work/.install_done.dwm._usr_local create mode 100644 myports/dwm/work/.license-catalog.mk create mode 100644 myports/dwm/work/.license-report create mode 100644 myports/dwm/work/.license_done.dwm._usr_local create mode 100644 myports/dwm/work/.patch_done.dwm._usr_local create mode 100644 myports/dwm/work/.stage_done.dwm._usr_local create mode 100644 myports/dwm/work/dwm-6.3/LICENSE create mode 100644 myports/dwm/work/dwm-6.3/Makefile create mode 100644 myports/dwm/work/dwm-6.3/README create mode 100644 myports/dwm/work/dwm-6.3/config.def.h create mode 100644 myports/dwm/work/dwm-6.3/config.def.h.orig create mode 100644 myports/dwm/work/dwm-6.3/config.h create mode 100644 myports/dwm/work/dwm-6.3/config.mk create mode 100644 myports/dwm/work/dwm-6.3/config.mk.bak create mode 100644 myports/dwm/work/dwm-6.3/drw.c create mode 100644 myports/dwm/work/dwm-6.3/drw.h create mode 100644 myports/dwm/work/dwm-6.3/drw.o create mode 100755 myports/dwm/work/dwm-6.3/dwm create mode 100644 myports/dwm/work/dwm-6.3/dwm.1 create mode 100644 myports/dwm/work/dwm-6.3/dwm.c create mode 100644 myports/dwm/work/dwm-6.3/dwm.c.orig create mode 100644 myports/dwm/work/dwm-6.3/dwm.o create mode 100644 myports/dwm/work/dwm-6.3/dwm.png create mode 100644 myports/dwm/work/dwm-6.3/transient.c create mode 100644 myports/dwm/work/dwm-6.3/util.c create mode 100644 myports/dwm/work/dwm-6.3/util.h create mode 100644 myports/dwm/work/dwm-6.3/util.o create mode 100644 myports/dwm/work/dwm.desktop create mode 100755 myports/dwm/work/stage/usr/local/bin/dwm create mode 100644 myports/dwm/work/stage/usr/local/share/doc/dwm/README create mode 100644 myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/LICENSE create mode 100644 myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/MIT create mode 100644 myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/catalog.mk create mode 100644 myports/dwm/work/stage/usr/local/share/man/man1/dwm.1.gz create mode 100644 myports/dwm/work/stage/usr/local/share/xsessions/dwm.desktop create mode 100644 myports/sterm/Makefile create mode 100644 myports/sterm/Makefile.new create mode 100644 myports/sterm/distinfo create mode 100644 myports/sterm/pkg-descr create mode 100644 myports/sterm/work/.PLIST.flattened create mode 100644 myports/sterm/work/.PLIST.mktmp create mode 100644 myports/sterm/work/.PLIST.readelf create mode 100644 myports/sterm/work/.PLIST.setuid create mode 100644 myports/sterm/work/.PLIST.writable create mode 100755 myports/sterm/work/.bin/tic create mode 100644 myports/sterm/work/.build_done.sterm._usr_local create mode 100644 myports/sterm/work/.configure_done.sterm._usr_local create mode 100644 myports/sterm/work/.extract_done.sterm._usr_local create mode 100644 myports/sterm/work/.install_done.sterm._usr_local create mode 100644 myports/sterm/work/.license-catalog.mk create mode 100644 myports/sterm/work/.license-report create mode 100644 myports/sterm/work/.license_done.sterm._usr_local create mode 100644 myports/sterm/work/.patch_done.sterm._usr_local create mode 100644 myports/sterm/work/.stage_done.sterm._usr_local create mode 100644 myports/sterm/work/st-0.8.5/FAQ create mode 100644 myports/sterm/work/st-0.8.5/LEGACY create mode 100644 myports/sterm/work/st-0.8.5/LICENSE create mode 100644 myports/sterm/work/st-0.8.5/Makefile create mode 100644 myports/sterm/work/st-0.8.5/README create mode 100644 myports/sterm/work/st-0.8.5/TODO create mode 100644 myports/sterm/work/st-0.8.5/arg.h create mode 100644 myports/sterm/work/st-0.8.5/config.def.h create mode 100644 myports/sterm/work/st-0.8.5/config.def.h.orig create mode 100644 myports/sterm/work/st-0.8.5/config.h create mode 100644 myports/sterm/work/st-0.8.5/config.mk create mode 100644 myports/sterm/work/st-0.8.5/config.mk.bak create mode 100755 myports/sterm/work/st-0.8.5/st create mode 100644 myports/sterm/work/st-0.8.5/st.1 create mode 100644 myports/sterm/work/st-0.8.5/st.c create mode 100644 myports/sterm/work/st-0.8.5/st.c.orig create mode 100644 myports/sterm/work/st-0.8.5/st.h create mode 100644 myports/sterm/work/st-0.8.5/st.h.orig create mode 100644 myports/sterm/work/st-0.8.5/st.info create mode 100644 myports/sterm/work/st-0.8.5/st.o create mode 100644 myports/sterm/work/st-0.8.5/win.h create mode 100644 myports/sterm/work/st-0.8.5/x.c create mode 100644 myports/sterm/work/st-0.8.5/x.o create mode 100755 myports/sterm/work/stage/usr/local/bin/st create mode 100644 myports/sterm/work/stage/usr/local/man/man1/st.1.gz create mode 100644 myports/sterm/work/stage/usr/local/share/doc/sterm/FAQ create mode 100644 myports/sterm/work/stage/usr/local/share/doc/sterm/LEGACY create mode 100644 myports/sterm/work/stage/usr/local/share/doc/sterm/README create mode 100644 myports/sterm/work/stage/usr/local/share/doc/sterm/TODO create mode 100644 myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/LICENSE create mode 100644 myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/MIT create mode 100644 myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/catalog.mk create mode 100644 myports/sterm/work/stage/usr/local/share/sterm/config.def.h create mode 100644 myports/sterm/work/stage/usr/local/share/sterm/st.info create mode 100644 suckless/dwm/config.def.h create mode 100644 suckless/dwm/config.h create mode 100644 suckless/st/config.def.h create mode 100644 suckless/st/config.h diff --git a/myports/dwm/Makefile b/myports/dwm/Makefile new file mode 100644 index 0000000..c85fbdb --- /dev/null +++ b/myports/dwm/Makefile @@ -0,0 +1,88 @@ +# Created by: Jeroen Schot + +PORTNAME= dwm +DISTVERSION= 6.3 +CATEGORIES= x11-wm +MASTER_SITES= http://dl.suckless.org/${PORTNAME}/ + +MAINTAINER= 0mp@FreeBSD.org +COMMENT= Dynamic, small, fast and simple window manager + +LICENSE= MIT +LICENSE_FILE= ${WRKSRC}/LICENSE + +LIB_DEPENDS= libfontconfig.so:x11-fonts/fontconfig +# Kyua is not used by the upstream to test. It's only used in the port's +# do-test target. +TEST_DEPENDS= ${LOCALBASE}/libexec/atf-check:devel/kyua + +USES= xorg +USE_XORG= x11 xft + +MAKE_ARGS= CC="${CC}" \ + FREETYPEINC="${LOCALBASE}/include/freetype2" \ + PREFIX="${PREFIX}" \ + VERSION="${PORTVERSION}" \ + X11INC="${LOCALBASE}/include" \ + X11LIB="${LOCALBASE}/lib" + +SUB_FILES= dwm.desktop +SUB_LIST= COMMENT="${COMMENT}" +PLIST_FILES= bin/dwm \ + share/man/man1/dwm.1.gz \ + share/xsessions/dwm.desktop +PORTDOCS= README +DWM_CONF=/home/loftur/suckless/dwm/config.h +OPTIONS_DEFINE= DOCS SUPERASMODKEY XINERAMA VOLUMECONTROL +OPTIONS_DEFINE+= CENTEREDWINDOWNAME ROTATESTACK FULLSCREEN NOBORDERFLOATING +OPTIONS_DEFAULT=XINERAMA SUPERASMODKEY + +CENTEREDWINDOWNAME_DESC= Center the WM_NAME of the window on the status bar +ROTATESTACK_DESC= Stack rotate moves a client from the bottom to the top +FULLSCREEN_DESC= Aplyy fullscreen +NOBORDERFLOATING_DESC= Remove the border when there is only one window visible +SUPERASMODKEY_DESC= Use Super instead of Alt for the dwm mod key +VOLUMECONTROL_DESC= Use multimedia keys to raise or lower volume + +SUPERASMODKEY_EXTRA_PATCHES= ${PATCHDIR}/superasmodkey-patch-config.def.h +VOLUMECONTROL_EXTRA_PATCHES= ${PATCHDIR}/volumecontrol-patch-config.def.h +CENTEREDWINDOWNAME_EXTRA_PATCHES= ${PATCHDIR}/patches/dwm-centeredwindowname-20200723.diff:-p1 +ROTATESTACK_EXTRA_PATCHES= ${PATCHDIR}/patches/dwm-rotatestack-20161021.diff:-p1 +FULLSCREEN_EXTRA_PATCHES= ${PATCHDIR}/patches/dwm-fullscreen-6.2.diff:-p1 +NOBORDERFLOATING_EXTRA_PATCHES= ${PATCHDIR}/patches/dwm-noborderfloatingfix-6.2.diff:-p1 + +XINERAMA_USE= XORG=xinerama +XINERAMA_MAKE_ARGS_OFF= XINERAMAFLAGS= XINERAMALIBS= + +pre-everything:: + @${ECHO_MSG} "You can build dwm with your own config.h using the DWM_CONF knob:" + @${ECHO_MSG} "make DWM_CONF=/path/to/dwm/config.h install clean" + @${ECHO_MSG} "Note: Pre-${PORTVERSION} config.h-files may not work." + +.if exists(${DWM_CONF}) +post-extract: + @${ECHO_MSG} "Creating symlink: config.h -> ${DWM_CONF}" + ${LN} -fs "${DWM_CONF}" ${WRKSRC}/config.h +.endif + +post-configure: + @${REINPLACE_CMD} -E \ + -e "s|(CFLAGS[[:space:]]*)= |\1+= |" \ + -e "s|(CPPFLAGS[[:space:]]*)= |\1+= |" \ + -e "s|(LDFLAGS[[:space:]]*)= |\1+= |" \ + ${WRKSRC}/config.mk + +post-install: + @${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/dwm + @${MKDIR} ${STAGEDIR}${PREFIX}/share/xsessions + ${INSTALL_DATA} ${WRKDIR}/dwm.desktop ${STAGEDIR}${PREFIX}/share/xsessions + +post-install-DOCS-on: + @${MKDIR} ${STAGEDIR}${DOCSDIR} + ${INSTALL_DATA} ${WRKSRC}/README ${STAGEDIR}${DOCSDIR} + +do-test: + ${LOCALBASE}/libexec/atf-check -s exit:1 -e match:"dwm-${PORTVERSION}" \ + ${STAGEDIR}${PREFIX}/bin/dwm -v + +.include diff --git a/myports/dwm/distinfo b/myports/dwm/distinfo new file mode 100644 index 0000000..e13e54a --- /dev/null +++ b/myports/dwm/distinfo @@ -0,0 +1,13 @@ +TIMESTAMP = 1642674880 +SHA256 (dwm-6.3.tar.gz) = badaa028529b1fba1fd7f9a84f3b64f31190466c858011b53e2f7b70c6a3078d +SIZE (dwm-6.3.tar.gz) = 25351 +SHA256 (dwm-centeredwindowname-20200723-f035e1e.diff) = badaa028529b1fba1fd7f9a84f3b64f31190466c858011b53e2f7b70c6a3078d +SIZE (dwm-centeredwindowname-20200723-f035e1e.diff) = 25351 +SHA256 (dwm-rotatestack-20161021-ab9571b.diff) = badaa028529b1fba1fd7f9a84f3b64f31190466c858011b53e2f7b70c6a3078d +SIZE (dwm-rotatestack-20161021-ab9571b.diff) = 25351 +SHA256 (dwm-fullscreen-6.2.diff) = badaa028529b1fba1fd7f9a84f3b64f31190466c858011b53e2f7b70c6a3078d +SIZE (dwm-fullscreen-6.2.diff) = 25351 +SHA256 (dwm-noborderfloatingfix-6.2.diff) = badaa028529b1fba1fd7f9a84f3b64f31190466c858011b53e2f7b70c6a3078d +SIZE (dwm-noborderfloatingfix-6.2.diff) = 25351 + + diff --git a/myports/dwm/files/dwm.desktop.in b/myports/dwm/files/dwm.desktop.in new file mode 100644 index 0000000..a3fc2be --- /dev/null +++ b/myports/dwm/files/dwm.desktop.in @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=dwm +Comment=%%COMMENT%% +TryExec=dwm +Exec=dwm +Type=Application diff --git a/myports/dwm/files/patches/dwm-centeredwindowname-20200723.diff b/myports/dwm/files/patches/dwm-centeredwindowname-20200723.diff new file mode 100644 index 0000000..67ae4d3 --- /dev/null +++ b/myports/dwm/files/patches/dwm-centeredwindowname-20200723.diff @@ -0,0 +1,30 @@ +From f035e1e5abb19df5dced9c592ca986deac460435 Mon Sep 17 00:00:00 2001 +From: bastila <20937049+silentfault@users.noreply.github.com> +Date: Thu, 23 Jul 2020 02:45:12 +0300 +Subject: [PATCH] Fix overflow when window name is bigger than window width + +--- + dwm.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dwm.c b/dwm.c +index 9fd0286..42cb8dd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -731,8 +731,12 @@ drawbar(Monitor *m) + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { ++ /* fix overflow when window name is bigger than window width */ ++ int mid = (m->ww - (int)TEXTW(m->sel->name)) / 2 - x; ++ /* make sure name will not overlap on tags even when it is very long */ ++ mid = mid >= lrpad / 2 ? mid : lrpad / 2; + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); ++ drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { +-- +2.27.0 + diff --git a/myports/dwm/files/patches/dwm-fullscreen-6.2.diff b/myports/dwm/files/patches/dwm-fullscreen-6.2.diff new file mode 100644 index 0000000..36e3140 --- /dev/null +++ b/myports/dwm/files/patches/dwm-fullscreen-6.2.diff @@ -0,0 +1,56 @@ +From 54719285bd1a984e2efce6e8a8eab184fec11abf Mon Sep 17 00:00:00 2001 +From: Sermak +Date: Mon, 8 Jul 2019 01:06:44 +0200 +Subject: [PATCH] Simulate toggleable fullscreen mode + +--- + config.def.h | 1 + + dwm.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..f774cc5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -76,6 +76,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 4465af1..04b1e06 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -199,6 +199,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void fullscreen(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -1497,6 +1498,19 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++Layout *last_layout; ++void ++fullscreen(const Arg *arg) ++{ ++ if (selmon->showbar) { ++ for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); ++ setlayout(&((Arg) { .v = &layouts[2] })); ++ } else { ++ setlayout(&((Arg) { .v = last_layout })); ++ } ++ togglebar(arg); ++} ++ + void + setlayout(const Arg *arg) + { +-- +2.22.0 diff --git a/myports/dwm/files/patches/dwm-noborderfloatingfix-6.2.diff b/myports/dwm/files/patches/dwm-noborderfloatingfix-6.2.diff new file mode 100644 index 0000000..f34758d --- /dev/null +++ b/myports/dwm/files/patches/dwm-noborderfloatingfix-6.2.diff @@ -0,0 +1,31 @@ +From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001 +From: Aidan Hall +Date: Tue, 2 Jun 2020 14:41:53 +0000 +Subject: [PATCH] Prevents hiding the border if layout is floating. + +--- + dwm.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/dwm.c b/dwm.c +index 4465af1..2dd959d 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1061,6 +1061,14 @@ resizeclient(Client *c, int x, int y, int w, int h) + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; ++ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) ++ || &monocle == c->mon->lt[c->mon->sellt]->arrange) ++ && !c->isfullscreen && !c->isfloating ++ && NULL != c->mon->lt[c->mon->sellt]->arrange) { ++ c->w = wc.width += c->bw * 2; ++ c->h = wc.height += c->bw * 2; ++ wc.border_width = 0; ++ } + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +-- +2.26.2 + diff --git a/myports/dwm/files/patches/dwm-rotatestack-20161021.diff b/myports/dwm/files/patches/dwm-rotatestack-20161021.diff new file mode 100644 index 0000000..ed74c6d --- /dev/null +++ b/myports/dwm/files/patches/dwm-rotatestack-20161021.diff @@ -0,0 +1,102 @@ +diff --git a/config.def.h b/config.def.h +index fd77a07..09737d7 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -64,6 +64,8 @@ static Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, ++ { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, +diff --git a/dwm.c b/dwm.c +index 421bf27..1ec8b10 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -165,6 +165,8 @@ static void detachstack(Client *c); + static Monitor *dirtomon(int dir); + static void drawbar(Monitor *m); + static void drawbars(void); ++static void enqueue(Client *c); ++static void enqueuestack(Client *c); + static void enternotify(XEvent *e); + static void expose(XEvent *e); + static void focus(Client *c); +@@ -194,6 +196,7 @@ static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); + static void restack(Monitor *m); ++static void rotatestack(const Arg *arg); + static void run(void); + static void scan(void); + static int sendevent(Client *c, Atom proto); +@@ -765,6 +768,28 @@ drawbars(void) + } + + void ++enqueue(Client *c) ++{ ++ Client *l; ++ for (l = c->mon->clients; l && l->next; l = l->next); ++ if (l) { ++ l->next = c; ++ c->next = NULL; ++ } ++} ++ ++void ++enqueuestack(Client *c) ++{ ++ Client *l; ++ for (l = c->mon->stack; l && l->snext; l = l->snext); ++ if (l) { ++ l->snext = c; ++ c->snext = NULL; ++ } ++} ++ ++void + enternotify(XEvent *e) + { + Client *c; +@@ -1390,6 +1415,38 @@ restack(Monitor *m) + } + + void ++rotatestack(const Arg *arg) ++{ ++ Client *c = NULL, *f; ++ ++ if (!selmon->sel) ++ return; ++ f = selmon->sel; ++ if (arg->i > 0) { ++ for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); ++ if (c){ ++ detach(c); ++ attach(c); ++ detachstack(c); ++ attachstack(c); ++ } ++ } else { ++ if ((c = nexttiled(selmon->clients))){ ++ detach(c); ++ enqueue(c); ++ detachstack(c); ++ enqueuestack(c); ++ } ++ } ++ if (c){ ++ arrange(selmon); ++ //unfocus(f, 1); ++ focus(f); ++ restack(selmon); ++ } ++} ++ ++void + run(void) + { + XEvent ev; diff --git a/myports/dwm/files/superasmodkey-patch-config.def.h b/myports/dwm/files/superasmodkey-patch-config.def.h new file mode 100644 index 0000000..ba8f304 --- /dev/null +++ b/myports/dwm/files/superasmodkey-patch-config.def.h @@ -0,0 +1,11 @@ +--- config.def.h.orig 2018-01-16 16:05:12 UTC ++++ config.def.h +@@ -42,7 +42,7 @@ static const Layout layouts[] = { + }; + + /* key definitions */ +-#define MODKEY Mod1Mask ++#define MODKEY Mod4Mask + #define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ diff --git a/myports/dwm/files/volumecontrol-patch-config.def.h b/myports/dwm/files/volumecontrol-patch-config.def.h new file mode 100644 index 0000000..2a14410 --- /dev/null +++ b/myports/dwm/files/volumecontrol-patch-config.def.h @@ -0,0 +1,23 @@ +--- config.def.h.orig 2015-11-08 23:39:37.000000000 +0100 ++++ config.def.h 2018-03-25 21:26:37.860145000 +0200 +@@ -56,7 +56,11 @@ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "st", NULL }; ++static const char *incrvol[] = { "mixer", "vol", "+1:+1", NULL}; ++static const char *decrvol[] = { "mixer", "vol", "-1:-1", NULL}; + ++#define XK_XF86AudioLowerVolume 0x1008ff11 ++#define XK_XF86AudioRaiseVolume 0x1008ff13 + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -92,6 +96,8 @@ + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { 0x0, XK_XF86AudioRaiseVolume, spawn, {.v = incrvol } }, ++ { 0x0, XK_XF86AudioLowerVolume, spawn, {.v = decrvol } }, + }; + + /* button definitions */ diff --git a/myports/dwm/pkg-descr b/myports/dwm/pkg-descr new file mode 100644 index 0000000..f539df1 --- /dev/null +++ b/myports/dwm/pkg-descr @@ -0,0 +1,9 @@ +dwm is a minimalistic window manager. It manages windows in tiling and floating +modes, much like ion, larswm and wmii. dwm however is much smaller, faster and +simpler. + +It consists of a single binary, configuration is done at compile-time by a +single config.h file. dwm reads from standard input to print arbitrary status +text such as the date and/or system load. + +WWW: https://dwm.suckless.org/ diff --git a/myports/dwm/work/.PLIST.flattened b/myports/dwm/work/.PLIST.flattened new file mode 100644 index 0000000..a36e2b0 --- /dev/null +++ b/myports/dwm/work/.PLIST.flattened @@ -0,0 +1,7 @@ +/usr/local/bin/dwm +/usr/local/share/man/man1/dwm.1.gz +/usr/local/share/xsessions/dwm.desktop +/usr/local/share/licenses/dwm-6.3/catalog.mk +/usr/local/share/licenses/dwm-6.3/LICENSE +/usr/local/share/licenses/dwm-6.3/MIT +/usr/local/share/doc/dwm/README diff --git a/myports/dwm/work/.PLIST.mktmp b/myports/dwm/work/.PLIST.mktmp new file mode 100644 index 0000000..d4c3e0d --- /dev/null +++ b/myports/dwm/work/.PLIST.mktmp @@ -0,0 +1,7 @@ +bin/dwm +share/man/man1/dwm.1.gz +share/xsessions/dwm.desktop +/usr/local/share/licenses/dwm-6.3/catalog.mk +/usr/local/share/licenses/dwm-6.3/LICENSE +/usr/local/share/licenses/dwm-6.3/MIT +/usr/local/share/doc/dwm/README diff --git a/myports/dwm/work/.PLIST.readelf b/myports/dwm/work/.PLIST.readelf new file mode 100644 index 0000000..a5b37bf --- /dev/null +++ b/myports/dwm/work/.PLIST.readelf @@ -0,0 +1,142 @@ + +File: /usr/local/bin/dwm + +Relocation section with addend (.rela.dyn): +r_offset r_info r_type st_value st_name + r_addend +00000020eea0 007b00000005 R_X86_64_COPY 000000000020eea0 __stack_chk_guard + 0 +00000020eee0 007c00000005 R_X86_64_COPY 000000000020eee0 __stderrp + 0 + +Relocation section with addend (.rela.plt): +r_offset r_info r_type st_value st_name + r_addend +00000020e818 000200000007 R_X86_64_JUMP_SLOT 0000000000000000 atexit + 0 +00000020e820 000100000007 R_X86_64_JUMP_SLOT 0000000000000000 _init_tls + 0 +00000020e828 000300000007 R_X86_64_JUMP_SLOT 0000000000000000 exit + 0 +00000020e830 000400000007 R_X86_64_JUMP_SLOT 0000000000000000 _Jv_RegisterClasses + 0 +00000020e838 001300000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreatePixmap + 0 +00000020e840 001200000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateGC + 0 +00000020e848 001a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetLineAttributes + 0 +00000020e850 001800000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreePixmap + 0 +00000020e858 001700000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreeGC + 0 +00000020e860 002800000007 R_X86_64_JUMP_SLOT 0000000000000000 free + 0 +00000020e868 002300000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontOpenName + 0 +00000020e870 000a00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcNameParse + 0 +00000020e878 002400000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontOpenPattern + 0 +00000020e880 002700000007 R_X86_64_JUMP_SLOT 0000000000000000 fprintf + 0 +00000020e888 002100000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontClose + 0 +00000020e890 000f00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternGetBool + 0 +00000020e898 002900000007 R_X86_64_JUMP_SLOT 0000000000000000 fwrite + 0 +00000020e8a0 002600000007 R_X86_64_JUMP_SLOT 0000000000000000 __stack_chk_fail + 0 +00000020e8a8 000d00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternDestroy + 0 +00000020e8b0 001d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftColorAllocName + 0 +00000020e8b8 001900000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetForeground + 0 +00000020e8c0 001500000007 R_X86_64_JUMP_SLOT 0000000000000000 XFillRectangle + 0 +00000020e8c8 001400000007 R_X86_64_JUMP_SLOT 0000000000000000 XDrawRectangle + 0 +00000020e8d0 001e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawCreate + 0 +00000020e8d8 001c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftCharExists + 0 +00000020e8e0 002500000007 R_X86_64_JUMP_SLOT 0000000000000000 XftTextExtentsUtf8 + 0 +00000020e8e8 002a00000007 R_X86_64_JUMP_SLOT 0000000000000000 memcpy + 0 +00000020e8f0 002b00000007 R_X86_64_JUMP_SLOT 0000000000000000 memset + 0 +00000020e8f8 002000000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawStringUtf8 + 0 +00000020e900 000600000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetCreate + 0 +00000020e908 000500000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetAddChar + 0 +00000020e910 000e00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternDuplicate + 0 +00000020e918 000c00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddCharSet + 0 +00000020e920 000b00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddBool + 0 +00000020e928 000800000007 R_X86_64_JUMP_SLOT 0000000000000000 FcConfigSubstitute + 0 +00000020e930 000900000007 R_X86_64_JUMP_SLOT 0000000000000000 FcDefaultSubstitute + 0 +00000020e938 002200000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontMatch + 0 +00000020e940 000700000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetDestroy + 0 +00000020e948 001f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawDestroy + 0 +00000020e950 001000000007 R_X86_64_JUMP_SLOT 0000000000000000 XCopyArea + 0 +00000020e958 001b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSync + 0 +00000020e960 001100000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateFontCursor + 0 +00000020e968 001600000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreeCursor + 0 +00000020e970 007100000007 R_X86_64_JUMP_SLOT 0000000000000000 strcmp + 0 +00000020e978 006d00000007 R_X86_64_JUMP_SLOT 0000000000000000 setlocale + 0 +00000020e980 005e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSupportsLocale + 0 +00000020e988 006b00000007 R_X86_64_JUMP_SLOT 0000000000000000 fputs + 0 +00000020e990 005100000007 R_X86_64_JUMP_SLOT 0000000000000000 XOpenDisplay + 0 +00000020e998 005a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetErrorHandler + 0 +00000020e9a0 005600000007 R_X86_64_JUMP_SLOT 0000000000000000 XSelectInput + 0 +00000020e9a8 004700000007 R_X86_64_JUMP_SLOT 0000000000000000 XInternAtom + 0 +00000020e9b0 003200000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateSimpleWindow + 0 +00000020e9b8 002d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XChangeProperty + 0 +00000020e9c0 003500000007 R_X86_64_JUMP_SLOT 0000000000000000 XDeleteProperty + 0 +00000020e9c8 002e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XChangeWindowAttributes + 0 +00000020e9d0 005300000007 R_X86_64_JUMP_SLOT 0000000000000000 XQueryTree + 0 +00000020e9d8 004100000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWindowAttributes + 0 +00000020e9e0 003d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetTransientForHint + 0 +00000020e9e8 003700000007 R_X86_64_JUMP_SLOT 0000000000000000 XFree + 0 +00000020e9f0 005000000007 R_X86_64_JUMP_SLOT 0000000000000000 XNextEvent + 0 +00000020e9f8 006000000007 R_X86_64_JUMP_SLOT 0000000000000000 XUngrabKey + 0 +00000020ea00 003600000007 R_X86_64_JUMP_SLOT 0000000000000000 XDestroyWindow + 0 +00000020ea08 005b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetInputFocus + 0 +00000020ea10 003000000007 R_X86_64_JUMP_SLOT 0000000000000000 XCloseDisplay + 0 +00000020ea18 006f00000007 R_X86_64_JUMP_SLOT 0000000000000000 signal + 0 +00000020ea20 007400000007 R_X86_64_JUMP_SLOT 0000000000000000 waitpid + 0 +00000020ea28 006500000007 R_X86_64_JUMP_SLOT 0000000000000000 XineramaIsActive + 0 +00000020ea30 006600000007 R_X86_64_JUMP_SLOT 0000000000000000 XineramaQueryScreens + 0 +00000020ea38 003300000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateWindow + 0 +00000020ea40 003400000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefineCursor + 0 +00000020ea48 004b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XMapRaised + 0 +00000020ea50 005800000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetClassHint + 0 +00000020ea58 004900000007 R_X86_64_JUMP_SLOT 0000000000000000 XKeysymToKeycode + 0 +00000020ea60 004400000007 R_X86_64_JUMP_SLOT 0000000000000000 XGrabKey + 0 +00000020ea68 005d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWindowBorder + 0 +00000020ea70 007200000007 R_X86_64_JUMP_SLOT 0000000000000000 strncpy + 0 +00000020ea78 006300000007 R_X86_64_JUMP_SLOT 0000000000000000 XUnmapWindow + 0 +00000020ea80 005200000007 R_X86_64_JUMP_SLOT 0000000000000000 XQueryPointer + 0 +00000020ea88 007000000007 R_X86_64_JUMP_SLOT 0000000000000000 snprintf + 0 +00000020ea90 003100000007 R_X86_64_JUMP_SLOT 0000000000000000 XConfigureWindow + 0 +00000020ea98 005700000007 R_X86_64_JUMP_SLOT 0000000000000000 XSendEvent + 0 +00000020eaa0 003c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetTextProperty + 0 +00000020eaa8 006700000007 R_X86_64_JUMP_SLOT 0000000000000000 XmbTextPropertyToTextList + 0 +00000020eab0 003900000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreeStringList + 0 +00000020eab8 003b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetModifierMapping + 0 +00000020eac0 003800000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreeModifiermap + 0 +00000020eac8 006a00000007 R_X86_64_JUMP_SLOT 0000000000000000 fork + 0 +00000020ead0 006800000007 R_X86_64_JUMP_SLOT 0000000000000000 close + 0 +00000020ead8 006e00000007 R_X86_64_JUMP_SLOT 0000000000000000 setsid + 0 +00000020eae0 006900000007 R_X86_64_JUMP_SLOT 0000000000000000 execvp + 0 +00000020eae8 006c00000007 R_X86_64_JUMP_SLOT 0000000000000000 perror + 0 +00000020eaf0 004e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XMoveResizeWindow + 0 +00000020eaf8 004600000007 R_X86_64_JUMP_SLOT 0000000000000000 XGrabServer + 0 +00000020eb00 005900000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetCloseDownMode + 0 +00000020eb08 004a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XKillClient + 0 +00000020eb10 006200000007 R_X86_64_JUMP_SLOT 0000000000000000 XUngrabServer + 0 +00000020eb18 004f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XMoveWindow + 0 +00000020eb20 005400000007 R_X86_64_JUMP_SLOT 0000000000000000 XRaiseWindow + 0 +00000020eb28 002f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XCheckMaskEvent + 0 +00000020eb30 004000000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWMProtocols + 0 +00000020eb38 005f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XUngrabButton + 0 +00000020eb40 004300000007 R_X86_64_JUMP_SLOT 0000000000000000 XGrabButton + 0 +00000020eb48 004500000007 R_X86_64_JUMP_SLOT 0000000000000000 XGrabPointer + 0 +00000020eb50 004d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XMaskEvent + 0 +00000020eb58 006100000007 R_X86_64_JUMP_SLOT 0000000000000000 XUngrabPointer + 0 +00000020eb60 006400000007 R_X86_64_JUMP_SLOT 0000000000000000 XWarpPointer + 0 +00000020eb68 004800000007 R_X86_64_JUMP_SLOT 0000000000000000 XKeycodeToKeysym + 0 +00000020eb70 002c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XAllowEvents + 0 +00000020eb78 005500000007 R_X86_64_JUMP_SLOT 0000000000000000 XRefreshKeyboardMapping + 0 +00000020eb80 003a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetClassHint + 0 +00000020eb88 007300000007 R_X86_64_JUMP_SLOT 0000000000000000 strstr + 0 +00000020eb90 004c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XMapWindow + 0 +00000020eb98 003f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWMNormalHints + 0 +00000020eba0 003e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWMHints + 0 +00000020eba8 005c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMHints + 0 +00000020ebb0 004200000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWindowProperty + 0 +00000020ebb8 007500000007 R_X86_64_JUMP_SLOT 0000000000000000 calloc + 0 +00000020ebc0 007800000007 R_X86_64_JUMP_SLOT 0000000000000000 vfprintf + 0 +00000020ebc8 007700000007 R_X86_64_JUMP_SLOT 0000000000000000 strlen + 0 +00000020ebd0 007600000007 R_X86_64_JUMP_SLOT 0000000000000000 fputc + 0 + +File: /usr/local/share/man/man1/dwm.1.gz + +File: /usr/local/share/xsessions/dwm.desktop + +File: /usr/local/share/licenses/dwm-6.3/catalog.mk + +File: /usr/local/share/licenses/dwm-6.3/LICENSE + +File: /usr/local/share/licenses/dwm-6.3/MIT + +File: /usr/local/share/doc/dwm/README diff --git a/myports/dwm/work/.PLIST.setuid b/myports/dwm/work/.PLIST.setuid new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.PLIST.writable b/myports/dwm/work/.PLIST.writable new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.build_done.dwm._usr_local b/myports/dwm/work/.build_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.configure_done.dwm._usr_local b/myports/dwm/work/.configure_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.extract_done.dwm._usr_local b/myports/dwm/work/.extract_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.install_done.dwm._usr_local b/myports/dwm/work/.install_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.license-catalog.mk b/myports/dwm/work/.license-catalog.mk new file mode 100644 index 0000000..1268426 --- /dev/null +++ b/myports/dwm/work/.license-catalog.mk @@ -0,0 +1,5 @@ +_LICENSE=MIT +_LICENSE_NAME=MIT license / X11 license +_LICENSE_PERMS=dist-mirror dist-sell pkg-mirror pkg-sell auto-accept +_LICENSE_GROUPS=COPYFREE FSF GPL OSI +_LICENSE_DISTFILES=dwm-6.3.tar.gz diff --git a/myports/dwm/work/.license-report b/myports/dwm/work/.license-report new file mode 100644 index 0000000..6657117 --- /dev/null +++ b/myports/dwm/work/.license-report @@ -0,0 +1 @@ +This package has a single license: MIT (MIT license / X11 license). diff --git a/myports/dwm/work/.license_done.dwm._usr_local b/myports/dwm/work/.license_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.patch_done.dwm._usr_local b/myports/dwm/work/.patch_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/.stage_done.dwm._usr_local b/myports/dwm/work/.stage_done.dwm._usr_local new file mode 100644 index 0000000..e69de29 diff --git a/myports/dwm/work/dwm-6.3/LICENSE b/myports/dwm/work/dwm-6.3/LICENSE new file mode 100644 index 0000000..d221f09 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/LICENSE @@ -0,0 +1,37 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/myports/dwm/work/dwm-6.3/Makefile b/myports/dwm/work/dwm-6.3/Makefile new file mode 100644 index 0000000..77bcbc0 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/Makefile @@ -0,0 +1,51 @@ +# 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: options dwm + +options: + @echo dwm build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.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 options clean dist install uninstall diff --git a/myports/dwm/work/dwm-6.3/README b/myports/dwm/work/dwm-6.3/README new file mode 100644 index 0000000..95d4fd0 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/README @@ -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. diff --git a/myports/dwm/work/dwm-6.3/config.def.h b/myports/dwm/work/dwm-6.3/config.def.h new file mode 100644 index 0000000..d05dc04 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/config.def.h @@ -0,0 +1,125 @@ +/* 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 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 char *incrvol[] = { "mixer", "vol", "+1:+1", NULL}; +static const char *decrvol[] = { "mixer", "vol", "-1:-1", NULL}; + +#define XK_XF86AudioLowerVolume 0x1008ff11 +#define XK_XF86AudioRaiseVolume 0x1008ff13 +static 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|ShiftMask, XK_j, rotatestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { 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|ShiftMask, XK_f, fullscreen, {0} }, + { 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} }, + { 0x0, XK_XF86AudioRaiseVolume, spawn, {.v = incrvol } }, + { 0x0, XK_XF86AudioLowerVolume, spawn, {.v = decrvol } }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/myports/dwm/work/dwm-6.3/config.def.h.orig b/myports/dwm/work/dwm-6.3/config.def.h.orig new file mode 100644 index 0000000..b075a07 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/config.def.h.orig @@ -0,0 +1,119 @@ +/* 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 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 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|ShiftMask, XK_j, rotatestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { 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|ShiftMask, XK_f, fullscreen, {0} }, + { 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 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} }, +}; + diff --git a/myports/dwm/work/dwm-6.3/config.h b/myports/dwm/work/dwm-6.3/config.h new file mode 100644 index 0000000..1aa8b7d --- /dev/null +++ b/myports/dwm/work/dwm-6.3/config.h @@ -0,0 +1,130 @@ +/* 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 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 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|ShiftMask, XK_i, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY|ShiftMask, XK_i, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_k, rotatestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, 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} }, + +/* Modos de captura de pantalla */ +{ 0, XK_Print, spawn, SHCMD("scrot /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Pantalla en portapapeles'") }, // Captura de pantalla al portapapeles +{ ControlMask, XK_Print, spawn, SHCMD("scrot -u /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Ventana en portapapeles'") }, // Ventana seleccionada al portapapeles +{ ShiftMask, XK_Print, spawn, SHCMD("sleep 1; scrot -s /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Área en portapapeles'") }, // Area seleccionada al portapapeles + +{ MODKEY, XK_Print, spawn, SHCMD("scrot 'c_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; sleep 1; exec herbe 'Pantalla en ~/Capturas'") },//Captura de pantalla +{ MODKEY|ControlMask, XK_Print, spawn, SHCMD("scrot -u 'v_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; sleep 1; exec herbe 'Ventana en ~/Capturas'") } ,//Captura de ventana +{ MODKEY|ShiftMask, XK_Print, spawn, SHCMD("sleep 1; scrot -s 'a_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; exec herbe 'Área en ~/Capturas'") },// Captura de Area + + +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/myports/dwm/work/dwm-6.3/config.mk b/myports/dwm/work/dwm-6.3/config.mk new file mode 100644 index 0000000..40e5c47 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/config.mk @@ -0,0 +1,38 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = ${X11INC}/freetype2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} + +# flags +CPPFLAGS += -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS += -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS += -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS += ${LIBS} + +# Solaris +#CFLAGS += -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS += ${LIBS} + +# compiler and linker +CC = cc diff --git a/myports/dwm/work/dwm-6.3/config.mk.bak b/myports/dwm/work/dwm-6.3/config.mk.bak new file mode 100644 index 0000000..b6eb7e0 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/config.mk.bak @@ -0,0 +1,38 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = ${X11INC}/freetype2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/myports/dwm/work/dwm-6.3/drw.c b/myports/dwm/work/dwm-6.3/drw.c new file mode 100644 index 0000000..4cdbcbe --- /dev/null +++ b/myports/dwm/work/dwm-6.3/drw.c @@ -0,0 +1,436 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + 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."); + } + + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +{ + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +{ + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t i, len; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + while (1) { + utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; + text += utf8charlen; + } else { + nextfont = curfont; + } + break; + } + } + + if (!charexists || nextfont) + break; + else + charexists = 0; + } + + if (utf8strlen) { + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); + /* shorten text if necessary */ + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + + if (len) { + memcpy(buf, utf8str, len); + buf[len] = '\0'; + if (len < utf8strlen) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)buf, len); + } + x += ew; + w -= ew; + } + } + + if (!*text) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} diff --git a/myports/dwm/work/dwm-6.3/drw.h b/myports/dwm/work/dwm-6.3/drw.h new file mode 100644 index 0000000..4bcd5ad --- /dev/null +++ b/myports/dwm/work/dwm-6.3/drw.h @@ -0,0 +1,57 @@ +/* See LICENSE file for copyright and license details. */ + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg, 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); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); + +/* Colorscheme abstraction */ +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/myports/dwm/work/dwm-6.3/drw.o b/myports/dwm/work/dwm-6.3/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..975bbc8dfc12c1d6a280390eef4967e03f1ba556 GIT binary patch literal 10744 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 Lf4XA=cG~|Z=fod; literal 0 HcmV?d00001 diff --git a/myports/dwm/work/dwm-6.3/dwm.1 b/myports/dwm/work/dwm-6.3/dwm.1 new file mode 100644 index 0000000..ddc8321 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/dwm.1 @@ -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. diff --git a/myports/dwm/work/dwm-6.3/dwm.c b/myports/dwm/work/dwm-6.3/dwm.c new file mode 100644 index 0000000..7b8438f --- /dev/null +++ b/myports/dwm/work/dwm-6.3/dwm.c @@ -0,0 +1,2238 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + int topbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + unsigned int tags; + int isfloating; + int monitor; +} Rule; + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void enqueue(Client *c); +static void enqueuestack(Client *c); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void monocle(Monitor *m); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void rotatestack(const Arg *arg); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void fullscreen(const Arg *arg); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void sigchld(int unused); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void tile(Monitor *); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewindowtype(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static char stext[256]; +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh, blw = 0; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + unsigned int i, x, click; + Arg arg = {0}; + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; + + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; + size_t i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = blw = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + /* fix overflow when window name is bigger than window width */ + int mid = (m->ww - (int)TEXTW(m->sel->name)) / 2 - x; + /* make sure name will not overlap on tags even when it is very long */ + mid = mid >= lrpad / 2 ? mid : lrpad / 2; + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +} + +void +drawbars(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +enqueue(Client *c) +{ + Client *l; + for (l = c->mon->clients; l && l->next; l = l->next); + if (l) { + l->next = c; + c->next = NULL; + } +} + +void +enqueuestack(Client *c) +{ + Client *l; + for (l = c->mon->stack; l && l->snext; l = l->snext); + if (l) { + l->snext = c; + c->snext = NULL; + } +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) + drawbar(m); +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) + strncpy(text, (char *)name.value, size - 1); + else { + if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + } else { + c->mon = selmon; + applyrules(c); + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; + if (wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +monocle(Monitor *m) +{ + unsigned int n = 0; + Client *c; + + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ + else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + updatesizehints(c); + break; + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +} + +void +quit(const Arg *arg) +{ + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) + || &monocle == c->mon->lt[c->mon->sellt]->arrange) + && !c->isfullscreen && !c->isfloating + && NULL != c->mon->lt[c->mon->sellt]->arrange) { + c->w = wc.width += c->bw * 2; + c->h = wc.height += c->bw * 2; + wc.border_width = 0; + } + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + break; + } + } while (ev.type != ButtonRelease); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +void +restack(Monitor *m) +{ + Client *c; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +rotatestack(const Arg *arg) +{ + Client *c = NULL, *f; + + if (!selmon->sel) + return; + f = selmon->sel; + if (arg->i > 0) { + for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); + if (c){ + detach(c); + attach(c); + detachstack(c); + attachstack(c); + } + } else { + if ((c = nexttiled(selmon->clients))){ + detach(c); + enqueue(c); + detachstack(c); + enqueuestack(c); + } + } + if (c){ + arrange(selmon); + //unfocus(f, 1); + focus(f); + restack(selmon); + } +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + if (wins) + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +Layout *last_layout; +void +fullscreen(const Arg *arg) +{ + if (selmon->showbar) { + for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); + setlayout(&((Arg) { .v = &layouts[2] })); + } else { + setlayout(&((Arg) { .v = last_layout })); + } + togglebar(arg); +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + + /* clean up any zombies immediately */ + sigchld(0); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + updatebars(); + updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); +} + + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +sigchld(int unused) +{ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + while (0 < waitpid(-1, NULL, WNOHANG)); +} + +void +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} + +void +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, dirtomon(arg->i)); +} + +void +tile(Monitor *m) +{ + unsigned int i, n, h, mw, my, ty; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; + for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); + if (my + HEIGHT(c) < m->wh) + my += HEIGHT(c); + } else { + h = (m->wh - ty) / (n - i); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); + if (ty + HEIGHT(c) < m->wh) + ty += HEIGHT(c); + } +} + +void +togglebar(const Arg *arg) +{ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + arrange(selmon); +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + free(c); + focus(NULL); + updateclientlist(); + arrange(m); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +} + +void +updatebarpos(Monitor *m) +{ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + if (n <= nn) { /* new monitors available */ + for (i = 0; i < (nn - n); i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + } else { /* less monitors available nn < n */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); +} + +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + +void +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); +} + +void +updatewindowtype(Client *c) +{ + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + if (wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = 1; +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->barwin) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; + if (c == nexttiled(selmon->clients)) + if (!c || !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} diff --git a/myports/dwm/work/dwm-6.3/dwm.c.orig b/myports/dwm/work/dwm-6.3/dwm.c.orig new file mode 100644 index 0000000..6abafe0 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/dwm.c.orig @@ -0,0 +1,2181 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + int topbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + unsigned int tags; + int isfloating; + int monitor; +} Rule; + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void monocle(Monitor *m); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void fullscreen(const Arg *arg); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void sigchld(int unused); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void tile(Monitor *); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewindowtype(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static char stext[256]; +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh, blw = 0; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + unsigned int i, x, click; + Arg arg = {0}; + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; + + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; + size_t i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = blw = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + /* fix overflow when window name is bigger than window width */ + int mid = (m->ww - (int)TEXTW(m->sel->name)) / 2 - x; + /* make sure name will not overlap on tags even when it is very long */ + mid = mid >= lrpad / 2 ? mid : lrpad / 2; + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +} + +void +drawbars(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) + drawbar(m); +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) + strncpy(text, (char *)name.value, size - 1); + else { + if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + } else { + c->mon = selmon; + applyrules(c); + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; + if (wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +monocle(Monitor *m) +{ + unsigned int n = 0; + Client *c; + + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ + else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + updatesizehints(c); + break; + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +} + +void +quit(const Arg *arg) +{ + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) + || &monocle == c->mon->lt[c->mon->sellt]->arrange) + && !c->isfullscreen && !c->isfloating + && NULL != c->mon->lt[c->mon->sellt]->arrange) { + c->w = wc.width += c->bw * 2; + c->h = wc.height += c->bw * 2; + wc.border_width = 0; + } + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + break; + } + } while (ev.type != ButtonRelease); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +void +restack(Monitor *m) +{ + Client *c; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + if (wins) + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +Layout *last_layout; +void +fullscreen(const Arg *arg) +{ + if (selmon->showbar) { + for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); + setlayout(&((Arg) { .v = &layouts[2] })); + } else { + setlayout(&((Arg) { .v = last_layout })); + } + togglebar(arg); +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + + /* clean up any zombies immediately */ + sigchld(0); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + updatebars(); + updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); +} + + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +sigchld(int unused) +{ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + while (0 < waitpid(-1, NULL, WNOHANG)); +} + +void +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} + +void +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, dirtomon(arg->i)); +} + +void +tile(Monitor *m) +{ + unsigned int i, n, h, mw, my, ty; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; + for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); + if (my + HEIGHT(c) < m->wh) + my += HEIGHT(c); + } else { + h = (m->wh - ty) / (n - i); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); + if (ty + HEIGHT(c) < m->wh) + ty += HEIGHT(c); + } +} + +void +togglebar(const Arg *arg) +{ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + arrange(selmon); +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + free(c); + focus(NULL); + updateclientlist(); + arrange(m); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +} + +void +updatebarpos(Monitor *m) +{ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + if (n <= nn) { /* new monitors available */ + for (i = 0; i < (nn - n); i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + } else { /* less monitors available nn < n */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); +} + +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + +void +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); +} + +void +updatewindowtype(Client *c) +{ + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + if (wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = 1; +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->barwin) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; + if (c == nexttiled(selmon->clients)) + if (!c || !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} diff --git a/myports/dwm/work/dwm-6.3/dwm.o b/myports/dwm/work/dwm-6.3/dwm.o new file mode 100644 index 0000000000000000000000000000000000000000..7d6327f2f18cf33ff451654b5bb16362de8ec3b4 GIT binary patch literal 63152 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 literal 0 HcmV?d00001 diff --git a/myports/dwm/work/dwm-6.3/transient.c b/myports/dwm/work/dwm-6.3/transient.c new file mode 100644 index 0000000..040adb5 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/transient.c @@ -0,0 +1,42 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +int main(void) { + Display *d; + Window r, f, t = None; + XSizeHints h; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) + exit(1); + r = DefaultRootWindow(d); + + f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); + h.min_width = h.max_width = h.min_height = h.max_height = 400; + h.flags = PMinSize | PMaxSize; + XSetWMNormalHints(d, f, &h); + XStoreName(d, f, "floating"); + XMapWindow(d, f); + + XSelectInput(d, f, ExposureMask); + while (1) { + XNextEvent(d, &e); + + if (t == None) { + sleep(5); + t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); + XSetTransientForHint(d, t, f); + XStoreName(d, t, "transient"); + XMapWindow(d, t); + XSelectInput(d, t, ExposureMask); + } + } + + XCloseDisplay(d); + exit(0); +} diff --git a/myports/dwm/work/dwm-6.3/util.c b/myports/dwm/work/dwm-6.3/util.c new file mode 100644 index 0000000..fe044fc --- /dev/null +++ b/myports/dwm/work/dwm-6.3/util.c @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} + +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} diff --git a/myports/dwm/work/dwm-6.3/util.h b/myports/dwm/work/dwm-6.3/util.h new file mode 100644 index 0000000..f633b51 --- /dev/null +++ b/myports/dwm/work/dwm-6.3/util.h @@ -0,0 +1,8 @@ +/* See LICENSE file for copyright and license details. */ + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); diff --git a/myports/dwm/work/dwm-6.3/util.o b/myports/dwm/work/dwm-6.3/util.o new file mode 100644 index 0000000000000000000000000000000000000000..140da1a1ba893d8d88068f397eb09b1747cb3d1f GIT binary patch literal 2016 zcmbW0L2DC16vroNZKJJ{ibAO#)>})-nzREc?YK=Z{$b|5`Mo!9W@l#}Or$5n zq0m7h6e1T%NDdUM9oQWteK$$EAajO#U%uj)uGD#W_RR+RiMo$4Hcgj*e8jN#`%#?_ zZf*~(lp2i&*sE3OX4avbtwG0LLRY9mS9u5B{m*o5B?+0-D@CX`6{Q~SO?yc#?a_X^ z_EhsjsVH5WfKVzzUqxV*xW7`Eu3i8K*8Jq}qk5k30qSiv2lsj#qm@3oI)W)18gxES zG<@^DM@A0G$OfK=A2bcycFa*iCSAr-)8m?H8^xTqz}#})DQby?9@i6Ee=g6H(B><1 zy6F@~ZF`|`8oOA@b#610>k!lsIBqW1oD_@4a%YAu>+Fa%WDZ+w0G9N1OxV!UbrM>P zhE8;MM%H0N8t{`M=G(C&(Z}IShdZu7!dQ1l6k@&5k|O6lTA4#1wh6q)ECFdJzZ!c2 z0NO~n6$akEho1t1dkCrwpcS77eiZ7aA8)~JVz{{V&g9nfU{GlU>KQH)7m10RK~8=B-V5Q30*L6iJ7LQt^I zW)u7Q__$^MTZQ9ZCI29Ju+El}uh#jd@Q6}J6CCSclNuL}5q#oRpaBIxfj%$~+5hiIll(vm()p4rlu1YcsJjH_SUk$Cs2bvRQb9IkI4t+Y zgiujT%#-;tB(OgR8Qx)JaU3Wb5s6uap&Oi!>q@4kK5qqEEz|%2 literal 0 HcmV?d00001 diff --git a/myports/dwm/work/dwm.desktop b/myports/dwm/work/dwm.desktop new file mode 100644 index 0000000..a3aacf4 --- /dev/null +++ b/myports/dwm/work/dwm.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=dwm +Comment=Dynamic, small, fast and simple window manager +TryExec=dwm +Exec=dwm +Type=Application diff --git a/myports/dwm/work/stage/usr/local/bin/dwm b/myports/dwm/work/stage/usr/local/bin/dwm new file mode 100755 index 0000000000000000000000000000000000000000..6704ea39d73688612da5020d19ce56a693c2cc7c GIT binary patch literal 50296 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 AQUCw| literal 0 HcmV?d00001 diff --git a/myports/dwm/work/stage/usr/local/share/doc/dwm/README b/myports/dwm/work/stage/usr/local/share/doc/dwm/README new file mode 100644 index 0000000..95d4fd0 --- /dev/null +++ b/myports/dwm/work/stage/usr/local/share/doc/dwm/README @@ -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. diff --git a/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/LICENSE b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/LICENSE new file mode 100644 index 0000000..6657117 --- /dev/null +++ b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/LICENSE @@ -0,0 +1 @@ +This package has a single license: MIT (MIT license / X11 license). diff --git a/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/MIT b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/MIT new file mode 100644 index 0000000..d221f09 --- /dev/null +++ b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/MIT @@ -0,0 +1,37 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/catalog.mk b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/catalog.mk new file mode 100644 index 0000000..1268426 --- /dev/null +++ b/myports/dwm/work/stage/usr/local/share/licenses/dwm-6.3/catalog.mk @@ -0,0 +1,5 @@ +_LICENSE=MIT +_LICENSE_NAME=MIT license / X11 license +_LICENSE_PERMS=dist-mirror dist-sell pkg-mirror pkg-sell auto-accept +_LICENSE_GROUPS=COPYFREE FSF GPL OSI +_LICENSE_DISTFILES=dwm-6.3.tar.gz diff --git a/myports/dwm/work/stage/usr/local/share/man/man1/dwm.1.gz b/myports/dwm/work/stage/usr/local/share/man/man1/dwm.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..d5adf005d7d7da9df23c3c2ecd1db3d0206946d0 GIT binary patch literal 1868 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 G6953ow~tK# literal 0 HcmV?d00001 diff --git a/myports/dwm/work/stage/usr/local/share/xsessions/dwm.desktop b/myports/dwm/work/stage/usr/local/share/xsessions/dwm.desktop new file mode 100644 index 0000000..a3aacf4 --- /dev/null +++ b/myports/dwm/work/stage/usr/local/share/xsessions/dwm.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=dwm +Comment=Dynamic, small, fast and simple window manager +TryExec=dwm +Exec=dwm +Type=Application diff --git a/myports/sterm/Makefile b/myports/sterm/Makefile new file mode 100644 index 0000000..f064dc3 --- /dev/null +++ b/myports/sterm/Makefile @@ -0,0 +1,72 @@ +# Created by: Matthew Donovan + +PORTNAME= sterm +DISTVERSION= 0.8.5 +CATEGORIES= x11 +MASTER_SITES= http://dl.suckless.org/st/ +DISTNAME= st-${PORTVERSION} + +MAINTAINER= pkubaj@FreeBSD.org +COMMENT= Simple X terminal + +LICENSE= MIT +LICENSE_FILE= ${WRKSRC}/LICENSE + +LIB_DEPENDS= libfontconfig.so:x11-fonts/fontconfig \ + libfreetype.so:print/freetype2 + +ST_CONF= /home/loftur/suckless/st/config.h + +USES= pkgconfig xorg +USE_XORG= x11 xext xft + +PLIST_FILES= bin/st man/man1/st.1.gz + +# This way we avoid running tic on st.info which does not work as expected. +BINARY_ALIAS= tic=true + +PORTDATA= config.def.h st.info +PORTDOCS= FAQ LEGACY README TODO + +OPTIONS_DEFINE= DOCS SCROLLBACK XRESOURCES aa +SCROLLBACK_DESC= Scroll back through terminal output +XRESOURCES_DESC= Allow to handle settings from Xresources +ALPHA_DESC= Allow to handle transparency + +ALPHA_PATCH_SITES=https://st.suckless.org/patches/alpha/ +ALPHA_PATCHFILES=st-alpha-20220206-0.8.5.diff:-p1 + +SCROLLBACK_PATCH_SITES= https://st.suckless.org/patches/scrollback/ +SCROLLBACK_PATCHFILES= st-scrollback-20210507-4536f46.diff:-p1 \ + st-scrollback-mouse-20191024-a2c479c.diff:-p1 + +XRESOURCES_PATCH_SITES= https://st.suckless.org/patches/xresources/ +XRESOURCES_PATCHFILES= st-xresources-20200604-9ba7ecf.diff:-p1 + +pre-everything:: + @${ECHO_MSG} "You can build st with your own config.h using the ST_CONF knob:" + @${ECHO_MSG} "make ST_CONF=/path/to/st/config.h install clean" + +post-patch: +.if defined(ST_CONF) + @${ECHO_MSG} "creating config.h from ${ST_CONF}" + @${LN} -sf ${ST_CONF} ${WRKSRC}/config.h +.endif + @${REINPLACE_CMD} -e 's|^VERSION = .*|VERSION = ${PORTVERSION}|' \ + -e 's|^PREFIX = .*|PREFIX = ${PREFIX}|' \ + -e "s|^MANPREFIX = .*|MANPREFIX = ${MANPREFIX}/man|" \ + -e "s|^X11INC = .*|X11INC = ${LOCALBASE}/include|" \ + -e "s|^X11LIB = .*|X11LIB = ${LOCALBASE}/lib|" \ + -e "s|^CPPFLAGS =|CPPFLAGS +=|" \ + ${WRKSRC}/config.mk + +post-install: + @${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/st + @${MKDIR} ${STAGEDIR}${DATADIR} + cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDATA} ${STAGEDIR}${DATADIR} + +post-install-DOCS-on: + @${MKDIR} ${STAGEDIR}${DOCSDIR} + cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDOCS} ${STAGEDIR}${DOCSDIR} + +.include diff --git a/myports/sterm/Makefile.new b/myports/sterm/Makefile.new new file mode 100644 index 0000000..b1e25ce --- /dev/null +++ b/myports/sterm/Makefile.new @@ -0,0 +1,70 @@ +# Created by: Matthew Donovan + +PORTNAME= sterm +DISTVERSION= 0.8.5 +CATEGORIES= x11 +MASTER_SITES= http://dl.suckless.org/st/ +DISTNAME= st-${PORTVERSION} + +MAINTAINER= pkubaj@FreeBSD.org +COMMENT= Simple X terminal + +LICENSE= MIT +LICENSE_FILE= ${WRKSRC}/LICENSE + +LIB_DEPENDS= libfontconfig.so:x11-fonts/fontconfig \ + libfreetype.so:print/freetype2 + +USES= pkgconfig xorg +USE_XORG= x11 xext xft + +PLIST_FILES= bin/st man/man1/st.1.gz + +# This way we avoid running tic on st.info which does not work as expected. +BINARY_ALIAS= tic=true + +PORTDATA= config.def.h st.info +PORTDOCS= FAQ LEGACY README TODO + +OPTIONS_DEFINE= DOCS SCROLLBACK XRESOURCES ALPHA +SCROLLBACK_DESC= Scroll back through terminal output +XRESOURCES_DESC= Allow to handle settings from Xresources +ALPHA_DESC= Allow to handle transparency + +ALPHA_PATCH_SITES=https://st.suckless.org/patches/alpha/ +ALPHA_PATCHFILES=st-alpha-20220206-0.8.5.diff:-p1 + +SCROLLBACK_PATCH_SITES= https://st.suckless.org/patches/scrollback/ +SCROLLBACK_PATCHFILES= st-scrollback-20210507-4536f46.diff:-p1 \ + st-scrollback-mouse-20191024-a2c479c.diff:-p1 + +XRESOURCES_PATCH_SITES= https://st.suckless.org/patches/xresources/ +XRESOURCES_PATCHFILES= st-xresources-20200604-9ba7ecf.diff:-p1 + +pre-everything:: + @${ECHO_MSG} "You can build st with your own config.h using the ST_CONF knob:" + @${ECHO_MSG} "make ST_CONF=/path/to/st/config.h install clean" + +post-patch: +.if defined(ST_CONF) + @${ECHO_MSG} "creating config.h from ${ST_CONF}" + @${LN} -sf ${ST_CONF} ${WRKSRC}/config.h +.endif + @${REINPLACE_CMD} -e 's|^VERSION = .*|VERSION = ${PORTVERSION}|' \ + -e 's|^PREFIX = .*|PREFIX = ${PREFIX}|' \ + -e "s|^MANPREFIX = .*|MANPREFIX = ${MANPREFIX}/man|" \ + -e "s|^X11INC = .*|X11INC = ${LOCALBASE}/include|" \ + -e "s|^X11LIB = .*|X11LIB = ${LOCALBASE}/lib|" \ + -e "s|^CPPFLAGS =|CPPFLAGS +=|" \ + ${WRKSRC}/config.mk + +post-install: + @${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/st + @${MKDIR} ${STAGEDIR}${DATADIR} + cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDATA} ${STAGEDIR}${DATADIR} + +post-install-DOCS-on: + @${MKDIR} ${STAGEDIR}${DOCSDIR} + cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDOCS} ${STAGEDIR}${DOCSDIR} + +.include diff --git a/myports/sterm/distinfo b/myports/sterm/distinfo new file mode 100644 index 0000000..25f8105 --- /dev/null +++ b/myports/sterm/distinfo @@ -0,0 +1,11 @@ +IMESTAMP = 1641656444 +SHA256 (st-0.8.5.tar.gz) = ea6832203ed02ff74182bcb8adaa9ec454c8f989e79232cb859665e2f544ab37 +SIZE (st-0.8.5.tar.gz) = 47829 +SHA256 (st-scrollback-20210507-4536f46.diff) = 19d8f4e7fd0d1933dc6fcf6c7333db08e1b40fc75795464660c4d723eb62511c +SIZE (st-scrollback-20210507-4536f46.diff) = 8916 +SHA256 (st-scrollback-mouse-20191024-a2c479c.diff) = 319458d980195d18fa0f81a6898d58f8d046c5ff982ab872d741f54bb60e267d +SIZE (st-scrollback-mouse-20191024-a2c479c.diff) = 622 +SHA256 (st-xresources-20200604-9ba7ecf.diff) = 5be9b40d2b51761685f6503e92028a7858cc6571a8867b88612fce8a70514d5b +SIZE (st-xresources-20200604-9ba7ecf.diff) = 4840 +SHA256 (st-alpha-20220206-0.8.5.diff) = 42e4803ce2a67835f7e533a707a8a28e3804a26ced163145108970b9aee5fb81 +SIZE (alpha-20220206-0.8.5.diff) = 4339 diff --git a/myports/sterm/pkg-descr b/myports/sterm/pkg-descr new file mode 100644 index 0000000..0ab4ebb --- /dev/null +++ b/myports/sterm/pkg-descr @@ -0,0 +1,6 @@ +st is a minimalistic X terminal. + +It consists of a single binary, configuration is done at compile-time by a +config.h file. + +WWW: https://st.suckless.org/ diff --git a/myports/sterm/work/.PLIST.flattened b/myports/sterm/work/.PLIST.flattened new file mode 100644 index 0000000..ca727cd --- /dev/null +++ b/myports/sterm/work/.PLIST.flattened @@ -0,0 +1,11 @@ +/usr/local/bin/st +/usr/local/man/man1/st.1.gz +/usr/local/share/licenses/sterm-0.8.5/catalog.mk +/usr/local/share/licenses/sterm-0.8.5/LICENSE +/usr/local/share/licenses/sterm-0.8.5/MIT +/usr/local/share/doc/sterm/FAQ +/usr/local/share/doc/sterm/LEGACY +/usr/local/share/doc/sterm/README +/usr/local/share/doc/sterm/TODO +/usr/local/share/sterm/config.def.h +/usr/local/share/sterm/st.info diff --git a/myports/sterm/work/.PLIST.mktmp b/myports/sterm/work/.PLIST.mktmp new file mode 100644 index 0000000..dff57b8 --- /dev/null +++ b/myports/sterm/work/.PLIST.mktmp @@ -0,0 +1,11 @@ +bin/st +man/man1/st.1.gz +/usr/local/share/licenses/sterm-0.8.5/catalog.mk +/usr/local/share/licenses/sterm-0.8.5/LICENSE +/usr/local/share/licenses/sterm-0.8.5/MIT +/usr/local/share/doc/sterm/FAQ +/usr/local/share/doc/sterm/LEGACY +/usr/local/share/doc/sterm/README +/usr/local/share/doc/sterm/TODO +/usr/local/share/sterm/config.def.h +/usr/local/share/sterm/st.info diff --git a/myports/sterm/work/.PLIST.readelf b/myports/sterm/work/.PLIST.readelf new file mode 100644 index 0000000..388b5b1 --- /dev/null +++ b/myports/sterm/work/.PLIST.readelf @@ -0,0 +1,180 @@ + +File: /usr/local/bin/st + +Relocation section with addend (.rela.dyn): +r_offset r_info r_type st_value st_name + r_addend +000000218170 000500000012 R_X86_64_TPOFF64 0000000000000000 _ThreadRuneLocale + 0 +00000021e380 009600000005 R_X86_64_COPY 000000000021e380 _CurrentRuneLocale + 0 +00000021e3c0 009700000005 R_X86_64_COPY 000000000021e3c0 __isthreaded + 0 +00000021e388 009800000005 R_X86_64_COPY 000000000021e388 __mb_sb_limit + 0 +00000021e340 009900000005 R_X86_64_COPY 000000000021e340 __stack_chk_guard + 0 +00000021e338 009a00000005 R_X86_64_COPY 000000000021e338 __stderrp + 0 + +Relocation section with addend (.rela.plt): +r_offset r_info r_type st_value st_name + r_addend +0000002194f8 000200000007 R_X86_64_JUMP_SLOT 0000000000000000 atexit + 0 +000000219500 000100000007 R_X86_64_JUMP_SLOT 0000000000000000 _init_tls + 0 +000000219508 000300000007 R_X86_64_JUMP_SLOT 0000000000000000 exit + 0 +000000219510 000400000007 R_X86_64_JUMP_SLOT 0000000000000000 _Jv_RegisterClasses + 0 +000000219518 001800000007 R_X86_64_JUMP_SLOT 0000000000000000 malloc + 0 +000000219520 000700000007 R_X86_64_JUMP_SLOT 0000000000000000 __error + 0 +000000219528 002b00000007 R_X86_64_JUMP_SLOT 0000000000000000 strerror + 0 +000000219530 003100000007 R_X86_64_JUMP_SLOT 0000000000000000 vfprintf + 0 +000000219538 002300000007 R_X86_64_JUMP_SLOT 0000000000000000 realloc + 0 +000000219540 002a00000007 R_X86_64_JUMP_SLOT 0000000000000000 strdup + 0 +000000219548 002900000007 R_X86_64_JUMP_SLOT 0000000000000000 strcmp + 0 +000000219550 001d00000007 R_X86_64_JUMP_SLOT 0000000000000000 open + 0 +000000219558 001000000007 R_X86_64_JUMP_SLOT 0000000000000000 fprintf + 0 +000000219560 000d00000007 R_X86_64_JUMP_SLOT 0000000000000000 dup2 + 0 +000000219568 002c00000007 R_X86_64_JUMP_SLOT 0000000000000000 strlen + 0 +000000219570 001a00000007 R_X86_64_JUMP_SLOT 0000000000000000 memcpy + 0 +000000219578 002e00000007 R_X86_64_JUMP_SLOT 0000000000000000 system + 0 +000000219580 001f00000007 R_X86_64_JUMP_SLOT 0000000000000000 perror + 0 +000000219588 001e00000007 R_X86_64_JUMP_SLOT 0000000000000000 openpty + 0 +000000219590 000f00000007 R_X86_64_JUMP_SLOT 0000000000000000 fork + 0 +000000219598 000c00000007 R_X86_64_JUMP_SLOT 0000000000000000 close + 0 +0000002195a0 002600000007 R_X86_64_JUMP_SLOT 0000000000000000 signal + 0 +0000002195a8 000800000007 R_X86_64_JUMP_SLOT 0000000000000000 __stack_chk_fail + 0 +0000002195b0 002500000007 R_X86_64_JUMP_SLOT 0000000000000000 setsid + 0 +0000002195b8 001600000007 R_X86_64_JUMP_SLOT 0000000000000000 ioctl + 0 +0000002195c0 001500000007 R_X86_64_JUMP_SLOT 0000000000000000 getuid + 0 +0000002195c8 001400000007 R_X86_64_JUMP_SLOT 0000000000000000 getpwuid + 0 +0000002195d0 001300000007 R_X86_64_JUMP_SLOT 0000000000000000 getenv + 0 +0000002195d8 003000000007 R_X86_64_JUMP_SLOT 0000000000000000 unsetenv + 0 +0000002195e0 002400000007 R_X86_64_JUMP_SLOT 0000000000000000 setenv + 0 +0000002195e8 000e00000007 R_X86_64_JUMP_SLOT 0000000000000000 execvp + 0 +0000002195f0 000a00000007 R_X86_64_JUMP_SLOT 0000000000000000 _exit + 0 +0000002195f8 003200000007 R_X86_64_JUMP_SLOT 0000000000000000 waitpid + 0 +000000219600 002200000007 R_X86_64_JUMP_SLOT 0000000000000000 read + 0 +000000219608 001b00000007 R_X86_64_JUMP_SLOT 0000000000000000 memmove + 0 +000000219610 001900000007 R_X86_64_JUMP_SLOT 0000000000000000 memchr + 0 +000000219618 002000000007 R_X86_64_JUMP_SLOT 0000000000000000 pselect + 0 +000000219620 003400000007 R_X86_64_JUMP_SLOT 0000000000000000 write + 0 +000000219628 001700000007 R_X86_64_JUMP_SLOT 0000000000000000 kill + 0 +000000219630 001c00000007 R_X86_64_JUMP_SLOT 0000000000000000 memset + 0 +000000219638 001100000007 R_X86_64_JUMP_SLOT 0000000000000000 free + 0 +000000219640 002700000007 R_X86_64_JUMP_SLOT 0000000000000000 snprintf + 0 +000000219648 002f00000007 R_X86_64_JUMP_SLOT 0000000000000000 tcsendbreak + 0 +000000219650 003300000007 R_X86_64_JUMP_SLOT 0000000000000000 wcschr + 0 +000000219658 000600000007 R_X86_64_JUMP_SLOT 0000000000000000 ___runetype + 0 +000000219660 002d00000007 R_X86_64_JUMP_SLOT 0000000000000000 strtol + 0 +000000219668 002800000007 R_X86_64_JUMP_SLOT 0000000000000000 strchr + 0 +000000219670 001200000007 R_X86_64_JUMP_SLOT 0000000000000000 fwrite + 0 +000000219678 000b00000007 R_X86_64_JUMP_SLOT 0000000000000000 atoi + 0 +000000219680 002100000007 R_X86_64_JUMP_SLOT 0000000000000000 putc + 0 +000000219688 000900000007 R_X86_64_JUMP_SLOT 0000000000000000 __swbuf + 0 +000000219690 006200000007 R_X86_64_JUMP_SLOT 0000000000000000 XInternAtom + 0 +000000219698 007400000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetSelectionOwner + 0 +0000002196a0 005f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetSelectionOwner + 0 +0000002196a8 008200000007 R_X86_64_JUMP_SLOT 0000000000000000 XftColorFree + 0 +0000002196b0 008000000007 R_X86_64_JUMP_SLOT 0000000000000000 XftColorAllocName + 0 +0000002196b8 008100000007 R_X86_64_JUMP_SLOT 0000000000000000 XftColorAllocValue + 0 +0000002196c0 008700000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawRect + 0 +0000002196c8 008f00000007 R_X86_64_JUMP_SLOT 0000000000000000 Xutf8TextListToTextProperty + 0 +0000002196d0 007700000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMIconName + 0 +0000002196d8 007500000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetTextProperty + 0 +0000002196e0 005d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XFree + 0 +0000002196e8 007800000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMName + 0 +0000002196f0 007f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftCharIndex + 0 +0000002196f8 003d00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcFontSort + 0 +000000219700 004600000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternDuplicate + 0 +000000219708 003600000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetCreate + 0 +000000219710 003500000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetAddChar + 0 +000000219718 004100000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddCharSet + 0 +000000219720 004000000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddBool + 0 +000000219728 003800000007 R_X86_64_JUMP_SLOT 0000000000000000 FcConfigSubstitute + 0 +000000219730 003900000007 R_X86_64_JUMP_SLOT 0000000000000000 FcDefaultSubstitute + 0 +000000219738 003c00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcFontSetMatch + 0 +000000219740 008b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontOpenPattern + 0 +000000219748 004500000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternDestroy + 0 +000000219750 003700000007 R_X86_64_JUMP_SLOT 0000000000000000 FcCharSetDestroy + 0 +000000219758 008900000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawSetClipRectangles + 0 +000000219760 008600000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawGlyphFontSpec + 0 +000000219768 008800000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawSetClip + 0 +000000219770 004e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XCopyArea + 0 +000000219778 006f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetForeground + 0 +000000219780 007100000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetICValues + 0 +000000219788 004b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XChangeWindowAttributes + 0 +000000219790 006000000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWMHints + 0 +000000219798 007600000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMHints + 0 +0000002197a0 006900000007 R_X86_64_JUMP_SLOT 0000000000000000 XParseGeometry + 0 +0000002197a8 009300000007 R_X86_64_JUMP_SLOT 0000000000000000 setlocale + 0 +0000002197b0 007300000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetLocaleModifiers + 0 +0000002197b8 009000000007 R_X86_64_JUMP_SLOT 0000000000000000 abort + 0 +0000002197c0 009200000007 R_X86_64_JUMP_SLOT 0000000000000000 getpid + 0 +0000002197c8 006600000007 R_X86_64_JUMP_SLOT 0000000000000000 XOpenDisplay + 0 +0000002197d0 005600000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefaultScreen + 0 +0000002197d8 005700000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefaultVisual + 0 +0000002197e0 003e00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcInit + 0 +0000002197e8 005400000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefaultColormap + 0 +0000002197f0 006d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XRootWindow + 0 +0000002197f8 005500000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefaultDepth + 0 +000000219800 005300000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateWindow + 0 +000000219808 005000000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateGC + 0 +000000219810 005200000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreatePixmap + 0 +000000219818 005a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XFillRectangle + 0 +000000219820 008500000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawCreate + 0 +000000219828 006c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XRegisterIMInstantiateCallback + 0 +000000219830 004f00000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateFontCursor + 0 +000000219838 005800000007 R_X86_64_JUMP_SLOT 0000000000000000 XDefineCursor + 0 +000000219840 006800000007 R_X86_64_JUMP_SLOT 0000000000000000 XParseColor + 0 +000000219848 006b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XRecolorCursor + 0 +000000219850 007a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMProtocols + 0 +000000219858 004a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XChangeProperty + 0 +000000219860 006400000007 R_X86_64_JUMP_SLOT 0000000000000000 XMapWindow + 0 +000000219868 007b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSync + 0 +000000219870 009100000007 R_X86_64_JUMP_SLOT 0000000000000000 clock_gettime + 0 +000000219878 004c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XConnectionNumber + 0 +000000219880 006500000007 R_X86_64_JUMP_SLOT 0000000000000000 XNextEvent + 0 +000000219888 005b00000007 R_X86_64_JUMP_SLOT 0000000000000000 XFilterEvent + 0 +000000219890 005c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XFlush + 0 +000000219898 006a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XPending + 0 +0000002198a0 008d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftXlfdParse + 0 +0000002198a8 003f00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcNameParse + 0 +0000002198b0 004400000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternDel + 0 +0000002198b8 004200000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddDouble + 0 +0000002198c0 004700000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternGetDouble + 0 +0000002198c8 004300000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternAddInteger + 0 +0000002198d0 006700000007 R_X86_64_JUMP_SLOT 0000000000000000 XOpenIM + 0 +0000002198d8 007200000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetIMValues + 0 +0000002198e0 007e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XVaCreateNestedList + 0 +0000002198e8 005100000007 R_X86_64_JUMP_SLOT 0000000000000000 XCreateIC + 0 +0000002198f0 007c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XUnregisterIMInstantiateCallback + 0 +0000002198f8 004900000007 R_X86_64_JUMP_SLOT 0000000000000000 XAllocSizeHints + 0 +000000219900 007900000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetWMProperties + 0 +000000219908 008300000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDefaultSubstitute + 0 +000000219910 003a00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcFontMatch + 0 +000000219918 004800000007 R_X86_64_JUMP_SLOT 0000000000000000 FcPatternGetInteger + 0 +000000219920 008c00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftTextExtentsUtf8 + 0 +000000219928 005e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XFreePixmap + 0 +000000219930 008400000007 R_X86_64_JUMP_SLOT 0000000000000000 XftDrawChange + 0 +000000219938 008e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XmbLookupString + 0 +000000219940 006300000007 R_X86_64_JUMP_SLOT 0000000000000000 XLookupString + 0 +000000219948 007000000007 R_X86_64_JUMP_SLOT 0000000000000000 XSetICFocus + 0 +000000219950 007d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XUnsetICFocus + 0 +000000219958 006e00000007 R_X86_64_JUMP_SLOT 0000000000000000 XSendEvent + 0 +000000219960 005900000007 R_X86_64_JUMP_SLOT 0000000000000000 XDeleteProperty + 0 +000000219968 006100000007 R_X86_64_JUMP_SLOT 0000000000000000 XGetWindowProperty + 0 +000000219970 004d00000007 R_X86_64_JUMP_SLOT 0000000000000000 XConvertSelection + 0 +000000219978 008a00000007 R_X86_64_JUMP_SLOT 0000000000000000 XftFontClose + 0 +000000219980 003b00000007 R_X86_64_JUMP_SLOT 0000000000000000 FcFontSetDestroy + 0 + +File: /usr/local/man/man1/st.1.gz + +File: /usr/local/share/licenses/sterm-0.8.5/catalog.mk + +File: /usr/local/share/licenses/sterm-0.8.5/LICENSE + +File: /usr/local/share/licenses/sterm-0.8.5/MIT + +File: /usr/local/share/doc/sterm/FAQ + +File: /usr/local/share/doc/sterm/LEGACY + +File: /usr/local/share/doc/sterm/README + +File: /usr/local/share/doc/sterm/TODO + +File: /usr/local/share/sterm/config.def.h + +File: /usr/local/share/sterm/st.info diff --git a/myports/sterm/work/.PLIST.setuid b/myports/sterm/work/.PLIST.setuid new file mode 100644 index 0000000..e69de29 diff --git a/myports/sterm/work/.PLIST.writable b/myports/sterm/work/.PLIST.writable new file mode 100644 index 0000000..e69de29 diff --git a/myports/sterm/work/.bin/tic b/myports/sterm/work/.bin/tic new file mode 100755 index 0000000000000000000000000000000000000000..c97e27e4915027cd981a66ce41d3a5c4b19c1115 GIT binary patch literal 4952 zcmbVQZ){W76~A@@aZ9P)zoY|}*NIeQYF=Vk#h-1hT^xGNjGBgKL+vu-I4`z~W25Ki z2w2x5nN)ipdOUXsBCmK{c%a|?fTlDd)e5owF6saaiS=R$ zv@67Nu^8k=rE|tZLQ@^)X|JPa?sG)Z032~gX#9v*QzOhDP?8YLF()MCh+80yx(<&m zazy4L;K+!>p>7)I`7s~Egn*dW<8Y31l=$3g4b24eU6dGeH*UwB%3SQ&sHqO~kfRpe z#2JU>z<3%x5v@&A7R*Bwk2%+~=aMymb-CR<$&KhH+%+odwMHi%^ZQkFA((URp8*`^ z`M(n4@mHbeUZLmCT#`fP9Iqpr={I&8$&TzmyOAB#3wb?=rZ|7J!TD@94dcme5pnGE z`)Ya|V?A_hdJJE$$Fc7tT=w^V&%lGX(6`<~|6|Z=@N*O9eUEsswm$fIu2lMFF-Gf# z^+I^np9f})SZp5$PRm>zU%j^pZMc4DgG(Oy58wyXSOIg?z1Kbb`kPE4nOw$-TiJq0SjO&*C5+r~#?0r065?Bi<2^0q6nUS&0Os7}voi7}q# z4L`-Yp`XZoLOcqb*STkJkMQgcc$VMQeicI6i;k`mLY68X|J$;<|Gf3dzN;P9^z1)B z!13_=*hV*8F7%G$wETzdFT(b@V8ws<1dhCeO=-T#yd!vi9Bb=894`IN*IHZ|Eq4iN zcTGm@GxnF^YHvXKljW_G()L74A2owh^VswOco-488nds&>~E%j2p$%sIf!VVo!$c` zgPiXT^^m21G)uepoV1IRJWv0~C2$h9ubtetOcT>906dPH@(FBY+eB=1XOkTHO4=8r ze)*9+HQ!)8)fK!FK8e$tZGrlEZXA}Sc~8{8`D|>%oV9XGx$&}cRGRmipGEAy$#QX0 zmV3`tCudJj{}z0VH$%O{A7Is^ZD+QQ=9;#Sz})6)(W1exDA|r78Mlm?ijv<#8MlO)<0un>tjI01KG3YGE;>fSJr;@YBaS4*GU^;^ z)Km`xBkfSFvxj0gP5aROr04yX&rn~3rbd>~cr)=u#3SUNt`p)J(qFz_&0}|p@Vv)0 zlKn$uhl>(vxoT+-gFavDUZnXhrSStK&s81&$I1V7k}D)b{ZxFe6Txe2p7P-POKpHU zZ&REz#6KtgSK@R=YsqXPm(qp}vyjQ>v>==kdQe-P%2*-zrHlP~GC#C2n;jnNz@{C} zqZf>%rNf|xioBU>cR=l(?Wv!v9UNTu*x;Jv+CigD#4@>^hPhFT#UeGw9QHqB+kIq>%!J$dK_IpLq|A;~3+4|B8?S?_cCb zJ!|eGe-3_Vit|9?{q+#xcPOnB1NUIgpX)yWI;_hYvg3Vdp78GV!ZPzL;W>Z)9^&sL z-p9%PP4(aF!Uq;<%2Zvvq4zT-Ei{}zYxYA2bK&y=F9=Bd{rV^uUTGKZ|0If6p;M3N z{ryD>#OsgksVpptgDyOu2M2Bw{|6U-jP~;}!gtpqIUT%Z)YEGqVE#N!{@&*ATerQt zeurIn(WZe0h`y`;8~!Mm*2l-&4^n{e?s#tb&tQu+=KT5mZN5$XyMV=K&v-sR`TqhT zOb&?SGUs_sz*v3${C@}je+1hrCv|>UKJUWw{UuEoko9ax-0kmE(4&s?=kM4t!gHSN z#*P011~C6lHXzRUw_JKEhr-~{6#Q6+GE)y-u-x(8w)oz2?u, so it is mandatory that +applications which want to test against keypad keys send these +sequences. + +But buggy applications (like bash and irssi, for example) don't do this. A fast +solution for them is to use the following command: + + $ printf '\033[?1h\033=' >/dev/tty + +or + $ tput smkx + +In the case of bash, readline is used. Readline has a different note in its +manpage about this issue: + + enable-keypad (Off) + When set to On, readline will try to enable the + application keypad when it is called. Some systems + need this to enable arrow keys. + +Adding this option to your .inputrc will fix the keypad problem for all +applications using readline. + +If you are using zsh, then read the zsh FAQ +: + + It should be noted that the O / [ confusion can occur with other keys + such as Home and End. Some systems let you query the key sequences + sent by these keys from the system's terminal database, terminfo. + Unfortunately, the key sequences given there typically apply to the + mode that is not the one zsh uses by default (it's the "application" + mode rather than the "raw" mode). Explaining the use of terminfo is + outside of the scope of this FAQ, but if you wish to use the key + sequences given there you can tell the line editor to turn on + "application" mode when it starts and turn it off when it stops: + + function zle-line-init () { echoti smkx } + function zle-line-finish () { echoti rmkx } + zle -N zle-line-init + zle -N zle-line-finish + +Putting these lines into your .zshrc will fix the problems. + + +## How can I use meta in 8bit mode? + +St supports meta in 8bit mode, but the default terminfo entry doesn't +use this capability. If you want it, you have to use the 'st-meta' value +in TERM. + + +## I cannot compile st in OpenBSD + +OpenBSD lacks librt, despite it being mandatory in POSIX +. +If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and +st will compile without any loss of functionality, because all the functions are +included in libc on this platform. + + +## The Backspace Case + +St is emulating the Linux way of handling backspace being delete and delete being +backspace. + +This is an issue that was discussed in suckless mailing list +. Here is why some old grumpy +terminal users wants its backspace to be how he feels it: + + Well, I am going to comment why I want to change the behaviour + of this key. When ASCII was defined in 1968, communication + with computers was done using punched cards, or hardcopy + terminals (basically a typewriter machine connected with the + computer using a serial port). ASCII defines DELETE as 7F, + because, in punched-card terms, it means all the holes of the + card punched; it is thus a kind of 'physical delete'. In the + same way, the BACKSPACE key was a non-destructive backspace, + as on a typewriter. So, if you wanted to delete a character, + you had to BACKSPACE and then DELETE. Another use of BACKSPACE + was to type accented characters, for example 'a BACKSPACE `'. + The VT100 had no BACKSPACE key; it was generated using the + CONTROL key as another control character (CONTROL key sets to + 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code + 0x08)), but it had a DELETE key in a similar position where + the BACKSPACE key is located today on common PC keyboards. + All the terminal emulators emulated the difference between + these keys correctly: the backspace key generated a BACKSPACE + (^H) and delete key generated a DELETE (^?). + + But a problem arose when Linus Torvalds wrote Linux. Unlike + earlier terminals, the Linux virtual terminal (the terminal + emulator integrated in the kernel) returned a DELETE when + backspace was pressed, due to the VT100 having a DELETE key in + the same position. This created a lot of problems (see [1] + and [2]). Since Linux has become the king, a lot of terminal + emulators today generate a DELETE when the backspace key is + pressed in order to avoid problems with Linux. The result is + that the only way of generating a BACKSPACE on these systems + is by using CONTROL + H. (I also think that emacs had an + important point here because the CONTROL + H prefix is used + in emacs in some commands (help commands).) + + From point of view of the kernel, you can change the key + for deleting a previous character with stty erase. When you + connect a real terminal into a machine you describe the type + of terminal, so getty configures the correct value of stty + erase for this terminal. In the case of terminal emulators, + however, you don't have any getty that can set the correct + value of stty erase, so you always get the default value. + For this reason, it is necessary to add 'stty erase ^H' to your + profile if you have changed the value of the backspace key. + Of course, another solution is for st itself to modify the + value of stty erase. I usually have the inverse problem: + when I connect to non-Unix machines, I have to press CONTROL + + h to get a BACKSPACE. The inverse problem occurs when a user + connects to my Unix machines from a different system with a + correct backspace key. + + [1] http://www.ibb.net/~anne/keyboard.html + [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html + + +## But I really want the old grumpy behaviour of my terminal + +Apply [1]. + +[1] https://st.suckless.org/patches/delkey + + +## Why do images not work in st 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. diff --git a/myports/sterm/work/st-0.8.5/LEGACY b/myports/sterm/work/st-0.8.5/LEGACY new file mode 100644 index 0000000..bf28b1e --- /dev/null +++ b/myports/sterm/work/st-0.8.5/LEGACY @@ -0,0 +1,17 @@ +A STATEMENT ON LEGACY SUPPORT + +In the terminal world there is much cruft that comes from old and unsup‐ +ported terminals that inherit incompatible modes and escape sequences +which noone is able to know, except when he/she comes from that time and +developed a graphical vt100 emulator at that time. + +One goal of st is to only support what is really needed. When you en‐ +counter a sequence which you really need, implement it. But while you +are at it, do not add the other cruft you might encounter while sneek‐ +ing at other terminal emulators. History has bloated them and there is +no real evidence that most of the sequences are used today. + + +Christoph Lohmann <20h@r-36.net> +2012-09-13T07:00:36.081271045+02:00 + diff --git a/myports/sterm/work/st-0.8.5/LICENSE b/myports/sterm/work/st-0.8.5/LICENSE new file mode 100644 index 0000000..d80eb47 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/LICENSE @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2020 Hiltjo Posthuma +© 2018 Devin J. Pohly +© 2014-2017 Quentin Rameau +© 2009-2012 Aurélien APTEL +© 2008-2017 Anselm R Garbe +© 2012-2017 Roberto E. Vargas Caballero +© 2012-2016 Christoph Lohmann <20h at r-36 dot net> +© 2013 Eon S. Jeon +© 2013 Alexander Sedov +© 2013 Mark Edgar +© 2013-2014 Eric Pruitt +© 2013 Michael Forney +© 2013-2014 Markus Teich +© 2014-2015 Laslo Hunhold + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/myports/sterm/work/st-0.8.5/Makefile b/myports/sterm/work/st-0.8.5/Makefile new file mode 100644 index 0000000..470ac86 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/Makefile @@ -0,0 +1,57 @@ +# st - simple terminal +# See LICENSE file for copyright and license details. +.POSIX: + +include config.mk + +SRC = st.c x.c +OBJ = $(SRC:.c=.o) + +all: options st + +options: + @echo st build options: + @echo "CFLAGS = $(STCFLAGS)" + @echo "LDFLAGS = $(STLDFLAGS)" + @echo "CC = $(CC)" + +config.h: + cp config.def.h config.h + +.c.o: + $(CC) $(STCFLAGS) -c $< + +st.o: config.h st.h win.h +x.o: arg.h config.h st.h win.h + +$(OBJ): config.h config.mk + +st: $(OBJ) + $(CC) -o $@ $(OBJ) $(STLDFLAGS) + +clean: + rm -f st $(OBJ) st-$(VERSION).tar.gz + +dist: clean + mkdir -p st-$(VERSION) + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ + config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ + st-$(VERSION) + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz + rm -rf st-$(VERSION) + +install: st + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f st $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/st + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 + tic -sx st.info + @echo Please see the README file regarding the terminfo entry of st. + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + +.PHONY: all options clean dist install uninstall diff --git a/myports/sterm/work/st-0.8.5/README b/myports/sterm/work/st-0.8.5/README new file mode 100644 index 0000000..6a846ed --- /dev/null +++ b/myports/sterm/work/st-0.8.5/README @@ -0,0 +1,34 @@ +st - simple terminal +-------------------- +st is a simple terminal emulator for X which sucks less. + + +Requirements +------------ +In order to build st you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (st is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install st (if +necessary as root): + + make clean install + + +Running st +---------- +If you did not install st with make clean install, you must compile +the st terminfo entry with the following command: + + tic -sx st.info + +See the man page for additional details. + +Credits +------- +Based on Aurélien APTEL bt source code. + diff --git a/myports/sterm/work/st-0.8.5/TODO b/myports/sterm/work/st-0.8.5/TODO new file mode 100644 index 0000000..5f74cd5 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/TODO @@ -0,0 +1,28 @@ +vt emulation +------------ + +* double-height support + +code & interface +---------------- + +* add a simple way to do multiplexing + +drawing +------- +* add diacritics support to xdraws() + * switch to a suckless font drawing library +* make the font cache simpler +* add better support for brightening of the upper colors + +bugs +---- + +* fix shift up/down (shift selection in emacs) +* remove DEC test sequence when appropriate + +misc +---- + + $ grep -nE 'XXX|TODO' st.c + diff --git a/myports/sterm/work/st-0.8.5/arg.h b/myports/sterm/work/st-0.8.5/arg.h new file mode 100644 index 0000000..a22e019 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/arg.h @@ -0,0 +1,50 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + int i_;\ + for (i_ = 1, brk_ = 0, argv_ = argv;\ + argv[0][i_] && !brk_;\ + i_++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][i_];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/myports/sterm/work/st-0.8.5/config.def.h b/myports/sterm/work/st-0.8.5/config.def.h new file mode 100644 index 0000000..c217315 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/config.def.h @@ -0,0 +1,478 @@ +/* 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 */ + { ShiftMask, Button4, kscrollup, {.i = 1} }, + { ShiftMask, Button5, kscrolldown, {.i = 1} }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/myports/sterm/work/st-0.8.5/config.def.h.orig b/myports/sterm/work/st-0.8.5/config.def.h.orig new file mode 100644 index 0000000..e3b469b --- /dev/null +++ b/myports/sterm/work/st-0.8.5/config.def.h.orig @@ -0,0 +1,476 @@ +/* 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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/myports/sterm/work/st-0.8.5/config.h b/myports/sterm/work/st-0.8.5/config.h new file mode 100644 index 0000000..5937481 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/config.h @@ -0,0 +1,479 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Hack:style=Regular:pixelsize=16: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"} }, + { ShiftMask, Button4, kscrollup, {.i = 1} }, + { ShiftMask, Button5, kscrolldown, {.i = 1} }, +}; + +/* 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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/myports/sterm/work/st-0.8.5/config.mk b/myports/sterm/work/st-0.8.5/config.mk new file mode 100644 index 0000000..9a82cd3 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/config.mk @@ -0,0 +1,35 @@ +# st version +VERSION = 0.8.5 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = /usr/local/man + +X11INC = /usr/local/include +X11LIB = /usr/local/lib + +PKG_CONFIG = pkg-config + +# includes and libs +INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +# flags +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `$(PKG_CONFIG) --libs fontconfig` \ +# `$(PKG_CONFIG) --libs freetype2` + +# compiler and linker +# CC = c99 diff --git a/myports/sterm/work/st-0.8.5/config.mk.bak b/myports/sterm/work/st-0.8.5/config.mk.bak new file mode 100644 index 0000000..4c4c5d5 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/config.mk.bak @@ -0,0 +1,35 @@ +# st version +VERSION = 0.8.5 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +PKG_CONFIG = pkg-config + +# includes and libs +INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +# flags +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `$(PKG_CONFIG) --libs fontconfig` \ +# `$(PKG_CONFIG) --libs freetype2` + +# compiler and linker +# CC = c99 diff --git a/myports/sterm/work/st-0.8.5/st b/myports/sterm/work/st-0.8.5/st new file mode 100755 index 0000000000000000000000000000000000000000..578a6e2e920ca08bc15f5c417e0a63fbcee24ba6 GIT binary patch literal 116112 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

64SFxp_d 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 c7$_#VDzp|A7aH{xX}][{+-}{+-}]. See +.BR XParseGeometry (3) +for further details. +.TP +.B \-i +will fixate the position given with the -g option. +.TP +.BI \-n " name" +defines the window instance name (default $TERM). +.TP +.BI \-o " iofile" +writes all the I/O to +.I iofile. +This feature is useful when recording st sessions. A value of "-" means +standard output. +.TP +.BI \-T " title" +defines the window title (default 'st'). +.TP +.BI \-t " title" +defines the window title (default 'st'). +.TP +.BI \-w " windowid" +embeds st within the window identified by +.I windowid +.TP +.BI \-l " line" +use a tty +.I line +instead of a pseudo terminal. +.I line +should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port +0). +When this flag is given +remaining arguments are used as flags for +.BR stty(1). +By default st initializes the serial line to 8 bits, no parity, 1 stop bit +and a 38400 baud rate. The speed is set by appending it as last argument +(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are +.BR stty(1) +flags. If you want to set odd parity on 115200 baud use for example 'st -l +/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for +example 'st -l /dev/ttyS0 cs7 115200'. See +.BR stty(1) +for more arguments and cases. +.TP +.B \-v +prints version information to stderr, then exits. +.TP +.BI \-e " command " [ " arguments " "... ]" +st executes +.I command +instead of the shell. If this is used it +.B must be the last option +on the command line, as in xterm / rxvt. +This option is only intended for compatibility, +and all the remaining arguments are used as a command +even without it. +.SH SHORTCUTS +.TP +.B Break +Send a break in the serial line. +Break key is obtained in PC keyboards +pressing at the same time control and pause. +.TP +.B Ctrl-Print Screen +Toggle if st should print to the +.I iofile. +.TP +.B Shift-Print Screen +Print the full screen to the +.I iofile. +.TP +.B Print Screen +Print the selection to the +.I iofile. +.TP +.B Ctrl-Shift-Page Up +Increase font size. +.TP +.B Ctrl-Shift-Page Down +Decrease font size. +.TP +.B Ctrl-Shift-Home +Reset to default font size. +.TP +.B Ctrl-Shift-y +Paste from primary selection (middle mouse button). +.TP +.B Ctrl-Shift-c +Copy the selected text to the clipboard selection. +.TP +.B Ctrl-Shift-v +Paste from the clipboard selection. +.SH CUSTOMIZATION +.B st +can be customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH AUTHORS +See the LICENSE file for the authors. +.SH LICENSE +See the LICENSE file for the terms of redistribution. +.SH SEE ALSO +.BR tabbed (1), +.BR utmp (1), +.BR stty (1), +.BR scroll (1) +.SH BUGS +See the TODO file in the distribution. + diff --git a/myports/sterm/work/st-0.8.5/st.c b/myports/sterm/work/st-0.8.5/st.c new file mode 100644 index 0000000..f3af82b --- /dev/null +++ b/myports/sterm/work/st-0.8.5/st.c @@ -0,0 +1,2761 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "win.h" + +#if defined(__linux) + #include +#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) + #include +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include +#endif + +/* Arbitrary sizes */ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128*UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ +#define HISTSIZE 2000 + +/* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ + term.scr + HISTSIZE + 1) % HISTSIZE] : \ + term.line[(y) - term.scr]) + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, +}; + +enum cursor_movement { + CURSOR_SAVE, + CURSOR_LOAD +}; + +enum cursor_state { + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 +}; + +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + +enum escape_state { + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, +}; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + Line hist[HISTSIZE]; /* history buffer */ + int histi; /* history index */ + int scr; /* scroll back */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ +} Term; + +/* CSI Escape sequence structs */ +/* ESC '[' [[ [] [;]] []] */ +typedef struct { + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; +} CSIEscape; + +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + +static void execsh(char *, char **); +static void stty(char **); +static void sigchld(int); +static void ttywriteraw(const char *, size_t); + +static void csidump(void); +static void csihandle(void); +static void csiparse(void); +static void csireset(void); +static int eschandle(uchar); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); + +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int, int); +static void tscrolldown(int, int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, const int *, int); +static int twrite(const char *, int, int); +static void tfulldirt(void); +static void tcontrolcode(uchar ); +static void tdectest(char ); +static void tdefutf8(char); +static int32_t tdefcolor(const int *, int *, int); +static void tdeftran(char); +static void tstrsequence(uchar); + +static void drawregion(int, int, int, int); + +static void selnormalize(void); +static void selscroll(int, int); +static void selsnap(int *, int *, int); + +static size_t utf8decode(const char *, Rune *, size_t); +static Rune utf8decodebyte(char, size_t *); +static char utf8encodebyte(Rune, size_t); +static size_t utf8validate(Rune *, size_t); + +static char *base64dec(const char *); +static char base64dec_getc(const char **); + +static ssize_t xwrite(int, const char *, size_t); + +/* Globals */ +static Term term; +static Selection sel; +static CSIEscape csiescseq; +static STREscape strescseq; +static int iofd = 1; +static int cmdfd; +static pid_t pid; + +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +ssize_t +xwrite(int fd, const char *s, size_t len) +{ + size_t aux = len; + ssize_t r; + + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } + + return aux; +} + +void * +xmalloc(size_t len) +{ + void *p; + + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); + + return p; +} + +void * +xrealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + + return p; +} + +char * +xstrdup(const char *s) +{ + char *p; + + if ((p = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); + + return p; +} + +size_t +utf8decode(const char *c, Rune *u, size_t clen) +{ + size_t i, j, len, type; + Rune udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Rune +utf8decodebyte(char c, size_t *i) +{ + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; + + return 0; +} + +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +static const char base64_digits[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, + 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +char +base64dec_getc(const char **src) +{ + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char * +base64dec(const char *src) +{ + size_t in_len = strlen(src); + char *result, *dst; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; +} + +void +selinit(void) +{ + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} + +int +tlinelen(int y) +{ + int i = term.col; + + if (TLINE(y)[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && TLINE(y)[i - 1].u == ' ') + --i; + + return i; +} + +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type, int done) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + +void +selnormalize(void) +{ + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int +selected(int x, int y) +{ + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &TLINE(*y)[*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &TLINE(newy)[newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(TLINE(*y-1)[term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row-1; *y += direction) { + if (!(TLINE(*y)[term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } + break; + } +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &TLINE(y)[sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + last = &TLINE(y)[MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void +selclear(void) +{ + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +void +execsh(char *cmd, char **args) +{ + char *sh, *prog, *arg; + const struct passwd *pw; + + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); +} + +void +sigchld(int a) +{ + int stat; + pid_t p; + + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + + if (pid != p) + return; + + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); +} + +void +stty(char **args) +{ + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; + + if ((n = strlen(stty_args)) > sizeof(cmd)-1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz-1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); +} + +int +ttynew(const char *line, char *cmd, const char *out, char **args) +{ + int m, s; + + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + out, strerror(errno)); + } + } + + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", + line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + close(m); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + if (s > 2) + close(s); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; +} + +size_t +ttyread(void) +{ + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; + + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } +} + +void +ttywrite(const char *s, size_t n, int may_echo) +{ + const char *next; + Arg arg = (Arg) { .i = term.scr }; + + kscrolldown(&arg); + + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } +} + +void +ttywriteraw(const char *s, size_t n) +{ + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); + + /* Check if we can write. */ + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); +} + +void +ttyresize(int tw, int th) +{ + struct winsize w; + + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); +} + +void +ttyhangup() +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + +int +tattrset(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) + return 1; + } + } + + return 0; +} + +void +tsetdirt(int top, int bot) +{ + int i; + + LIMIT(top, 0, term.row-1); + LIMIT(bot, 0, term.row-1); + + for (i = top; i <= bot; i++) + term.dirty[i] = 1; +} + +void +tsetdirtattr(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) { + tsetdirt(i, i); + break; + } + } + } +} + +void +tfulldirt(void) +{ + tsetdirt(0, term.row-1); +} + +void +tcursor(int mode) +{ + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); + + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } +} + +void +treset(void) +{ + uint i; + + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP|MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); + tswapscreen(); + } +} + +void +tnew(int col, int row) +{ + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); +} + +void +tswapscreen(void) +{ + Line *tmp = term.line; + + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void +kscrolldown(const Arg* a) +{ + int n = a->i; + + if (n < 0) + n = term.row + n; + + if (n > term.scr) + n = term.scr; + + if (term.scr > 0) { + term.scr -= n; + selscroll(0, -n); + tfulldirt(); + } +} + +void +kscrollup(const Arg* a) +{ + int n = a->i; + + if (n < 0) + n = term.row + n; + + if (term.scr <= HISTSIZE-n) { + term.scr += n; + selscroll(0, n); + tfulldirt(); + } +} + +void +tscrolldown(int orig, int n, int copyhist) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + if (copyhist) { + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; + temp = term.hist[term.histi]; + term.hist[term.histi] = term.line[term.bot]; + term.line[term.bot] = temp; + } + + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); + + for (i = term.bot; i >= orig+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + if (term.scr == 0) + selscroll(orig, n); +} + +void +tscrollup(int orig, int n, int copyhist) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + if (copyhist) { + term.histi = (term.histi + 1) % HISTSIZE; + temp = term.hist[term.histi]; + term.hist[term.histi] = term.line[orig]; + term.line[orig] = temp; + } + + if (term.scr > 0 && term.scr < HISTSIZE) + term.scr = MIN(term.scr + n, HISTSIZE-1); + + tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig+n, term.bot); + + for (i = orig; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + if (term.scr == 0) + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) +{ + if (sel.ob.x == -1) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void +tnewline(int first_col) +{ + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + +void +csiparse(void) +{ + char *p = csiescseq.buf, *np; + long int v; + + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } + + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf+csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; +} + +/* for absolute user moves, when decom is set */ +void +tmoveato(int x, int y) +{ + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +} + +void +tmoveto(int x, int y) +{ + int miny, maxy; + + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); +} + +void +tsetchar(Rune u, const Glyph *attr, int x, int y) +{ + static const char *vt100_0[62] = { /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + + if (term.line[y][x].mode & ATTR_WIDE) { + if (x+1 < term.col) { + term.line[y][x+1].u = ' '; + term.line[y][x+1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x-1].u = ' '; + term.line[y][x-1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; +} + +void +tclearregion(int x1, int y1, int x2, int y2) +{ + int x, y, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.col-1); + LIMIT(x2, 0, term.col-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + } +} + +void +tdeletechar(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); +} + +void +tinsertblank(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +void +tinsertblankline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n, 0); +} + +void +tdeleteline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n, 0); +} + +int32_t +tdefcolor(const int *attr, int *npar, int l) +{ + int32_t idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } + + return idx; +} + +void +tsetattr(const int *attr, int l) +{ + int i; + int32_t idx; + + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, + "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } + } +} + +void +tsetscroll(int t, int b) +{ + int temp; + + LIMIT(t, 0, term.row-1); + LIMIT(b, 0, term.row-1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; +} + +void +tsetmode(int priv, int set, const int *args, int narg) +{ + int alt; const int *lim; + + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col-1, + term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} + +void +csihandle(void) +{ + char buf[40]; + int len; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y-csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); + if (term.c.y < term.row-1) { + tclearregion(0, term.c.y+1, term.col-1, + term.row-1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col-1, term.row-1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col-1, + term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col-1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0], 0); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0], 0); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0]-1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR – Device Status Report (cursor position) */ + if (csiescseq.arg[0] == 6) { + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buf, len, 0); + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } +} + +void +csidump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); +} + +void +csireset(void) +{ + memset(&csiescseq, 0, sizeof(csiescseq)); +} + +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +strhandle(void) +{ + char *p = NULL, *dec; + int j, narg, par; + + term.esc &= ~(ESC_STR_END|ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + redraw(); + return; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + redraw(); + return; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + redraw(); + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + + if (p && !strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + redraw(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); +} + +void +strparse(void) +{ + int c; + char *p = strescseq.buf; + + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; + + if (*p == '\0') + return; + + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } +} + +void +strdump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} + +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} + +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} + +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } +} + +void +toggleprinter(const Arg *arg) +{ + term.mode ^= MODE_PRINT; +} + +void +printscreen(const Arg *arg) +{ + tdump(); +} + +void +printsel(const Arg *arg) +{ + tdumpsel(); +} + +void +tdumpsel(void) +{ + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } +} + +void +tdumpline(int n) +{ + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +void +tdump(void) +{ + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); +} + +void +tputtab(int n) +{ + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } + term.c.x = LIMIT(x, 0, term.col-1); +} + +void +tdefutf8(char ascii) +{ + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; +} + +void +tdeftran(char ascii) +{ + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; + + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +void +tdectest(char c) +{ + int x, y; + + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) +{ + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; +} + +void +tcontrolcode(uchar ascii) +{ + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END|ESC_STR); +} + +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) +{ + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1, 1); + } else { + tmoveto(term.c.x, term.c.y-1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; + } + return 1; +} + +void +tputc(Rune u) +{ + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; + + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } + + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { + term.esc &= ~(ESC_START|ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (strescseq.len+len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } + +check_control_code: + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &term.line[term.c.y][term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + + if (term.c.x+width > term.col) { + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x+width < term.col) { + tmoveto(term.c.x+width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } +} + +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + +void +tresize(int col, int row) +{ + int i, j; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int *bp; + TCursor c; + + if (col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + for (i = 0; i < HISTSIZE; i++) { + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); + for (j = mincol; j < col; j++) { + term.hist[i][j] = term.c.attr; + term.hist[i][j].u = ' '; + } + } + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + term.alt[i] = xmalloc(col * sizeof(Glyph)); + } + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; +} + +void +resettitle(void) +{ + xsettitle(NULL); +} + +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(TLINE(y), x1, y, x2); + } +} + +void +draw(void) +{ + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + if (term.scr == 0) + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx]); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/myports/sterm/work/st-0.8.5/st.c.orig b/myports/sterm/work/st-0.8.5/st.c.orig new file mode 100644 index 0000000..51049ba --- /dev/null +++ b/myports/sterm/work/st-0.8.5/st.c.orig @@ -0,0 +1,2690 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "win.h" + +#if defined(__linux) + #include +#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) + #include +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include +#endif + +/* Arbitrary sizes */ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128*UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ + +/* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, +}; + +enum cursor_movement { + CURSOR_SAVE, + CURSOR_LOAD +}; + +enum cursor_state { + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 +}; + +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + +enum escape_state { + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, +}; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ +} Term; + +/* CSI Escape sequence structs */ +/* ESC '[' [[ [] [;]] []] */ +typedef struct { + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; +} CSIEscape; + +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + +static void execsh(char *, char **); +static void stty(char **); +static void sigchld(int); +static void ttywriteraw(const char *, size_t); + +static void csidump(void); +static void csihandle(void); +static void csiparse(void); +static void csireset(void); +static int eschandle(uchar); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); + +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int); +static void tscrolldown(int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, const int *, int); +static int twrite(const char *, int, int); +static void tfulldirt(void); +static void tcontrolcode(uchar ); +static void tdectest(char ); +static void tdefutf8(char); +static int32_t tdefcolor(const int *, int *, int); +static void tdeftran(char); +static void tstrsequence(uchar); + +static void drawregion(int, int, int, int); + +static void selnormalize(void); +static void selscroll(int, int); +static void selsnap(int *, int *, int); + +static size_t utf8decode(const char *, Rune *, size_t); +static Rune utf8decodebyte(char, size_t *); +static char utf8encodebyte(Rune, size_t); +static size_t utf8validate(Rune *, size_t); + +static char *base64dec(const char *); +static char base64dec_getc(const char **); + +static ssize_t xwrite(int, const char *, size_t); + +/* Globals */ +static Term term; +static Selection sel; +static CSIEscape csiescseq; +static STREscape strescseq; +static int iofd = 1; +static int cmdfd; +static pid_t pid; + +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +ssize_t +xwrite(int fd, const char *s, size_t len) +{ + size_t aux = len; + ssize_t r; + + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } + + return aux; +} + +void * +xmalloc(size_t len) +{ + void *p; + + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); + + return p; +} + +void * +xrealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + + return p; +} + +char * +xstrdup(const char *s) +{ + char *p; + + if ((p = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); + + return p; +} + +size_t +utf8decode(const char *c, Rune *u, size_t clen) +{ + size_t i, j, len, type; + Rune udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Rune +utf8decodebyte(char c, size_t *i) +{ + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; + + return 0; +} + +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +static const char base64_digits[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, + 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +char +base64dec_getc(const char **src) +{ + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char * +base64dec(const char *src) +{ + size_t in_len = strlen(src); + char *result, *dst; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; +} + +void +selinit(void) +{ + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} + +int +tlinelen(int y) +{ + int i = term.col; + + if (term.line[y][i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && term.line[y][i - 1].u == ' ') + --i; + + return i; +} + +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type, int done) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + +void +selnormalize(void) +{ + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int +selected(int x, int y) +{ + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &term.line[*y][*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(term.line[yt][xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &term.line[newy][newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(term.line[*y-1][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row-1; *y += direction) { + if (!(term.line[*y][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } + break; + } +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &term.line[y][sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + last = &term.line[y][MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void +selclear(void) +{ + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +void +execsh(char *cmd, char **args) +{ + char *sh, *prog, *arg; + const struct passwd *pw; + + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); +} + +void +sigchld(int a) +{ + int stat; + pid_t p; + + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + + if (pid != p) + return; + + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); +} + +void +stty(char **args) +{ + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; + + if ((n = strlen(stty_args)) > sizeof(cmd)-1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz-1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); +} + +int +ttynew(const char *line, char *cmd, const char *out, char **args) +{ + int m, s; + + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + out, strerror(errno)); + } + } + + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", + line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + close(m); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + if (s > 2) + close(s); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; +} + +size_t +ttyread(void) +{ + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; + + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } +} + +void +ttywrite(const char *s, size_t n, int may_echo) +{ + const char *next; + + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } +} + +void +ttywriteraw(const char *s, size_t n) +{ + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); + + /* Check if we can write. */ + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); +} + +void +ttyresize(int tw, int th) +{ + struct winsize w; + + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); +} + +void +ttyhangup() +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + +int +tattrset(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) + return 1; + } + } + + return 0; +} + +void +tsetdirt(int top, int bot) +{ + int i; + + LIMIT(top, 0, term.row-1); + LIMIT(bot, 0, term.row-1); + + for (i = top; i <= bot; i++) + term.dirty[i] = 1; +} + +void +tsetdirtattr(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) { + tsetdirt(i, i); + break; + } + } + } +} + +void +tfulldirt(void) +{ + tsetdirt(0, term.row-1); +} + +void +tcursor(int mode) +{ + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); + + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } +} + +void +treset(void) +{ + uint i; + + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP|MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); + tswapscreen(); + } +} + +void +tnew(int col, int row) +{ + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); +} + +void +tswapscreen(void) +{ + Line *tmp = term.line; + + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void +tscrolldown(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); + + for (i = term.bot; i >= orig+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + selscroll(orig, n); +} + +void +tscrollup(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig+n, term.bot); + + for (i = orig; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) +{ + if (sel.ob.x == -1) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void +tnewline(int first_col) +{ + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + +void +csiparse(void) +{ + char *p = csiescseq.buf, *np; + long int v; + + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } + + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf+csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; +} + +/* for absolute user moves, when decom is set */ +void +tmoveato(int x, int y) +{ + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +} + +void +tmoveto(int x, int y) +{ + int miny, maxy; + + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); +} + +void +tsetchar(Rune u, const Glyph *attr, int x, int y) +{ + static const char *vt100_0[62] = { /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + + if (term.line[y][x].mode & ATTR_WIDE) { + if (x+1 < term.col) { + term.line[y][x+1].u = ' '; + term.line[y][x+1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x-1].u = ' '; + term.line[y][x-1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; +} + +void +tclearregion(int x1, int y1, int x2, int y2) +{ + int x, y, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.col-1); + LIMIT(x2, 0, term.col-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + } +} + +void +tdeletechar(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); +} + +void +tinsertblank(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +void +tinsertblankline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); +} + +void +tdeleteline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); +} + +int32_t +tdefcolor(const int *attr, int *npar, int l) +{ + int32_t idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } + + return idx; +} + +void +tsetattr(const int *attr, int l) +{ + int i; + int32_t idx; + + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, + "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } + } +} + +void +tsetscroll(int t, int b) +{ + int temp; + + LIMIT(t, 0, term.row-1); + LIMIT(b, 0, term.row-1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; +} + +void +tsetmode(int priv, int set, const int *args, int narg) +{ + int alt; const int *lim; + + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col-1, + term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} + +void +csihandle(void) +{ + char buf[40]; + int len; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y-csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); + if (term.c.y < term.row-1) { + tclearregion(0, term.c.y+1, term.col-1, + term.row-1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col-1, term.row-1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col-1, + term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col-1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0]-1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR – Device Status Report (cursor position) */ + if (csiescseq.arg[0] == 6) { + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buf, len, 0); + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } +} + +void +csidump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); +} + +void +csireset(void) +{ + memset(&csiescseq, 0, sizeof(csiescseq)); +} + +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +strhandle(void) +{ + char *p = NULL, *dec; + int j, narg, par; + + term.esc &= ~(ESC_STR_END|ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + redraw(); + return; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + redraw(); + return; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + redraw(); + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + + if (p && !strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + redraw(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); +} + +void +strparse(void) +{ + int c; + char *p = strescseq.buf; + + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; + + if (*p == '\0') + return; + + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } +} + +void +strdump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} + +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} + +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} + +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } +} + +void +toggleprinter(const Arg *arg) +{ + term.mode ^= MODE_PRINT; +} + +void +printscreen(const Arg *arg) +{ + tdump(); +} + +void +printsel(const Arg *arg) +{ + tdumpsel(); +} + +void +tdumpsel(void) +{ + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } +} + +void +tdumpline(int n) +{ + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +void +tdump(void) +{ + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); +} + +void +tputtab(int n) +{ + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } + term.c.x = LIMIT(x, 0, term.col-1); +} + +void +tdefutf8(char ascii) +{ + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; +} + +void +tdeftran(char ascii) +{ + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; + + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +void +tdectest(char c) +{ + int x, y; + + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) +{ + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; +} + +void +tcontrolcode(uchar ascii) +{ + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END|ESC_STR); +} + +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) +{ + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y-1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; + } + return 1; +} + +void +tputc(Rune u) +{ + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; + + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } + + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { + term.esc &= ~(ESC_START|ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (strescseq.len+len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } + +check_control_code: + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &term.line[term.c.y][term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + + if (term.c.x+width > term.col) { + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x+width < term.col) { + tmoveto(term.c.x+width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } +} + +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + +void +tresize(int col, int row) +{ + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int *bp; + TCursor c; + + if (col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + term.alt[i] = xmalloc(col * sizeof(Glyph)); + } + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; +} + +void +resettitle(void) +{ + xsettitle(NULL); +} + +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(term.line[y], x1, y, x2); + } +} + +void +draw(void) +{ + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx]); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/myports/sterm/work/st-0.8.5/st.h b/myports/sterm/work/st-0.8.5/st.h new file mode 100644 index 0000000..da36b34 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/st.h @@ -0,0 +1,130 @@ +/* See LICENSE for license details. */ + +#include +#include + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ + (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +#define Glyph Glyph_ +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef union { + int i; + uint ui; + float f; + const void *v; + const char *s; +} Arg; + +void die(const char *, ...); +void redraw(void); +void draw(void); + +void kscrolldown(const Arg *); +void kscrollup(const Arg *); +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 *); + +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + +/* 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; diff --git a/myports/sterm/work/st-0.8.5/st.h.orig b/myports/sterm/work/st-0.8.5/st.h.orig new file mode 100644 index 0000000..519b9bd --- /dev/null +++ b/myports/sterm/work/st-0.8.5/st.h.orig @@ -0,0 +1,128 @@ +/* See LICENSE for license details. */ + +#include +#include + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ + (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +#define Glyph Glyph_ +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef union { + int i; + uint ui; + float f; + const void *v; + const char *s; +} Arg; + +void die(const char *, ...); +void redraw(void); +void draw(void); + +void printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + +int tattrset(int); +void tnew(int, int); +void tresize(int, int); +void tsetdirtattr(int); +void ttyhangup(void); +int ttynew(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 *); + +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + +/* 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; diff --git a/myports/sterm/work/st-0.8.5/st.info b/myports/sterm/work/st-0.8.5/st.info new file mode 100644 index 0000000..8201ad6 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/st.info @@ -0,0 +1,239 @@ +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, +# disabled rep for now: causes some issues with older ncurses versions. +# rep=%p1%c\E[%p2%{1}%-%db, +# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) + Tc, + Ms=\E]52;%p1%s;%p2%s\007, + Se=\E[2 q, + Ss=\E[%p1%d q, + +st| simpleterm, + use=st-mono, + colors#8, + setab=\E[4%p1%dm, + setaf=\E[3%p1%dm, + setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, + +st-256color| simpleterm with 256 colors, + use=st, + ccc, + colors#256, + oc=\E]104\007, + pairs#32767, +# Nicked from xterm-256color + initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, + +st-meta| simpleterm with meta key, + use=st, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-meta-256color| simpleterm with meta key and 256 colors, + use=st-256color, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-bs| simpleterm with backspace as backspace, + use=st, + kbs=\010, + kdch1=\177, + +st-bs-256color| simpleterm with backspace as backspace and 256colors, + use=st-256color, + kbs=\010, + kdch1=\177, diff --git a/myports/sterm/work/st-0.8.5/st.o b/myports/sterm/work/st-0.8.5/st.o new file mode 100644 index 0000000000000000000000000000000000000000..04adf38bcb81f006f4b4bb372be882ba680a8814 GIT binary patch literal 109488 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 literal 0 HcmV?d00001 diff --git a/myports/sterm/work/st-0.8.5/win.h b/myports/sterm/work/st-0.8.5/win.h new file mode 100644 index 0000000..e6e4369 --- /dev/null +++ b/myports/sterm/work/st-0.8.5/win.h @@ -0,0 +1,40 @@ +/* See LICENSE for license details. */ + +enum win_mode { + MODE_VISIBLE = 1 << 0, + MODE_FOCUSED = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_MOUSEBTN = 1 << 3, + MODE_MOUSEMOTION = 1 << 4, + MODE_REVERSE = 1 << 5, + MODE_KBDLOCK = 1 << 6, + MODE_HIDE = 1 << 7, + MODE_APPCURSOR = 1 << 8, + MODE_MOUSESGR = 1 << 9, + MODE_8BIT = 1 << 10, + MODE_BLINK = 1 << 11, + MODE_FBLINK = 1 << 12, + MODE_FOCUS = 1 << 13, + MODE_MOUSEX10 = 1 << 14, + MODE_MOUSEMANY = 1 << 15, + MODE_BRCKTPASTE = 1 << 16, + MODE_NUMLOCK = 1 << 17, + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ + |MODE_MOUSEMANY, +}; + +void xbell(void); +void xclipcopy(void); +void xdrawcursor(int, int, Glyph, int, int, Glyph); +void xdrawline(Line, int, int, int); +void xfinishdraw(void); +void xloadcols(void); +int xsetcolorname(int, const char *); +void xseticontitle(char *); +void xsettitle(char *); +int xsetcursor(int); +void xsetmode(int, unsigned int); +void xsetpointermotion(int); +void xsetsel(char *); +int xstartdraw(void); +void xximspot(int, int); diff --git a/myports/sterm/work/st-0.8.5/x.c b/myports/sterm/work/st-0.8.5/x.c new file mode 100644 index 0000000..8a16faa --- /dev/null +++ b/myports/sterm/work/st-0.8.5/x.c @@ -0,0 +1,2080 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *argv0; +#include "arg.h" +#include "st.h" +#include "win.h" + +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +typedef struct { + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ +} Key; + +/* X modifiers */ +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 +#define XK_SWITCH_MOD (1<<13|1<<14) + +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void numlock(const Arg *); +static void selpaste(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); +static void ttysend(const Arg *); + +/* config.h for applying patches and the configuration. */ +#include "config.h" + +/* XEMBED messages */ +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 + +/* macros */ +#define IS_SET(flag) ((win.mode & (flag)) != 0) +#define TRUERED(x) (((x) & 0xff0000) >> 8) +#define TRUEGREEN(x) (((x) & 0xff00)) +#define TRUEBLUE(x) (((x) & 0xff) << 8) + +typedef XftDraw *Draw; +typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; + +/* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ +} TermWindow; + +typedef struct { + Display *dpy; + Colormap cmap; + Window win; + Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; + Draw draw; + Visual *vis; + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ +} XWindow; + +typedef struct { + Atom xtarget; + char *primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; +} XSelection; + +/* Font structure */ +#define Font Font_ +typedef struct { + int height; + int width; + int ascent; + int descent; + int badslant; + int badweight; + short lbearing; + short rbearing; + XftFont *match; + FcFontSet *set; + FcPattern *pattern; +} Font; + +/* Drawing Context */ +typedef struct { + Color *col; + size_t collen; + Font font, bfont, ifont, ibfont; + GC gc; +} DC; + +static inline ushort sixd_to_16bit(int); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyph(Glyph, int, int); +static void xclear(int, int, int, int); +static int xgeommasktogravity(int); +static int ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); +static void xinit(int, int); +static void cresize(int, int); +static void xresize(int, int); +static void xhints(void); +static int xloadcolor(int, const char *, Color *); +static int xloadfont(Font *, FcPattern *); +static void xloadfonts(const char *, double); +static void xunloadfont(Font *); +static void xunloadfonts(void); +static void xsetenv(void); +static void xseturgency(int); +static int evcol(XEvent *); +static int evrow(XEvent *); + +static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); +static void kpress(XEvent *); +static void cmessage(XEvent *); +static void resize(XEvent *); +static void focus(XEvent *); +static uint buttonmask(uint); +static int mouseaction(XEvent *, uint); +static void brelease(XEvent *); +static void bpress(XEvent *); +static void bmotion(XEvent *); +static void propnotify(XEvent *); +static void selnotify(XEvent *); +static void selclear_(XEvent *); +static void selrequest(XEvent *); +static void setsel(char *, Time); +static void mousesel(XEvent *, int); +static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); + +static void run(void); +static void usage(void); + +static void (*handler[LASTEvent])(XEvent *) = { + [KeyPress] = kpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = resize, + [VisibilityNotify] = visibility, + [UnmapNotify] = unmap, + [Expose] = expose, + [FocusIn] = focus, + [FocusOut] = focus, + [MotionNotify] = bmotion, + [ButtonPress] = bpress, + [ButtonRelease] = brelease, +/* + * Uncomment if you want the selection to disappear when you select something + * different in another window. + */ +/* [SelectionClear] = selclear_, */ + [SelectionNotify] = selnotify, +/* + * PropertyNotify is only turned on when there is some INCR transfer happening + * for the selection retrieval. + */ + [PropertyNotify] = propnotify, + [SelectionRequest] = selrequest, +}; + +/* Globals */ +static DC dc; +static XWindow xw; +static XSelection xsel; +static TermWindow win; + +/* Font Ring Cache */ +enum { + FRC_NORMAL, + FRC_ITALIC, + FRC_BOLD, + FRC_ITALICBOLD +}; + +typedef struct { + XftFont *font; + int flags; + Rune unicodep; +} Fontcache; + +/* Fontcache is an array now. A new font will be appended to the array. */ +static Fontcache *frc = NULL; +static int frclen = 0; +static int frccap = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; + +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + +static int oldbutton = 3; /* button event on startup: 3 = release */ + +void +clipcopy(const Arg *dummy) +{ + Atom clipboard; + + free(xsel.clipboard); + xsel.clipboard = NULL; + + if (xsel.primary != NULL) { + xsel.clipboard = xstrdup(xsel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } +} + +void +clippaste(const Arg *dummy) +{ + Atom clipboard; + + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, + xw.win, CurrentTime); +} + +void +selpaste(const Arg *dummy) +{ + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, + xw.win, CurrentTime); +} + +void +numlock(const Arg *dummy) +{ + win.mode ^= MODE_NUMLOCK; +} + +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + +int +evcol(XEvent *e) +{ + int x = e->xbutton.x - borderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; +} + +int +evrow(XEvent *e) +{ + int y = e->xbutton.y - borderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; +} + +void +mousesel(XEvent *e, int done) +{ + int type, seltype = SEL_REGULAR; + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + + for (type = 1; type < LEN(selmasks); ++type) { + if (match(selmasks[type], state)) { + seltype = type; + break; + } + } + selextend(evcol(e), evrow(e), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); +} + +void +mousereport(XEvent *e) +{ + int len, x = evcol(e), y = evrow(e), + button = e->xbutton.button, state = e->xbutton.state; + char buf[40]; + static int ox, oy; + + /* from urxvt */ + if (e->xbutton.type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MOUSE_MOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + return; + + button = oldbutton + 32; + ox = x; + oy = y; + } else { + if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { + button = 3; + } else { + button -= Button1; + if (button >= 7) + button += 128 - 7; + else if (button >= 3) + button += 64 - 3; + } + if (e->xbutton.type == ButtonPress) { + oldbutton = button; + ox = x; + oy = y; + } else if (e->xbutton.type == ButtonRelease) { + oldbutton = 3; + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + if (button == 64 || button == 65) + return; + } + } + + if (!IS_SET(MODE_MOUSEX10)) { + button += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + button, x+1, y+1, + e->xbutton.type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+button, 32+x+1, 32+y+1); + } else { + return; + } + + ttywrite(buf, len, 0); +} + +uint +buttonmask(uint button) +{ + return button == Button1 ? Button1Mask + : button == Button2 ? Button2Mask + : button == Button3 ? Button3Mask + : button == Button4 ? Button4Mask + : button == Button5 ? Button5Mask + : 0; +} + +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + + /* ignore Buttonmask for Button - it's set on release */ + uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (match(ms->mod, state) || /* exact or forced */ + match(ms->mod, state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + +void +bpress(XEvent *e) +{ + struct timespec now; + int snap; + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 0)) + return; + + if (e->xbutton.button == Button1) { + /* + * If the user clicks below predefined timeouts specific + * snapping behaviour is exposed. + */ + clock_gettime(CLOCK_MONOTONIC, &now); + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { + snap = SNAP_LINE; + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { + snap = SNAP_WORD; + } else { + snap = 0; + } + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; + + selstart(evcol(e), evrow(e), snap); + } +} + +void +propnotify(XEvent *e) +{ + XPropertyEvent *xpev; + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + + xpev = &e->xproperty; + if (xpev->state == PropertyNewValue && + (xpev->atom == XA_PRIMARY || + xpev->atom == clipboard)) { + selnotify(e); + } +} + +void +selnotify(XEvent *e) +{ + ulong nitems, ofs, rem; + int format; + uchar *data, *last, *repl; + Atom type, incratom, property = None; + + incratom = XInternAtom(xw.dpy, "INCR", 0); + + ofs = 0; + if (e->type == SelectionNotify) + property = e->xselection.property; + else if (e->type == PropertyNotify) + property = e->xproperty.atom; + + if (property == None) + return; + + do { + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, + BUFSIZ/4, False, AnyPropertyType, + &type, &format, &nitems, &rem, + &data)) { + fprintf(stderr, "Clipboard allocation failed\n"); + return; + } + + if (e->type == PropertyNotify && nitems == 0 && rem == 0) { + /* + * If there is some PropertyNotify with no data, then + * this is the signal of the selection owner that all + * data has been transferred. We won't need to receive + * PropertyNotify events anymore. + */ + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + } + + if (type == incratom) { + /* + * Activate the PropertyNotify events so we receive + * when the selection owner does send us the next + * chunk of data. + */ + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + + /* + * Deleting the property is the transfer start signal. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); + continue; + } + + /* + * As seen in getsel: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while ((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) + ttywrite("\033[201~", 6, 0); + XFree(data); + /* number of 32-bit chunks returned */ + ofs += nitems * format / 32; + } while (rem > 0); + + /* + * Deleting the property again tells the selection owner to send the + * next data chunk in the property. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); +} + +void +xclipcopy(void) +{ + clipcopy(NULL); +} + +void +selclear_(XEvent *e) +{ + selclear(); +} + +void +selrequest(XEvent *e) +{ + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + Atom xa_targets, string, clipboard; + char *seltext; + + xsre = (XSelectionRequestEvent *) e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + if (xsre->property == None) + xsre->property = xsre->target; + + /* reject */ + xev.property = None; + + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); + if (xsre->target == xa_targets) { + /* respond with the supported type */ + string = xsel.xtarget; + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + XA_ATOM, 32, PropModeReplace, + (uchar *) &string, 1); + xev.property = xsre->property; + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if (xsre->selection == XA_PRIMARY) { + seltext = xsel.primary; + } else if (xsre->selection == clipboard) { + seltext = xsel.clipboard; + } else { + fprintf(stderr, + "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if (seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, + xsre->property, xsre->target, + 8, PropModeReplace, + (uchar *)seltext, strlen(seltext)); + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) + fprintf(stderr, "Error sending SelectionNotify event\n"); +} + +void +setsel(char *str, Time t) +{ + if (!str) + return; + + free(xsel.primary); + xsel.primary = str; + + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + selclear(); +} + +void +xsetsel(char *str) +{ + setsel(str, CurrentTime); +} + +void +brelease(XEvent *e) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 1)) + return; + if (e->xbutton.button == Button1) + mousesel(e, 1); +} + +void +bmotion(XEvent *e) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + mousesel(e, 0); +} + +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + col = MAX(1, col); + row = MAX(1, row); + + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +} + +void +xresize(int col, int row) +{ + win.tw = col * win.cw; + win.th = row * win.ch; + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); +} + +ushort +sixd_to_16bit(int x) +{ + return x == 0 ? 0 : 0x3737 + 0x2828 * x; +} + +int +xloadcolor(int i, const char *name, Color *ncolor) +{ + XRenderColor color = { .alpha = 0xffff }; + + if (!name) { + if (BETWEEN(i, 16, 255)) { /* 256 color */ + if (i < 6*6*6+16) { /* same colors as xterm */ + color.red = sixd_to_16bit( ((i-16)/36)%6 ); + color.green = sixd_to_16bit( ((i-16)/6) %6 ); + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); + } else { /* greyscale */ + color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); + color.green = color.blue = color.red; + } + return XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, ncolor); + } else + name = colorname[i]; + } + + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); +} + +void +xloadcols(void) +{ + int i; + static int loaded; + Color *cp; + + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); + } + + for (i = 0; i < dc.collen; i++) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } + loaded = 1; +} + +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + +int +xsetcolorname(int x, const char *name) +{ + Color ncolor; + + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + if (!xloadcolor(x, name, &ncolor)) + return 1; + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + + return 0; +} + +/* + * Absolute coordinates. + */ +void +xclear(int x1, int y1, int x2, int y2) +{ + XftDrawRect(xw.draw, + &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], + x1, y1, x2-x1, y2-y1); +} + +void +xhints(void) +{ + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints *sizeh; + + sizeh = XAllocSizeHints(); + + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; + sizeh->height_inc = win.ch; + sizeh->width_inc = win.cw; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; + sizeh->min_width = win.cw + 2 * borderpx; + if (xw.isfixed) { + sizeh->flags |= PMaxSize; + sizeh->min_width = sizeh->max_width = win.w; + sizeh->min_height = sizeh->max_height = win.h; + } + if (xw.gm & (XValue|YValue)) { + sizeh->flags |= USPosition | PWinGravity; + sizeh->x = xw.l; + sizeh->y = xw.t; + sizeh->win_gravity = xgeommasktogravity(xw.gm); + } + + XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, + &class); + XFree(sizeh); +} + +int +xgeommasktogravity(int mask) +{ + switch (mask & (XNegative|YNegative)) { + case 0: + return NorthWestGravity; + case XNegative: + return NorthEastGravity; + case YNegative: + return SouthWestGravity; + } + + return SouthEastGravity; +} + +int +xloadfont(Font *f, FcPattern *pattern) +{ + FcPattern *configured; + FcPattern *match; + FcResult result; + XGlyphInfo extents; + int wantattr, haveattr; + + /* + * Manually configure instead of calling XftMatchFont + * so that we can use the configured pattern for + * "missing glyph" lookups. + */ + configured = FcPatternDuplicate(pattern); + if (!configured) + return 1; + + FcConfigSubstitute(NULL, configured, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, configured); + + match = FcFontMatch(NULL, configured, &result); + if (!match) { + FcPatternDestroy(configured); + return 1; + } + + if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(configured); + FcPatternDestroy(match); + return 1; + } + + if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == + XftResultMatch)) { + /* + * Check if xft was unable to find a font with the appropriate + * slant but gave us one anyway. Try to mitigate. + */ + if ((XftPatternGetInteger(f->match->pattern, "slant", 0, + &haveattr) != XftResultMatch) || haveattr < wantattr) { + f->badslant = 1; + fputs("font slant does not match\n", stderr); + } + } + + if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == + XftResultMatch)) { + if ((XftPatternGetInteger(f->match->pattern, "weight", 0, + &haveattr) != XftResultMatch) || haveattr != wantattr) { + f->badweight = 1; + fputs("font weight does not match\n", stderr); + } + } + + XftTextExtentsUtf8(xw.dpy, f->match, + (const FcChar8 *) ascii_printable, + strlen(ascii_printable), &extents); + + f->set = NULL; + f->pattern = configured; + + f->ascent = f->match->ascent; + f->descent = f->match->descent; + f->lbearing = 0; + f->rbearing = f->match->max_advance_width; + + f->height = f->ascent + f->descent; + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); + + return 0; +} + +void +xloadfonts(const char *fontstr, double fontsize) +{ + FcPattern *pattern; + double fontval; + + if (fontstr[0] == '-') + pattern = XftXlfdParse(fontstr, False, False); + else + pattern = FcNameParse((const FcChar8 *)fontstr); + + if (!pattern) + die("can't open font %s\n", fontstr); + + if (fontsize > 1) { + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); + usedfontsize = fontsize; + } else { + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = fontval; + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = -1; + } else { + /* + * Default font size is 12, if none given. This is to + * have a known usedfontsize value. + */ + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); + usedfontsize = 12; + } + defaultfontsize = usedfontsize; + } + + if (xloadfont(&dc.font, pattern)) + die("can't open font %s\n", fontstr); + + if (usedfontsize < 0) { + FcPatternGetDouble(dc.font.match->pattern, + FC_PIXEL_SIZE, 0, &fontval); + usedfontsize = fontval; + if (fontsize == 0) + defaultfontsize = fontval; + } + + /* Setting character width and height. */ + win.cw = ceilf(dc.font.width * cwscale); + win.ch = ceilf(dc.font.height * chscale); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadfont(&dc.ifont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadfont(&dc.ibfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadfont(&dc.bfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDestroy(pattern); +} + +void +xunloadfont(Font *f) +{ + XftFontClose(xw.dpy, f->match); + FcPatternDestroy(f->pattern); + if (f->set) + FcFontSetDestroy(f->set); +} + +void +xunloadfonts(void) +{ + /* Free the loaded fonts in the font cache. */ + while (frclen > 0) + XftFontClose(xw.dpy, frc[--frclen].font); + + xunloadfont(&dc.font); + xunloadfont(&dc.bfont); + xunloadfont(&dc.ifont); + xunloadfont(&dc.ibfont); +} + +int +ximopen(Display *dpy) +{ + XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; + XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; + + xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if (xw.ime.xim == NULL) + return 0; + + if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) + fprintf(stderr, "XSetIMValues: " + "Could not set XNDestroyCallback.\n"); + + xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, + NULL); + + if (xw.ime.xic == NULL) { + xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, + XNDestroyCallback, &icdestroy, + NULL); + } + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); + + return 1; +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.ime.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + XFree(xw.ime.spotlist); +} + +int +xicdestroy(XIC xim, XPointer client, XPointer call) +{ + xw.ime.xic = NULL; + return 1; +} + +void +xinit(int cols, int rows) +{ + XGCValues gcvalues; + Cursor cursor; + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); + xw.vis = XDefaultVisual(xw.dpy, xw.scr); + + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); + + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + + /* colors */ + xw.cmap = XDefaultColormap(xw.dpy, xw.scr); + xloadcols(); + + /* adjust fixed window geometry */ + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; + + /* Events */ + xw.attrs.background_pixel = dc.col[defaultbg].pixel; + xw.attrs.border_pixel = dc.col[defaultbg].pixel; + xw.attrs.bit_gravity = NorthWestGravity; + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; + + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, + win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, + &gcvalues); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + + /* font spec buffer */ + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + + /* Xft rendering context */ + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + + /* input methods */ + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } + + /* white cursor, black outline */ + cursor = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, cursor); + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { + xmousefg.red = 0xffff; + xmousefg.green = 0xffff; + xmousefg.blue = 0xffff; + } + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { + xmousebg.red = 0x0000; + xmousebg.green = 0x0000; + xmousebg.blue = 0x0000; + } + + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); + + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&thispid, 1); + + win.mode = MODE_NUMLOCK; + resettitle(); + xhints(); + XMapWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); + + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); + if (xsel.xtarget == None) + xsel.xtarget = XA_STRING; +} + +int +xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +{ + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; + float runewidth = win.cw; + Rune rune; + FT_UInt glyphidx; + FcResult fcres; + FcPattern *fcpattern, *fontpattern; + FcFontSet *fcsets[] = { NULL }; + FcCharSet *fccharset; + int i, f, numspecs = 0; + + for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + /* Fetch rune and mode for current glyph. */ + rune = glyphs[i].u; + mode = glyphs[i].mode; + + /* Skip dummy wide-character spacing. */ + if (mode == ATTR_WDUMMY) + continue; + + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + font = &dc.font; + frcflags = FRC_NORMAL; + runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { + font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } else if (mode & ATTR_ITALIC) { + font = &dc.ifont; + frcflags = FRC_ITALIC; + } else if (mode & ATTR_BOLD) { + font = &dc.bfont; + frcflags = FRC_BOLD; + } + yp = winy + font->ascent; + } + + /* Lookup character index with default font. */ + glyphidx = XftCharIndex(xw.dpy, font->match, rune); + if (glyphidx) { + specs[numspecs].font = font->match; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + continue; + } + + /* Fallback on font cache, search the font cache for match. */ + for (f = 0; f < frclen; f++) { + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); + /* Everything correct. */ + if (glyphidx && frc[f].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if (!glyphidx && frc[f].flags == frcflags + && frc[f].unicodep == rune) { + break; + } + } + + /* Nothing was found. Use fontconfig to find matching font. */ + if (f >= frclen) { + if (!font->set) + font->set = FcFontSort(0, font->pattern, + 1, 0, &fcres); + fcsets[0] = font->set; + + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + * + * Xft and fontconfig are design failures. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, rune); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); + + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); + + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + frc[frclen].font = XftFontOpenPattern(xw.dpy, + fontpattern); + if (!frc[frclen].font) + die("XftFontOpenPattern failed seeking fallback font: %s\n", + strerror(errno)); + frc[frclen].flags = frcflags; + frc[frclen].unicodep = rune; + + glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); + + f = frclen; + frclen++; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + } + + specs[numspecs].font = frc[f].font; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + } + + return numspecs; +} + +void +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) +{ + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; + XRectangle r; + + /* Fallback on color display for attributes not supported by the font */ + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { + if (dc.ibfont.badslant || dc.ibfont.badweight) + base.fg = defaultattr; + } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || + (base.mode & ATTR_BOLD && dc.bfont.badweight)) { + base.fg = defaultattr; + } + + if (IS_TRUECOL(base.fg)) { + colfg.alpha = 0xffff; + colfg.red = TRUERED(base.fg); + colfg.green = TRUEGREEN(base.fg); + colfg.blue = TRUEBLUE(base.fg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); + fg = &truefg; + } else { + fg = &dc.col[base.fg]; + } + + if (IS_TRUECOL(base.bg)) { + colbg.alpha = 0xffff; + colbg.green = TRUEGREEN(base.bg); + colbg.red = TRUERED(base.bg); + colbg.blue = TRUEBLUE(base.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); + bg = &truebg; + } else { + bg = &dc.col[base.bg]; + } + + /* Change basic system colors [0-7] to bright system colors [8-15] */ + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) + fg = &dc.col[base.fg + 8]; + + if (IS_SET(MODE_REVERSE)) { + if (fg == &dc.col[defaultfg]) { + fg = &dc.col[defaultbg]; + } else { + colfg.red = ~fg->color.red; + colfg.green = ~fg->color.green; + colfg.blue = ~fg->color.blue; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, + &revfg); + fg = &revfg; + } + + if (bg == &dc.col[defaultbg]) { + bg = &dc.col[defaultfg]; + } else { + colbg.red = ~bg->color.red; + colbg.green = ~bg->color.green; + colbg.blue = ~bg->color.blue; + colbg.alpha = bg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, + &revbg); + bg = &revbg; + } + } + + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + + if (base.mode & ATTR_REVERSE) { + temp = fg; + fg = bg; + bg = temp; + } + + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) + fg = bg; + + if (base.mode & ATTR_INVISIBLE) + fg = bg; + + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0)? 0 : winy, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + + /* Set the clip region because Xft is sometimes dirty. */ + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, + width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, + width, 1); + } + + /* Reset clip to none. */ + XftDrawSetClip(xw.draw, 0); +} + +void +xdrawglyph(Glyph g, int x, int y) +{ + int numspecs; + XftGlyphFontSpec spec; + + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y); +} + +void +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +{ + Color drawcol; + + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + xdrawglyph(og, ox, oy); + + if (IS_SET(MODE_HIDE)) + return; + + /* + * Select the right color for the right mode. + */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; + + if (IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.bg = defaultfg; + if (selected(cx, cy)) { + drawcol = dc.col[defaultcs]; + g.fg = defaultrcs; + } else { + drawcol = dc.col[defaultrcs]; + g.fg = defaultcs; + } + } else { + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; + } else { + g.fg = defaultbg; + g.bg = defaultcs; + } + drawcol = dc.col[g.bg]; + } + + /* draw the new one */ + if (IS_SET(MODE_FOCUSED)) { + switch (win.cursor) { + case 7: /* st extension */ + g.u = 0x2603; /* snowman (U+2603) */ + /* FALLTHROUGH */ + case 0: /* Blinking Block */ + case 1: /* Blinking Block (Default) */ + case 2: /* Steady Block */ + xdrawglyph(g, cx, cy); + break; + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } +} + +void +xsetenv(void) +{ + char buf[sizeof(long) * 8 + 1]; + + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); +} + +void +xseticontitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMIconName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); + XFree(prop.value); +} + +void +xsettitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); + XFree(prop.value); +} + +int +xstartdraw(void) +{ + return IS_SET(MODE_VISIBLE); +} + +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, x, ox, numspecs; + Glyph base, new; + XftGlyphFontSpec *specs = xw.specbuf; + + numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1); +} + +void +xfinishdraw(void) +{ + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, + win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); +} + +void +xximspot(int x, int y) +{ + if (xw.ime.xic == NULL) + return; + + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; + + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); +} + +void +expose(XEvent *ev) +{ + redraw(); +} + +void +visibility(XEvent *ev) +{ + XVisibilityEvent *e = &ev->xvisibility; + + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); +} + +void +unmap(XEvent *ev) +{ + win.mode &= ~MODE_VISIBLE; +} + +void +xsetpointermotion(int set) +{ + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); +} + +void +xsetmode(int set, unsigned int flags) +{ + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); +} + +int +xsetcursor(int cursor) +{ + if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ + return 1; + win.cursor = cursor; + return 0; +} + +void +xseturgency(int add) +{ + XWMHints *h = XGetWMHints(xw.dpy, xw.win); + + MODBIT(h->flags, add, XUrgencyHint); + XSetWMHints(xw.dpy, xw.win, h); + XFree(h); +} + +void +xbell(void) +{ + if (!(IS_SET(MODE_FOCUSED))) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); +} + +void +focus(XEvent *ev) +{ + XFocusChangeEvent *e = &ev->xfocus; + + if (e->mode == NotifyGrab) + return; + + if (ev->type == FocusIn) { + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); + } +} + +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + return kp->s; + } + + return NULL; +} + +void +kpress(XEvent *ev) +{ + XKeyEvent *e = &ev->xkey; + KeySym ksym; + char buf[64], *customkey; + int len; + Rune c; + Status status; + Shortcut *bp; + + if (IS_SET(MODE_KBDLOCK)) + return; + + if (xw.ime.xic) + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + else + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + /* 1. shortcuts */ + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state)) { + bp->func(&(bp->arg)); + return; + } + } + + /* 2. custom keys from config.h */ + if ((customkey = kmap(ksym, e->state))) { + ttywrite(customkey, strlen(customkey), 1); + return; + } + + /* 3. composed string from input method */ + if (len == 0) + return; + if (len == 1 && e->state & Mod1Mask) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, len, 1); +} + +void +cmessage(XEvent *e) +{ + /* + * See xembed specs + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html + */ + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { + win.mode |= MODE_FOCUSED; + xseturgency(0); + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { + win.mode &= ~MODE_FOCUSED; + } + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { + ttyhangup(); + exit(0); + } +} + +void +resize(XEvent *e) +{ + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) + return; + + cresize(e->xconfigure.width, e->xconfigure.height); +} + +void +run(void) +{ + XEvent ev; + int w = win.w, h = win.h; + fd_set rfd; + int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; + struct timespec seltv, *tv, now, lastblink, trigger; + double timeout; + + /* Waiting for window mapping */ + do { + XNextEvent(xw.dpy, &ev); + /* + * This XFilterEvent call is required because of XOpenIM. It + * does filter out the key event and some client message for + * the input method too. + */ + if (XFilterEvent(&ev, None)) + continue; + if (ev.type == ConfigureNotify) { + w = ev.xconfigure.width; + h = ev.xconfigure.height; + } + } while (ev.type != MapNotify); + + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); + cresize(w, h); + + for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (XPending(xw.dpy)) + timeout = 0; /* existing events might not set xfd */ + + seltv.tv_sec = timeout / 1E3; + seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); + tv = timeout >= 0 ? &seltv : NULL; + + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + clock_gettime(CLOCK_MONOTONIC, &now); + + if (FD_ISSET(ttyfd, &rfd)) + ttyread(); + + xev = 0; + while (XPending(xw.dpy)) { + xev = 1; + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + /* + * To reduce flicker and tearing, when new content or event + * triggers drawing, we first wait a bit to ensure we got + * everything, and if nothing new arrives - we draw. + * We start with trying to wait minlatency ms. If more content + * arrives sooner, we retry with shorter and shorter periods, + * and eventually draw even without idle after maxlatency ms. + * Typically this results in low latency while interacting, + * maximum latency intervals during `cat huge.txt`, and perfect + * sync with periodic updates from animations/key-repeats/etc. + */ + if (FD_ISSET(ttyfd, &rfd) || xev) { + if (!drawing) { + trigger = now; + drawing = 1; + } + timeout = (maxlatency - TIMEDIFF(now, trigger)) \ + / maxlatency * minlatency; + if (timeout > 0) + continue; /* we have time, try to find idle */ + } + + /* idle detected or maxlatency exhausted -> draw */ + timeout = -1; + if (blinktimeout && tattrset(ATTR_BLINK)) { + timeout = blinktimeout - TIMEDIFF(now, lastblink); + if (timeout <= 0) { + if (-timeout > blinktimeout) /* start visible */ + win.mode |= MODE_BLINK; + win.mode ^= MODE_BLINK; + tsetdirtattr(ATTR_BLINK); + lastblink = now; + timeout = blinktimeout; + } + } + + draw(); + XFlush(xw.dpy); + drawing = 0; + } +} + +void +usage(void) +{ + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + +int +main(int argc, char *argv[]) +{ + xw.l = xw.t = 0; + xw.isfixed = False; + xsetcursor(cursorshape); + + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + if (argc > 0) + --argc, ++argv; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + xw.gm = XParseGeometry(EARGF(usage()), + &xw.l, &xw.t, &cols, &rows); + break; + case 'i': + xw.isfixed = 1; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 'l': + opt_line = EARGF(usage()); + break; + case 'n': + opt_name = EARGF(usage()); + break; + case 't': + case 'T': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + die("%s " VERSION "\n", argv0); + break; + default: + usage(); + } ARGEND; + +run: + if (argc > 0) /* eat all remaining arguments */ + opt_cmd = argv; + + if (!opt_title) + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; + + setlocale(LC_CTYPE, ""); + XSetLocaleModifiers(""); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); + + return 0; +} diff --git a/myports/sterm/work/st-0.8.5/x.o b/myports/sterm/work/st-0.8.5/x.o new file mode 100644 index 0000000000000000000000000000000000000000..ece31dacc48e5e54cbdd9c0591fccbe1a9b5f23e GIT binary patch literal 78256 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 literal 0 HcmV?d00001 diff --git a/myports/sterm/work/stage/usr/local/bin/st b/myports/sterm/work/stage/usr/local/bin/st new file mode 100755 index 0000000000000000000000000000000000000000..a3f5f19ee374c7878e3181b491b14190e1bb9fd5 GIT binary patch literal 94832 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 I{EqYg2LPgjF8}}l literal 0 HcmV?d00001 diff --git a/myports/sterm/work/stage/usr/local/man/man1/st.1.gz b/myports/sterm/work/stage/usr/local/man/man1/st.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..28e52f2ff93f39ff5c5ff0abdc1b29c02ee2ad56 GIT binary patch literal 1523 zcmV<|(orgsa|DXy_MGlp zfDxCI25m71B3A_653jYO&O1 zNrhfQ|>tJMS-srP5V98?JTVic|kS0^D9KTa)i!7}=2V&`T zKpF{9oN9DDroj5`4sfMVqC&~gIK|aM8;YiEJKL&E@Oo1mFU@xuK8e2Lqe0Z_LCj6)9C89Sr8wgd+RPLD#_knfZ zD{qe3q6@8ZnytA)o3LKC64}_D1Ho#Q1b6buXjpEKk~vpJQteff+pUd~?J56gn-agk z(ZlxC(ScV^!?L+rXtZ~zl6gYM_&P@Z^n@Uu_u4coRy1{IYwLnI0oC8QQ6V<5lymN2 z6q<0VlGEs0crn4=@nF6KOc`=CvQqb;`6p?yDqk`79p{2xC05S~4 z=6T12i{9pMv2(w<{AwlRoNdvF9vZ|cGvhy;rNhRfBt$f(f%Y7$gKNg58_$Hf1G`E4 z6f^%zKh-xpfTv=%y$+-1nS@n)Gif1e3`J}%lw${@t2`QIoJveQRv$Q}VM&RrJ7&Kd2iwJrBWdap$vIN5C^& zCx+``XmY`;GmDAp(LbKOjIGs@=L;a{ii=``vt{giEdh4h_lw}lqX{>j(s-|nsh!Uu zGF`-J-p-+@3>HCm8EVVw@C*e%QZyT2>k=Z=Xc*yy) zQnlxSUI5%7kYxPC;OO?P+9Eo;o5DLOtkOFF{pjNACcUEgxMtJxqHJI{=i7+x#P=h3 zFnFFjPT`@8S0TEvtwMTrMQ88Rah#?>&hRK84AjH;-Gr)s`r=vJ`^sRplD}h~^SgIX Zz^CKOaf_id`tI+FzX9mD(6;*x001@a5=a05 literal 0 HcmV?d00001 diff --git a/myports/sterm/work/stage/usr/local/share/doc/sterm/FAQ b/myports/sterm/work/stage/usr/local/share/doc/sterm/FAQ new file mode 100644 index 0000000..969b195 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/doc/sterm/FAQ @@ -0,0 +1,250 @@ +## 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 +: + + It should be noted that the O / [ confusion can occur with other keys + such as Home and End. Some systems let you query the key sequences + sent by these keys from the system's terminal database, terminfo. + Unfortunately, the key sequences given there typically apply to the + mode that is not the one zsh uses by default (it's the "application" + mode rather than the "raw" mode). Explaining the use of terminfo is + outside of the scope of this FAQ, but if you wish to use the key + sequences given there you can tell the line editor to turn on + "application" mode when it starts and turn it off when it stops: + + function zle-line-init () { echoti smkx } + function zle-line-finish () { echoti rmkx } + zle -N zle-line-init + zle -N zle-line-finish + +Putting these lines into your .zshrc will fix the problems. + + +## How can I use meta in 8bit mode? + +St supports meta in 8bit mode, but the default terminfo entry doesn't +use this capability. If you want it, you have to use the 'st-meta' value +in TERM. + + +## I cannot compile st in OpenBSD + +OpenBSD lacks librt, despite it being mandatory in POSIX +. +If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and +st will compile without any loss of functionality, because all the functions are +included in libc on this platform. + + +## The Backspace Case + +St is emulating the Linux way of handling backspace being delete and delete being +backspace. + +This is an issue that was discussed in suckless mailing list +. Here is why some old grumpy +terminal users wants its backspace to be how he feels it: + + Well, I am going to comment why I want to change the behaviour + of this key. When ASCII was defined in 1968, communication + with computers was done using punched cards, or hardcopy + terminals (basically a typewriter machine connected with the + computer using a serial port). ASCII defines DELETE as 7F, + because, in punched-card terms, it means all the holes of the + card punched; it is thus a kind of 'physical delete'. In the + same way, the BACKSPACE key was a non-destructive backspace, + as on a typewriter. So, if you wanted to delete a character, + you had to BACKSPACE and then DELETE. Another use of BACKSPACE + was to type accented characters, for example 'a BACKSPACE `'. + The VT100 had no BACKSPACE key; it was generated using the + CONTROL key as another control character (CONTROL key sets to + 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code + 0x08)), but it had a DELETE key in a similar position where + the BACKSPACE key is located today on common PC keyboards. + All the terminal emulators emulated the difference between + these keys correctly: the backspace key generated a BACKSPACE + (^H) and delete key generated a DELETE (^?). + + But a problem arose when Linus Torvalds wrote Linux. Unlike + earlier terminals, the Linux virtual terminal (the terminal + emulator integrated in the kernel) returned a DELETE when + backspace was pressed, due to the VT100 having a DELETE key in + the same position. This created a lot of problems (see [1] + and [2]). Since Linux has become the king, a lot of terminal + emulators today generate a DELETE when the backspace key is + pressed in order to avoid problems with Linux. The result is + that the only way of generating a BACKSPACE on these systems + is by using CONTROL + H. (I also think that emacs had an + important point here because the CONTROL + H prefix is used + in emacs in some commands (help commands).) + + From point of view of the kernel, you can change the key + for deleting a previous character with stty erase. When you + connect a real terminal into a machine you describe the type + of terminal, so getty configures the correct value of stty + erase for this terminal. In the case of terminal emulators, + however, you don't have any getty that can set the correct + value of stty erase, so you always get the default value. + For this reason, it is necessary to add 'stty erase ^H' to your + profile if you have changed the value of the backspace key. + Of course, another solution is for st itself to modify the + value of stty erase. I usually have the inverse problem: + when I connect to non-Unix machines, I have to press CONTROL + + h to get a BACKSPACE. The inverse problem occurs when a user + connects to my Unix machines from a different system with a + correct backspace key. + + [1] http://www.ibb.net/~anne/keyboard.html + [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html + + +## But I really want the old grumpy behaviour of my terminal + +Apply [1]. + +[1] https://st.suckless.org/patches/delkey + + +## Why do images not work in st 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. diff --git a/myports/sterm/work/stage/usr/local/share/doc/sterm/LEGACY b/myports/sterm/work/stage/usr/local/share/doc/sterm/LEGACY new file mode 100644 index 0000000..bf28b1e --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/doc/sterm/LEGACY @@ -0,0 +1,17 @@ +A STATEMENT ON LEGACY SUPPORT + +In the terminal world there is much cruft that comes from old and unsup‐ +ported terminals that inherit incompatible modes and escape sequences +which noone is able to know, except when he/she comes from that time and +developed a graphical vt100 emulator at that time. + +One goal of st is to only support what is really needed. When you en‐ +counter a sequence which you really need, implement it. But while you +are at it, do not add the other cruft you might encounter while sneek‐ +ing at other terminal emulators. History has bloated them and there is +no real evidence that most of the sequences are used today. + + +Christoph Lohmann <20h@r-36.net> +2012-09-13T07:00:36.081271045+02:00 + diff --git a/myports/sterm/work/stage/usr/local/share/doc/sterm/README b/myports/sterm/work/stage/usr/local/share/doc/sterm/README new file mode 100644 index 0000000..6a846ed --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/doc/sterm/README @@ -0,0 +1,34 @@ +st - simple terminal +-------------------- +st is a simple terminal emulator for X which sucks less. + + +Requirements +------------ +In order to build st you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (st is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install st (if +necessary as root): + + make clean install + + +Running st +---------- +If you did not install st with make clean install, you must compile +the st terminfo entry with the following command: + + tic -sx st.info + +See the man page for additional details. + +Credits +------- +Based on Aurélien APTEL bt source code. + diff --git a/myports/sterm/work/stage/usr/local/share/doc/sterm/TODO b/myports/sterm/work/stage/usr/local/share/doc/sterm/TODO new file mode 100644 index 0000000..5f74cd5 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/doc/sterm/TODO @@ -0,0 +1,28 @@ +vt emulation +------------ + +* double-height support + +code & interface +---------------- + +* add a simple way to do multiplexing + +drawing +------- +* add diacritics support to xdraws() + * switch to a suckless font drawing library +* make the font cache simpler +* add better support for brightening of the upper colors + +bugs +---- + +* fix shift up/down (shift selection in emacs) +* remove DEC test sequence when appropriate + +misc +---- + + $ grep -nE 'XXX|TODO' st.c + diff --git a/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/LICENSE b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/LICENSE new file mode 100644 index 0000000..6657117 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/LICENSE @@ -0,0 +1 @@ +This package has a single license: MIT (MIT license / X11 license). diff --git a/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/MIT b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/MIT new file mode 100644 index 0000000..d80eb47 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/MIT @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2020 Hiltjo Posthuma +© 2018 Devin J. Pohly +© 2014-2017 Quentin Rameau +© 2009-2012 Aurélien APTEL +© 2008-2017 Anselm R Garbe +© 2012-2017 Roberto E. Vargas Caballero +© 2012-2016 Christoph Lohmann <20h at r-36 dot net> +© 2013 Eon S. Jeon +© 2013 Alexander Sedov +© 2013 Mark Edgar +© 2013-2014 Eric Pruitt +© 2013 Michael Forney +© 2013-2014 Markus Teich +© 2014-2015 Laslo Hunhold + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/catalog.mk b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/catalog.mk new file mode 100644 index 0000000..b2d7e37 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/licenses/sterm-0.8.5/catalog.mk @@ -0,0 +1,5 @@ +_LICENSE=MIT +_LICENSE_NAME=MIT license / X11 license +_LICENSE_PERMS=dist-mirror dist-sell pkg-mirror pkg-sell auto-accept +_LICENSE_GROUPS=COPYFREE FSF GPL OSI +_LICENSE_DISTFILES=st-0.8.5.tar.gz diff --git a/myports/sterm/work/stage/usr/local/share/sterm/config.def.h b/myports/sterm/work/stage/usr/local/share/sterm/config.def.h new file mode 100644 index 0000000..c217315 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/sterm/config.def.h @@ -0,0 +1,478 @@ +/* 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 */ + { ShiftMask, Button4, kscrollup, {.i = 1} }, + { ShiftMask, Button5, kscrolldown, {.i = 1} }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/myports/sterm/work/stage/usr/local/share/sterm/st.info b/myports/sterm/work/stage/usr/local/share/sterm/st.info new file mode 100644 index 0000000..8201ad6 --- /dev/null +++ b/myports/sterm/work/stage/usr/local/share/sterm/st.info @@ -0,0 +1,239 @@ +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, +# disabled rep for now: causes some issues with older ncurses versions. +# rep=%p1%c\E[%p2%{1}%-%db, +# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) + Tc, + Ms=\E]52;%p1%s;%p2%s\007, + Se=\E[2 q, + Ss=\E[%p1%d q, + +st| simpleterm, + use=st-mono, + colors#8, + setab=\E[4%p1%dm, + setaf=\E[3%p1%dm, + setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, + +st-256color| simpleterm with 256 colors, + use=st, + ccc, + colors#256, + oc=\E]104\007, + pairs#32767, +# Nicked from xterm-256color + initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, + +st-meta| simpleterm with meta key, + use=st, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-meta-256color| simpleterm with meta key and 256 colors, + use=st-256color, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-bs| simpleterm with backspace as backspace, + use=st, + kbs=\010, + kdch1=\177, + +st-bs-256color| simpleterm with backspace as backspace and 256colors, + use=st-256color, + kbs=\010, + kdch1=\177, diff --git a/suckless/dwm/config.def.h b/suckless/dwm/config.def.h new file mode 100644 index 0000000..d05dc04 --- /dev/null +++ b/suckless/dwm/config.def.h @@ -0,0 +1,125 @@ +/* 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 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 char *incrvol[] = { "mixer", "vol", "+1:+1", NULL}; +static const char *decrvol[] = { "mixer", "vol", "-1:-1", NULL}; + +#define XK_XF86AudioLowerVolume 0x1008ff11 +#define XK_XF86AudioRaiseVolume 0x1008ff13 +static 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|ShiftMask, XK_j, rotatestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { 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|ShiftMask, XK_f, fullscreen, {0} }, + { 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} }, + { 0x0, XK_XF86AudioRaiseVolume, spawn, {.v = incrvol } }, + { 0x0, XK_XF86AudioLowerVolume, spawn, {.v = decrvol } }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h new file mode 100644 index 0000000..1aa8b7d --- /dev/null +++ b/suckless/dwm/config.h @@ -0,0 +1,130 @@ +/* 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 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 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|ShiftMask, XK_i, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY|ShiftMask, XK_i, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_k, rotatestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, + { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, 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} }, + +/* Modos de captura de pantalla */ +{ 0, XK_Print, spawn, SHCMD("scrot /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Pantalla en portapapeles'") }, // Captura de pantalla al portapapeles +{ ControlMask, XK_Print, spawn, SHCMD("scrot -u /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Ventana en portapapeles'") }, // Ventana seleccionada al portapapeles +{ ShiftMask, XK_Print, spawn, SHCMD("sleep 1; scrot -s /tmp/'%F_%T.png' -e 'xclip -selection c -t image/png < $f'; sleep 1; exec herbe 'Área en portapapeles'") }, // Area seleccionada al portapapeles + +{ MODKEY, XK_Print, spawn, SHCMD("scrot 'c_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; sleep 1; exec herbe 'Pantalla en ~/Capturas'") },//Captura de pantalla +{ MODKEY|ControlMask, XK_Print, spawn, SHCMD("scrot -u 'v_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; sleep 1; exec herbe 'Ventana en ~/Capturas'") } ,//Captura de ventana +{ MODKEY|ShiftMask, XK_Print, spawn, SHCMD("sleep 1; scrot -s 'a_%F_%H%M%S_$wx$h.png' -e 'mv $f /home/loftur/Pictures/screenshots/'; exec herbe 'Área en ~/Capturas'") },// Captura de Area + + +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/suckless/st/config.def.h b/suckless/st/config.def.h new file mode 100644 index 0000000..c217315 --- /dev/null +++ b/suckless/st/config.def.h @@ -0,0 +1,478 @@ +/* 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 */ + { ShiftMask, Button4, kscrollup, {.i = 1} }, + { ShiftMask, Button5, kscrolldown, {.i = 1} }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/suckless/st/config.h b/suckless/st/config.h new file mode 100644 index 0000000..5937481 --- /dev/null +++ b/suckless/st/config.h @@ -0,0 +1,479 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Hack:style=Regular:pixelsize=16: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"} }, + { ShiftMask, Button4, kscrollup, {.i = 1} }, + { ShiftMask, Button5, kscrolldown, {.i = 1} }, +}; + +/* 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} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_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{|}~";