annotate config/dmenu/drw.c @ 4:7c8c5e548075 default tip

fix stuff
author Yasuri <yasuri@charliesmp.net>
date Sat, 03 Oct 2026 19:23:53 -0500
parents face7f4d84f7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
1 /* See LICENSE file for copyright and license details. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
2 #include <stdio.h>
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
3 #include <stdlib.h>
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
4 #include <string.h>
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
5 #include <X11/Xlib.h>
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
6 #include <X11/Xft/Xft.h>
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
7
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
8 #include "drw.h"
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
9 #include "util.h"
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
10
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
11 #define UTF_INVALID 0xFFFD
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
12
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
13 static int
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
14 utf8decode(const char *s_in, long *u, int *err)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
15 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
16 static const unsigned char lens[] = {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
17 /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
18 /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
19 /* 110XX */ 2, 2, 2, 2,
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
20 /* 1110X */ 3, 3,
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
21 /* 11110 */ 4,
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
22 /* 11111 */ 0, /* invalid */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
23 };
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
24 static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
25 static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 };
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
26
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
27 const unsigned char *s = (const unsigned char *)s_in;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
28 int len = lens[*s >> 3];
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
29 *u = UTF_INVALID;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
30 *err = 1;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
31 if (len == 0)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
32 return 1;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
33
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
34 long cp = s[0] & leading_mask[len - 1];
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
35 for (int i = 1; i < len; ++i) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
36 if (s[i] == '\0' || (s[i] & 0xC0) != 0x80)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
37 return i;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
38 cp = (cp << 6) | (s[i] & 0x3F);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
39 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
40 /* out of range, surrogate, overlong encoding */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
41 if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1])
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
42 return len;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
43
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
44 *err = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
45 *u = cp;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
46 return len;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
47 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
48
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
49 Drw *
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
50 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
51 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
52 Drw *drw = ecalloc(1, sizeof(Drw));
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
53
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
54 drw->dpy = dpy;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
55 drw->screen = screen;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
56 drw->root = root;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
57 drw->w = w;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
58 drw->h = h;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
59 drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
60 drw->gc = XCreateGC(dpy, root, 0, NULL);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
61 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
62
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
63 return drw;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
64 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
65
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
66 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
67 drw_resize(Drw *drw, unsigned int w, unsigned int h)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
68 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
69 if (!drw)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
70 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
71
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
72 drw->w = w;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
73 drw->h = h;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
74 if (drw->drawable)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
75 XFreePixmap(drw->dpy, drw->drawable);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
76 drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
77 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
78
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
79 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
80 drw_free(Drw *drw)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
81 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
82 XFreePixmap(drw->dpy, drw->drawable);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
83 XFreeGC(drw->dpy, drw->gc);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
84 drw_fontset_free(drw->fonts);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
85 free(drw);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
86 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
87
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
88 /* This function is an implementation detail. Library users should use
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
89 * drw_fontset_create instead.
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
90 */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
91 static Fnt *
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
92 xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
93 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
94 Fnt *font;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
95 XftFont *xfont = NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
96 FcPattern *pattern = NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
97
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
98 if (fontname) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
99 /* Using the pattern found at font->xfont->pattern does not yield the
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
100 * same substitution results as using the pattern returned by
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
101 * FcNameParse; using the latter results in the desired fallback
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
102 * behaviour whereas the former just results in missing-character
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
103 * rectangles being drawn, at least with some fonts. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
104 if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
105 fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
106 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
107 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
108 if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
109 fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
110 XftFontClose(drw->dpy, xfont);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
111 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
112 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
113 } else if (fontpattern) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
114 if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
115 fprintf(stderr, "error, cannot load font from pattern.\n");
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
116 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
117 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
118 } else {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
119 die("no font specified.");
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
120 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
121
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
122 font = ecalloc(1, sizeof(Fnt));
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
123 font->xfont = xfont;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
124 font->pattern = pattern;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
125 font->h = xfont->ascent + xfont->descent;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
126 font->dpy = drw->dpy;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
127
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
128 return font;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
129 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
130
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
131 static void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
132 xfont_free(Fnt *font)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
133 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
134 if (!font)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
135 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
136 if (font->pattern)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
137 FcPatternDestroy(font->pattern);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
138 XftFontClose(font->dpy, font->xfont);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
139 free(font);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
140 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
141
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
142 Fnt*
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
143 drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
144 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
145 Fnt *cur, *ret = NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
146 size_t i;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
147
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
148 if (!drw || !fonts)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
149 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
150
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
151 for (i = 1; i <= fontcount; i++) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
152 if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
153 cur->next = ret;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
154 ret = cur;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
155 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
156 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
157 return (drw->fonts = ret);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
158 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
159
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
160 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
161 drw_fontset_free(Fnt *font)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
162 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
163 if (font) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
164 drw_fontset_free(font->next);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
165 xfont_free(font);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
166 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
167 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
168
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
169 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
170 drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
171 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
172 if (!drw || !dest || !clrname)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
173 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
174
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
175 if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
176 DefaultColormap(drw->dpy, drw->screen),
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
177 clrname, dest))
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
178 die("error, cannot allocate color '%s'", clrname);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
179 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
180
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
181 /* Create color schemes. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
182 Clr *
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
183 drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
184 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
185 size_t i;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
186 Clr *ret;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
187
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
188 /* need at least two colors for a scheme */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
189 if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr))))
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
190 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
191
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
192 for (i = 0; i < clrcount; i++)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
193 drw_clr_create(drw, &ret[i], clrnames[i]);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
194 return ret;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
195 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
196
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
197 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
198 drw_clr_free(Drw *drw, Clr *c)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
199 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
200 if (!drw || !c)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
201 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
202
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
203 /* c is typedef XftColor Clr */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
204 XftColorFree(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
205 DefaultColormap(drw->dpy, drw->screen), c);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
206 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
207
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
208 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
209 drw_scm_free(Drw *drw, Clr *scm, size_t clrcount)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
210 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
211 size_t i;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
212
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
213 if (!drw || !scm)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
214 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
215
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
216 for (i = 0; i < clrcount; i++)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
217 drw_clr_free(drw, &scm[i]);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
218 free(scm);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
219 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
220
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
221 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
222 drw_setfontset(Drw *drw, Fnt *set)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
223 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
224 if (drw)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
225 drw->fonts = set;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
226 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
227
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
228 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
229 drw_setscheme(Drw *drw, Clr *scm)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
230 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
231 if (drw)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
232 drw->scheme = scm;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
233 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
234
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
235 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
236 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
237 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
238 if (!drw || !drw->scheme)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
239 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
240 XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
241 if (filled)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
242 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
243 else
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
244 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
245 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
246
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
247 int
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
248 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
249 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
250 int ty, ellipsis_x = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
251 unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
252 XftDraw *d = NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
253 Fnt *usedfont, *curfont, *nextfont;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
254 int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
255 long utf8codepoint = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
256 const char *utf8str;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
257 FcCharSet *fccharset;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
258 FcPattern *fcpattern;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
259 FcPattern *match;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
260 XftResult result;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
261 int charexists = 0, overflow = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
262 /* keep track of a couple codepoints for which we have no match. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
263 static unsigned int nomatches[128], ellipsis_width, invalid_width;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
264 static const char invalid[] = "�";
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
265
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
266 if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
267 return 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
268
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
269 if (!render) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
270 w = invert ? invert : ~invert;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
271 } else {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
272 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
273 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
274 if (w < lpad)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
275 return x + w;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
276 d = XftDrawCreate(drw->dpy, drw->drawable,
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
277 DefaultVisual(drw->dpy, drw->screen),
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
278 DefaultColormap(drw->dpy, drw->screen));
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
279 x += lpad;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
280 w -= lpad;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
281 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
282
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
283 usedfont = drw->fonts;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
284 if (!ellipsis_width && render)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
285 ellipsis_width = drw_fontset_getwidth(drw, "...");
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
286 if (!invalid_width && render)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
287 invalid_width = drw_fontset_getwidth(drw, invalid);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
288 while (1) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
289 ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
290 utf8str = text;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
291 nextfont = NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
292 while (*text) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
293 utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
294 for (curfont = drw->fonts; curfont; curfont = curfont->next) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
295 charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
296 if (charexists) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
297 drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
298 if (ew + ellipsis_width <= w) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
299 /* keep track where the ellipsis still fits */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
300 ellipsis_x = x + ew;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
301 ellipsis_w = w - ew;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
302 ellipsis_len = utf8strlen;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
303 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
304
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
305 if (ew + tmpw > w) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
306 overflow = 1;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
307 /* called from drw_fontset_getwidth_clamp():
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
308 * it wants the width AFTER the overflow
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
309 */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
310 if (!render)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
311 x += tmpw;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
312 else
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
313 utf8strlen = ellipsis_len;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
314 } else if (curfont == usedfont) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
315 text += utf8charlen;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
316 utf8strlen += utf8err ? 0 : utf8charlen;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
317 ew += utf8err ? 0 : tmpw;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
318 } else {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
319 nextfont = curfont;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
320 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
321 break;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
322 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
323 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
324
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
325 if (overflow || !charexists || nextfont || utf8err)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
326 break;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
327 else
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
328 charexists = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
329 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
330
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
331 if (utf8strlen) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
332 if (render) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
333 ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
334 XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
335 usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
336 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
337 x += ew;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
338 w -= ew;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
339 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
340 if (utf8err && (!render || invalid_width < w)) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
341 if (render)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
342 drw_text(drw, x, y, w, h, 0, invalid, invert);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
343 x += invalid_width;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
344 w -= invalid_width;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
345 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
346 if (render && overflow)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
347 drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
348
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
349 if (!*text || overflow) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
350 break;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
351 } else if (nextfont) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
352 charexists = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
353 usedfont = nextfont;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
354 } else {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
355 /* Regardless of whether or not a fallback font is found, the
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
356 * character must be drawn. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
357 charexists = 1;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
358
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
359 hash = (unsigned int)utf8codepoint;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
360 hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
361 hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
362 h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
363 h1 = (hash >> 17) % LENGTH(nomatches);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
364 /* avoid expensive XftFontMatch call when we know we won't find a match */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
365 if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
366 goto no_match;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
367
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
368 fccharset = FcCharSetCreate();
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
369 FcCharSetAddChar(fccharset, utf8codepoint);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
370
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
371 if (!drw->fonts->pattern) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
372 /* Refer to the comment in xfont_create for more information. */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
373 die("the first font in the cache must be loaded from a font string.");
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
374 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
375
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
376 fcpattern = FcPatternDuplicate(drw->fonts->pattern);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
377 FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
378 FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
379
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
380 FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
381 FcDefaultSubstitute(fcpattern);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
382 match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
383
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
384 FcCharSetDestroy(fccharset);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
385 FcPatternDestroy(fcpattern);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
386
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
387 if (match) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
388 usedfont = xfont_create(drw, NULL, match);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
389 if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
390 for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
391 ; /* NOP */
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
392 curfont->next = usedfont;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
393 } else {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
394 xfont_free(usedfont);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
395 nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
396 no_match:
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
397 usedfont = drw->fonts;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
398 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
399 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
400 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
401 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
402 if (d)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
403 XftDrawDestroy(d);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
404
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
405 return x + (render ? w : 0);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
406 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
407
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
408 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
409 drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
410 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
411 if (!drw)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
412 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
413
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
414 XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
415 XSync(drw->dpy, False);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
416 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
417
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
418 unsigned int
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
419 drw_fontset_getwidth(Drw *drw, const char *text)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
420 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
421 if (!drw || !drw->fonts || !text)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
422 return 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
423 return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
424 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
425
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
426 unsigned int
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
427 drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
428 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
429 unsigned int tmp = 0;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
430 if (drw && drw->fonts && text && n)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
431 tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
432 return MIN(n, tmp);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
433 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
434
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
435 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
436 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
437 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
438 XGlyphInfo ext;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
439
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
440 if (!font || !text)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
441 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
442
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
443 XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
444 if (w)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
445 *w = ext.xOff;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
446 if (h)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
447 *h = font->h;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
448 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
449
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
450 Cur *
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
451 drw_cur_create(Drw *drw, int shape)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
452 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
453 Cur *cur;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
454
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
455 if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
456 return NULL;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
457
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
458 cur->cursor = XCreateFontCursor(drw->dpy, shape);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
459
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
460 return cur;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
461 }
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
462
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
463 void
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
464 drw_cur_free(Drw *drw, Cur *cursor)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
465 {
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
466 if (!cursor)
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
467 return;
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
468
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
469 XFreeCursor(drw->dpy, cursor->cursor);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
470 free(cursor);
face7f4d84f7 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
471 }