X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=draw.c;h=41022f03c38041695c15b3770d1ba5cc6ef28b45;hb=08b264393d41321c1b7ae3644f73c67cb825c95c;hp=75075952cab9948e377760e3611c2d7200d7520c;hpb=b497a13bde8a02ea42a1f475d76a47eca37babd1;p=dmenu.git diff --git a/draw.c b/draw.c index 7507595..41022f0 100644 --- a/draw.c +++ b/draw.c @@ -1,159 +1,143 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe - * See LICENSE file for license details. - */ -#include "dmenu.h" -#include -#include -#include - -/* static */ - -static void -drawborder(void) -{ - XPoint points[5]; +/* See LICENSE file for copyright and license details. */ - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - XSetForeground(dpy, dc.gc, dc.border); - points[0].x = dc.x; - points[0].y = dc.y; - points[1].x = dc.w - 1; - points[1].y = 0; - points[2].x = 0; - points[2].y = dc.h - 1; - points[3].x = -(dc.w - 1); - points[3].y = 0; - points[4].x = 0; - points[4].y = -(dc.h - 1); - XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious); -} +/* enums */ +enum { ColFG, ColBG, ColLast }; -static unsigned int -textnw(const char *text, unsigned int len) -{ - XRectangle r; +/* typedefs */ +typedef struct { + int x, y, w, h; + unsigned long norm[ColLast]; + unsigned long sel[ColLast]; + Drawable drawable; + GC gc; + struct { + XFontStruct *xfont; + XFontSet set; + int ascent; + int descent; + int height; + } font; +} DC; /* draw context */ + +/* forward declarations */ +static void dccleanup(void); +static void dcsetup(void); +static void drawtext(const char *text, unsigned long col[ColLast]); +static unsigned long getcolor(const char *colstr); +static void initfont(const char *fontstr); +static int textnw(const char *text, unsigned int len); +static int textw(const char *text); + +static DC dc; - if(dc.font.set) { - XmbTextExtents(dc.font.set, text, len, NULL, &r); - return r.width; - } - return XTextWidth(dc.font.xfont, text, len); +void +dccleanup(void) { + if(dc.font.set) + XFreeFontSet(dpy, dc.font.set); + else + XFreeFont(dpy, dc.font.xfont); + XFreePixmap(dpy, dc.drawable); + XFreeGC(dpy, dc.gc); } -/* extern */ +void +dcsetup(void) { + /* style */ + dc.norm[ColBG] = getcolor(normbgcolor); + dc.norm[ColFG] = getcolor(normfgcolor); + dc.sel[ColBG] = getcolor(selbgcolor); + dc.sel[ColFG] = getcolor(selfgcolor); + initfont(font); + + /* 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); +} void -drawtext(const char *text, Bool invert, Bool border) -{ - int x, y, w, h; - static char buf[256]; - unsigned int len; - XGCValues gcv; +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, invert ? dc.fg : dc.bg); + XSetForeground(dpy, dc.gc, col[ColBG]); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - - w = 0; - if(border) - drawborder(); - if(!text) return; - - len = strlen(text); - if(len >= sizeof(buf)) - len = sizeof(buf) - 1; - memcpy(buf, text, len); - buf[len] = 0; - - h = dc.font.ascent + dc.font.descent; - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; + olen = strlen(text); + h = dc.font.height; + y = dc.y + ((h+2) / 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(w > dc.w) - return; /* too long */ - - gcv.foreground = invert ? dc.bg : dc.fg; - gcv.background = invert ? dc.fg : dc.bg; - if(dc.font.set) { - XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv); - XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc, - x, y, buf, len); - } - else { - gcv.font = dc.font.xfont->fid; - XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv); - XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len); - } + 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); + else + XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); } unsigned long -getcolor(const char *colstr) -{ +getcolor(const char *colstr) { Colormap cmap = DefaultColormap(dpy, screen); XColor color; - XAllocNamedColor(dpy, cmap, colstr, &color, &color); + if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) + eprint("drawtext: cannot allocate color '%s'\n", colstr); return color.pixel; } void -setfont(const char *fontstr) -{ - char **missing, *def; +initfont(const char *fontstr) { + char *def, **missing = NULL; int i, n; - missing = NULL; - setlocale(LC_ALL, ""); - if(dc.font.set) - XFreeFontSet(dpy, dc.font.set); + if(!fontstr || fontstr[0] == '\0') + eprint("drawtext: cannot load font: '%s'\n", fontstr); dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); - if(missing) { + if(missing) XFreeStringList(missing); - if(dc.font.set) { - XFreeFontSet(dpy, dc.font.set); - dc.font.set = NULL; - } - } if(dc.font.set) { - XFontSetExtents *font_extents; XFontStruct **xfonts; char **font_names; - dc.font.ascent = dc.font.descent = 0; - font_extents = XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); - for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { - if(dc.font.ascent < (*xfonts)->ascent) - dc.font.ascent = (*xfonts)->ascent; - if(dc.font.descent < (*xfonts)->descent) - dc.font.descent = (*xfonts)->descent; + for(i = 0; i < n; i++) { + dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); + dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent); xfonts++; } } else { - if(dc.font.xfont) - XFreeFont(dpy, dc.font.xfont); - dc.font.xfont = NULL; - dc.font.xfont = XLoadQueryFont(dpy, fontstr); - if (!dc.font.xfont) - dc.font.xfont = XLoadQueryFont(dpy, "fixed"); - if (!dc.font.xfont) - eprint("error, cannot init 'fixed' font\n"); + if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) + && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) + eprint("drawtext: cannot load font: '%s'\n", fontstr); dc.font.ascent = dc.font.xfont->ascent; dc.font.descent = dc.font.xfont->descent; } dc.font.height = dc.font.ascent + dc.font.descent; } -unsigned int -textw(const char *text) -{ +int +textnw(const char *text, unsigned int len) { + XRectangle r; + + if(dc.font.set) { + XmbTextExtents(dc.font.set, text, len, NULL, &r); + return r.width; + } + return XTextWidth(dc.font.xfont, text, len); +} + +int +textw(const char *text) { return textnw(text, strlen(text)) + dc.font.height; }