diff options
| author | zachir <zachir@librem.one> | 2023-02-21 14:30:34 -0600 | 
|---|---|---|
| committer | zachir <zachir@librem.one> | 2023-02-21 14:30:34 -0600 | 
| commit | ee4eee0e05b567fe72f94eabcec9656a096625bc (patch) | |
| tree | af857dbbee2fae2f7ff2674750c0871b24c753b5 /dmenu.c | |
| parent | 0e8723fdc24c099954f6356f22d1a1df47eddb20 (diff) | |
| parent | 96e4a549ce8b3da7d5d339a94487bb2849520ae7 (diff) | |
merge master to version 5.25.2
Diffstat (limited to 'dmenu.c')
| -rw-r--r-- | dmenu.c | 207 | 
1 files changed, 88 insertions, 119 deletions
| @@ -24,8 +24,6 @@  /* macros */  #define INTERSECT(x,y,w,h,r)  (MAX(0, MIN((x)+(w),(r).x_org+(r).width)  - MAX((x),(r).x_org)) \                               * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) -#define BOOL_INTERSECT(x,y,w,h,r)  (MAX(0, MIN((x)+(w),(r).x_org+(r).width)  - MAX((x),(r).x_org)) \ -                             && MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))  #define LENGTH(X)             (sizeof X / sizeof X[0])  #define TEXTW(X)              (drw_fontset_getwidth(drw, (X)) + lrpad) @@ -36,7 +34,7 @@ enum { SchemeNorm, SchemeSel, SchemeNormHighlight, SchemeSelHighlight,  struct item {  	char *text; -        char *text_output; +	char *text_output;  	struct item *left, *right;  	int out;  	double distance; @@ -44,9 +42,8 @@ struct item {  static char text[BUFSIZ] = "";  static char *embed; -static char separator; -static int separator_greedy; -static int separator_reverse; +static char separator, separator_reverse; +static char * (*sepchr)(const char *, int);  static int bh, mw, mh;  static int inputw = 0, promptw, passwd = 0;  static int lrpad; /* sum of left and right padding */ @@ -66,7 +63,7 @@ static Drw *drw;  static Clr *scheme[SchemeLast];  /* Temporary arrays to allow overriding xresources values */ -static char *colortemp[4]; +static char *colortemp[8];  static char *tempfonts;  #include "config.h" @@ -74,6 +71,13 @@ static char *tempfonts;  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)  { @@ -98,10 +102,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;  } @@ -122,6 +126,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(separator_reverse ? items[i].text_output : items[i].text); +	free(items);  	drw_free(drw);  	XSync(dpy, False);  	XCloseDisplay(dpy); @@ -159,19 +166,17 @@ drawhighlights(struct item *item, int x, int y, int maxw)  	                   ? SchemeSelHighlight  	                   : SchemeNormHighlight]);  	for (i = 0, highlight = item->text; *highlight && text[i];) { -		if (!fstrncmp(&(*highlight), &text[i], 1)) { +		if (!fstrncmp(&text[i], highlight, 1)) { +			c = highlight[1]; +			highlight[1] = '\0'; +  			/* get indentation */ -			c = *highlight; -			*highlight = '\0';  			indent = TEXTW(item->text); -			*highlight = c;  			/* highlight character */ -			c = highlight[1]; -			highlight[1] = '\0';  			drw_text(  				drw, -				x + indent - (lrpad / 2), +				x + indent - lrpad,  				y,  				MIN(maxw - indent, TEXTW(highlight) - lrpad),  				bh, 0, highlight, 0 @@ -220,7 +225,7 @@ drawmenu(void)  	drw_setscheme(drw, scheme[SchemeNorm]);  	if (passwd) {  	        censort = ecalloc(1, sizeof(text)); -		memset(censort, '.', strlen(text)); +		memset(censort, '*', strlen(text));  		drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);  		free(censort);  	} else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); @@ -245,7 +250,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]); @@ -390,7 +395,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; @@ -577,7 +582,7 @@ keypress(XKeyEvent *ev)  	switch(ksym) {  	default:  insert: -		if (!iscntrl(*buf)) +		if (!iscntrl((unsigned char)*buf))  			insert(buf, len);  		break;  	case XK_Delete: @@ -679,9 +684,9 @@ insert:  	case XK_Tab:  		if (!sel)  			return; -		strncpy(text, sel->text, sizeof text - 1); -		text[sizeof text - 1] = '\0'; -		cursor = strlen(text); +		cursor = strnlen(sel->text, sizeof text - 1); +		memcpy(text, sel->text, cursor); +		text[cursor] = '\0';  		match();  		break;  	} @@ -744,11 +749,8 @@ buttonpress(XEvent *e)  	}  	if (ev->button != Button1)  		return; -	/* disabled below, needs to be fixed */ -	/*  	if (ev->state & ~ControlMask)  		return; -	*/  	if (lines > 0) {  		/* vertical list: (ctrl)left-click on item */  		w = mw - x; @@ -807,40 +809,6 @@ buttonpress(XEvent *e)  }  static void -mousemove(XEvent *e) -{ -	struct item *item; -	XPointerMovedEvent *ev = &e->xmotion; -	int x = 0, y = 0, h = bh, w; - -	if (lines > 0) { -		w = mw - x; -		for (item = curr; item != next; item = item->right) { -			y += h; -			if (ev->y >= y && ev->y <= (y + h)) { -				sel = item; -				calcoffsets(); -				drawmenu(); -				return; -			} -		} -	} else if (matches) { -		x += inputw; -		w = TEXTW("<"); -		for (item = curr; item != next; item = item->right) { -			x += w; -			w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); -			if (ev->x >= x && ev->x <= x + w) { -				sel = item; -				calcoffsets(); -				drawmenu(); -				return; -			} -		} -	} -} - -static void  paste(void)  {  	char *p, *q; @@ -861,26 +829,25 @@ paste(void)  static void  readstdin(void)  { -	char buf[sizeof text], *p; -	size_t i, imax = 0, size = 0; -	unsigned int tmpmax = 0; -	if(passwd){ -    	inputw = lines = 0; -    	return; -  	} +	char *p, *line = NULL; +	size_t i, junk, size = 0; +	ssize_t len; +        if(passwd) { +                inputw = lines = 0; +                return; +        }  	/* 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 %u bytes:", size); -		if ((p = strchr(buf, '\n'))) -			*p = '\0'; -		if (!(items[i].text = strdup(buf))) -			die("cannot strdup %u bytes:", strlen(buf) + 1); -		if (separator && (p = separator_greedy ? -		    strrchr(items[i].text, separator) : strchr(items[i].text, separator))) { +				die("cannot realloc %zu bytes:", size); +		if (line[len - 1] == '\n') +			line[len - 1] = '\0'; +		items[i].text = line; + +		if (separator && (p = sepchr(items[i].text, separator)) != NULL) {  			*p = '\0';  			items[i].text_output = ++p;  		} else { @@ -891,16 +858,11 @@ readstdin(void)  			items[i].text = items[i].text_output;  			items[i].text_output = p;  		} +  		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);  } @@ -921,9 +883,6 @@ run(void)  		case ButtonPress:  			buttonpress(&ev);  			break; -                case MotionNotify: -                        mousemove(&ev); -                        break;  		case Expose:  			if (ev.xexpose.count == 0)  				drw_map(drw, win, 0, 0, mw, mh); @@ -1004,7 +963,7 @@ setup(void)  		/* no focused window is on screen, so use pointer location instead */  		if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))  			for (i = 0; i < n; i++) -				if (BOOL_INTERSECT(x, y, 1, 1, info[i])) +				if (INTERSECT(x, y, 1, 1, info[i]) != 0)  					break;  		if (centered) { @@ -1035,14 +994,15 @@ setup(void)  			mw = wa.width;  		}  	} -	inputw = MIN(inputw, mw/3); +	promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; +	inputw = mw / 3; /* input width: ~33% of monitor width */  	match();  	/* create menu window */  	swa.override_redirect = True;  	swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;  	swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | -                         ButtonPressMask | PointerMotionMask; +                         ButtonPressMask;  	win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,  	                    CopyFromParent, CopyFromParent, CopyFromParent,  	                    CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); @@ -1075,11 +1035,10 @@ setup(void)  static void  usage(void)  { -	fputs("usage: dmenu [-bfirvP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" -	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-bw width]\n" -	      "             [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]\n" -              "             [-d separator] [-D separator]\n", stderr); -	exit(1); +	die("usage: dmenu [-bfirvP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" +	    "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" +            "             [-nhb color] [-nhf color] [-shb color] [-shf color]\n" +	    "             [-d separator] [-D separator] [-h height]");  }  void @@ -1112,22 +1071,22 @@ readxresources(void) {  			colors[SchemeSel][ColFg] = strdup(xval.addr);  		else  			colors[SchemeSel][ColFg] = strdup(colors[SchemeSel][ColFg]); +		if (XrmGetResource(xdb, "dmenu.hibackground", "*", &type, &xval)) +			colors[SchemeNormHighlight][ColBg] = strdup(xval.addr); +		else +			colors[SchemeNormHighlight][ColBg] = strdup(colors[SchemeSel][ColFg]); +		if (XrmGetResource(xdb, "dmenu.hiforeground", "*", &type, &xval)) +			colors[SchemeNormHighlight][ColFg] = strdup(xval.addr); +		else +			colors[SchemeNormHighlight][ColFg] = strdup(colors[SchemeSel][ColFg]);  		if (XrmGetResource(xdb, "dmenu.selhibackground", "*", &type, &xval))  			colors[SchemeSelHighlight][ColBg] = strdup(xval.addr);  		else -			colors[SchemeSelHighlight][ColBg] = strdup(colors[SchemeSel][ColBg]); +			colors[SchemeSelHighlight][ColBg] = strdup(colors[SchemeSel][ColFg]);  		if (XrmGetResource(xdb, "dmenu.selhiforeground", "*", &type, &xval))  			colors[SchemeSelHighlight][ColFg] = strdup(xval.addr);  		else  			colors[SchemeSelHighlight][ColFg] = strdup(colors[SchemeSel][ColFg]); -		if (XrmGetResource(xdb, "dmenu.hibackground", "*", &type, &xval)) -			colors[SchemeNormHighlight][ColBg] = strdup(xval.addr); -		else -			colors[SchemeNormHighlight][ColBg] = strdup(colors[SchemeNorm][ColBg]); -		if (XrmGetResource(xdb, "dmenu.hiforeground", "*", &type, &xval)) -			colors[SchemeNormHighlight][ColFg] = strdup(xval.addr); -		else -			colors[SchemeNormHighlight][ColFg] = strdup(colors[SchemeNorm][ColFg]);  		XrmDestroyDatabase(xdb);  	} @@ -1148,14 +1107,14 @@ 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], "-c"))   /* centers dmenu on screen */ -                        centered = 1; -		else if (!strcmp(argv[i], "-F"))   /* grabs keyboard before reading stdin */ -			fuzzy = 1; +                else if (!strcmp(argv[i], "-F"))   /* toggles fuzzy matching */ +                        fuzzy = fuzzy ? 0 : 1; +		else if (!strcmp(argv[i], "-c"))   /* centers dmenu on screen */ +			centered = 1;  		else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */  			fstrncmp = strncasecmp;  			fstrstr = cistrstr; -		} else if (!strcmp(argv[i], "-P"))   /* is the input a password */ +		} else if (!strcmp(argv[i], "-P")) /* is the input a password */  			passwd = 1;                  else if (!strcmp(argv[i], "-r")) /* reject input which results in no match */                          reject_no_match = 1; @@ -1182,22 +1141,24 @@ main(int argc, char *argv[])  			colortemp[2] = argv[++i];  		else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */  			colortemp[3] = argv[++i]; -                else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */ -                        colors[SchemeNormHighlight][ColBg] = argv[++i]; -                else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */ -                        colors[SchemeNormHighlight][ColFg] = argv[++i]; -                else if (!strcmp(argv[i], "-shb")) /* selected hi background color */ -                        colors[SchemeSelHighlight][ColBg] = argv[++i]; -                else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */ -                        colors[SchemeSelHighlight][ColFg] = argv[++i]; +		else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */ +			colortemp[4] = argv[++i]; +		else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */ +			colortemp[5] = argv[++i]; +		else if (!strcmp(argv[i], "-shb")) /* selected hi background color */ +			colortemp[6] = argv[++i]; +		else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */ +			colortemp[7] = argv[++i];  		else if (!strcmp(argv[i], "-w"))   /* embedding window id */  			embed = argv[++i]; +                else if (!strcmp(argv[i], "-bw")) +                        border_width = atoi(argv[++i]); /* border width */  		else if (!strcmp(argv[i], "-d") || /* field separator */ -			(separator_greedy = !strcmp(argv[i], "-D"))) { -                        separator = argv[++i][0]; -                        separator_reverse = argv[i][1] == '|'; -                } else if (!strcmp(argv[i], "-bw")) -			border_width = atoi(argv[++i]); /* border width */ +		         !strcmp(argv[i], "-D")) { +			sepchr = argv[i][1] == 'D' ? strrchr : strchr; +			separator = argv[++i][0]; +			separator_reverse = argv[i][1] == '|'; +		}  		else  			usage(); @@ -1225,6 +1186,14 @@ main(int argc, char *argv[])  	   colors[SchemeSel][ColBg]  = strdup(colortemp[2]);  	if ( colortemp[3])  	   colors[SchemeSel][ColFg]  = strdup(colortemp[3]); +        if ( colortemp[4]) +           colors[SchemeNormHighlight][ColBg] = strdup(colortemp[4]); +        if ( colortemp[5]) +           colors[SchemeNormHighlight][ColFg] = strdup(colortemp[5]); +        if ( colortemp[6]) +           colors[SchemeSelHighlight][ColBg] = strdup(colortemp[6]); +        if ( colortemp[7]) +           colors[SchemeSelHighlight][ColFg] = strdup(colortemp[7]);  	if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts)))  		die("no fonts could be loaded."); | 
