Skip to content

Commit 7ef1e6c

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents ac5553f + 0fe460d commit 7ef1e6c

File tree

7 files changed

+142
-99
lines changed

7 files changed

+142
-99
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ MIT/X Consortium License
88
© 2009 Markus Schnalke <meillo@marmaro.de>
99
© 2009 Evan Gates <evan.gates@gmail.com>
1010
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
11-
© 2014-2020 Hiltjo Posthuma <hiltjo@codemadness.org>
11+
© 2014-2022 Hiltjo Posthuma <hiltjo@codemadness.org>
1212
© 2015-2019 Quentin Rameau <quinq@fifth.space>
1313

1414
Permission is hereby granted, free of charge, to any person obtaining a

config.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# dmenu version
2-
VERSION = 5.0
2+
VERSION = 5.2
33

44
# paths
55
PREFIX = /usr/local
@@ -17,6 +17,7 @@ FREETYPELIBS = -lfontconfig -lXft
1717
FREETYPEINC = /usr/include/freetype2
1818
# OpenBSD (uncomment)
1919
#FREETYPEINC = $(X11INC)/freetype2
20+
#MANPREFIX = ${PREFIX}/man
2021

2122
# includes and libs
2223
INCS = -I$(X11INC) -I$(FREETYPEINC)

dmenu.c

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ static Clr *scheme[SchemeLast];
6565
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
6666
static char *(*fstrstr)(const char *, const char *) = strstr;
6767

68+
static unsigned int
69+
textw_clamp(const char *str, unsigned int n)
70+
{
71+
unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad;
72+
return MIN(w, n);
73+
}
74+
6875
static void
6976
appenditem(struct item *item, struct item **list, struct item **last)
7077
{
@@ -89,10 +96,10 @@ calcoffsets(void)
8996
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
9097
/* calculate which items will begin the next page and previous page */
9198
for (i = 0, next = curr; next; next = next->right)
92-
if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
99+
if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n)
93100
break;
94101
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
95-
if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
102+
if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n)
96103
break;
97104
}
98105

@@ -104,19 +111,29 @@ cleanup(void)
104111
XUngrabKey(dpy, AnyKey, AnyModifier, root);
105112
for (i = 0; i < SchemeLast; i++)
106113
free(scheme[i]);
114+
for (i = 0; items && items[i].text; ++i)
115+
free(items[i].text);
116+
free(items);
107117
drw_free(drw);
108118
XSync(dpy, False);
109119
XCloseDisplay(dpy);
110120
}
111121

112122
static char *
113-
cistrstr(const char *s, const char *sub)
123+
cistrstr(const char *h, const char *n)
114124
{
115-
size_t len;
125+
size_t i;
126+
127+
if (!n[0])
128+
return (char *)h;
116129

117-
for (len = strlen(sub); *s; s++)
118-
if (!strncasecmp(s, sub, len))
119-
return (char *)s;
130+
for (; *h; ++h) {
131+
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
132+
tolower((unsigned char)h[i]); ++i)
133+
;
134+
if (n[i] == '\0')
135+
return (char *)h;
136+
}
120137
return NULL;
121138
}
122139

