JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
cf7f14e202c91c5d440ea53f3852be56a8147280
[dwm.git] / draw.c
1 /*
2  * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
3  * See LICENSE file for license details.
4  */
5
6 #include <stdio.h>
7 #include <string.h>
8
9 #include "draw.h"
10 #include "util.h"
11
12 static void
13 drawborder(Display *dpy, Brush *b)
14 {
15         XPoint points[5];
16         XSetLineAttributes(dpy, b->gc, 1, LineSolid, CapButt, JoinMiter);
17         XSetForeground(dpy, b->gc, b->border);
18         points[0].x = b->rect.x;
19         points[0].y = b->rect.y;
20         points[1].x = b->rect.width - 1;
21         points[1].y = 0;
22         points[2].x = 0;
23         points[2].y = b->rect.height - 1;
24         points[3].x = -(b->rect.width - 1);
25         points[3].y = 0;
26         points[4].x = 0;
27         points[4].y = -(b->rect.height - 1);
28         XDrawLines(dpy, b->drawable, b->gc, points, 5, CoordModePrevious);
29 }
30
31 void
32 draw(Display *dpy, Brush *b, Bool border, const char *text)
33 {
34         unsigned int x, y, w, h, len;
35         static char buf[256];
36         XGCValues gcv;
37
38         XSetForeground(dpy, b->gc, b->bg);
39         XFillRectangles(dpy, b->drawable, b->gc, &b->rect, 1);
40
41         if(border)
42                 drawborder(dpy, b);
43
44         if(!text)
45                 return;
46
47         len = strlen(text);
48         if(len >= sizeof(buf))
49                 len = sizeof(buf) - 1;
50         memcpy(buf, text, len);
51         buf[len] = 0;
52
53         h = b->font.ascent + b->font.descent;
54         y = b->rect.y + (b->rect.height / 2) - (h / 2) + b->font.ascent;
55         x = b->rect.x + (h / 2);
56
57         /* shorten text if necessary */
58         while(len && (w = textwidth_l(&b->font, buf, len)) > b->rect.width - h)
59                 buf[--len] = 0;
60
61         if(w > b->rect.width)
62                 return; /* too long */
63
64         gcv.foreground = b->fg;
65         gcv.background = b->bg;
66         if(b->font.set) {
67                 XChangeGC(dpy, b->gc, GCForeground | GCBackground, &gcv);
68                 XmbDrawImageString(dpy, b->drawable, b->font.set, b->gc,
69                                 x, y, buf, len);
70         }
71         else {
72                 gcv.font = b->font.xfont->fid;
73                 XChangeGC(dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
74                 XDrawImageString(dpy, b->drawable, b->gc, x, y, buf, len);
75         }
76 }
77
78 static unsigned long
79 xloadcolors(Display *dpy, Colormap cmap, const char *colstr)
80 {
81         XColor color;
82         XAllocNamedColor(dpy, cmap, colstr, &color, &color);
83         return color.pixel;
84 }
85
86 void
87 loadcolors(Display *dpy, int screen, Brush *b,
88                 const char *bg, const char *fg, const char *border)
89 {
90         Colormap cmap = DefaultColormap(dpy, screen);
91         b->bg = xloadcolors(dpy, cmap, bg);
92         b->fg = xloadcolors(dpy, cmap, fg);
93         b->border = xloadcolors(dpy, cmap, border);
94 }
95
96 unsigned int
97 textwidth_l(Fnt *font, char *text, unsigned int len)
98 {
99         if(font->set) {
100                 XRectangle r;
101                 XmbTextExtents(font->set, text, len, 0, &r);
102                 return r.width;
103         }
104         return XTextWidth(font->xfont, text, len);
105 }
106
107 unsigned int
108 textwidth(Fnt *font, char *text)
109 {
110         return textwidth_l(font, text, strlen(text));
111 }
112
113 void
114 loadfont(Display *dpy, Fnt *font, const char *fontstr)
115 {
116         char **missing, *def;
117         int n;
118
119         missing = 0;
120         def = "?";
121         setlocale(LC_ALL, "");
122         if(font->set)
123                 XFreeFontSet(dpy, font->set);
124         font->set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
125         if(missing) {
126                 while(n--)
127                         fprintf(stderr, "missing fontset: %s\n", missing[n]);
128                 XFreeStringList(missing);
129                 if(font->set) {
130                         XFreeFontSet(dpy, font->set);
131                         font->set = 0;
132                 }
133         }
134         if(font->set) {
135                 XFontSetExtents *font_extents;
136                 XFontStruct **xfonts;
137                 char **font_names;
138                 unsigned int i;
139
140                 font->ascent = font->descent = 0;
141                 font_extents = XExtentsOfFontSet(font->set);
142                 n = XFontsOfFontSet(font->set, &xfonts, &font_names);
143                 for(i = 0, font->ascent = 0, font->descent = 0; i < n; i++) {
144                         if(font->ascent < (*xfonts)->ascent)
145                                 font->ascent = (*xfonts)->ascent;
146                         if(font->descent < (*xfonts)->descent)
147                                 font->descent = (*xfonts)->descent;
148                         xfonts++;
149                 }
150         }
151         else {
152                 if(font->xfont)
153                         XFreeFont(dpy, font->xfont);
154                 font->xfont = 0;
155                 font->xfont = XLoadQueryFont(dpy, fontstr);
156                 if (!font->xfont)
157                         font->xfont = XLoadQueryFont(dpy, "fixed");
158                 if (!font->xfont)
159                         error("error, cannot load 'fixed' font\n");
160                 font->ascent = font->xfont->ascent;
161                 font->descent = font->xfont->descent;
162         }
163         font->height = font->ascent + font->descent;
164 }