drw.c (6245B)
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, unsigned int h) 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, screen)); 22 drw->gc = XCreateGC(dpy, root, 0, NULL); 23 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); 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, DefaultDepth(drw->dpy, drw->screen)); 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", missing[n]); 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)->ascent); 68 font->descent = MAX(font->descent,(*xfonts)->descent); 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_clr_free(Drw *drw, Clr *c) 136 { 137 if (!drw || !c) 138 return; 139 140 /* c is typedef XColor Clr */ 141 /* TODO: free XColor? */ 142 } 143 144 void 145 drw_scm_free(Drw *drw, Clr *scm, size_t clrcount) 146 { 147 size_t i; 148 149 if (!drw || !scm) 150 return; 151 152 for (i = 0; i < clrcount; i++) 153 drw_clr_free(drw, &scm[i]); 154 free(scm); 155 } 156 157 void 158 drw_setfontset(Drw *drw, Fnt *set) 159 { 160 drw->fonts = set; 161 } 162 163 void 164 drw_setscheme(Drw *drw, Clr *scheme) 165 { 166 drw->scheme = scheme; 167 } 168 169 void 170 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, 171 int invert) 172 { 173 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColBg : ColFg].pixel); 174 if (filled) 175 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1); 176 else 177 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 178 } 179 180 int 181 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, 182 const char *text, int invert) 183 { 184 char buf[256]; 185 int i, tx, ty, th, len, olen, render = x || y || w || h; 186 unsigned int texw, texh; 187 188 if (!render) { 189 w = ~w; 190 } else { 191 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); 192 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 193 x += lpad; 194 w -= lpad; 195 } 196 197 olen = strlen(text); 198 drw_font_getexts(drw->fonts, text, olen, &texw, &texh); 199 th = drw->fonts->ascent + drw->fonts->descent; 200 ty = y + (h / 2) - (th / 2) + drw->fonts->ascent; 201 tx = x; 202 /* shorten text if necessary */ 203 for (len = MIN(olen, sizeof buf); len && texw > w; len--) 204 drw_font_getexts(drw->fonts, text, len, &texw, &texh); 205 if (!len) 206 return x; 207 memcpy(buf, text, len); 208 if (len < olen) 209 for (i = len; i && i > len - 3; buf[--i] = '.') 210 ; 211 XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); 212 if (drw->fonts->set) 213 XmbDrawString(drw->dpy, drw->drawable, drw->fonts->set, drw->gc, tx, ty, buf, len); 214 else 215 XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len); 216 217 x += texw; 218 w -= texw; 219 220 return x + (render ? w : 0); 221 } 222 223 void 224 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) 225 { 226 XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); 227 XSync(drw->dpy, False); 228 } 229 230 static unsigned int 231 drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) 232 { 233 unsigned int w; 234 235 drw_font_getexts(font, text, len, &w, NULL); 236 237 return w; 238 } 239 240 unsigned int 241 drw_fontset_getwidth(Drw *drw, const char *text) 242 { 243 return drw_font_getexts_width(drw->fonts, text, strlen(text)); 244 } 245 246 unsigned int 247 drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) 248 { 249 unsigned int tmp = 0; 250 if (drw && drw->fonts && text && n) 251 tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); 252 return MIN(n, tmp); 253 } 254 255 void 256 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) 257 { 258 XRectangle r; 259 260 if (font->set) { 261 XmbTextExtents(font->set, text, len, NULL, &r); 262 if (w) 263 *w = r.width; 264 if (h) 265 *h = r.height; 266 } else { 267 if (w) 268 *w = XTextWidth(font->xfont, text, len); 269 if (h) 270 *h = font->ascent + font->descent; 271 } 272 } 273 274 Cur * 275 drw_cur_create(Drw *drw, int shape) 276 { 277 Cur *cur; 278 279 cur = ecalloc(1, sizeof(Cur)); 280 cur->cursor = XCreateFontCursor(drw->dpy, shape); 281 282 return cur; 283 } 284 285 void 286 drw_cur_free(Drw *drw, Cur *cursor) 287 { 288 XFreeCursor(drw->dpy, cursor->cursor); 289 free(cursor); 290 }