59 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
59 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
60 XSync(dpy, False); |
60 XSync(dpy, False); |
61 free(seltag); |
61 free(seltag); |
62 } |
62 } |
63 |
63 |
64 static unsigned int |
|
65 textnw(const char *text, unsigned int len) { |
|
66 XRectangle r; |
|
67 |
|
68 if(dc.font.set) { |
|
69 XmbTextExtents(dc.font.set, text, len, NULL, &r); |
|
70 return r.width; |
|
71 } |
|
72 return XTextWidth(dc.font.xfont, text, len); |
|
73 } |
|
74 |
|
75 static void |
|
76 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { |
|
77 int x; |
|
78 XGCValues gcv; |
|
79 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
|
80 |
|
81 gcv.foreground = col[ColFG]; |
|
82 XChangeGC(dpy, dc.gc, GCForeground, &gcv); |
|
83 x = (dc.font.ascent + dc.font.descent + 2) / 4; |
|
84 r.x = dc.x + 1; |
|
85 r.y = dc.y + 1; |
|
86 if(filled) { |
|
87 r.width = r.height = x + 1; |
|
88 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
|
89 } |
|
90 else if(empty) { |
|
91 r.width = r.height = x; |
|
92 XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
|
93 } |
|
94 } |
|
95 |
|
96 static unsigned long |
64 static unsigned long |
97 getcolor(const char *colstr) { |
65 getcolor(const char *colstr) { |
98 Colormap cmap = DefaultColormap(dpy, screen); |
66 Colormap cmap = DefaultColormap(dpy, screen); |
99 XColor color; |
67 XColor color; |
100 |
68 |
101 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
69 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
102 eprint("error, cannot allocate color '%s'\n", colstr); |
70 eprint("error, cannot allocate color '%s'\n", colstr); |
103 return color.pixel; |
71 return color.pixel; |
104 } |
|
105 |
|
106 static Bool |
|
107 isoccupied(unsigned int t) { |
|
108 Client *c; |
|
109 |
|
110 for(c = clients; c; c = c->next) |
|
111 if(c->tags[t]) |
|
112 return True; |
|
113 return False; |
|
114 } |
72 } |
115 |
73 |
116 static void |
74 static void |
117 scan(void) { |
75 scan(void) { |
118 unsigned int i, num; |
76 unsigned int i, num; |
262 } |
220 } |
263 |
221 |
264 /* extern */ |
222 /* extern */ |
265 |
223 |
266 void |
224 void |
267 drawstatus(void) { |
|
268 int i, x; |
|
269 |
|
270 dc.x = dc.y = 0; |
|
271 for(i = 0; i < ntags; i++) { |
|
272 dc.w = textw(tags[i]); |
|
273 if(seltag[i]) { |
|
274 drawtext(tags[i], dc.sel); |
|
275 drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel); |
|
276 } |
|
277 else { |
|
278 drawtext(tags[i], dc.norm); |
|
279 drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm); |
|
280 } |
|
281 dc.x += dc.w; |
|
282 } |
|
283 dc.w = blw; |
|
284 drawtext(lt->symbol, dc.norm); |
|
285 x = dc.x + dc.w; |
|
286 dc.w = textw(stext); |
|
287 dc.x = sw - dc.w; |
|
288 if(dc.x < x) { |
|
289 dc.x = x; |
|
290 dc.w = sw - x; |
|
291 } |
|
292 drawtext(stext, dc.norm); |
|
293 if((dc.w = dc.x - x) > bh) { |
|
294 dc.x = x; |
|
295 drawtext(sel ? sel->name : NULL, sel ? dc.sel : dc.norm); |
|
296 } |
|
297 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); |
|
298 XSync(dpy, False); |
|
299 } |
|
300 |
|
301 void |
|
302 drawtext(const char *text, unsigned long col[ColLast]) { |
|
303 int x, y, w, h; |
|
304 static char buf[256]; |
|
305 unsigned int len, olen; |
|
306 XGCValues gcv; |
|
307 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
|
308 |
|
309 XSetForeground(dpy, dc.gc, col[ColBG]); |
|
310 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
|
311 if(!text) |
|
312 return; |
|
313 w = 0; |
|
314 olen = len = strlen(text); |
|
315 if(len >= sizeof buf) |
|
316 len = sizeof buf - 1; |
|
317 memcpy(buf, text, len); |
|
318 buf[len] = 0; |
|
319 h = dc.font.ascent + dc.font.descent; |
|
320 y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; |
|
321 x = dc.x + (h / 2); |
|
322 /* shorten text if necessary */ |
|
323 while(len && (w = textnw(buf, len)) > dc.w - h) |
|
324 buf[--len] = 0; |
|
325 if(len < olen) { |
|
326 if(len > 1) |
|
327 buf[len - 1] = '.'; |
|
328 if(len > 2) |
|
329 buf[len - 2] = '.'; |
|
330 if(len > 3) |
|
331 buf[len - 3] = '.'; |
|
332 } |
|
333 if(w > dc.w) |
|
334 return; /* too long */ |
|
335 gcv.foreground = col[ColFG]; |
|
336 if(dc.font.set) { |
|
337 XChangeGC(dpy, dc.gc, GCForeground, &gcv); |
|
338 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); |
|
339 } |
|
340 else { |
|
341 gcv.font = dc.font.xfont->fid; |
|
342 XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv); |
|
343 XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); |
|
344 } |
|
345 } |
|
346 |
|
347 void |
|
348 sendevent(Window w, Atom a, long value) { |
225 sendevent(Window w, Atom a, long value) { |
349 XEvent e; |
226 XEvent e; |
350 |
227 |
351 e.type = ClientMessage; |
228 e.type = ClientMessage; |
352 e.xclient.window = w; |
229 e.xclient.window = w; |
354 e.xclient.format = 32; |
231 e.xclient.format = 32; |
355 e.xclient.data.l[0] = value; |
232 e.xclient.data.l[0] = value; |
356 e.xclient.data.l[1] = CurrentTime; |
233 e.xclient.data.l[1] = CurrentTime; |
357 XSendEvent(dpy, w, False, NoEventMask, &e); |
234 XSendEvent(dpy, w, False, NoEventMask, &e); |
358 XSync(dpy, False); |
235 XSync(dpy, False); |
359 } |
|
360 |
|
361 unsigned int |
|
362 textw(const char *text) { |
|
363 return textnw(text, strlen(text)) + dc.font.height; |
|
364 } |
236 } |
365 |
237 |
366 void |
238 void |
367 quit(Arg *arg) { |
239 quit(Arg *arg) { |
368 readin = running = False; |
240 readin = running = False; |