Skip to content

Commit

Permalink
merge with upstream 5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
0jdxt committed Mar 26, 2024
2 parents a759dc0 + 7be720c commit 6d34a92
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 57 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MIT/X Consortium License
© 2009 Markus Schnalke <[email protected]>
© 2009 Evan Gates <[email protected]>
© 2010-2012 Connor Lane Smith <[email protected]>
© 2014-2020 Hiltjo Posthuma <[email protected]>
© 2014-2022 Hiltjo Posthuma <[email protected]>
© 2015-2019 Quentin Rameau <[email protected]>
© 2024 Jay Tauron <[email protected]>

Expand Down
10 changes: 2 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ include config.mk
SRC = drw.c dmenu.c stest.c util.c
OBJ = $(SRC:.c=.o)

all: options dmenu stest

options:
@echo dmenu build options:
@echo "CFLAGS = $(CFLAGS)"
@echo "LDFLAGS = $(LDFLAGS)"
@echo "CC = $(CC)"
all: dmenu stest

.c.o:
$(CC) -c $(CFLAGS) $<
Expand Down Expand Up @@ -61,4 +55,4 @@ uninstall:
$(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
$(DESTDIR)$(MANPREFIX)/man1/stest.1

.PHONY: all options clean dist install uninstall
.PHONY: all clean dist install uninstall
3 changes: 2 additions & 1 deletion config.mk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# dmenu version
VERSION = 5.0
VERSION = 5.3

# paths
PREFIX = /usr/local
Expand All @@ -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)
Expand Down
53 changes: 41 additions & 12 deletions dmenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ static Clr *scheme[SchemeLast];
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
static char *(*fstrstr)(const char *, const char *) = strstr;

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) {
if (*last)
Expand All @@ -93,9 +98,9 @@ static void 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) break;
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;
}

Expand All @@ -111,6 +116,8 @@ static void 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);
Expand Down Expand Up @@ -440,11 +447,11 @@ static void movewordedge(int dir) {
}

static void keypress(XKeyEvent *ev) {
char buf[32];
char buf[64];
int len;
KeySym ksym;
Status status;
int i;

struct item *tmpsel;
bool offscreen = false;

Expand Down Expand Up @@ -600,6 +607,7 @@ static void keypress(XKeyEvent *ev) {
cleanup();
exit(1);
case XK_Home:
case XK_KP_Home:
if (sel == matches) {
cursor = 0;
break;
Expand Down Expand Up @@ -835,6 +843,27 @@ static void mousemove(XEvent *e) {
}
}

static void readstdin(void) {
char *line = NULL;
size_t i, itemsiz = 0, linesiz = 0;
ssize_t len;
/* read each line from stdin and add it to the item list */
for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) {
if (i + 1 >= itemsiz) {
itemsiz += 256;
if (!(items = realloc(items, itemsiz * sizeof(*items))))
die("cannot realloc %zu bytes:", itemsiz * sizeof(*items));
}
if (line[len - 1] == '\n') line[len - 1] = '\0';
if (!(items[i].text = strdup(line))) die("strdup:");

items[i].out = 0;
}
free(line);
if (items) items[i].text = NULL;
lines = MIN(lines, i);
}

static void paste(void) {
char *p, *q;
int di;
Expand Down Expand Up @@ -966,7 +995,7 @@ static void setup(void) {
if (mon < 0 && !area &&
XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
for (i = 0; i < n; i++)
if (INTERSECT(x, y, 1, 1, info[i])) break;
if (INTERSECT(x, y, 1, 1, info[i]) != 0) break;

mw = (dmw > 0 ? dmw : MIN(MAX(max_textw(), 100), info[i].width));
x = info[i].x_org + ((info[i].width - mw) / 2);
Expand All @@ -989,8 +1018,8 @@ static void setup(void) {
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
ButtonPressMask | PointerMotionMask;
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,
CopyFromParent, CopyFromParent, CopyFromParent,
win = XCreateWindow(dpy, root, x, y, mw, mh, border_width, CopyFromParent,
CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
XSetClassHint(dpy, win, &ch);
Expand All @@ -1004,6 +1033,7 @@ static void setup(void) {

XMapRaised(dpy, win);
if (embed) {
XReparentWindow(dpy, win, parentwin, x, y);
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
for (i = 0; i < du && dws[i] != win; ++i)
Expand All @@ -1017,13 +1047,12 @@ static void setup(void) {
}

static void usage(void) {
fputs(
"usage: dmenu [-bfiv] [-l lines] [-g columns] [-p prompt] [-fn font] \n"
die("usage: dmenu [-bfiv] [-l lines] [-g columns] [-p prompt] [-fn "
"font] \n"
" [-m monitor] [-h height] [-z width] [-w windowid]\n"
" [-nb color] [-nf color] [-sb color] [-sf color]\n"
" [-nhb color] [-nhf color] [-shb color] [-shf color]\n",
stderr);
exit(1);
" [-nhb color] [-nhf color] [-shb color] [-shf "
"color]\n");
}

int main(int argc, char *argv[]) {
Expand Down
103 changes: 68 additions & 35 deletions drw.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,25 +203,26 @@ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h,

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, hash, h0, h1;
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;
int charexists = 0, overflow = 0;
/* keep track of a couple codepoints for which we have no match. */
static unsigned int nomatches[128], ellipsis_width;

if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0;
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0;

if (!render) {
w = ~w;
w = invert ? invert : ~invert;
} else {
XSetForeground(drw->dpy, drw->gc,
drw->scheme[invert ? ColFg : ColBg].pixel);
Expand All @@ -234,8 +235,10 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h,
}

usedfont = drw->fonts;
if (!ellipsis_width && render)
ellipsis_width = drw_fontset_getwidth(drw, "...");
while (1) {
utf8strlen = 0;
ew = ellipsis_len = utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
Expand All @@ -245,62 +248,82 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h,
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;
/* called from drw_fontset_getwidth_clamp():
* it wants the width AFTER the overflow
*/
if (!render)
x += tmpw;
else
utf8strlen = ellipsis_len;
} else if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
ew += tmpw;
} else {
nextfont = curfont;
}
break;
}
}

if (!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;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn. */
/* Regardless of whether or not a fallback font is found,
* the character must be drawn. */
charexists = 1;

hash = (unsigned int)utf8codepoint;
hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches);
h1 = (hash >> 17) % LENGTH(nomatches);
/* avoid expensive XftFontMatch call when we know we won't
* find a match */
if (nomatches[h0] == utf8codepoint ||
nomatches[h1] == utf8codepoint)
goto no_match;

fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);

if (!drw->fonts->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("the first font in the cache must be loaded from a font "
/* Refer to the comment in xfont_create for more
* information. */
die("the first font in the cache must be loaded from a "
"font "
"string.");
}

Expand All @@ -326,6 +349,8 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h,
curfont->next = usedfont;
} else {
xfont_free(usedfont);
nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
no_match:
usedfont = drw->fonts;
}
}
Expand All @@ -349,6 +374,14 @@ unsigned int 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) {
XGlyphInfo ext;
Expand Down
2 changes: 2 additions & 0 deletions drw.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ 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);

Expand Down
1 change: 1 addition & 0 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ void die(const char *fmt, ...) {

exit(1);
}

1 change: 1 addition & 0 deletions util.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#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))
#define LENGTH(X) (sizeof(X) / sizeof(X)[0])

void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);

0 comments on commit 6d34a92

Please sign in to comment.