The patch has been updated: fg highlighting now works in vertical mode.

--
Henri

On Wed, Sep 01, 2010 at 07:57:03PM +0300, Henri Mannerberg wrote:
> My pleasure. I will take a look at the issue with the '-l' switch when I have
> the time. 
>
> ...
>
> On Wed, Sep 01, 2010 at 01:29:37PM +0200, Arian Kuschki wrote:
> > 
> > Thanks for this, Henri. The only issue I have is that the font colour
> > does not change when highlighted when I call dmenu with the '-l' option.
> > -- 
> > 
diff -up dmenu-4.1.1/config.def.h dmenu-4.1.1-xft/config.def.h
--- dmenu-4.1.1/config.def.h    2010-05-29 14:56:51.000000000 +0300
+++ dmenu-4.1.1-xft/config.def.h        2010-09-02 17:31:01.176669712 +0300
@@ -7,3 +7,5 @@ static const char *normfgcolor = "#00000
 static const char *selbgcolor  = "#0066ff";
 static const char *selfgcolor  = "#ffffff";
 static unsigned int spaceitem  = 30; /* px between menu items */
+static const char *fontxft     = "Monospace-10:normal"; 
+#define USE_XFT 1 /* if set xft is used */
diff -up dmenu-4.1.1/config.mk dmenu-4.1.1-xft/config.mk
--- dmenu-4.1.1/config.mk       2010-05-29 14:56:51.000000000 +0300
+++ dmenu-4.1.1-xft/config.mk   2010-09-02 16:37:56.253340190 +0300
@@ -15,8 +15,8 @@ XINERAMALIBS = -L${X11LIB} -lXinerama
 XINERAMAFLAGS = -DXINERAMA
 
 # includes and libs
-INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS}
+INCS = -I. -I/usr/include -I${X11INC} -I/usr/include -I/usr/include/freetype2
+LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} -lXft -lXrender 
-lfreetype -lz -lfontconfig -lXrender
 
 # flags
 CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff -up dmenu-4.1.1/dmenu.1 dmenu-4.1.1-xft/dmenu.1
--- dmenu-4.1.1/dmenu.1 2010-05-29 14:56:51.000000000 +0300
+++ dmenu-4.1.1-xft/dmenu.1     2010-09-02 16:37:56.283340181 +0300
@@ -7,6 +7,7 @@ dmenu \- dynamic menu
 .RB [ \-b ]
 .RB [ \-l " <lines>"]
 .RB [ \-fn " <font>"]
+.RB [ \-fa " <xftfont>"]
 .RB [ \-nb " <color>"]
 .RB [ \-nf " <color>"]
 .RB [ \-p " <prompt>"]
@@ -34,6 +35,9 @@ The given number of lines will be displa
 .B \-fn <font>
 defines the font.
 .TP
+.B \-fa <font>
+defines the xft font.
+.TP
 .B \-nb <color>
 defines the normal background color (#RGB, #RRGGBB, and color names are 
supported).
 .TP
diff -up dmenu-4.1.1/dmenu.c dmenu-4.1.1-xft/dmenu.c
--- dmenu-4.1.1/dmenu.c 2010-05-29 14:56:51.000000000 +0300
+++ dmenu-4.1.1-xft/dmenu.c     2010-09-02 17:28:10.510006842 +0300
@@ -13,6 +13,7 @@
 #ifdef XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif
+#include <X11/Xft/Xft.h>
 
 /* macros */
 #define CLEANMASK(mask)         (mask & ~(numlockmask | LockMask))
