X-Git-Url: https://git.xinqibao.xyz/dmenu.git/blobdiff_plain/3f244b1d52d5409776467704ca95d561cdab78e9..3e60c5d836c1f9f3b4415782de48476663943274:/dmenu.c

diff --git a/dmenu.c b/dmenu.c
index bf74edb..18f2a56 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -1,4 +1,5 @@
 /* See LICENSE file for copyright and license details. */
+#define _BSD_SOURCE
 #include <ctype.h>
 #include <locale.h>
 #include <stdarg.h>
@@ -15,18 +16,18 @@
 #endif
 
 /* macros */
-#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
+#define CLEANMASK(mask)         (mask & ~(numlockmask | LockMask))
+#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
+#define MIN(a, b)               ((a) < (b) ? (a) : (b))
 
 /* enums */
 enum { ColFG, ColBG, ColLast };
 
 /* typedefs */
-typedef unsigned int uint;
-typedef unsigned long ulong;
 typedef struct {
 	int x, y, w, h;
-	ulong norm[ColLast];
-	ulong sel[ColLast];
+	unsigned long norm[ColLast];
+	unsigned long sel[ColLast];
 	Drawable drawable;
 	GC gc;
 	struct {
@@ -51,10 +52,9 @@ static void calcoffsets(void);
 static char *cistrstr(const char *s, const char *sub);
 static void cleanup(void);
 static void drawmenu(void);
-static void drawtext(const char *text, ulong col[ColLast]);
-static void *emalloc(uint size);
+static void drawtext(const char *text, unsigned long col[ColLast]);
 static void eprint(const char *errstr, ...);
-static ulong getcolor(const char *colstr);
+static unsigned long getcolor(const char *colstr);
 static Bool grabkeyboard(void);
 static void initfont(const char *fontstr);
 static void kpress(XKeyEvent * e);
@@ -62,7 +62,7 @@ static void match(char *pattern);
 static void readstdin(void);
 static void run(void);
 static void setup(Bool topbar);
-static int textnw(const char *text, uint len);
+static int textnw(const char *text, unsigned int len);
 static int textw(const char *text);
 
 #include "config.h"
@@ -75,8 +75,8 @@ static int cmdw = 0;
 static int promptw = 0;
 static int ret = 0;
 static int screen;
-static uint mw, mh;
-static uint numlockmask = 0;
+static unsigned int mw, mh;
+static unsigned int numlockmask = 0;
 static Bool running = True;
 static Display *dpy;
 static DC dc = {0};
@@ -104,7 +104,7 @@ appenditem(Item *i, Item **list, Item **last) {
 void
 calcoffsets(void) {
 	int tw;
-	uint w;
+	unsigned int w;
 
 	if(!curr)
 		return;
@@ -131,7 +131,7 @@ calcoffsets(void) {
 char *
 cistrstr(const char *s, const char *sub) {
 	int c, csub;
-	uint len;
+	unsigned int len;
 
 	if(!sub)
 		return (char *)s;
@@ -213,38 +213,26 @@ drawmenu(void) {
 }
 
 void
-drawtext(const char *text, ulong col[ColLast]) {
-	int x, y, w, h;
-	static char buf[256];
-	uint len, olen;
+drawtext(const char *text, unsigned long col[ColLast]) {
+	char buf[256];
+	int i, x, y, h, len, olen;
 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 
 	XSetForeground(dpy, dc.gc, col[ColBG]);
 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
 	if(!text)
 		return;
-	w = 0;
-	olen = len = strlen(text);
-	if(len >= sizeof buf)
-		len = sizeof buf - 1;
-	memcpy(buf, text, len);
-	buf[len] = 0;
+	olen = strlen(text);
 	h = dc.font.ascent + dc.font.descent;
 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
 	x = dc.x + (h / 2);
 	/* shorten text if necessary */
-	while(len && (w = textnw(buf, len)) > dc.w - h)
-		buf[--len] = 0;
-	if(len < olen) {
-		if(len > 1)
-			buf[len - 1] = '.';
-		if(len > 2)
-			buf[len - 2] = '.';
-		if(len > 3)
-			buf[len - 3] = '.';
-	}
-	if(w > dc.w)
-		return; /* too long */
+	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
+	if(!len)
+		return;
+	memcpy(buf, text, len);
+	if(len < olen)
+		for(i = len; i && i > len - 3; buf[--i] = '.');
 	XSetForeground(dpy, dc.gc, col[ColFG]);
 	if(dc.font.set)
 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
@@ -252,15 +240,6 @@ drawtext(const char *text, ulong col[ColLast]) {
 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
 }
 
-void *
-emalloc(uint size) {
-	void *res = malloc(size);
-
-	if(!res)
-		eprint("fatal: could not malloc() %u bytes\n", size);
-	return res;
-}
-
 void
 eprint(const char *errstr, ...) {
 	va_list ap;
@@ -271,7 +250,7 @@ eprint(const char *errstr, ...) {
 	exit(EXIT_FAILURE);
 }
 
-ulong
+unsigned long
 getcolor(const char *colstr) {
 	Colormap cmap = DefaultColormap(dpy, screen);
 	XColor color;
@@ -283,7 +262,7 @@ getcolor(const char *colstr) {
 
 Bool
 grabkeyboard(void) {
-	uint len;
+	unsigned int len;
 
 	for(len = 1000; len; len--) {
 		if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
@@ -302,8 +281,6 @@ initfont(const char *fontstr) {
 	if(!fontstr || fontstr[0] == '\0')
 		eprint("error, cannot load font: '%s'\n", fontstr);
 	missing = NULL;
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
 	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
 	if(missing)
 		XFreeStringList(missing);
@@ -339,7 +316,7 @@ void
 kpress(XKeyEvent * e) {
 	char buf[32];
 	int i, num;
-	uint len;
+	unsigned int len;
 	KeySym ksym;
 
 	len = strlen(text);
@@ -507,7 +484,7 @@ kpress(XKeyEvent * e) {
 
 void
 match(char *pattern) {
-	uint plen;
+	unsigned int plen;
 	Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
 
 	if(!pattern)
@@ -549,7 +526,7 @@ match(char *pattern) {
 void
 readstdin(void) {
 	char *p, buf[1024];
-	uint len = 0, max = 0;
+	unsigned int len = 0, max = 0;
 	Item *i, *new;
 
 	i = 0;
@@ -563,7 +540,8 @@ readstdin(void) {
 			maxname = p;
 			max = len;
 		}
-		new = emalloc(sizeof(Item));
+		if((new = (Item *)malloc(sizeof(Item))) == NULL)
+			eprint("fatal: could not malloc() %u bytes\n", sizeof(Item));
 		new->next = new->left = new->right = NULL;
 		new->text = p;
 		if(!i)
@@ -596,11 +574,12 @@ run(void) {
 void
 setup(Bool topbar) {
 	int i, j, x, y;
-	XModifierKeymap *modmap;
-	XSetWindowAttributes wa;
 #if XINERAMA
+	int n;
 	XineramaScreenInfo *info = NULL;
 #endif
+	XModifierKeymap *modmap;
+	XSetWindowAttributes wa;
 
 	/* init modifier map */
 	modmap = XGetModifierMapping(dpy);
@@ -627,11 +606,20 @@ setup(Bool topbar) {
 	/* menu window geometry */
 	mh = dc.font.height + 2;
 #if XINERAMA
-	if(XineramaIsActive(dpy)) {
-		info = XineramaQueryScreens(dpy, &i);
-		x = info[xidx].x_org;
-		y = topbar ? info[xidx].y_org : info[xidx].y_org + info[xidx].height - mh;
-		mw = info[xidx].width;
+	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
+		i = 0;
+		if(n > 1) {
+			int di;
+			unsigned int dui;
+			Window dummy;
+			if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
+				for(i = 0; i < n; i++)
+					if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
+						break;
+		}
+		x = info[i].x_org;
+		y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh;
+		mw = info[i].width;
 		XFree(info);
 	}
 	else
@@ -667,7 +655,7 @@ setup(Bool topbar) {
 }
 
 int
-textnw(const char *text, uint len) {
+textnw(const char *text, unsigned int len) {
 	XRectangle r;
 
 	if(dc.font.set) {
@@ -684,7 +672,7 @@ textw(const char *text) {
 
 int
 main(int argc, char *argv[]) {
-	uint i;
+	unsigned int i;
 	Bool topbar = True;
 
 	/* command line args */
@@ -718,7 +706,8 @@ main(int argc, char *argv[]) {
 		else
 			eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
 			       "             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
-	setlocale(LC_CTYPE, "");
+	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
+		fprintf(stderr, "warning: no locale support\n");
 	if(!(dpy = XOpenDisplay(0)))
 		eprint("dmenu: cannot open display\n");
 	screen = DefaultScreen(dpy);