]> git.armaanb.net Git - dmenu.git/blobdiff - dmenu.c
backported drawtext() simplifications to dmenu
[dmenu.git] / dmenu.c
diff --git a/dmenu.c b/dmenu.c
index a37471ac9aeb0cb20265534b76772a1271bc695e..a9c0f60f048164fa437619070316f4853f9ecacd 100644 (file)
--- a/dmenu.c
+++ b/dmenu.c
@@ -1,6 +1,6 @@
 /* See LICENSE file for copyright and license details. */
+#define _BSD_SOURCE
 #include <ctype.h>
-#include <locale.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #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 +51,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,26 +61,21 @@ 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"
 
 /* variables */
-static char *font = FONT;
 static char *maxname = NULL;
-static char *normbg = NORMBGCOLOR;
-static char *normfg = NORMFGCOLOR;
 static char *prompt = NULL;
-static char *selbg = SELBGCOLOR;
-static char *selfg = SELFGCOLOR;
 static char text[4096];
 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};
@@ -109,7 +103,7 @@ appenditem(Item *i, Item **list, Item **last) {
 void
 calcoffsets(void) {
        int tw;
-       uint w;
+       unsigned int w;
 
        if(!curr)
                return;
@@ -136,7 +130,7 @@ calcoffsets(void) {
 char *
 cistrstr(const char *s, const char *sub) {
        int c, csub;
-       uint len;
+       unsigned int len;
 
        if(!sub)
                return (char *)s;
@@ -218,38 +212,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]) {
+       int i, x, y, h, len, olen;
+       char buf[256];
        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 && (i = textnw(buf, 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);
@@ -257,15 +239,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;
@@ -276,7 +249,7 @@ eprint(const char *errstr, ...) {
        exit(EXIT_FAILURE);
 }
 
-ulong
+unsigned long
 getcolor(const char *colstr) {
        Colormap cmap = DefaultColormap(dpy, screen);
        XColor color;
@@ -288,7 +261,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)
@@ -344,7 +317,7 @@ void
 kpress(XKeyEvent * e) {
        char buf[32];
        int i, num;
-       uint len;
+       unsigned int len;
        KeySym ksym;
 
        len = strlen(text);
@@ -482,11 +455,11 @@ kpress(XKeyEvent * e) {
                calcoffsets();
                break;
        case XK_Return:
-               if((e->state & ShiftMask) && text)
+               if((e->state & ShiftMask) && *text)
                        fprintf(stdout, "%s", text);
                else if(sel)
                        fprintf(stdout, "%s", sel->text);
-               else if(text)
+               else if(*text)
                        fprintf(stdout, "%s", text);
                fflush(stdout);
                running = False;
@@ -512,7 +485,7 @@ kpress(XKeyEvent * e) {
 
 void
 match(char *pattern) {
-       uint plen;
+       unsigned int plen;
        Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
 
        if(!pattern)
@@ -554,7 +527,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;
@@ -568,7 +541,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)
@@ -601,11 +575,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);
@@ -618,10 +593,10 @@ setup(Bool topbar) {
        XFreeModifiermap(modmap);
 
        /* style */
-       dc.norm[ColBG] = getcolor(normbg);
-       dc.norm[ColFG] = getcolor(normfg);
-       dc.sel[ColBG] = getcolor(selbg);
-       dc.sel[ColFG] = getcolor(selfg);
+       dc.norm[ColBG] = getcolor(normbgcolor);
+       dc.norm[ColFG] = getcolor(normfgcolor);
+       dc.sel[ColBG] = getcolor(selbgcolor);
+       dc.sel[ColFG] = getcolor(selfgcolor);
        initfont(font);
 
        /* menu window */
@@ -632,11 +607,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
@@ -672,7 +656,7 @@ setup(Bool topbar) {
 }
 
 int
-textnw(const char *text, uint len) {
+textnw(const char *text, unsigned int len) {
        XRectangle r;
 
        if(dc.font.set) {
@@ -689,7 +673,7 @@ textw(const char *text) {
 
 int
 main(int argc, char *argv[]) {
-       uint i;
+       unsigned int i;
        Bool topbar = True;
 
        /* command line args */
@@ -704,26 +688,27 @@ main(int argc, char *argv[]) {
                        if(++i < argc) font = argv[i];
                }
                else if(!strcmp(argv[i], "-nb")) {
-                       if(++i < argc) normbg = argv[i];
+                       if(++i < argc) normbgcolor = argv[i];
                }
                else if(!strcmp(argv[i], "-nf")) {
-                       if(++i < argc) normfg = argv[i];
+                       if(++i < argc) normfgcolor = argv[i];
                }
                else if(!strcmp(argv[i], "-p")) {
                        if(++i < argc) prompt = argv[i];
                }
                else if(!strcmp(argv[i], "-sb")) {
-                       if(++i < argc) selbg = argv[i];
+                       if(++i < argc) selbgcolor = argv[i];
                }
                else if(!strcmp(argv[i], "-sf")) {
-                       if(++i < argc) selfg = argv[i];
+                       if(++i < argc) selfgcolor = argv[i];
                }
                else if(!strcmp(argv[i], "-v"))
                        eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
                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(!XSupportsLocale())
+               fprintf(stderr, "warning: no locale support\n");
        if(!(dpy = XOpenDisplay(0)))
                eprint("dmenu: cannot open display\n");
        screen = DefaultScreen(dpy);