@@ -236,7 +253,7 @@ drawmenu(void)
236253
}
237254
x += w;
238255
for (item = curr; item != next; item = item->right)
239-
x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">") - TEXTW(numbers)));
256+
x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">") - TEXTW(numbers)));
240257
if (next) {
241258
w = TEXTW(">");
242259
drw_setscheme(drw, scheme[SchemeNorm]);
@@ -383,7 +400,7 @@ match(void)
383400
/* separate input text into tokens to be matched individually */
384401
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
385402
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
386-
die("cannot realloc %u bytes:", tokn * sizeof *tokv);
403+
die("cannot realloc %zu bytes:", tokn * sizeof *tokv);
387404
len = tokc ? strlen(tokv[0]) : 0;
388405

389406
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
@@ -472,19 +489,19 @@ movewordedge(int dir)
472489
static void
473490
keypress(XKeyEvent *ev)
474491
{
475-
char buf[32];
492+
char buf[64];
476493
int len;
477-
KeySym ksym;
494+
KeySym ksym = NoSymbol;
478495
Status status;
479496

480497
len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
481498
switch (status) {
482499
default: /* XLookupNone, XBufferOverflow */
483500
return;
484-
case XLookupChars:
501+
case XLookupChars: /* composed string from input method */
485502
goto insert;
486503
case XLookupKeySym:
487-
case XLookupBoth:
504+
case XLookupBoth: /* a KeySym and a string are returned: use keysym */
488505
break;
489506
}
490507

@@ -525,9 +542,11 @@ keypress(XKeyEvent *ev)
525542
utf8, utf8, win, CurrentTime);
526543
return;
527544
case XK_Left:
545+
case XK_KP_Left:
528546
movewordedge(-1);
529547
goto draw;
530548
case XK_Right:
549+
case XK_KP_Right:
531550
movewordedge(+1);
532551
goto draw;
533552
case XK_Return:
@@ -561,10 +580,11 @@ keypress(XKeyEvent *ev)
561580
switch(ksym) {
562581
default:
563582
insert:
564-
if (!iscntrl(*buf))
583+
if (!iscntrl((unsigned char)*buf))
565584
insert(buf, len);
566585
break;
567586
case XK_Delete:
587+
case XK_KP_Delete:
568588
if (text[cursor] == '\0')
569589
return;
570590
cursor = nextrune(+1);
@@ -575,6 +595,7 @@ keypress(XKeyEvent *ev)
575595
insert(NULL, nextrune(-1) - cursor);
576596
break;
577597
case XK_End:
598+
case XK_KP_End:
578599
if (text[cursor] != '\0') {
579600
cursor = strlen(text);
580601
break;
@@ -594,6 +615,7 @@ keypress(XKeyEvent *ev)
594615
cleanup();
595616
exit(1);
596617
case XK_Home:
618+
case XK_KP_Home:
597619
if (sel == matches) {
598620
cursor = 0;
599621
break;
@@ -602,6 +624,7 @@ keypress(XKeyEvent *ev)
602624
calcoffsets();
603625
break;
604626
case XK_Left:
627+
case XK_KP_Left:
605628
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
606629
cursor = nextrune(-1);
607630
break;
@@ -610,18 +633,21 @@ keypress(XKeyEvent *ev)
610633
return;
611634
/* fallthrough */
612635
case XK_Up:
636+
case XK_KP_Up:
613637
if (sel && sel->left && (sel = sel->left)->right == curr) {
614638
curr = prev;
615639
calcoffsets();
616640
}
617641
break;
618642
case XK_Next:
643+
case XK_KP_Next:
619644
if (!next)
620645
return;
621646
sel = curr = next;
622647
calcoffsets();
623648
break;
624649
case XK_Prior:
650+
case XK_KP_Prior:
625651
if (!prev)
626652
return;
627653
sel = curr = prev;
@@ -638,6 +664,7 @@ keypress(XKeyEvent *ev)
638664
sel->out = 1;
639665
break;
640666
case XK_Right:
667+
case XK_KP_Right:
641668
if (text[cursor] != '\0') {
642669
cursor = nextrune(+1);
643670
break;
@@ -646,6 +673,7 @@ keypress(XKeyEvent *ev)
646673
return;
647674
/* fallthrough */
648675
case XK_Down:
676+
case XK_KP_Down:
649677
if (sel && sel->right && (sel = sel->right) == next) {
650678
curr = next;
651679
calcoffsets();
@@ -654,9 +682,9 @@ keypress(XKeyEvent *ev)
654682
case XK_Tab:
655683
if (!sel)
656684
return;
657-
strncpy(text, sel->text, sizeof text - 1);
658-
text[sizeof text - 1] = '\0';
659-
cursor = strlen(text);
685+
cursor = strnlen(sel->text, sizeof text - 1);
686+
memcpy(text, sel->text, cursor);
687+
text[cursor] = '\0';
660688
match();
661689
break;
662690
}
@@ -686,34 +714,32 @@ paste(void)
686714
static void
687715
readstdin(void)
688716
{
689-
char buf[sizeof text], *p;
690-
size_t i, imax = 0, size = 0;
691-
unsigned int tmpmax = 0;
717+
char *line = NULL;
718+
size_t i, itemsiz = 0, linesiz = 0;
719+
ssize_t len;
692720

693721
if(passwd){
694722
inputw = lines = 0;
695723
return;
696724
}
697725

698726
/* read each line from stdin and add it to the item list */
699-
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
700-
if (i + 1 >= size / sizeof *items)
701-
if (!(items = realloc(items, (size += BUFSIZ))))
702-
die("cannot realloc %u bytes:", size);
703-
if ((p = strchr(buf, '\n')))
704-
*p = '\0';
705-
if (!(items[i].text = strdup(buf)))
706-
die("cannot strdup %u bytes:", strlen(buf) + 1);
707-
items[i].out = 0;
708-
drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL);
709-
if (tmpmax > inputw) {
710-
inputw = tmpmax;
711-
imax = i;
727+
for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) {
728+
if (i + 1 >= itemsiz) {
729+
itemsiz += 256;
730+
if (!(items = realloc(items, itemsiz * sizeof(*items))))
731+
die("cannot realloc %zu bytes:", itemsiz * sizeof(*items));
712732
}
733+
if (line[len - 1] == '\n')
734+
line[len - 1] = '\0';
735+
if (!(items[i].text = strdup(line)))
736+
die("strdup:");
737+
738+
items[i].out = 0;
713739
}
740+
free(line);
714741
if (items)
715742
items[i].text = NULL;
716-
inputw = items ? TEXTW(items[imax].text) : 0;
717743
lines = MIN(lines, i);
718744
}
719745

@@ -804,7 +830,7 @@ setup(void)
804830
/* no focused window is on screen, so use pointer location instead */
805831
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
806832
for (i = 0; i < n; i++)
807-
if (INTERSECT(x, y, 1, 1, info[i]))
833+
if (INTERSECT(x, y, 1, 1, info[i]) != 0)
808834
break;
809835

810836
x = info[i].x_org;
@@ -822,14 +848,14 @@ setup(void)
822848
mw = wa.width;
823849
}
824850
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
825-
inputw = MIN(inputw, mw/3);
851+
inputw = mw / 3; /* input width: ~33% of monitor width */
826852
match();
827853

828854
/* create menu window */
829855
swa.override_redirect = True;
830856
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
831857
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
832-
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
858+
win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
833859
CopyFromParent, CopyFromParent, CopyFromParent,
834860
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
835861
XSetClassHint(dpy, win, &ch);
@@ -844,6 +870,7 @@ setup(void)
844870

845871
XMapRaised(dpy, win);
846872
if (embed) {
873+
XReparentWindow(dpy, win, parentwin, x, y);
847874
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
848875
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
849876
for (i = 0; i < du && dws[i] != win; ++i)
@@ -859,10 +886,9 @@ setup(void)
859886
static void
860887
usage(void)
861888
{
862-
fputs("usage: dmenu [-bfiv] [-n|P] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
863-
" [-nb color] [-nf color] [-sb color] [-sf color]\n"
864-
" [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]\n", stderr);
865-
exit(1);
889+
die("usage: dmenu [-bfiv] [-n|P] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
890+
" [-nb color] [-nf color] [-sb color] [-sf color]\n"
891+
" [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]\n");
866892
}
867893

868894
int

0 commit comments

Comments
 (0)