92f07ca786b705d991a6d06fd3051d64ff8e76e3
[dmenu.git] / draw.c
1 /* (C)opyright MMIV-MMVII Anselm R. Garbe <garbeam at gmail dot com>
2  * See LICENSE file for license details.
3  */
4 #include "dmenu.h"
5 #include <stdio.h>
6 #include <string.h>
7
8 /* static */
9
10 static unsigned int
11 textnw(const char *text, unsigned int len) {
12         XRectangle r;
13
14         if(dc.font.set) {
15                 XmbTextExtents(dc.font.set, text, len, NULL, &r);
16                 return r.width;
17         }
18         return XTextWidth(dc.font.xfont, text, len);
19 }
20
21 /* extern */
22
23 void
24 drawtext(const char *text, unsigned long col[ColLast]) {
25         int x, y, w, h;
26         static char buf[256];
27         unsigned int len, olen;
28         XGCValues gcv;
29         XRectangle r = { dc.x, dc.y, dc.w, dc.h };
30
31         XSetForeground(dpy, dc.gc, col[ColBG]);
32         XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
33         if(!text)
34                 return;
35         w = 0;
36         olen = len = strlen(text);
37         if(len >= sizeof buf)
38                 len = sizeof buf - 1;
39         memcpy(buf, text, len);
40         buf[len] = 0;
41         h = dc.font.ascent + dc.font.descent;
42         y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
43         x = dc.x + (h / 2);
44         /* shorten text if necessary */
45         while(len && (w = textnw(buf, len)) > dc.w - h)
46                 buf[--len] = 0;
47         if(len < olen) {
48                 if(len > 1)
49                         buf[len - 1] = '.';
50                 if(len > 2)
51                         buf[len - 2] = '.';
52                 if(len > 3)
53                         buf[len - 3] = '.';
54         }
55         if(w > dc.w)
56                 return; /* too long */
57         gcv.foreground = col[ColFG];
58         if(dc.font.set) {
59                 XChangeGC(dpy, dc.gc, GCForeground, &gcv);
60                 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc,
61                                 x, y, buf, len);
62         }
63         else {
64                 gcv.font = dc.font.xfont->fid;
65                 XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
66                 XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
67         }
68 }
69
70 unsigned long
71 getcolor(const char *colstr) {
72         Colormap cmap = DefaultColormap(dpy, screen);
73         XColor color;
74
75         if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
76                 eprint("error, cannot allocate color '%s'\n", colstr);
77         return color.pixel;
78 }
79
80 void
81 setfont(const char *fontstr) {
82         char *def, **missing;
83         int i, n;
84
85         missing = NULL;
86         if(dc.font.set)
87                 XFreeFontSet(dpy, dc.font.set);
88         dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
89         if(missing)
90                 XFreeStringList(missing);
91         if(dc.font.set) {
92                 XFontSetExtents *font_extents;
93                 XFontStruct **xfonts;
94                 char **font_names;
95                 dc.font.ascent = dc.font.descent = 0;
96                 font_extents = XExtentsOfFontSet(dc.font.set);
97                 n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
98                 for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
99                         if(dc.font.ascent < (*xfonts)->ascent)
100                                 dc.font.ascent = (*xfonts)->ascent;
101                         if(dc.font.descent < (*xfonts)->descent)
102                                 dc.font.descent = (*xfonts)->descent;
103                         xfonts++;
104                 }
105         }
106         else {
107                 if(dc.font.xfont)
108                         XFreeFont(dpy, dc.font.xfont);
109                 dc.font.xfont = NULL;
110                 if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
111                         eprint("error, cannot load font: '%s'\n", fontstr);
112                 dc.font.ascent = dc.font.xfont->ascent;
113                 dc.font.descent = dc.font.xfont->descent;
114         }
115         dc.font.height = dc.font.ascent + dc.font.descent;
116 }
117
118 unsigned int
119 textw(const char *text) {
120         return textnw(text, strlen(text)) + dc.font.height;
121 }