From 93b21c779dc6111963ea225f95b6a2a938ec05ce Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:14:09 +0100 Subject: [PATCH 01/32] Added gitignore & config --- .gitignore | 12 ++++++++++++ config.h | 23 +++++++++++++++++++++++ dmenu_path => dmenu_path.sh | 0 dmenu_run => dmenu_run.sh | 0 4 files changed, 35 insertions(+) create mode 100644 .gitignore create mode 100644 config.h rename dmenu_path => dmenu_path.sh (100%) rename dmenu_run => dmenu_run.sh (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f2d4bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.rej +*.orig + +# build artifacts +*.o +dmenu +stest + +# makepkg +src/ +pkg/ +*.pkg* diff --git a/config.h b/config.h new file mode 100644 index 0000000..1edb647 --- /dev/null +++ b/config.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/dmenu_path b/dmenu_path.sh similarity index 100% rename from dmenu_path rename to dmenu_path.sh diff --git a/dmenu_run b/dmenu_run.sh similarity index 100% rename from dmenu_run rename to dmenu_run.sh From 7630d80f21842aabcb6702679ffbb0a83cd300a3 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:28:01 +0100 Subject: [PATCH 02/32] Added PKGBUILD & CI pipeline for publishing --- .woodpecker.yml | 27 +++++++++++++++++++++++++ Makefile | 4 +++- PKGBUILD | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ config.mk | 2 +- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 .woodpecker.yml create mode 100644 PKGBUILD diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..8e4f11d --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,27 @@ +branches: master + +when: + event: push + +pipeline: + build: + image: 'archlinux:latest' + commands: + # Update packages + - pacman -Syu --needed --noconfirm base-devel + # Create non-root user to perform build & switch to their home + - groupadd -g 1000 builder + - useradd -mg builder builder + - chown -R builder:builder "$PWD" + - "echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers" + - su builder + # Build the package + - MAKEFLAGS="-j$(nproc)" makepkg -s --noconfirm --needed + + publish: + image: 'archlinux:latest' + commands: + # Publish the package + - 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/publish' + secrets: + - api_key diff --git a/Makefile b/Makefile index a03a95c..2fdc765 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,9 @@ dist: clean install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin + cp -f dmenu stest $(DESTDIR)$(PREFIX)/bin + cp -f dmenu_path.sh $(DESTDIR)$(PREFIX)/bin/dmenu_path + cp -f dmenu_run.sh $(DESTDIR)$(PREFIX)/bin/dmenu_run chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..b58ab76 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,53 @@ +# Maintainer: Jef Roosens + +pkgname="jjr-dmenu" +pkgver="5.1" +pkgrel=1 +pkgdesc="Chewing_Bever's custom build of Suckless's dmenu." +arch=("x86_64") + +url="https://git.rustybever.be/Chewing_Bever/dmenu" +license=("MIT") + +depends=("libxinerama" "libxft" "fontconfig" "freetype2") +makedepends=("glibc" "gcc") +provides=("dmenu") +conflicts=("dmenu-git") + +source=("arg.h" "config.h" "config.mk" "dmenu.1" "dmenu.c" "dmenu_path.sh" +"dmenu_run.sh" "drw.c" "drw.h" "LICENSE" "Makefile" "README" "stest.1" +"stest.c" "util.c" "util.h") +sha256sums=('9ed2b2e3396fdebc8ecab2cdbb09db115cca015f63ec0443b8ccc56340b6b03c' + '7720b411b3bd1da5ee547711c03a10bcf456bf235c44f624e83108ea6b9f53ed' + '72a08af1c5846331eae8268294aa66ca7be58c675084ece0a3ba6bbe21d5c943' + '5b078d9606bceb8ac0acbd0580ef0a232c77fff92775d6db7dda2ecb8011ef19' + '1f2db0b593ad88aa20e79af395f84e5473fe0b7c3aaac456f0b6b21961325bc2' + 'a3f19e648e20eb80532dfe87e9bd9feeaa92df838e6ecc061f274c9da579d617' + '564035fd8a8ade6504521d98fa10e8732e135403d546d04ca77316fe4a67b21c' + 'a7c7358ce13c8571044b79d5d91d01314d9174793474a27faa37d23c75ab603f' + 'c35796210ea8410ae096025cc0d7996dccb3d9936306dff7531a0bb253e079f5' + '9f8e922fcfc18ffcc4975dd0b1bee38302bd4e0c538251dfef6d77cd7ed59c89' + 'c32b5173eddf376296af085725cb878e4ca2603d4fda8bba3faac6a2bb1b4390' + 'ec98e8759049af796598f0790752a21a69eaea1d438b09c39922d4a9f4a7cfe2' + '00d3389ef8858a565cf3fb3445620b90eb67d1a9b31434f4d54b05ed6c5abefb' + 'ba76404e61abbd734e315999ffe4e883419c4c69ff17a5d4d88a5cd11dd4b055' + 'dec870d0b5834c9008ff62f495710daf524cffdf12d0cf8ba4fadf5643623987' + '1196a7b6efbf4cb3f5c435fffd72e7647f977483845d5c78c1c48d9ab8b96819') + +build() { + make +} + +package() { + local installopts='--mode 0644 -D --target-directory' + local shrdir="$pkgdir/usr/share" + local licdir="$shrdir/licenses/$pkgname" + local docdir="$shrdir/doc/$pkgname" + + make PREFIX=/usr DESTDIR="$pkgdir" install + + install $installopts "$licdir" "LICENSE" + install $installopts "$docdir" "README" + # install $installopts "$docdir" README.terminfo.rst + # install $installopts "$shrdir/$pkgname" "$_sourcedir/st.info" +} diff --git a/config.mk b/config.mk index 0df3fc8..802fcb1 100644 --- a/config.mk +++ b/config.mk @@ -24,7 +24,7 @@ LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) -CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) +CFLAGS = -std=c99 -pedantic -Wall -O3 $(INCS) $(CPPFLAGS) LDFLAGS = $(LIBS) # compiler and linker From a140c508b0d6d7c3121da24922b25e8eb52c4422 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:29:48 +0100 Subject: [PATCH 03/32] Changed branch & added platform restriction to CI --- .woodpecker.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 8e4f11d..f3d4a20 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,4 +1,5 @@ -branches: master +branches: main +platform: linux/amd64 when: event: push From d8ff6423a6d686bfa77d063fa42dc59628cbcd77 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:42:28 +0100 Subject: [PATCH 04/32] Applied patch dmenu-caseinsensitive-5.0 --- dmenu.1 | 6 +++--- dmenu.c | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/dmenu.1 b/dmenu.1 index 323f93c..3e3b31b 100644 --- a/dmenu.1 +++ b/dmenu.1 @@ -3,7 +3,7 @@ dmenu \- dynamic menu .SH SYNOPSIS .B dmenu -.RB [ \-bfiv ] +.RB [ \-bfsv ] .RB [ \-l .IR lines ] .RB [ \-m @@ -44,8 +44,8 @@ dmenu appears at the bottom of the screen. dmenu grabs the keyboard before reading stdin if not reading from a tty. This is faster, but will lock up X until stdin reaches end\-of\-file. .TP -.B \-i -dmenu matches menu items case insensitively. +.B \-s +dmenu matches menu items case sensitively. .TP .BI \-l " lines" dmenu lists items vertically, with the given number of lines. diff --git a/dmenu.c b/dmenu.c index eca67ac..d96ba56 100644 --- a/dmenu.c +++ b/dmenu.c @@ -55,8 +55,9 @@ static Clr *scheme[SchemeLast]; #include "config.h" -static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; -static char *(*fstrstr)(const char *, const char *) = strstr; +static char * cistrstr(const char *s, const char *sub); +static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; +static char *(*fstrstr)(const char *, const char *) = cistrstr; static void appenditem(struct item *item, struct item **list, struct item **last) @@ -727,9 +728,9 @@ main(int argc, char *argv[]) topbar = 0; else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; + else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ + fstrncmp = strncmp; + fstrstr = strstr; } else if (i + 1 == argc) usage(); /* these options take one argument */ From 0d852f8a7cf60d66503b6489ae56762761e608f2 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:47:28 +0100 Subject: [PATCH 05/32] Applied patch dmenu-fuzzymatch-4.9 --- config.def.h | 1 + config.h | 1 + config.mk | 2 +- dmenu.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 1edb647..51612b9 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,7 @@ /* Default settings; can be overriden by command line. */ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */ /* -fn option overrides fonts[0]; default X11 font or font set */ static const char *fonts[] = { "monospace:size=10" diff --git a/config.h b/config.h index 1edb647..51612b9 100644 --- a/config.h +++ b/config.h @@ -2,6 +2,7 @@ /* Default settings; can be overriden by command line. */ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */ /* -fn option overrides fonts[0]; default X11 font or font set */ static const char *fonts[] = { "monospace:size=10" diff --git a/config.mk b/config.mk index 802fcb1..8bed68c 100644 --- a/config.mk +++ b/config.mk @@ -20,7 +20,7 @@ FREETYPEINC = /usr/include/freetype2 # includes and libs INCS = -I$(X11INC) -I$(FREETYPEINC) -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) diff --git a/dmenu.c b/dmenu.c index d96ba56..b264d53 100644 --- a/dmenu.c +++ b/dmenu.c @@ -1,6 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ struct item { char *text; struct item *left, *right; int out; + double distance; }; static char text[BUFSIZ] = ""; @@ -218,9 +220,94 @@ grabkeyboard(void) die("cannot grab keyboard"); } +int +compare_distance(const void *a, const void *b) +{ + struct item *da = *(struct item **) a; + struct item *db = *(struct item **) b; + + if (!db) + return 1; + if (!da) + return -1; + + return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1; +} + +void +fuzzymatch(void) +{ + /* bang - we have so much memory */ + struct item *it; + struct item **fuzzymatches = NULL; + char c; + int number_of_matches = 0, i, pidx, sidx, eidx; + int text_len = strlen(text), itext_len; + + matches = matchend = NULL; + + /* walk through all items */ + for (it = items; it && it->text; it++) { + if (text_len) { + itext_len = strlen(it->text); + pidx = 0; /* pointer */ + sidx = eidx = -1; /* start of match, end of match */ + /* walk through item text */ + for (i = 0; i < itext_len && (c = it->text[i]); i++) { + /* fuzzy match pattern */ + if (!fstrncmp(&text[pidx], &c, 1)) { + if(sidx == -1) + sidx = i; + pidx++; + if (pidx == text_len) { + eidx = i; + break; + } + } + } + /* build list of matches */ + if (eidx != -1) { + /* compute distance */ + /* add penalty if match starts late (log(sidx+2)) + * add penalty for long a match without many matching characters */ + it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len); + /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */ + appenditem(it, &matches, &matchend); + number_of_matches++; + } + } else { + appenditem(it, &matches, &matchend); + } + } + + if (number_of_matches) { + /* initialize array with matches */ + if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) + die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*)); + for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) { + fuzzymatches[i] = it; + } + /* sort matches according to distance */ + qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance); + /* rebuild list of matches */ + matches = matchend = NULL; + for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \ + it->text; i++, it = fuzzymatches[i]) { + appenditem(it, &matches, &matchend); + } + free(fuzzymatches); + } + curr = sel = matches; + calcoffsets(); +} + static void match(void) { + if (fuzzy) { + fuzzymatch(); + return; + } static char **tokv = NULL; static int tokn = 0; @@ -728,6 +815,8 @@ main(int argc, char *argv[]) topbar = 0; else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ fast = 1; + else if (!strcmp(argv[i], "-F")) /* disable fuzzy search */ + fuzzy = 0; else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ fstrncmp = strncmp; fstrstr = strstr; From 9ce1c3e3dafe46f4436081704b3dfa0dc06b380a Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 10:57:50 +0100 Subject: [PATCH 06/32] Bumped version --- PKGBUILD | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index b58ab76..9114b02 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Jef Roosens pkgname="jjr-dmenu" -pkgver="5.1" +pkgver="5.2" pkgrel=1 pkgdesc="Chewing_Bever's custom build of Suckless's dmenu." arch=("x86_64") diff --git a/config.mk b/config.mk index 8bed68c..ddb33fa 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dmenu version -VERSION = 5.1 +VERSION = 5.2 # paths PREFIX = /usr/local From 2055ca2d9b17f784d8b86a957c901e63a6f86cd2 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 5 Mar 2022 11:27:29 +0100 Subject: [PATCH 07/32] Updated PKGBUILD checksums --- PKGBUILD | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 9114b02..291d7c2 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -18,10 +18,10 @@ source=("arg.h" "config.h" "config.mk" "dmenu.1" "dmenu.c" "dmenu_path.sh" "dmenu_run.sh" "drw.c" "drw.h" "LICENSE" "Makefile" "README" "stest.1" "stest.c" "util.c" "util.h") sha256sums=('9ed2b2e3396fdebc8ecab2cdbb09db115cca015f63ec0443b8ccc56340b6b03c' - '7720b411b3bd1da5ee547711c03a10bcf456bf235c44f624e83108ea6b9f53ed' - '72a08af1c5846331eae8268294aa66ca7be58c675084ece0a3ba6bbe21d5c943' - '5b078d9606bceb8ac0acbd0580ef0a232c77fff92775d6db7dda2ecb8011ef19' - '1f2db0b593ad88aa20e79af395f84e5473fe0b7c3aaac456f0b6b21961325bc2' + '9ae33f74aed02823abb8381e553d38455541ce3b6a0d642282b693992e71caef' + 'f6de4c72dab3b9bef214bd52e6a7dff22e87a3118abaffd26ec1ae589cf68b3f' + '9f749419697381a1db77e9b23cb41629808fd7e451d475c9b5ee0e88bee803f6' + '5b2a53db7ba608d392efaa96be5530665b46107dc4e0ee1a864745a6e8a8587d' 'a3f19e648e20eb80532dfe87e9bd9feeaa92df838e6ecc061f274c9da579d617' '564035fd8a8ade6504521d98fa10e8732e135403d546d04ca77316fe4a67b21c' 'a7c7358ce13c8571044b79d5d91d01314d9174793474a27faa37d23c75ab603f' From 39850bd5005e5db0619edc8ea8a5c7061d954f4e Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 7 Apr 2022 22:18:18 +0200 Subject: [PATCH 08/32] Updated to new vieter & multi-arch setup --- .woodpecker.yml | 15 ++++++++++----- PKGBUILD | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index f3d4a20..626f70e 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,15 +1,20 @@ +matrix: + PLATFORM: + - linux/amd64 + - linux/arm64 + branches: main -platform: linux/amd64 +platform: ${PLATFORM} when: event: push pipeline: build: - image: 'archlinux:latest' + image: 'menci/archlinuxarm:base-devel' commands: # Update packages - - pacman -Syu --needed --noconfirm base-devel + - pacman -Syu --noconfirm # Create non-root user to perform build & switch to their home - groupadd -g 1000 builder - useradd -mg builder builder @@ -20,9 +25,9 @@ pipeline: - MAKEFLAGS="-j$(nproc)" makepkg -s --noconfirm --needed publish: - image: 'archlinux:latest' + image: 'curlimages/curl' commands: # Publish the package - - 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/publish' + - 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/vieter/publish' secrets: - api_key diff --git a/PKGBUILD b/PKGBUILD index 291d7c2..79cfbc1 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -4,7 +4,7 @@ pkgname="jjr-dmenu" pkgver="5.2" pkgrel=1 pkgdesc="Chewing_Bever's custom build of Suckless's dmenu." -arch=("x86_64") +arch=("x86_64" "aarch64") url="https://git.rustybever.be/Chewing_Bever/dmenu" license=("MIT") From e1a14e69f61b22f75bc1bb9384241bb23ee5d6ee Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 7 Apr 2022 22:27:45 +0200 Subject: [PATCH 09/32] Deployed to wrong repo --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 626f70e..9216fbd 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -28,6 +28,6 @@ pipeline: image: 'curlimages/curl' commands: # Publish the package - - 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/vieter/publish' + - 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/jjr/publish' secrets: - api_key From f84f1080d8eaec5a34bb21a342484d0ed941c54f Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 28 Aug 2022 11:20:24 +0200 Subject: [PATCH 10/32] ci: publish to vieter arch-repos --- .woodpecker.yml | 22 +++++++++++++++++----- PKGBUILD | 7 ++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 9216fbd..e4f6c15 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,10 +1,16 @@ matrix: - PLATFORM: - - linux/amd64 - - linux/arm64 + # PLATFORM: + # - linux/amd64 + # - linux/arm64 + + ARCH: + # tuur + - tigerlake + # cenny + - skylake branches: main -platform: ${PLATFORM} +platform: linux/amd64 when: event: push @@ -13,6 +19,8 @@ pipeline: build: image: 'menci/archlinuxarm:base-devel' commands: + # Add my bur repo to pacman for the libxft-bgra dependency + - echo -e '[bur]\nServer = https://arch.r8r.be/$repo/$arch\nSigLevel = Optional' >> /etc/pacman.conf # Update packages - pacman -Syu --noconfirm # Create non-root user to perform build & switch to their home @@ -22,7 +30,11 @@ pipeline: - "echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers" - su builder # Build the package - - MAKEFLAGS="-j$(nproc)" makepkg -s --noconfirm --needed + - > + MAKEFLAGS="-j$(nproc)" + makepkg -s --noconfirm --needed + CFLAGS="-O3 -flto -march=${ARCH}" + CARCH="x86_64_${ARCH}" publish: image: 'curlimages/curl' diff --git a/PKGBUILD b/PKGBUILD index 79cfbc1..44a319f 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -4,7 +4,12 @@ pkgname="jjr-dmenu" pkgver="5.2" pkgrel=1 pkgdesc="Chewing_Bever's custom build of Suckless's dmenu." -arch=("x86_64" "aarch64") +arch=( + "x86_64" + "x86_64_tigerlake" + "x86_64_skylake" + "aarch64" +) url="https://git.rustybever.be/Chewing_Bever/dmenu" license=("MIT") From 2f8a3053764e8ef3689ec4d5106de44fbd207f58 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 00:37:55 +0600 Subject: [PATCH 11/32] drw_text: improve both performance and correctness this patch makes some non-trivial changes, which significantly improves the performance of drawing large strings as well as fixes any issues regarding the printing of the ellipsis when string gets truncated. * performance: before there were two O(n) loops, one which finds how long we can go without changing font, and the second loop would (incorrectly) truncate the string if it's too big. this patch merges the overflow calculation into the first loop and exits out when overflow is detected. when dumping lots of emojies into dmenu, i see some noticeable startup time improvement: before -> after 460ms -> 360ms input latency when scrolling up/down is also noticeably better and can be tested with the following: for _ in $(seq 20); do cat /dev/urandom | base64 | tr -d '\n' | head -c 1000000 echo done | ./dmenu -l 10 * correctness: the previous version would incorrectly assumed single byte chars and would overwrite them with '.' , this caused a whole bunch of obvious problems, including the ellipsis not getting rendered if then font changed. in addition to exiting out when we detect overflow, this patch also keeps track of the last x-position where the ellipsis would fit. if we detect overflow, we simply make a recursing call to drw_text() at the ellipsis_x position and overwrite what was there. so now the ellipsis will always be printed properly, regardless of weather the font changes or if the string is single byte char or not. the idea of rendering the ellipsis on top incase of overflow was from Bakkeby , thanks! however the original patch had some issues incorrectly truncating the prompt (-p flag) and cutting off emojies. those have been fixed in here. --- drw.c | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drw.c b/drw.c index 4cdbcbe..e65d069 100644 --- a/drw.c +++ b/drw.c @@ -251,12 +251,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int 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; + int ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width; 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; @@ -264,7 +262,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcPattern *fcpattern; FcPattern *match; XftResult result; - int charexists = 0; + int charexists = 0, overflow = 0; if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0; @@ -282,8 +280,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } usedfont = drw->fonts; + drw_font_getexts(usedfont, "...", 3, &ellipsis_width, NULL); while (1) { - utf8strlen = 0; + ew = ellipsis_len = utf8strlen = 0; utf8str = text; nextfont = NULL; while (*text) { @@ -291,9 +290,21 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp for (curfont = drw->fonts; curfont; curfont = curfont->next) { charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); if (charexists) { - if (curfont == usedfont) { + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (ew + ellipsis_width <= w) { + /* keep track where the ellipsis still fits */ + ellipsis_x = x + ew; + ellipsis_w = w - ew; + ellipsis_len = utf8strlen; + } + + if (ew + tmpw > w) { + overflow = 1; + utf8strlen = ellipsis_len; + } else if (curfont == usedfont) { utf8strlen += utf8charlen; text += utf8charlen; + ew += tmpw; } else { nextfont = curfont; } @@ -301,36 +312,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } } - if (!charexists || nextfont) + if (overflow || !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 (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); } + x += ew; + w -= ew; } + if (render && overflow) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - if (!*text) { + if (!*text || overflow) { break; } else if (nextfont) { charexists = 0; From 576d46bf00fb3f52e577de62713847a753791c45 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 02:00:00 +0600 Subject: [PATCH 12/32] introduce drw_fontset_getwidth_clamp() getting the width of a string is an O(n) operation, and in many cases users only care about getting the width upto a certain number. instead of calling drw_fontset_getwidth() and *then* clamping the result, this patch introduces drw_fontset_getwidth_clamp() function, similar to strnlen(), which will stop once we reach n. the `invert` parameter was overloaded internally to preserve the API, however library users should be calling drw_fontset_getwidth_clamp() and not depend upon internal behavior of drw_text(). --- drw.c | 19 +++++++++++++++++-- drw.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drw.c b/drw.c index e65d069..7d985b1 100644 --- a/drw.c +++ b/drw.c @@ -268,7 +268,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return 0; if (!render) { - w = ~w; + w = invert ? invert : ~invert; } else { XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); @@ -300,7 +300,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (ew + tmpw > w) { overflow = 1; - utf8strlen = ellipsis_len; + /* called from drw_fontset_getwidth_clamp(): + * it wants the width AFTER the overflow + */ + if (!render) + x += tmpw; + else + utf8strlen = ellipsis_len; } else if (curfont == usedfont) { utf8strlen += utf8charlen; text += utf8charlen; @@ -397,6 +403,15 @@ drw_fontset_getwidth(Drw *drw, const char *text) return drw_text(drw, 0, 0, 0, 0, 0, text, 0); } +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->fonts && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); + return MIN(n, tmp); +} + void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { diff --git a/drw.h b/drw.h index 4c67419..fd7631b 100644 --- a/drw.h +++ b/drw.h @@ -35,6 +35,7 @@ void drw_free(Drw *drw); Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); void drw_fontset_free(Fnt* set); unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); /* Colorscheme abstraction */ From 49c6f40235c21943aece610dc8c1b9c2db022765 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 02:04:04 +0600 Subject: [PATCH 13/32] significantly improve performance on large strings this replaces inefficient pattern of `MIN(TEXTW(..), n)` with drw_fontset_getwidth_clamp() instead, which is far more efficient when we only want up to a certain width. dumping a decently sized (unicode) emoji file into dmenu, I see the startup time drop significantly with this patch. before -> after 360ms -> 160ms this should also noticeably improve input latency (responsiveness) given that calcoffsets() and drawmenu() are pretty hot functions. --- dmenu.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dmenu.c b/dmenu.c index b264d53..79d7a02 100644 --- a/dmenu.c +++ b/dmenu.c @@ -61,6 +61,13 @@ static char * cistrstr(const char *s, const char *sub); static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; static char *(*fstrstr)(const char *, const char *) = cistrstr; +static unsigned int +textw_clamp(const char *str, unsigned int n) +{ + unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; + return MIN(w, n); +} + static void appenditem(struct item *item, struct item **list, struct item **last) { @@ -85,10 +92,10 @@ calcoffsets(void) n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); /* calculate which items will begin the next page and previous page */ for (i = 0, next = curr; next; next = next->right) - if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) + if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) break; for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) + if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) break; } @@ -175,7 +182,7 @@ drawmenu(void) } x += w; for (item = curr; item != next; item = item->right) - x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">"))); + x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); if (next) { w = TEXTW(">"); drw_setscheme(drw, scheme[SchemeNorm]); From 3450386f770f17a2b921d83a0aac397735201a61 Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 00:37:55 +0600 Subject: [PATCH 14/32] inputw: improve correctness and startup performance a massive amount of time inside readstdin() is spent trying to get the max input width and then put it into inputw, only for it to get clamped down to mw/3 inside setup(). it makes more sense to calculate inputw inside setup() once we have mw available. similar to the last patch, i see noticeable startup performance improvement: before -> after 160ms -> 60ms additionally this will take fallback fonts into account compared to the previous version, so it's not only more performant but also more correct. --- dmenu.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dmenu.c b/dmenu.c index 79d7a02..773f49a 100644 --- a/dmenu.c +++ b/dmenu.c @@ -635,8 +635,7 @@ static void readstdin(void) { char buf[sizeof text], *p; - size_t i, imax = 0, size = 0; - unsigned int tmpmax = 0; + size_t i, size = 0; /* read each line from stdin and add it to the item list */ for (i = 0; fgets(buf, sizeof buf, stdin); i++) { @@ -648,15 +647,9 @@ readstdin(void) if (!(items[i].text = strdup(buf))) die("cannot strdup %u bytes:", strlen(buf) + 1); items[i].out = 0; - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); - if (tmpmax > inputw) { - inputw = tmpmax; - imax = i; - } } if (items) items[i].text = NULL; - inputw = items ? TEXTW(items[imax].text) : 0; lines = MIN(lines, i); } @@ -702,12 +695,13 @@ static void setup(void) { int x, y, i, j; - unsigned int du; + unsigned int du, tmp; XSetWindowAttributes swa; XIM xim; Window w, dw, *dws; XWindowAttributes wa; XClassHint ch = {"dmenu", "dmenu"}; + struct item *item; #ifdef XINERAMA XineramaScreenInfo *info; Window pw; @@ -765,7 +759,12 @@ setup(void) mw = wa.width; } promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = MIN(inputw, mw/3); + for (item = items; item && item->text; ++item) { + if ((tmp = textw_clamp(item->text, mw/3)) > inputw) { + if ((inputw = tmp) == mw/3) + break; + } + } match(); /* create menu window */ From 3a060d98f52465a5c1ef643cd6705aedfb4e6c6e Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 24 Mar 2022 00:37:55 +0600 Subject: [PATCH 15/32] drw_text: improve performance when there's no match this was the last piece of the puzzle, the case where we can't find any font to draw the codepoint. in such cases, we use XftFontMatch() which is INSANELY slow. but that's not the real problem. the real problem was we were continuously trying to match the same thing over and over again. this patch introduces a small cache, which keeps track a couple codepoints for which we know we won't find any matches. with this, i can dump lots of emojies into dmenu where some of them don't have any matching font, and still not have dmenu lag insanely or FREEZE completely when scrolling up and down. this also improves startup time, which will of course depend on the system and all installed fonts; but on my system and test case i see the following startup time drop: before -> after 60ms -> 34ms --- drw.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drw.c b/drw.c index 7d985b1..a50c9ee 100644 --- a/drw.c +++ b/drw.c @@ -251,7 +251,7 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { - int ty, ellipsis_x = 0; + int i, ty, ellipsis_x = 0; unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width; XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont; @@ -263,6 +263,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp FcPattern *match; XftResult result; int charexists = 0, overflow = 0; + /* keep track of a couple codepoints for which we have no match. */ + enum { nomatches_len = 64 }; + static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0; @@ -346,6 +349,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp * character must be drawn. */ charexists = 1; + for (i = 0; i < nomatches_len; ++i) { + /* avoid calling XftFontMatch if we know we won't find a match */ + if (utf8codepoint == nomatches.codepoint[i]) + goto no_match; + } + fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); @@ -374,6 +383,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp curfont->next = usedfont; } else { xfont_free(usedfont); + nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; +no_match: usedfont = drw->fonts; } } From cced315e68e34a1dba8c68d7eaa86884a03c8a38 Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 25 Mar 2022 22:51:09 +0100 Subject: [PATCH 16/32] free all allocated items, use %zu for size_t `items` itself is not checked for NULL as calling free on NULL is defined to be a no-op. --- dmenu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dmenu.c b/dmenu.c index 773f49a..0293dac 100644 --- a/dmenu.c +++ b/dmenu.c @@ -107,6 +107,9 @@ cleanup(void) XUngrabKey(dpy, AnyKey, AnyModifier, root); for (i = 0; i < SchemeLast; i++) free(scheme[i]); + for (i = 0; items && items[i].text; ++i) + free(items[i].text); + free(items); drw_free(drw); XSync(dpy, False); XCloseDisplay(dpy); @@ -327,7 +330,7 @@ match(void) /* separate input text into tokens to be matched individually */ for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) - die("cannot realloc %u bytes:", tokn * sizeof *tokv); + die("cannot realloc %zu bytes:", tokn * sizeof *tokv); len = tokc ? strlen(tokv[0]) : 0; matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; @@ -641,11 +644,11 @@ readstdin(void) for (i = 0; fgets(buf, sizeof buf, stdin); i++) { if (i + 1 >= size / sizeof *items) if (!(items = realloc(items, (size += BUFSIZ)))) - die("cannot realloc %u bytes:", size); + die("cannot realloc %zu bytes:", size); if ((p = strchr(buf, '\n'))) *p = '\0'; if (!(items[i].text = strdup(buf))) - die("cannot strdup %u bytes:", strlen(buf) + 1); + die("cannot strdup %zu bytes:", strlen(buf) + 1); items[i].out = 0; } if (items) From ad50c7b7417788c81e08f3711e737da7b4aed004 Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 25 Mar 2022 22:51:45 +0100 Subject: [PATCH 17/32] avoid redraw when there's no change while i was timing the performance issue, i noticed that there was lots of random redrawing going on. turns out there were coming from here; if someone presses CTRL/ALT etc without pressing anything else, nothing will be inserted, so nothing will change. but the code will `break`, go down and do a needless redraw. this patch changes it to simply return if the keypress iscntrl() also avoid potential UB by casting *buf into an unsigned char. --- dmenu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dmenu.c b/dmenu.c index 0293dac..4f485ce 100644 --- a/dmenu.c +++ b/dmenu.c @@ -503,8 +503,9 @@ keypress(XKeyEvent *ev) switch(ksym) { default: insert: - if (!iscntrl(*buf)) - insert(buf, len); + if (iscntrl((unsigned char)*buf)) + return; + insert(buf, len); break; case XK_Delete: case XK_KP_Delete: From 273d967324335f39d26afcf28f6b30c9e9fc782d Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 26 Mar 2022 17:57:50 +0100 Subject: [PATCH 18/32] Revert "avoid redraw when there's no change" This reverts commit 6818e07291f3b2913e687c8ec3d3fe4711724050. This broke keys such as ^W to delete-backward-word --- dmenu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dmenu.c b/dmenu.c index 4f485ce..0293dac 100644 --- a/dmenu.c +++ b/dmenu.c @@ -503,9 +503,8 @@ keypress(XKeyEvent *ev) switch(ksym) { default: insert: - if (iscntrl((unsigned char)*buf)) - return; - insert(buf, len); + if (!iscntrl(*buf)) + insert(buf, len); break; case XK_Delete: case XK_KP_Delete: From d4b980b76342ec07652eb0b0a8d93423692b327b Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 26 Mar 2022 17:58:47 +0100 Subject: [PATCH 19/32] fix UB with the function iscntrl() From commit 6818e07291f3b2913e687c8ec3d3fe4711724050 by NRK, thanks --- dmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmenu.c b/dmenu.c index 0293dac..6975e64 100644 --- a/dmenu.c +++ b/dmenu.c @@ -503,7 +503,7 @@ keypress(XKeyEvent *ev) switch(ksym) { default: insert: - if (!iscntrl(*buf)) + if (!iscntrl((unsigned char)*buf)) insert(buf, len); break; case XK_Delete: From e29eca6fdb19ae7c41843382cab6a0196eb11387 Mon Sep 17 00:00:00 2001 From: NRK Date: Mon, 28 Mar 2022 01:02:52 +0600 Subject: [PATCH 20/32] drw_text: don't segfault when called with 0 width this patch just rejects *any* 0 width draws, which is surely an error by the caller. this also guards against cases where the width is too small for the ellipsis to fit, so ellipsis_w will remain 0. reported by Bakkeby --- drw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drw.c b/drw.c index a50c9ee..2f3a5df 100644 --- a/drw.c +++ b/drw.c @@ -267,7 +267,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp enum { nomatches_len = 64 }; static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) return 0; if (!render) { From af8fbc7a90f51e95b1171cec50738b517249f352 Mon Sep 17 00:00:00 2001 From: NRK Date: Mon, 28 Mar 2022 21:38:49 +0600 Subject: [PATCH 21/32] drw_text: account for fallback fonts in ellipsis_width additionally, ellipsis_width (which shouldn't change) is made static to avoid re-calculating it on each drw_text() call. --- drw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drw.c b/drw.c index 2f3a5df..ced7d37 100644 --- a/drw.c +++ b/drw.c @@ -252,7 +252,7 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { int i, ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont; int utf8strlen, utf8charlen, render = x || y || w || h; @@ -266,6 +266,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp /* keep track of a couple codepoints for which we have no match. */ enum { nomatches_len = 64 }; static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; + static unsigned int ellipsis_width = 0; if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) return 0; @@ -283,7 +284,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } usedfont = drw->fonts; - drw_font_getexts(usedfont, "...", 3, &ellipsis_width, NULL); + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, "..."); while (1) { ew = ellipsis_len = utf8strlen = 0; utf8str = text; From a5a24f475f4b9b87b1cd2c6dc29f215b0371f17e Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 29 Apr 2022 20:15:48 +0200 Subject: [PATCH 22/32] inputw: improve correctness and startup performance, by NRK Always use ~30% of the monitor width for the input in horizontal mode. Patch adapted from NRK patches. This also does not calculate inputw when using vertical mode anymore (because the code is removed). --- dmenu.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/dmenu.c b/dmenu.c index 6975e64..1cee70f 100644 --- a/dmenu.c +++ b/dmenu.c @@ -698,13 +698,12 @@ static void setup(void) { int x, y, i, j; - unsigned int du, tmp; + unsigned int du; XSetWindowAttributes swa; XIM xim; Window w, dw, *dws; XWindowAttributes wa; XClassHint ch = {"dmenu", "dmenu"}; - struct item *item; #ifdef XINERAMA XineramaScreenInfo *info; Window pw; @@ -762,12 +761,7 @@ setup(void) mw = wa.width; } promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - for (item = items; item && item->text; ++item) { - if ((tmp = textw_clamp(item->text, mw/3)) > inputw) { - if ((inputw = tmp) == mw/3) - break; - } - } + inputw = mw / 3; /* input width: ~30% of monitor width */ match(); /* create menu window */ From 801a3e50dd89821b7c56bb2fea91773d44cdc808 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 30 Apr 2022 13:19:33 +0200 Subject: [PATCH 23/32] fix incorrect comment, math is hard --- dmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmenu.c b/dmenu.c index 1cee70f..2639530 100644 --- a/dmenu.c +++ b/dmenu.c @@ -761,7 +761,7 @@ setup(void) mw = wa.width; } promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = mw / 3; /* input width: ~30% of monitor width */ + inputw = mw / 3; /* input width: ~33% of monitor width */ match(); /* create menu window */ From 78e64ffb9c997cdf070910b7d3af3c12fe1e991a Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 1 May 2022 18:38:25 +0200 Subject: [PATCH 24/32] Makefile: add manual path for OpenBSD --- config.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mk b/config.mk index ddb33fa..cc68342 100644 --- a/config.mk +++ b/config.mk @@ -17,6 +17,7 @@ FREETYPELIBS = -lfontconfig -lXft FREETYPEINC = /usr/include/freetype2 # OpenBSD (uncomment) #FREETYPEINC = $(X11INC)/freetype2 +#MANPREFIX = ${PREFIX}/man # includes and libs INCS = -I$(X11INC) -I$(FREETYPEINC) From 16524400dca94f0232a826094f67f253449e2161 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Mon, 8 Aug 2022 10:42:54 +0200 Subject: [PATCH 25/32] sync code-style patch from libsl --- util.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/util.c b/util.c index fe044fc..96b82c9 100644 --- a/util.c +++ b/util.c @@ -6,18 +6,9 @@ #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, ...) { +die(const char *fmt, ...) +{ va_list ap; va_start(ap, fmt); @@ -33,3 +24,13 @@ die(const char *fmt, ...) { exit(1); } + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} From 61d32c8d358ba8c65aca63b70ab62de4b070a8da Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 2 Sep 2022 00:35:18 +0600 Subject: [PATCH 26/32] readstdin: use getline(3) currently readstdin(): - fgets() into a local buffer, - strchr() the buffer to eleminate the newline - stdups() the buffer into items a simpler way is to just use getline(3), which will do the allocation for us; eliminating the need for stdup()-ing. additionally getline returns back the amount of bytes read, which eliminates the need for strchr()-ing to find the newline. --- dmenu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dmenu.c b/dmenu.c index 2639530..ae5f694 100644 --- a/dmenu.c +++ b/dmenu.c @@ -637,18 +637,18 @@ paste(void) static void readstdin(void) { - char buf[sizeof text], *p; - size_t i, size = 0; + char *line = NULL; + size_t i, junk, size = 0; + ssize_t len; /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { + for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++, line = NULL) { if (i + 1 >= size / sizeof *items) if (!(items = realloc(items, (size += BUFSIZ)))) die("cannot realloc %zu bytes:", size); - if ((p = strchr(buf, '\n'))) - *p = '\0'; - if (!(items[i].text = strdup(buf))) - die("cannot strdup %zu bytes:", strlen(buf) + 1); + if (line[len - 1] == '\n') + line[len - 1] = '\0'; + items[i].text = line; items[i].out = 0; } if (items) From 2960a6644f01b241193d898fd8ffa5e044271d3a Mon Sep 17 00:00:00 2001 From: NRK Date: Thu, 1 Sep 2022 23:51:43 +0600 Subject: [PATCH 27/32] tab-complete: figure out the size before copying we already need to know the string length since `cursor` needs to be adjusted. so just calculate the length beforehand and use `memcpy` to copy exactly as much as needed (as opposed to `strncpy` which always writes `n` bytes). --- dmenu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmenu.c b/dmenu.c index ae5f694..da66121 100644 --- a/dmenu.c +++ b/dmenu.c @@ -605,9 +605,9 @@ insert: case XK_Tab: if (!sel) return; - strncpy(text, sel->text, sizeof text - 1); + cursor = strnlen(sel->text, sizeof text - 1); + memcpy(text, sel->text, cursor); text[sizeof text - 1] = '\0'; - cursor = strlen(text); match(); break; } From 4717a35cfb0c30f26dd729da3f810c833fe4f6df Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 2 Sep 2022 19:09:50 +0200 Subject: [PATCH 28/32] fix a regression in the previous commit for tab complete Reported by Santtu Lakkala , thanks! --- dmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmenu.c b/dmenu.c index da66121..07b466d 100644 --- a/dmenu.c +++ b/dmenu.c @@ -607,7 +607,7 @@ insert: return; cursor = strnlen(sel->text, sizeof text - 1); memcpy(text, sel->text, cursor); - text[sizeof text - 1] = '\0'; + text[cursor] = '\0'; match(); break; } From c0783a60ad5033664727e46173ec50a4200d5ca8 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 16 Sep 2022 23:05:07 +0200 Subject: [PATCH 29/32] remove workaround for a crash with color emojis on some systems, now fixed in libXft 2.3.5 https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS --- drw.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drw.c b/drw.c index ced7d37..a58a2b4 100644 --- a/drw.c +++ b/drw.c @@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) 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; @@ -368,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp 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); From e68533eb4bde738fd71a4f975aeffaa95bfecf53 Mon Sep 17 00:00:00 2001 From: Tom Schwindl Date: Mon, 26 Sep 2022 09:24:15 +0000 Subject: [PATCH 30/32] dmenu: use die() to print the usage message --- dmenu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dmenu.c b/dmenu.c index 07b466d..0363aa0 100644 --- a/dmenu.c +++ b/dmenu.c @@ -798,9 +798,8 @@ setup(void) static void usage(void) { - fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); - exit(1); + die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); } int From 8dfee8f81b57d5802e4ab1067b09ce036c415728 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 19 Oct 2022 17:40:07 +0200 Subject: [PATCH 31/32] Updated PKGBUILD --- PKGBUILD | 23 +++++++++++++---------- config.mk | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 44a319f..5476feb 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,9 +1,11 @@ # Maintainer: Jef Roosens -pkgname="jjr-dmenu" -pkgver="5.2" +pkgname=jjr-dmenu +pkgver=5.3 pkgrel=1 pkgdesc="Chewing_Bever's custom build of Suckless's dmenu." +url="https://git.rustybever.be/Chewing_Bever/dmenu" + arch=( "x86_64" "x86_64_tigerlake" @@ -11,11 +13,10 @@ arch=( "aarch64" ) -url="https://git.rustybever.be/Chewing_Bever/dmenu" license=("MIT") -depends=("libxinerama" "libxft" "fontconfig" "freetype2") -makedepends=("glibc" "gcc") +depends=("glibc" "libxinerama" "libxft" "fontconfig" "freetype2") +makedepends=("gcc") provides=("dmenu") conflicts=("dmenu-git") @@ -24,19 +25,19 @@ source=("arg.h" "config.h" "config.mk" "dmenu.1" "dmenu.c" "dmenu_path.sh" "stest.c" "util.c" "util.h") sha256sums=('9ed2b2e3396fdebc8ecab2cdbb09db115cca015f63ec0443b8ccc56340b6b03c' '9ae33f74aed02823abb8381e553d38455541ce3b6a0d642282b693992e71caef' - 'f6de4c72dab3b9bef214bd52e6a7dff22e87a3118abaffd26ec1ae589cf68b3f' + '5a6066f1cf97aaee4792708893faa1f16fad39d4dce22c79ccfb7590349fe0cc' '9f749419697381a1db77e9b23cb41629808fd7e451d475c9b5ee0e88bee803f6' - '5b2a53db7ba608d392efaa96be5530665b46107dc4e0ee1a864745a6e8a8587d' + 'dc93fd213531f01c968ec073382d4c91c14a3fb2464e1a62e23e94653a74fb81' 'a3f19e648e20eb80532dfe87e9bd9feeaa92df838e6ecc061f274c9da579d617' '564035fd8a8ade6504521d98fa10e8732e135403d546d04ca77316fe4a67b21c' - 'a7c7358ce13c8571044b79d5d91d01314d9174793474a27faa37d23c75ab603f' - 'c35796210ea8410ae096025cc0d7996dccb3d9936306dff7531a0bb253e079f5' + '8c9f81b98f447440cf59dd3eefda99eec4e7733266ad0c072612163ccff4e1df' + '7ed1cf72bfcb0f5444f338293aef74c455ce4ed5463f171a48358f64d7835d49' '9f8e922fcfc18ffcc4975dd0b1bee38302bd4e0c538251dfef6d77cd7ed59c89' 'c32b5173eddf376296af085725cb878e4ca2603d4fda8bba3faac6a2bb1b4390' 'ec98e8759049af796598f0790752a21a69eaea1d438b09c39922d4a9f4a7cfe2' '00d3389ef8858a565cf3fb3445620b90eb67d1a9b31434f4d54b05ed6c5abefb' 'ba76404e61abbd734e315999ffe4e883419c4c69ff17a5d4d88a5cd11dd4b055' - 'dec870d0b5834c9008ff62f495710daf524cffdf12d0cf8ba4fadf5643623987' + '1c093b9969daaf3e1a001b924c6c2da3770993916b444dfe65fe39aa0090aa1a' '1196a7b6efbf4cb3f5c435fffd72e7647f977483845d5c78c1c48d9ab8b96819') build() { @@ -56,3 +57,5 @@ package() { # install $installopts "$docdir" README.terminfo.rst # install $installopts "$shrdir/$pkgname" "$_sourcedir/st.info" } + +# vim: ft=bash diff --git a/config.mk b/config.mk index cc68342..0ea1efd 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dmenu version -VERSION = 5.2 +VERSION = 5.3 # paths PREFIX = /usr/local From 78280fae2bb95017f72318f6c2c1b94c3d541c2f Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 19 Oct 2022 17:43:01 +0200 Subject: [PATCH 32/32] Updated checksums --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKGBUILD b/PKGBUILD index 5476feb..a718c1d 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -25,7 +25,7 @@ source=("arg.h" "config.h" "config.mk" "dmenu.1" "dmenu.c" "dmenu_path.sh" "stest.c" "util.c" "util.h") sha256sums=('9ed2b2e3396fdebc8ecab2cdbb09db115cca015f63ec0443b8ccc56340b6b03c' '9ae33f74aed02823abb8381e553d38455541ce3b6a0d642282b693992e71caef' - '5a6066f1cf97aaee4792708893faa1f16fad39d4dce22c79ccfb7590349fe0cc' + 'a2a83c2343343e44d6c0f50a9de1ace023599974e5cb4b12d90e69ed66cdb22f' '9f749419697381a1db77e9b23cb41629808fd7e451d475c9b5ee0e88bee803f6' 'dc93fd213531f01c968ec073382d4c91c14a3fb2464e1a62e23e94653a74fb81' 'a3f19e648e20eb80532dfe87e9bd9feeaa92df838e6ecc061f274c9da579d617'