Compare commits
No commits in common. "main" and "3a505cebe8adab204e5619357e0bfe3f9f3a92ff" have entirely different histories.
main
...
3a505cebe8
|
|
@ -1,12 +0,0 @@
|
||||||
*.rej
|
|
||||||
*.orig
|
|
||||||
|
|
||||||
# build artifacts
|
|
||||||
*.o
|
|
||||||
dmenu
|
|
||||||
stest
|
|
||||||
|
|
||||||
# makepkg
|
|
||||||
src/
|
|
||||||
pkg/
|
|
||||||
*.pkg*
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
matrix:
|
|
||||||
# PLATFORM:
|
|
||||||
# - linux/amd64
|
|
||||||
# - linux/arm64
|
|
||||||
|
|
||||||
ARCH:
|
|
||||||
# tuur
|
|
||||||
- tigerlake
|
|
||||||
# cenny
|
|
||||||
- skylake
|
|
||||||
|
|
||||||
branches: main
|
|
||||||
platform: linux/amd64
|
|
||||||
|
|
||||||
when:
|
|
||||||
event: push
|
|
||||||
|
|
||||||
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
|
|
||||||
- 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
|
|
||||||
CFLAGS="-O3 -flto -march=${ARCH}"
|
|
||||||
CARCH="x86_64_${ARCH}"
|
|
||||||
|
|
||||||
publish:
|
|
||||||
image: 'curlimages/curl'
|
|
||||||
commands:
|
|
||||||
# Publish the package
|
|
||||||
- 'curl -s -XPOST -H "X-API-KEY: $API_KEY" -T "$(ls *.pkg*)" https://arch.r8r.be/jjr/publish'
|
|
||||||
secrets:
|
|
||||||
- api_key
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -42,9 +42,7 @@ dist: clean
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
cp -f dmenu stest $(DESTDIR)$(PREFIX)/bin
|
cp -f dmenu dmenu_path dmenu_run 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
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
|
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
|
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
|
||||||
|
|
|
||||||
61
PKGBUILD
61
PKGBUILD
|
|
@ -1,61 +0,0 @@
|
||||||
# Maintainer: Jef Roosens
|
|
||||||
|
|
||||||
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"
|
|
||||||
"x86_64_skylake"
|
|
||||||
"aarch64"
|
|
||||||
)
|
|
||||||
|
|
||||||
license=("MIT")
|
|
||||||
|
|
||||||
depends=("glibc" "libxinerama" "libxft" "fontconfig" "freetype2")
|
|
||||||
makedepends=("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'
|
|
||||||
'9ae33f74aed02823abb8381e553d38455541ce3b6a0d642282b693992e71caef'
|
|
||||||
'a2a83c2343343e44d6c0f50a9de1ace023599974e5cb4b12d90e69ed66cdb22f'
|
|
||||||
'9f749419697381a1db77e9b23cb41629808fd7e451d475c9b5ee0e88bee803f6'
|
|
||||||
'dc93fd213531f01c968ec073382d4c91c14a3fb2464e1a62e23e94653a74fb81'
|
|
||||||
'a3f19e648e20eb80532dfe87e9bd9feeaa92df838e6ecc061f274c9da579d617'
|
|
||||||
'564035fd8a8ade6504521d98fa10e8732e135403d546d04ca77316fe4a67b21c'
|
|
||||||
'8c9f81b98f447440cf59dd3eefda99eec4e7733266ad0c072612163ccff4e1df'
|
|
||||||
'7ed1cf72bfcb0f5444f338293aef74c455ce4ed5463f171a48358f64d7835d49'
|
|
||||||
'9f8e922fcfc18ffcc4975dd0b1bee38302bd4e0c538251dfef6d77cd7ed59c89'
|
|
||||||
'c32b5173eddf376296af085725cb878e4ca2603d4fda8bba3faac6a2bb1b4390'
|
|
||||||
'ec98e8759049af796598f0790752a21a69eaea1d438b09c39922d4a9f4a7cfe2'
|
|
||||||
'00d3389ef8858a565cf3fb3445620b90eb67d1a9b31434f4d54b05ed6c5abefb'
|
|
||||||
'ba76404e61abbd734e315999ffe4e883419c4c69ff17a5d4d88a5cd11dd4b055'
|
|
||||||
'1c093b9969daaf3e1a001b924c6c2da3770993916b444dfe65fe39aa0090aa1a'
|
|
||||||
'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"
|
|
||||||
}
|
|
||||||
|
|
||||||
# vim: ft=bash
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
/* Default settings; can be overriden by command line. */
|
/* Default settings; can be overriden by command line. */
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
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 */
|
/* -fn option overrides fonts[0]; default X11 font or font set */
|
||||||
static const char *fonts[] = {
|
static const char *fonts[] = {
|
||||||
"monospace:size=10"
|
"monospace:size=10"
|
||||||
|
|
|
||||||
24
config.h
24
config.h
|
|
@ -1,24 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
/* Default settings; can be overriden by command line. */
|
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
|
||||||
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"
|
|
||||||
};
|
|
||||||
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[] = " ";
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# dmenu version
|
# dmenu version
|
||||||
VERSION = 5.3
|
VERSION = 5.1
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
@ -17,15 +17,14 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||||
FREETYPEINC = /usr/include/freetype2
|
FREETYPEINC = /usr/include/freetype2
|
||||||
# OpenBSD (uncomment)
|
# OpenBSD (uncomment)
|
||||||
#FREETYPEINC = $(X11INC)/freetype2
|
#FREETYPEINC = $(X11INC)/freetype2
|
||||||
#MANPREFIX = ${PREFIX}/man
|
|
||||||
|
|
||||||
# includes and libs
|
# includes and libs
|
||||||
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
||||||
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm
|
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
||||||
CFLAGS = -std=c99 -pedantic -Wall -O3 $(INCS) $(CPPFLAGS)
|
CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
|
||||||
LDFLAGS = $(LIBS)
|
LDFLAGS = $(LIBS)
|
||||||
|
|
||||||
# compiler and linker
|
# compiler and linker
|
||||||
|
|
|
||||||
6
dmenu.1
6
dmenu.1
|
|
@ -3,7 +3,7 @@
|
||||||
dmenu \- dynamic menu
|
dmenu \- dynamic menu
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B dmenu
|
.B dmenu
|
||||||
.RB [ \-bfsv ]
|
.RB [ \-bfiv ]
|
||||||
.RB [ \-l
|
.RB [ \-l
|
||||||
.IR lines ]
|
.IR lines ]
|
||||||
.RB [ \-m
|
.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
|
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.
|
is faster, but will lock up X until stdin reaches end\-of\-file.
|
||||||
.TP
|
.TP
|
||||||
.B \-s
|
.B \-i
|
||||||
dmenu matches menu items case sensitively.
|
dmenu matches menu items case insensitively.
|
||||||
.TP
|
.TP
|
||||||
.BI \-l " lines"
|
.BI \-l " lines"
|
||||||
dmenu lists items vertically, with the given number of lines.
|
dmenu lists items vertically, with the given number of lines.
|
||||||
|
|
|
||||||
156
dmenu.c
156
dmenu.c
|
|
@ -1,7 +1,6 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <math.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -33,7 +32,6 @@ struct item {
|
||||||
char *text;
|
char *text;
|
||||||
struct item *left, *right;
|
struct item *left, *right;
|
||||||
int out;
|
int out;
|
||||||
double distance;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static char text[BUFSIZ] = "";
|
static char text[BUFSIZ] = "";
|
||||||
|
|
@ -57,16 +55,8 @@ static Clr *scheme[SchemeLast];
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
static char * cistrstr(const char *s, const char *sub);
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
static char *(*fstrstr)(const char *, const char *) = strstr;
|
||||||
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
|
static void
|
||||||
appenditem(struct item *item, struct item **list, struct item **last)
|
appenditem(struct item *item, struct item **list, struct item **last)
|
||||||
|
|
@ -92,10 +82,10 @@ calcoffsets(void)
|
||||||
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
||||||
/* calculate which items will begin the next page and previous page */
|
/* calculate which items will begin the next page and previous page */
|
||||||
for (i = 0, next = curr; next; next = next->right)
|
for (i = 0, next = curr; next; next = next->right)
|
||||||
if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n)
|
if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
|
||||||
break;
|
break;
|
||||||
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
||||||
if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n)
|
if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,9 +97,6 @@ cleanup(void)
|
||||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||||
for (i = 0; i < SchemeLast; i++)
|
for (i = 0; i < SchemeLast; i++)
|
||||||
free(scheme[i]);
|
free(scheme[i]);
|
||||||
for (i = 0; items && items[i].text; ++i)
|
|
||||||
free(items[i].text);
|
|
||||||
free(items);
|
|
||||||
drw_free(drw);
|
drw_free(drw);
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
|
|
@ -185,7 +172,7 @@ drawmenu(void)
|
||||||
}
|
}
|
||||||
x += w;
|
x += w;
|
||||||
for (item = curr; item != next; item = item->right)
|
for (item = curr; item != next; item = item->right)
|
||||||
x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">")));
|
x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
|
||||||
if (next) {
|
if (next) {
|
||||||
w = TEXTW(">");
|
w = TEXTW(">");
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
|
|
@ -230,94 +217,9 @@ grabkeyboard(void)
|
||||||
die("cannot grab keyboard");
|
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
|
static void
|
||||||
match(void)
|
match(void)
|
||||||
{
|
{
|
||||||
if (fuzzy) {
|
|
||||||
fuzzymatch();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static char **tokv = NULL;
|
static char **tokv = NULL;
|
||||||
static int tokn = 0;
|
static int tokn = 0;
|
||||||
|
|
||||||
|
|
@ -330,7 +232,7 @@ match(void)
|
||||||
/* separate input text into tokens to be matched individually */
|
/* separate input text into tokens to be matched individually */
|
||||||
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
||||||
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
||||||
die("cannot realloc %zu bytes:", tokn * sizeof *tokv);
|
die("cannot realloc %u bytes:", tokn * sizeof *tokv);
|
||||||
len = tokc ? strlen(tokv[0]) : 0;
|
len = tokc ? strlen(tokv[0]) : 0;
|
||||||
|
|
||||||
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
|
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
|
||||||
|
|
@ -503,7 +405,7 @@ keypress(XKeyEvent *ev)
|
||||||
switch(ksym) {
|
switch(ksym) {
|
||||||
default:
|
default:
|
||||||
insert:
|
insert:
|
||||||
if (!iscntrl((unsigned char)*buf))
|
if (!iscntrl(*buf))
|
||||||
insert(buf, len);
|
insert(buf, len);
|
||||||
break;
|
break;
|
||||||
case XK_Delete:
|
case XK_Delete:
|
||||||
|
|
@ -605,9 +507,9 @@ insert:
|
||||||
case XK_Tab:
|
case XK_Tab:
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return;
|
return;
|
||||||
cursor = strnlen(sel->text, sizeof text - 1);
|
strncpy(text, sel->text, sizeof text - 1);
|
||||||
memcpy(text, sel->text, cursor);
|
text[sizeof text - 1] = '\0';
|
||||||
text[cursor] = '\0';
|
cursor = strlen(text);
|
||||||
match();
|
match();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -637,22 +539,29 @@ paste(void)
|
||||||
static void
|
static void
|
||||||
readstdin(void)
|
readstdin(void)
|
||||||
{
|
{
|
||||||
char *line = NULL;
|
char buf[sizeof text], *p;
|
||||||
size_t i, junk, size = 0;
|
size_t i, imax = 0, size = 0;
|
||||||
ssize_t len;
|
unsigned int tmpmax = 0;
|
||||||
|
|
||||||
/* read each line from stdin and add it to the item list */
|
/* read each line from stdin and add it to the item list */
|
||||||
for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++, line = NULL) {
|
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
|
||||||
if (i + 1 >= size / sizeof *items)
|
if (i + 1 >= size / sizeof *items)
|
||||||
if (!(items = realloc(items, (size += BUFSIZ))))
|
if (!(items = realloc(items, (size += BUFSIZ))))
|
||||||
die("cannot realloc %zu bytes:", size);
|
die("cannot realloc %u bytes:", size);
|
||||||
if (line[len - 1] == '\n')
|
if ((p = strchr(buf, '\n')))
|
||||||
line[len - 1] = '\0';
|
*p = '\0';
|
||||||
items[i].text = line;
|
if (!(items[i].text = strdup(buf)))
|
||||||
|
die("cannot strdup %u bytes:", strlen(buf) + 1);
|
||||||
items[i].out = 0;
|
items[i].out = 0;
|
||||||
|
drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL);
|
||||||
|
if (tmpmax > inputw) {
|
||||||
|
inputw = tmpmax;
|
||||||
|
imax = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (items)
|
if (items)
|
||||||
items[i].text = NULL;
|
items[i].text = NULL;
|
||||||
|
inputw = items ? TEXTW(items[imax].text) : 0;
|
||||||
lines = MIN(lines, i);
|
lines = MIN(lines, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -761,7 +670,7 @@ setup(void)
|
||||||
mw = wa.width;
|
mw = wa.width;
|
||||||
}
|
}
|
||||||
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
||||||
inputw = mw / 3; /* input width: ~33% of monitor width */
|
inputw = MIN(inputw, mw/3);
|
||||||
match();
|
match();
|
||||||
|
|
||||||
/* create menu window */
|
/* create menu window */
|
||||||
|
|
@ -798,8 +707,9 @@ setup(void)
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
||||||
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
|
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -817,11 +727,9 @@ main(int argc, char *argv[])
|
||||||
topbar = 0;
|
topbar = 0;
|
||||||
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
|
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
|
||||||
fast = 1;
|
fast = 1;
|
||||||
else if (!strcmp(argv[i], "-F")) /* disable fuzzy search */
|
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
|
||||||
fuzzy = 0;
|
fstrncmp = strncasecmp;
|
||||||
else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */
|
fstrstr = cistrstr;
|
||||||
fstrncmp = strncmp;
|
|
||||||
fstrstr = strstr;
|
|
||||||
} else if (i + 1 == argc)
|
} else if (i + 1 == argc)
|
||||||
usage();
|
usage();
|
||||||
/* these options take one argument */
|
/* these options take one argument */
|
||||||
|
|
|
||||||
106
drw.c
106
drw.c
|
|
@ -133,6 +133,19 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||||
die("no font specified.");
|
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 = ecalloc(1, sizeof(Fnt));
|
||||||
font->xfont = xfont;
|
font->xfont = xfont;
|
||||||
font->pattern = pattern;
|
font->pattern = pattern;
|
||||||
|
|
@ -238,10 +251,12 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
|
||||||
int
|
int
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
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;
|
char buf[1024];
|
||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
int ty;
|
||||||
|
unsigned int ew;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
|
size_t i, len;
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
|
|
@ -249,17 +264,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
FcPattern *fcpattern;
|
FcPattern *fcpattern;
|
||||||
FcPattern *match;
|
FcPattern *match;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0, overflow = 0;
|
int charexists = 0;
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
|
||||||
enum { nomatches_len = 64 };
|
|
||||||
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
|
||||||
static unsigned int ellipsis_width = 0;
|
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = invert ? invert : ~invert;
|
w = ~w;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
|
@ -271,10 +282,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
if (!ellipsis_width && render)
|
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ew = ellipsis_len = utf8strlen = 0;
|
utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
|
@ -282,27 +291,9 @@ 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) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
if (curfont == usedfont) {
|
||||||
if (ew + ellipsis_width <= w) {
|
|
||||||
/* keep track where the ellipsis still fits */
|
|
||||||
ellipsis_x = x + ew;
|
|
||||||
ellipsis_w = w - ew;
|
|
||||||
ellipsis_len = utf8strlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ew + tmpw > w) {
|
|
||||||
overflow = 1;
|
|
||||||
/* called from drw_fontset_getwidth_clamp():
|
|
||||||
* it wants the width AFTER the overflow
|
|
||||||
*/
|
|
||||||
if (!render)
|
|
||||||
x += tmpw;
|
|
||||||
else
|
|
||||||
utf8strlen = ellipsis_len;
|
|
||||||
} else if (curfont == usedfont) {
|
|
||||||
utf8strlen += utf8charlen;
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
ew += tmpw;
|
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
|
|
@ -310,25 +301,36 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont)
|
if (!charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8strlen) {
|
if (utf8strlen) {
|
||||||
if (render) {
|
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
/* shorten text if necessary */
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
|
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
|
||||||
if (render && overflow)
|
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
|
||||||
|
|
||||||
if (!*text || overflow) {
|
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;
|
break;
|
||||||
} else if (nextfont) {
|
} else if (nextfont) {
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
|
|
@ -338,12 +340,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
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();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
|
|
@ -355,6 +351,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
|
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
FcDefaultSubstitute(fcpattern);
|
FcDefaultSubstitute(fcpattern);
|
||||||
|
|
@ -371,8 +368,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
|
||||||
no_match:
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -402,15 +397,6 @@ drw_fontset_getwidth(Drw *drw, const char *text)
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
|
||||||
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
|
|
||||||
{
|
|
||||||
unsigned int tmp = 0;
|
|
||||||
if (drw && drw->fonts && text && n)
|
|
||||||
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
|
||||||
return MIN(n, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
1
drw.h
1
drw.h
|
|
@ -35,7 +35,6 @@ void drw_free(Drw *drw);
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
void drw_fontset_free(Fnt* set);
|
void drw_fontset_free(Fnt* set);
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
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);
|
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
/* Colorscheme abstraction */
|
||||||
|
|
|
||||||
23
util.c
23
util.c
|
|
@ -6,9 +6,18 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void
|
void *
|
||||||
die(const char *fmt, ...)
|
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_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
@ -24,13 +33,3 @@ die(const char *fmt, ...)
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
|
||||||
ecalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
|
||||||
die("calloc:");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue