drw.c - libsl - draw back-ends for dwm, dmenu, etc | |
git clone git://git.codemadness.org/libsl | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
drw.c (5943B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <stdio.h> | |
3 #include <stdlib.h> | |
4 #include <string.h> | |
5 #include <X11/Xlib.h> | |
6 | |
7 #include "drw.h" | |
8 #include "util.h" | |
9 | |
10 Drw * | |
11 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsign… | |
12 { | |
13 Drw *drw; | |
14 | |
15 drw = ecalloc(1, sizeof(Drw)); | |
16 drw->dpy = dpy; | |
17 drw->screen = screen; | |
18 drw->root = root; | |
19 drw->w = w; | |
20 drw->h = h; | |
21 drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy,… | |
22 drw->gc = XCreateGC(dpy, root, 0, NULL); | |
23 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMite… | |
24 | |
25 return drw; | |
26 } | |
27 | |
28 void | |
29 drw_resize(Drw *drw, unsigned int w, unsigned int h) | |
30 { | |
31 drw->w = w; | |
32 drw->h = h; | |
33 if (drw->drawable) | |
34 XFreePixmap(drw->dpy, drw->drawable); | |
35 drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, Default… | |
36 } | |
37 | |
38 void | |
39 drw_free(Drw *drw) | |
40 { | |
41 XFreePixmap(drw->dpy, drw->drawable); | |
42 XFreeGC(drw->dpy, drw->gc); | |
43 free(drw); | |
44 } | |
45 | |
46 static Fnt * | |
47 xfont_create(Display *dpy, const char *fontname) | |
48 { | |
49 Fnt *font; | |
50 XFontStruct **xfonts; | |
51 char **font_names; | |
52 char *def, **missing; | |
53 int n; | |
54 | |
55 font = ecalloc(1, sizeof(Fnt)); | |
56 font->dpy = dpy; | |
57 font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def); | |
58 if (missing) { | |
59 while (n--) | |
60 fprintf(stderr, "drw: missing fontset: %s\n", mi… | |
61 XFreeStringList(missing); | |
62 } | |
63 if (font->set) { | |
64 XExtentsOfFontSet(font->set); | |
65 n = XFontsOfFontSet(font->set, &xfonts, &font_names); | |
66 while (n--) { | |
67 font->ascent = MAX(font->ascent, (*xfonts)->asce… | |
68 font->descent = MAX(font->descent,(*xfonts)->des… | |
69 xfonts++; | |
70 } | |
71 } else { | |
72 if (!(font->xfont = XLoadQueryFont(dpy, fontname)) | |
73 && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) | |
74 die("error, cannot load font: '%s'\n", fontname); | |
75 font->ascent = font->xfont->ascent; | |
76 font->descent = font->xfont->descent; | |
77 } | |
78 font->h = font->ascent + font->descent; | |
79 | |
80 return font; | |
81 } | |
82 | |
83 void | |
84 xfont_free(Display *dpy, Fnt *font) | |
85 { | |
86 if (font->set) | |
87 XFreeFontSet(dpy, font->set); | |
88 else | |
89 XFreeFont(dpy, font->xfont); | |
90 free(font); | |
91 } | |
92 | |
93 Fnt * | |
94 drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) | |
95 { | |
96 /* just create using first font */ | |
97 /* TODO: more? */ | |
98 drw->fonts = xfont_create(drw->dpy, fonts[0]); | |
99 return drw->fonts; | |
100 } | |
101 | |
102 void | |
103 drw_fontset_free(Fnt *font) | |
104 { | |
105 xfont_free(font->dpy, font); | |
106 } | |
107 | |
108 void | |
109 drw_clr_create(Drw *drw, Clr *dest, const char *clrname) | |
110 { | |
111 Colormap cmap; | |
112 XColor ecolor; | |
113 | |
114 cmap = DefaultColormap(drw->dpy, drw->screen); | |
115 if (!XAllocNamedColor(drw->dpy, cmap, clrname, dest, &ecolor)) | |
116 die("error, cannot allocate color '%s'\n", clrname); | |
117 } | |
118 | |
119 /* Wrapper to create color schemes. The caller has to call free(3) on the | |
120 * returned color scheme when done using it. */ | |
121 Clr * | |
122 drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) | |
123 { | |
124 size_t i; | |
125 Clr *ret; | |
126 | |
127 ret = ecalloc(clrcount, sizeof(Clr)); | |
128 for (i = 0; i < clrcount; i++) | |
129 drw_clr_create(drw, &ret[i], clrnames[i]); | |
130 | |
131 return ret; | |
132 } | |
133 | |
134 void | |
135 drw_setfontset(Drw *drw, Fnt *set) | |
136 { | |
137 drw->fonts = set; | |
138 } | |
139 | |
140 void | |
141 drw_setscheme(Drw *drw, Clr *scheme) | |
142 { | |
143 drw->scheme = scheme; | |
144 } | |
145 | |
146 void | |
147 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int fil… | |
148 int invert) | |
149 { | |
150 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColBg : C… | |
151 if (filled) | |
152 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w… | |
153 else | |
154 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w… | |
155 } | |
156 | |
157 int | |
158 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigne… | |
159 const char *text, int invert) | |
160 { | |
161 char buf[256]; | |
162 int i, tx, ty, th, len, olen, render = x || y || w || h; | |
163 unsigned int texw, texh; | |
164 | |
165 if (!render) { | |
166 w = ~w; | |
167 } else { | |
168 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? C… | |
169 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w… | |
170 x += lpad; | |
171 w -= lpad; | |
172 } | |
173 | |
174 olen = strlen(text); | |
175 drw_font_getexts(drw->fonts, text, olen, &texw, &texh); | |
176 th = drw->fonts->ascent + drw->fonts->descent; | |
177 ty = y + (h / 2) - (th / 2) + drw->fonts->ascent; | |
178 tx = x; | |
179 /* shorten text if necessary */ | |
180 for (len = MIN(olen, sizeof buf); len && texw > w; len--) | |
181 drw_font_getexts(drw->fonts, text, len, &texw, &texh); | |
182 if (!len) | |
183 return x; | |
184 memcpy(buf, text, len); | |
185 if (len < olen) | |
186 for (i = len; i && i > len - 3; buf[--i] = '.') | |
187 ; | |
188 XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pi… | |
189 if (drw->fonts->set) | |
190 XmbDrawString(drw->dpy, drw->drawable, drw->fonts->set, … | |
191 else | |
192 XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, bu… | |
193 | |
194 x += texw; | |
195 w -= texw; | |
196 | |
197 return x + (render ? w : 0); | |
198 } | |
199 | |
200 void | |
201 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int… | |
202 { | |
203 XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, … | |
204 XSync(drw->dpy, False); | |
205 } | |
206 | |
207 static unsigned int | |
208 drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) | |
209 { | |
210 unsigned int w; | |
211 | |
212 drw_font_getexts(font, text, len, &w, NULL); | |
213 | |
214 return w; | |
215 } | |
216 | |
217 unsigned int | |
218 drw_fontset_getwidth(Drw *drw, const char *text) | |
219 { | |
220 return drw_font_getexts_width(drw->fonts, text, strlen(text)); | |
221 } | |
222 | |
223 unsigned int | |
224 drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) | |
225 { | |
226 unsigned int tmp = 0; | |
227 if (drw && drw->fonts && text && n) | |
228 tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); | |
229 return MIN(n, tmp); | |
230 } | |
231 | |
232 void | |
233 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned… | |
234 { | |
235 XRectangle r; | |
236 | |
237 if (font->set) { | |
238 XmbTextExtents(font->set, text, len, NULL, &r); | |
239 if (w) | |
240 *w = r.width; | |
241 if (h) | |
242 *h = r.height; | |
243 } else { | |
244 if (w) | |
245 *w = XTextWidth(font->xfont, text, len); | |
246 if (h) | |
247 *h = font->ascent + font->descent; | |
248 } | |
249 } | |
250 | |
251 Cur * | |
252 drw_cur_create(Drw *drw, int shape) | |
253 { | |
254 Cur *cur; | |
255 | |
256 cur = ecalloc(1, sizeof(Cur)); | |
257 cur->cursor = XCreateFontCursor(drw->dpy, shape); | |
258 | |
259 return cur; | |
260 } | |
261 | |
262 void | |
263 drw_cur_free(Drw *drw, Cur *cursor) | |
264 { | |
265 XFreeCursor(drw->dpy, cursor->cursor); | |
266 free(cursor); | |
267 } |