Xinqi Bao's Git

dwm draws a small caret before the client title if it's a versatile client
[dwm.git] / draw.c
1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
2 * See LICENSE file for license details.
3 */
4 #include "dwm.h"
5 #include <string.h>
6
7 /* static */
8
9 static void
10 drawcaret(unsigned long col[ColLast]) {
11 int x;
12 XGCValues gcv;
13 XPoint pt[3];
14
15 gcv.foreground = col[ColFG];
16 XChangeGC(dpy, dc.gc, GCForeground, &gcv);
17 x = (dc.font.ascent + dc.font.descent) / 2;
18 pt[0].x = dc.x + 1;
19 pt[0].y = dc.y + 1 + x;
20 pt[1].x = 0;
21 pt[1].y = -x;
22 pt[2].x = x;
23 pt[2].y = 0;
24 XDrawLines(dpy, dc.drawable, dc.gc, pt, 3, CoordModePrevious);
25 }
26
27 static void
28 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
29 int x;
30 XGCValues gcv;
31 XRectangle r = { dc.x, dc.y, dc.w, dc.h };
32
33 gcv.foreground = col[ColFG];
34 XChangeGC(dpy, dc.gc, GCForeground, &gcv);
35 x = (dc.font.ascent + dc.font.descent + 2) / 4;
36 r.x = dc.x + 1;
37 r.y = dc.y + 1;
38 if(filled) {
39 r.width = r.height = x + 1;
40 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
41 }
42 else if(empty) {
43 r.width = r.height = x;
44 XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
45 }
46 }
47
48 static Bool
49 isoccupied(unsigned int t) {
50 Client *c;
51
52 for(c = clients; c; c = c->next)
53 if(c->tags[t])
54 return True;
55 return False;
56 }
57
58 static unsigned int
59 textnw(const char *text, unsigned int len) {
60 XRectangle r;
61
62 if(dc.font.set) {
63 XmbTextExtents(dc.font.set, text, len, NULL, &r);
64 return r.width;
65 }
66 return XTextWidth(dc.font.xfont, text, len);
67 }
68
69 /* extern */
70
71 void
72 drawstatus(void) {
73 int i, x;
74
75 dc.x = dc.y = 0;
76 for(i = 0; i < ntags; i++) {
77 dc.w = textw(tags[i]);
78 if(seltag[i]) {
79 drawtext(tags[i], dc.sel);
80 drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
81 }
82 else {
83 drawtext(tags[i], dc.norm);
84 drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
85 }
86 dc.x += dc.w;
87 }
88 dc.w = blw;
89 drawtext(lt->symbol, dc.norm);
90 x = dc.x + dc.w;
91 dc.w = textw(stext);
92 dc.x = sw - dc.w;
93 if(dc.x < x) {
94 dc.x = x;
95 dc.w = sw - x;
96 }
97 drawtext(stext, dc.norm);
98 if((dc.w = dc.x - x) > bh) {
99 dc.x = x;
100 if(sel) {
101 drawtext(sel->name, dc.sel);
102 if(sel->isversatile)
103 drawcaret(dc.sel);
104 }
105 else
106 drawtext(NULL, dc.norm);
107 }
108 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
109 XSync(dpy, False);
110 }
111
112 void
113 drawtext(const char *text, unsigned long col[ColLast]) {
114 int x, y, w, h;
115 static char buf[256];
116 unsigned int len, olen;
117 XGCValues gcv;
118 XRectangle r = { dc.x, dc.y, dc.w, dc.h };
119
120 XSetForeground(dpy, dc.gc, col[ColBG]);
121 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
122 if(!text)
123 return;
124 w = 0;
125 olen = len = strlen(text);
126 if(len >= sizeof buf)
127 len = sizeof buf - 1;
128 memcpy(buf, text, len);
129 buf[len] = 0;
130 h = dc.font.ascent + dc.font.descent;
131 y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
132 x = dc.x + (h / 2);
133 /* shorten text if necessary */
134 while(len && (w = textnw(buf, len)) > dc.w - h)
135 buf[--len] = 0;
136 if(len < olen) {
137 if(len > 1)
138 buf[len - 1] = '.';
139 if(len > 2)
140 buf[len - 2] = '.';
141 if(len > 3)
142 buf[len - 3] = '.';
143 }
144 if(w > dc.w)
145 return; /* too long */
146 gcv.foreground = col[ColFG];
147 if(dc.font.set) {
148 XChangeGC(dpy, dc.gc, GCForeground, &gcv);
149 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
150 }
151 else {
152 gcv.font = dc.font.xfont->fid;
153 XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
154 XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
155 }
156 }
157
158 unsigned int
159 textw(const char *text) {
160 return textnw(text, strlen(text)) + dc.font.height;
161 }