tdecoupled draw.c from dmenu & dinput - dmenu - Dmenu fork with xft fonts.
 (HTM) git clone git://r-36.net/dmenu
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 96c65400ccdcb76cf20ec7721920f944e6b490ec
 (DIR) parent 6c1d0e4d60b239e9533def6feaf8eb2138858c3e
 (HTM) Author: Connor Lane Smith <cls@lubutu.com>
       Date:   Thu, 24 Jun 2010 16:18:18 +0100
       
       decoupled draw.c from dmenu & dinput
       Diffstat:
         dinput.c                            |      40 +++++++++++++++++--------------
         dmenu.c                             |      49 ++++++++++++++++---------------
         draw.c                              |     109 +++++++++++++++----------------
         draw.h                              |      30 ++++++++++--------------------
       
       4 files changed, 111 insertions(+), 117 deletions(-)
       ---
 (DIR) diff --git a/dinput.c b/dinput.c
       t@@ -38,20 +38,18 @@ static char *prompt = NULL;
        static char text[4096];
        static int promptw = 0;
        static int ret = 0;
       +static int screen;
        static unsigned int cursor = 0;
        static unsigned int numlockmask = 0;
       +static unsigned int mw, mh;
        static Bool running = True;
       -static Window win;
       -
       -Display *dpy;
       -DC dc;
       -int screen;
       -unsigned int mw, mh;
       -Window parent;
       +static DC dc;
       +static Display *dpy;
       +static Window win, parent;
        
        void
        cleanup(void) {
       -        drawcleanup();
       +        cleanupdraw(&dc);
                XDestroyWindow(dpy, win);
                XUngrabKeyboard(dpy, CurrentTime);
        }
       t@@ -60,7 +58,7 @@ void
        drawcursor(void) {
                XRectangle r = { dc.x, dc.y + 2, 1, dc.font.height - 2 };
        
       -        r.x += textnw(text, cursor) + dc.font.height / 2;
       +        r.x += textnw(&dc, text, cursor) + dc.font.height / 2;
        
                XSetForeground(dpy, dc.gc, dc.norm[ColFG]);
                XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       t@@ -73,15 +71,15 @@ drawinput(void)
                dc.y = 0;
                dc.w = mw;
                dc.h = mh;
       -        drawtext(NULL, dc.norm);
       +        drawtext(&dc, NULL, dc.norm);
                /* print prompt? */
                if(prompt) {
                        dc.w = promptw;
       -                drawtext(prompt, dc.sel);
       +                drawtext(&dc, prompt, dc.sel);
                        dc.x += dc.w;
                }
                dc.w = mw - dc.x;
       -        drawtext(*text ? text : NULL, dc.norm);
       +        drawtext(&dc, *text ? text : NULL, dc.norm);
                drawcursor();
                XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
                XFlush(dpy);
       t@@ -269,15 +267,21 @@ setup(Bool topbar) {
                        }
                XFreeModifiermap(modmap);
        
       -        initfont(font);
       +        dc.dpy = dpy;
       +        dc.norm[ColBG] = getcolor(&dc, normbgcolor);
       +        dc.norm[ColFG] = getcolor(&dc, normfgcolor);
       +        dc.sel[ColBG] = getcolor(&dc, selbgcolor);
       +        dc.sel[ColFG] = getcolor(&dc, selfgcolor);
       +        initfont(&dc, font);
       +        fprintf(stderr, "dc.font.xfont: %u\n", (size_t)dc.font.xfont);
        
       -        /* menu window */
       +        /* input window */
                wa.override_redirect = True;
                wa.background_pixmap = ParentRelative;
                wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask | VisibilityChangeMask;
        
       -        /* menu window geometry */
       -        mh = (dc.font.height + 2);
       +        /* input window geometry */
       +        mh = dc.font.height + 2;
        #if XINERAMA
                if(parent == RootWindow(dpy, screen) && XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
                        i = 0;
       t@@ -309,9 +313,9 @@ setup(Bool topbar) {
                                DefaultVisual(dpy, screen),
                                CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
        
       -        drawsetup();
       +        setupdraw(&dc, win);
                if(prompt)
       -                promptw = MIN(textw(prompt), mw / 5);
       +                promptw = MIN(textw(&dc, prompt), mw / 5);
                cursor = strlen(text);
                XMapRaised(dpy, win);
        }
 (DIR) diff --git a/dmenu.c b/dmenu.c
       t@@ -55,26 +55,24 @@ static char text[4096];
        static int cmdw = 0;
        static int promptw = 0;
        static int ret = 0;
       +static int screen;
        static unsigned int lines = 0;
        static unsigned int numlockmask = 0;
       +static unsigned int mw, mh;
        static Bool running = True;
       +static DC dc;
       +static Display *dpy;
        static Item *allitems = NULL;  /* first of all items */
        static Item *item = NULL;      /* first of pattern matching items */
        static Item *sel = NULL;
        static Item *next = NULL;
        static Item *prev = NULL;
        static Item *curr = NULL;
       -static Window win;
       +static Window win, parent;
        static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
        static char *(*fstrstr)(const char *, const char *) = strstr;
        static void (*calcoffsets)(void) = calcoffsetsh;
        
       -Display *dpy;
       -DC dc;
       -int screen;
       -unsigned int mw, mh;
       -Window parent;
       -
        void
        appenditem(Item *i, Item **list, Item **last) {
                if(!(*last))
       t@@ -92,11 +90,11 @@ calcoffsetsh(void) {
        
                w = promptw + cmdw + (2 * spaceitem);
                for(next = curr; next; next = next->right)
       -                if((w += MIN(textw(next->text), mw / 3)) > mw)
       +                if((w += MIN(textw(&dc, next->text), mw / 3)) > mw)
                                break;
                w = promptw + cmdw + (2 * spaceitem);
                for(prev = curr; prev && prev->left; prev = prev->left)
       -                if((w += MIN(textw(prev->left->text), mw / 3)) > mw)
       +                if((w += MIN(textw(&dc, prev->left->text), mw / 3)) > mw)
                                break;
        }
        
       t@@ -143,7 +141,7 @@ cleanup(void) {
                        free(allitems);
                        allitems = itm;
                }
       -        drawcleanup();
       +        cleanupdraw(&dc);
                XDestroyWindow(dpy, win);
                XUngrabKeyboard(dpy, CurrentTime);
        }
       t@@ -161,18 +159,18 @@ drawmenu(void) {
                dc.y = 0;
                dc.w = mw;
                dc.h = mh;
       -        drawtext(NULL, dc.norm);
       +        drawtext(&dc, NULL, dc.norm);
                /* print prompt? */
                if(prompt) {
                        dc.w = promptw;
       -                drawtext(prompt, dc.sel);
       +                drawtext(&dc, prompt, dc.sel);
                        dc.x += dc.w;
                }
                dc.w = mw - dc.x;
                /* print command */
                if(cmdw && item && lines == 0)
                        dc.w = cmdw;
       -        drawtext(*text ? text : NULL, dc.norm);
       +        drawtext(&dc, *text ? text : NULL, dc.norm);
                if(curr) {
                        if(lines > 0)
                                drawmenuv();
       t@@ -189,16 +187,16 @@ drawmenuh(void) {
        
                dc.x += cmdw;
                dc.w = spaceitem;
       -        drawtext(curr->left ? "<" : NULL, dc.norm);
       +        drawtext(&dc, curr->left ? "<" : NULL, dc.norm);
                dc.x += dc.w;
                for(i = curr; i != next; i=i->right) {
       -                dc.w = MIN(textw(i->text), mw / 3);
       -                drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
       +                dc.w = MIN(textw(&dc, i->text), mw / 3);
       +                drawtext(&dc, i->text, (sel == i) ? dc.sel : dc.norm);
                        dc.x += dc.w;
                }
                dc.w = spaceitem;
                dc.x = mw - dc.w;
       -        drawtext(next ? ">" : NULL, dc.norm);
       +        drawtext(&dc, next ? ">" : NULL, dc.norm);
        }
        
        void
       t@@ -209,11 +207,11 @@ drawmenuv(void) {
                dc.h = dc.font.height + 2;
                dc.y = dc.h;
                for(i = curr; i != next; i=i->right) {
       -                drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
       +                drawtext(&dc, i->text, (sel == i) ? dc.sel : dc.norm);
                        dc.y += dc.h;
                }
                dc.h = mh - dc.y;
       -        drawtext(NULL, dc.norm);
       +        drawtext(&dc, NULL, dc.norm);
        }
        
        Bool
       t@@ -491,7 +489,12 @@ setup(Bool topbar) {
                        }
                XFreeModifiermap(modmap);
        
       -        initfont(font);
       +        dc.dpy = dpy;
       +        dc.norm[ColBG] = getcolor(&dc, normbgcolor);
       +        dc.norm[ColFG] = getcolor(&dc, normfgcolor);
       +        dc.sel[ColBG] = getcolor(&dc, selbgcolor);
       +        dc.sel[ColFG] = getcolor(&dc, selfgcolor);
       +        initfont(&dc, font);
        
                /* menu window */
                wa.override_redirect = True;
       t@@ -531,11 +534,11 @@ setup(Bool topbar) {
                                DefaultVisual(dpy, screen),
                                CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
        
       -        drawsetup();
       +        setupdraw(&dc, win);
                if(maxname)
       -                cmdw = MIN(textw(maxname), mw / 3);
       +                cmdw = MIN(textw(&dc, maxname), mw / 3);
                if(prompt)
       -                promptw = MIN(textw(prompt), mw / 5);
       +                promptw = MIN(textw(&dc, prompt), mw / 5);
                text[0] = '\0';
                match(text);
                XMapRaised(dpy, win);
 (DIR) diff --git a/draw.c b/draw.c
       t@@ -14,126 +14,123 @@
        #define MAX(a, b)               ((a) > (b) ? (a) : (b))
        
        /* variables */
       -char *progname;
       +const char *progname;
        
        void
       -drawcleanup(void) {
       -        if(dc.font.set)
       -                XFreeFontSet(dpy, dc.font.set);
       +cleanupdraw(DC *dc) {
       +        if(dc->font.set)
       +                XFreeFontSet(dc->dpy, dc->font.set);
                else
       -                XFreeFont(dpy, dc.font.xfont);
       -        XFreePixmap(dpy, dc.drawable);
       -        XFreeGC(dpy, dc.gc);
       +                XFreeFont(dc->dpy, dc->font.xfont);
       +        XFreePixmap(dc->dpy, dc->drawable);
       +        XFreeGC(dc->dpy, dc->gc);
        }
        
        void
       -drawsetup(void) {
       -        /* style */
       -        dc.norm[ColBG] = getcolor(normbgcolor);
       -        dc.norm[ColFG] = getcolor(normfgcolor);
       -        dc.sel[ColBG] = getcolor(selbgcolor);
       -        dc.sel[ColFG] = getcolor(selfgcolor);
       -
       -        /* pixmap */
       -        dc.drawable = XCreatePixmap(dpy, parent, mw, mh, DefaultDepth(dpy, screen));
       -        dc.gc = XCreateGC(dpy, parent, 0, NULL);
       -        XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
       -        if(!dc.font.set)
       -                XSetFont(dpy, dc.gc, dc.font.xfont->fid);
       +setupdraw(DC *dc, Window w) {
       +        XWindowAttributes wa;
       +
       +        XGetWindowAttributes(dc->dpy, w, &wa);
       +        dc->drawable = XCreatePixmap(dc->dpy, w, wa.width, wa.height,
       +                DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
       +        dc->gc = XCreateGC(dc->dpy, w, 0, NULL);
       +        XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter);
       +        if(!dc->font.set)
       +                XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid);
        }
        
        void
       -drawtext(const char *text, unsigned long col[ColLast]) {
       +drawtext(DC *dc, 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 };
       +        XRectangle r = { dc->x, dc->y, dc->w, dc->h };
        
       -        XSetForeground(dpy, dc.gc, col[ColBG]);
       -        XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
       +        XSetForeground(dc->dpy, dc->gc, col[ColBG]);
       +        XFillRectangles(dc->dpy, dc->drawable, dc->gc, &r, 1);
                if(!text)
                        return;
                olen = strlen(text);
       -        h = dc.font.height;
       -        y = dc.y + ((h+2) / 2) - (h / 2) + dc.font.ascent;
       -        x = dc.x + (h / 2);
       +        h = dc->font.height;
       +        y = dc->y + ((h+2) / 2) - (h / 2) + dc->font.ascent;
       +        x = dc->x + (h / 2);
                /* shorten text if necessary */
       -        for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
       +        for(len = MIN(olen, sizeof buf); len && textnw(dc, 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);
       +        XSetForeground(dc->dpy, dc->gc, col[ColFG]);
       +        if(dc->font.set)
       +                XmbDrawString(dc->dpy, dc->drawable, dc->font.set, dc->gc, x, y, buf, len);
                else
       -                XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
       +                XDrawString(dc->dpy, dc->drawable, dc->gc, x, y, buf, len);
        }
        
        void
       -eprint(const char *errstr, ...) {
       +eprint(const char *fmt, ...) {
                va_list ap;
        
                fprintf(stderr, "%s: ", progname);
       -        va_start(ap, errstr);
       -        vfprintf(stderr, errstr, ap);
       +        va_start(ap, fmt);
       +        vfprintf(stderr, fmt, ap);
                va_end(ap);
                exit(EXIT_FAILURE);
        }
        
        unsigned long
       -getcolor(const char *colstr) {
       -        Colormap cmap = DefaultColormap(dpy, screen);
       +getcolor(DC *dc, const char *colstr) {
       +        Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy));
                XColor color;
        
       -        if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
       +        if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color))
                        eprint("cannot allocate color '%s'\n", colstr);
                return color.pixel;
        }
        
        void
       -initfont(const char *fontstr) {
       +initfont(DC *dc, const char *fontstr) {
                char *def, **missing = NULL;
                int i, n;
        
                if(!fontstr || !*fontstr)
                        eprint("cannot load null font\n");
       -        dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
       +        dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def);
                if(missing)
                        XFreeStringList(missing);
       -        if(dc.font.set) {
       +        if(dc->font.set) {
                        XFontStruct **xfonts;
                        char **font_names;
       -                dc.font.ascent = dc.font.descent = 0;
       -                n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
       +                dc->font.ascent = dc->font.descent = 0;
       +                n = XFontsOfFontSet(dc->font.set, &xfonts, &font_names);
                        for(i = 0; i < n; i++) {
       -                        dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
       -                        dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent);
       +                        dc->font.ascent = MAX(dc->font.ascent, (*xfonts)->ascent);
       +                        dc->font.descent = MAX(dc->font.descent, (*xfonts)->descent);
                                xfonts++;
                        }
                }
                else {
       -                if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
       -                && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
       +                if(!(dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))
       +                && !(dc->font.xfont = XLoadQueryFont(dc->dpy, "fixed")))
                                eprint("cannot load font '%s'\n", fontstr);
       -                dc.font.ascent = dc.font.xfont->ascent;
       -                dc.font.descent = dc.font.xfont->descent;
       +                dc->font.ascent = dc->font.xfont->ascent;
       +                dc->font.descent = dc->font.xfont->descent;
                }
       -        dc.font.height = dc.font.ascent + dc.font.descent;
       +        dc->font.height = dc->font.ascent + dc->font.descent;
        }
        
        int
       -textnw(const char *text, unsigned int len) {
       +textnw(DC *dc, const char *text, unsigned int len) {
                XRectangle r;
        
       -        if(dc.font.set) {
       -                XmbTextExtents(dc.font.set, text, len, NULL, &r);
       +        if(dc->font.set) {
       +                XmbTextExtents(dc->font.set, text, len, NULL, &r);
                        return r.width;
                }
       -        return XTextWidth(dc.font.xfont, text, len);
       +        return XTextWidth(dc->font.xfont, text, len);
        }
        
        int
       -textw(const char *text) {
       -        return textnw(text, strlen(text)) + dc.font.height;
       +textw(DC *dc, const char *text) {
       +        return textnw(dc, text, strlen(text)) + dc->font.height;
        }
 (DIR) diff --git a/draw.h b/draw.h
       t@@ -9,6 +9,7 @@ typedef struct {
                unsigned long norm[ColLast];
                unsigned long sel[ColLast];
                Drawable drawable;
       +        Display *dpy;
                GC gc;
                struct {
                        XFontStruct *xfont;
       t@@ -20,25 +21,14 @@ typedef struct {
        } DC; /* draw context */
        
        /* forward declarations */
       -void drawcleanup(void);
       -void drawsetup(void);
       -void drawtext(const char *text, unsigned long col[ColLast]);
       -void eprint(const char *errstr, ...);
       -unsigned long getcolor(const char *colstr);
       -void initfont(const char *fontstr);
       -int textnw(const char *text, unsigned int len);
       -int textw(const char *text);
       +void cleanupdraw(DC *dc);
       +void setupdraw(DC *dc, Window w);
       +void drawtext(DC *dc, const char *text, unsigned long col[ColLast]);
       +void eprint(const char *fmt, ...);
       +unsigned long getcolor(DC *dc, const char *colstr);
       +void initfont(DC *dc, const char *fontstr);
       +int textnw(DC *dc, const char *text, unsigned int len);
       +int textw(DC *dc, const char *text);
        
        /* variables */
       -extern char *progname;
       -extern Display *dpy;
       -extern DC dc;
       -extern int screen;
       -extern unsigned int mw, mh;
       -extern Window parent;
       -
       -extern const char *font;
       -extern const char *normbgcolor;
       -extern const char *normfgcolor;
       -extern const char *selbgcolor;
       -extern const char *selfgcolor;
       +extern const char *progname;