diff options
Diffstat (limited to 'draw.c')
-rw-r--r-- | draw.c | 109 |
1 files changed, 53 insertions, 56 deletions
@@ -14,126 +14,123 @@ | |||
14 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | 14 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
15 | 15 | ||
16 | /* variables */ | 16 | /* variables */ |
17 | char *progname; | 17 | const char *progname; |
18 | 18 | ||
19 | void | 19 | void |
20 | drawcleanup(void) { | 20 | cleanupdraw(DC *dc) { |
21 | if(dc.font.set) | 21 | if(dc->font.set) |
22 | XFreeFontSet(dpy, dc.font.set); | 22 | XFreeFontSet(dc->dpy, dc->font.set); |
23 | else | 23 | else |
24 | XFreeFont(dpy, dc.font.xfont); | 24 | XFreeFont(dc->dpy, dc->font.xfont); |
25 | XFreePixmap(dpy, dc.drawable); | 25 | XFreePixmap(dc->dpy, dc->drawable); |
26 | XFreeGC(dpy, dc.gc); | 26 | XFreeGC(dc->dpy, dc->gc); |
27 | } | 27 | } |
28 | 28 | ||
29 | void | 29 | void |
30 | drawsetup(void) { | 30 | setupdraw(DC *dc, Window w) { |
31 | /* style */ | 31 | XWindowAttributes wa; |
32 | dc.norm[ColBG] = getcolor(normbgcolor); | 32 | |
33 | dc.norm[ColFG] = getcolor(normfgcolor); | 33 | XGetWindowAttributes(dc->dpy, w, &wa); |
34 | dc.sel[ColBG] = getcolor(selbgcolor); | 34 | dc->drawable = XCreatePixmap(dc->dpy, w, wa.width, wa.height, |
35 | dc.sel[ColFG] = getcolor(selfgcolor); | 35 | DefaultDepth(dc->dpy, DefaultScreen(dc->dpy))); |
36 | 36 | dc->gc = XCreateGC(dc->dpy, w, 0, NULL); | |
37 | /* pixmap */ | 37 | XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter); |
38 | dc.drawable = XCreatePixmap(dpy, parent, mw, mh, DefaultDepth(dpy, screen)); | 38 | if(!dc->font.set) |
39 | dc.gc = XCreateGC(dpy, parent, 0, NULL); | 39 | XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid); |
40 | XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); | ||
41 | if(!dc.font.set) | ||
42 | XSetFont(dpy, dc.gc, dc.font.xfont->fid); | ||
43 | } | 40 | } |
44 | 41 | ||
45 | void | 42 | void |
46 | drawtext(const char *text, unsigned long col[ColLast]) { | 43 | drawtext(DC *dc, const char *text, unsigned long col[ColLast]) { |
47 | char buf[256]; | 44 | char buf[256]; |
48 | int i, x, y, h, len, olen; | 45 | int i, x, y, h, len, olen; |
49 | XRectangle r = { dc.x, dc.y, dc.w, dc.h }; | 46 | XRectangle r = { dc->x, dc->y, dc->w, dc->h }; |
50 | 47 | ||
51 | XSetForeground(dpy, dc.gc, col[ColBG]); | 48 | XSetForeground(dc->dpy, dc->gc, col[ColBG]); |
52 | XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); | 49 | XFillRectangles(dc->dpy, dc->drawable, dc->gc, &r, 1); |
53 | if(!text) | 50 | if(!text) |
54 | return; | 51 | return; |
55 | olen = strlen(text); | 52 | olen = strlen(text); |
56 | h = dc.font.height; | 53 | h = dc->font.height; |
57 | y = dc.y + ((h+2) / 2) - (h / 2) + dc.font.ascent; | 54 | y = dc->y + ((h+2) / 2) - (h / 2) + dc->font.ascent; |
58 | x = dc.x + (h / 2); | 55 | x = dc->x + (h / 2); |
59 | /* shorten text if necessary */ | 56 | /* shorten text if necessary */ |
60 | for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); | 57 | for(len = MIN(olen, sizeof buf); len && textnw(dc, text, len) > dc->w - h; len--); |
61 | if(!len) | 58 | if(!len) |
62 | return; | 59 | return; |
63 | memcpy(buf, text, len); | 60 | memcpy(buf, text, len); |
64 | if(len < olen) | 61 | if(len < olen) |
65 | for(i = len; i && i > len - 3; buf[--i] = '.'); | 62 | for(i = len; i && i > len - 3; buf[--i] = '.'); |
66 | XSetForeground(dpy, dc.gc, col[ColFG]); | 63 | XSetForeground(dc->dpy, dc->gc, col[ColFG]); |
67 | if(dc.font.set) | 64 | if(dc->font.set) |
68 | XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); | 65 | XmbDrawString(dc->dpy, dc->drawable, dc->font.set, dc->gc, x, y, buf, len); |
69 | else | 66 | else |
70 | XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); | 67 | XDrawString(dc->dpy, dc->drawable, dc->gc, x, y, buf, len); |
71 | } | 68 | } |
72 | 69 | ||
73 | void | 70 | void |
74 | eprint(const char *errstr, ...) { | 71 | eprint(const char *fmt, ...) { |
75 | va_list ap; | 72 | va_list ap; |
76 | 73 | ||
77 | fprintf(stderr, "%s: ", progname); | 74 | fprintf(stderr, "%s: ", progname); |
78 | va_start(ap, errstr); | 75 | va_start(ap, fmt); |
79 | vfprintf(stderr, errstr, ap); | 76 | vfprintf(stderr, fmt, ap); |
80 | va_end(ap); | 77 | va_end(ap); |
81 | exit(EXIT_FAILURE); | 78 | exit(EXIT_FAILURE); |
82 | } | 79 | } |
83 | 80 | ||
84 | unsigned long | 81 | unsigned long |
85 | getcolor(const char *colstr) { | 82 | getcolor(DC *dc, const char *colstr) { |
86 | Colormap cmap = DefaultColormap(dpy, screen); | 83 | Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy)); |
87 | XColor color; | 84 | XColor color; |
88 | 85 | ||
89 | if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) | 86 | if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color)) |
90 | eprint("cannot allocate color '%s'\n", colstr); | 87 | eprint("cannot allocate color '%s'\n", colstr); |
91 | return color.pixel; | 88 | return color.pixel; |
92 | } | 89 | } |
93 | 90 | ||
94 | void | 91 | void |
95 | initfont(const char *fontstr) { | 92 | initfont(DC *dc, const char *fontstr) { |
96 | char *def, **missing = NULL; | 93 | char *def, **missing = NULL; |
97 | int i, n; | 94 | int i, n; |
98 | 95 | ||
99 | if(!fontstr || !*fontstr) | 96 | if(!fontstr || !*fontstr) |
100 | eprint("cannot load null font\n"); | 97 | eprint("cannot load null font\n"); |
101 | dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); | 98 | dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def); |
102 | if(missing) | 99 | if(missing) |
103 | XFreeStringList(missing); | 100 | XFreeStringList(missing); |
104 | if(dc.font.set) { | 101 | if(dc->font.set) { |
105 | XFontStruct **xfonts; | 102 | XFontStruct **xfonts; |
106 | char **font_names; | 103 | char **font_names; |
107 | dc.font.ascent = dc.font.descent = 0; | 104 | dc->font.ascent = dc->font.descent = 0; |
108 | n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); | 105 | n = XFontsOfFontSet(dc->font.set, &xfonts, &font_names); |
109 | for(i = 0; i < n; i++) { | 106 | for(i = 0; i < n; i++) { |
110 | dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); | 107 | dc->font.ascent = MAX(dc->font.ascent, (*xfonts)->ascent); |
111 | dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent); | 108 | dc->font.descent = MAX(dc->font.descent, (*xfonts)->descent); |
112 | xfonts++; | 109 | xfonts++; |
113 | } | 110 | } |
114 | } | 111 | } |
115 | else { | 112 | else { |
116 | if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) | 113 | if(!(dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr)) |
117 | && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) | 114 | && !(dc->font.xfont = XLoadQueryFont(dc->dpy, "fixed"))) |
118 | eprint("cannot load font '%s'\n", fontstr); | 115 | eprint("cannot load font '%s'\n", fontstr); |
119 | dc.font.ascent = dc.font.xfont->ascent; | 116 | dc->font.ascent = dc->font.xfont->ascent; |
120 | dc.font.descent = dc.font.xfont->descent; | 117 | dc->font.descent = dc->font.xfont->descent; |
121 | } | 118 | } |
122 | dc.font.height = dc.font.ascent + dc.font.descent; | 119 | dc->font.height = dc->font.ascent + dc->font.descent; |
123 | } | 120 | } |
124 | 121 | ||
125 | int | 122 | int |
126 | textnw(const char *text, unsigned int len) { | 123 | textnw(DC *dc, const char *text, unsigned int len) { |
127 | XRectangle r; | 124 | XRectangle r; |
128 | 125 | ||
129 | if(dc.font.set) { | 126 | if(dc->font.set) { |
130 | XmbTextExtents(dc.font.set, text, len, NULL, &r); | 127 | XmbTextExtents(dc->font.set, text, len, NULL, &r); |
131 | return r.width; | 128 | return r.width; |
132 | } | 129 | } |
133 | return XTextWidth(dc.font.xfont, text, len); | 130 | return XTextWidth(dc->font.xfont, text, len); |
134 | } | 131 | } |
135 | 132 | ||
136 | int | 133 | int |
137 | textw(const char *text) { | 134 | textw(DC *dc, const char *text) { |
138 | return textnw(text, strlen(text)) + dc.font.height; | 135 | return textnw(dc, text, strlen(text)) + dc->font.height; |
139 | } | 136 | } |