@@ -29,6 +30,7 @@ typedef struct {
        int x, y, w, h;
        unsigned long norm[ColLast];
        unsigned long sel[ColLast];
+       Bool selected;
        Drawable drawable;
        GC gc;
        struct {
@@ -38,6 +40,16 @@ typedef struct {
                int descent;
                int height;
        } font;
+       XftDraw *xftdraw;
+       XftColor xftselcolor;
+       XftColor xftcolor;
+       XGlyphInfo gi;
+       struct {
+               XftFont *xft_font;
+               int ascent;
+               int descent;
+               int height;
+       } xftfont;
 } DC; /* draw context */
 
 typedef struct Item Item;
@@ -135,18 +147,23 @@ calcoffsetsh(void) {
 void
 calcoffsetsv(void) {
        static unsigned int h;
+       int h2;
 
        if(!curr)
                return;
-       h = (dc.font.height + 2) * (lines + 1);
+       if(USE_XFT)
+         h2 = dc.xftfont.height;
+       else
+         h2 = dc.font.height;
+       h = (h2 + 2) * (lines + 1);
        for(next = curr; next; next=next->right) {
-               h -= dc.font.height + 2;
+               h -= h2 + 2;
                if(h <= 0)
                        break;
        }
-       h = (dc.font.height + 2) * (lines + 1);
+       h = (h2 + 2) * (lines + 1);
        for(prev = curr; prev && prev->left; prev=prev->left) {
-               h -= dc.font.height + 2;
+               h -= h2 + 2;
                if(h <= 0)
                        break;
        }
@@ -185,9 +202,14 @@ cleanup(void) {
                free(allitems);
                allitems = itm;
        }
+       if(USE_XFT) {
+               XftColorFree (dpy, DefaultVisual(dpy, screen), 
DefaultColormap(dpy, screen), &dc.xftcolor);
+               XftFontClose (dpy, dc.xftfont.xft_font);
+               XftDrawDestroy(dc.xftdraw);
+       }
        if(dc.font.set)
                XFreeFontSet(dpy, dc.font.set);
-       else
+       else if(!USE_XFT)
                XFreeFont(dpy, dc.font.xfont);
        XFreePixmap(dpy, dc.drawable);
        XFreeGC(dpy, dc.gc);
@@ -198,8 +220,15 @@ cleanup(void) {
 void
 drawcursor(void) {
        XRectangle r = { dc.x, dc.y + 2, 1, dc.font.height - 2 };
+       int h2;
+
+       if(USE_XFT)
+         h2 = dc.xftfont.height;
+       else
+         h2 = dc.font.height;
 
-       r.x += textnw(text, cursor) + dc.font.height / 2;
+       r.height = h2 - 2;
+       r.x += textnw(text, cursor) + h2 / 2;
 
        XSetForeground(dpy, dc.gc, dc.norm[ColFG]);
        XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
@@ -215,7 +244,9 @@ drawmenu(void) {
        /* print prompt? */
        if(prompt) {
                dc.w = promptw;
-               drawtext(prompt, dc.sel);
+        dc.selected = True;
+        drawtext(prompt, dc.sel);
+        dc.selected = False;
                dc.x += dc.w;
        }
        dc.w = mw - dc.x;
@@ -244,7 +275,13 @@ drawmenuh(void) {
        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);
+               if(sel == i) {
+                 dc.selected = True;
+                 drawtext(i->text, dc.sel);
+                 dc.selected = False;
+               } else {
+                 drawtext(i->text, dc.norm);
+               }
                dc.x += dc.w;
        }
        dc.w = spaceitem;
@@ -255,12 +292,24 @@ drawmenuh(void) {
 void
 drawmenuv(void) {
        Item *i;
+       int h2;
+
+       if(USE_XFT)
+         h2 = dc.xftfont.height;
+       else
+         h2 = dc.font.height;
 
        dc.w = mw - dc.x;
-       dc.y += dc.font.height + 2;
+       dc.y += h2 + 2;
        for(i = curr; i != next; i=i->right) {
-               drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
-               dc.y += dc.font.height + 2;
+               if(sel == i) {
+                 dc.selected = True;
+                 drawtext(i->text, dc.sel);
+                 dc.selected = False;
+               } else {
+                 drawtext(i->text, dc.norm);
+               }
+               dc.y += h2 + 2;
        }
        drawtext(NULL, dc.norm);
 }
@@ -268,7 +317,7 @@ drawmenuv(void) {
 void
 drawtext(const char *text, unsigned long col[ColLast]) {
        char buf[256];
-       int i, x, y, h, len, olen;
+       int i, x, y, h, a, len, olen;
        XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 
        XSetForeground(dpy, dc.gc, col[ColBG]);
@@ -276,8 +325,14 @@ drawtext(const char *text, unsigned long
        if(!text)
                return;
        olen = strlen(text);
-       h = dc.font.height;
-       y = dc.y + ((h+2) / 2) - (h / 2) + dc.font.ascent;
+       if(!USE_XFT) {
+         h = dc.font.height;
+         a = dc.font.ascent;
+       } else {
+         h = dc.xftfont.height;
+         a = dc.xftfont.ascent;
+       }
+       y = dc.y + ((h+2) / 2) - (h / 2) + a;
        x = dc.x + (h / 2);
        /* shorten text if necessary */
        for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; 
len--);
@@ -287,7 +342,15 @@ drawtext(const char *text, unsigned long
        if(len < olen)
                for(i = len; i && i > len - 3; buf[--i] = '.');
        XSetForeground(dpy, dc.gc, col[ColFG]);
-       if(dc.font.set)
+       if(USE_XFT) {
+               if (!dc.xftdraw)
+                       eprint("error, creating xft drawable failed");
+               if(dc.selected) {
+                       XftDrawStringUtf8(dc.xftdraw, &dc.xftselcolor, 
dc.xftfont.xft_font, x, y, (unsigned char*)buf, len);
+               } else {
+                       XftDrawStringUtf8(dc.xftdraw, &dc.xftcolor, 
dc.xftfont.xft_font, x, y, (unsigned char*)buf, len);
+               }
+       } else if(dc.font.set)
                XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, 
len);
        else
                XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
@@ -359,6 +422,15 @@ initfont(const char *fontstr) {
 }
 
 void
+initxft() {
+       if(!(dc.xftfont.xft_font = XftFontOpenName (dpy, screen, fontxft)))
+               eprint("error, cannot load xft font\n" );
+       dc.xftfont.ascent = dc.xftfont.xft_font->ascent;
+       dc.xftfont.descent = dc.xftfont.xft_font->descent;
+       dc.xftfont.height = dc.xftfont.ascent + dc.xftfont.descent;
+}
+
+void
 kpress(XKeyEvent * e) {
        char buf[sizeof text];
        int i, num, off;
@@ -697,7 +769,15 @@ setup(Bool topbar) {
        dc.norm[ColFG] = getcolor(normfgcolor);
        dc.sel[ColBG] = getcolor(selbgcolor);
        dc.sel[ColFG] = getcolor(selfgcolor);
-       initfont(font);
+       dc.selected = False;
+    if(USE_XFT){
+               if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), 
DefaultColormap(dpy, screen), (const char*)normfgcolor, &dc.xftcolor))
+                       eprint("error, cannot allocate xft font color '%s'\n", 
normfgcolor);
+               if(!XftColorAllocName(dpy, DefaultVisual(dpy, screen), 
DefaultColormap(dpy, screen), (const char*)selfgcolor, &dc.xftselcolor))
+                       eprint("error, cannot allocate xft font color '%s'\n", 
normfgcolor);
+        else
+                       initxft();
+       } else initfont(font);
 
        /* menu window */
        wa.override_redirect = True;
@@ -705,7 +785,10 @@ setup(Bool topbar) {
        wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask | 
VisibilityChangeMask;
 
        /* menu window geometry */
-       mh = (dc.font.height + 2) * (lines + 1);
+       if(USE_XFT) 
+         mh = (dc.xftfont.height + 2) * (lines + 1);
+       else
+         mh = (dc.font.height + 2) * (lines + 1);
 #if XINERAMA
        if(parent == RootWindow(dpy, screen) && XineramaIsActive(dpy) && (info 
= XineramaQueryScreens(dpy, &n))) {
                i = 0;
@@ -741,7 +824,7 @@ setup(Bool topbar) {
        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)
+       if(!dc.font.set && !USE_XFT)
                XSetFont(dpy, dc.gc, dc.font.xfont->fid);
        if(maxname)
                cmdw = MIN(textw(maxname), mw / 3);
@@ -750,13 +833,20 @@ setup(Bool topbar) {
        text[0] = '\0';
        match(text);
        XMapRaised(dpy, win);
+       if(USE_XFT) {
+               dc.xftdraw = XftDrawCreate(dpy, dc.drawable, 
DefaultVisual(dpy,screen), DefaultColormap(dpy,screen));
+               if(!dc.xftdraw)
+                       eprint("error, cannot create xft drawable\n");
+       }
 }
 
 int
 textnw(const char *text, unsigned int len) {
-       XRectangle r;
-
-       if(dc.font.set) {
+       if(USE_XFT) {
+               XftTextExtentsUtf8(dpy, dc.xftfont.xft_font, (const 
FcChar8*)text, len, &dc.gi);
+               return dc.gi.width;
+    } else if(dc.font.set) {
+           XRectangle r;
                XmbTextExtents(dc.font.set, text, len, NULL, &r);
                return r.width;
        }
@@ -765,6 +855,8 @@ textnw(const char *text, unsigned int le
 
 int
 textw(const char *text) {
+       if(USE_XFT)
+               return textnw(text, strlen(text)) + dc.xftfont.height;
        return textnw(text, strlen(text)) + dc.font.height;
 }
 
@@ -791,6 +883,9 @@ main(int argc, char *argv[]) {
                else if(!strcmp(argv[i], "-fn")) {
                        if(++i < argc) font = argv[i];
                }
+               else if(!strcmp(argv[i], "-fa")) {
+                       if(++i < argc) fontxft = argv[i];
+               }
                else if(!strcmp(argv[i], "-nb")) {
                        if(++i < argc) normbgcolor = argv[i];
                }
@@ -809,7 +904,7 @@ main(int argc, char *argv[]) {
                else if(!strcmp(argv[i], "-v"))
                        eprint("dmenu-"VERSION", © 2006-2010 dmenu engineers, 
see LICENSE for details\n");
                else
-                       eprint("usage: dmenu [-i] [-b] [-e <xid>] [-l <lines>] 
[-fn <font>] [-nb <color>]\n"
+                       eprint("usage: dmenu [-i] [-b] [-e <xid>] [-l <lines>] 
[-fn <font>] [-fa <xftfont>] [-nb <color>]\n"
                               "             [-nf <color>] [-p <prompt>] [-sb 
<color>] [-sf <color>] [-v]\n");
        if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
                fprintf(stderr, "warning: no locale support\n");

Reply via email to