Krolyxon
Commit aa6ccf4

Branches

Refs →

nsxivaa6ccf4

Merge branch 'userinfo'

Author
Bert Münnich
Date
2013-01-27 18:03 +0100
Parents
3a0a1ae 9c0a53b
Commit
aa6ccf42b8aace05154bf2eebcba8695524b0b17

+218 −155

8 files changed

  1. M Makefile +6 −2
  2. M README.md +2 −2
  3. A image-info +17 −0
  4. M main.c +90 −55
  5. M sxiv.1 +16 −14
  6. M thumbs.c +7 −5
  7. M window.c +72 −69
  8. M window.h +8 −8
M Makefile View
@@ -1,4 +1,4 @@
1−VERSION = git-20130112
1+VERSION = git-20130127
22
33 PREFIX = /usr/local
44 MANPREFIX = $(PREFIX)/share/man
@@ -32,9 +32,13 @@ install: all
3232 cp sxiv $(DESTDIR)$(PREFIX)/bin/
3333 chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv
3434 mkdir -p $(DESTDIR)$(MANPREFIX)/man1
35− sed "s/VERSION/$(VERSION)/g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
35+ sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
3636 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
37+ mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec
38+ cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
39+ chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
3740
3841 uninstall:
3942 rm -f $(DESTDIR)$(PREFIX)/bin/sxiv
4043 rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
44+ rm -rf $(DESTDIR)$(PREFIX)/share/sxiv
M README.md View
@@ -1,7 +1,7 @@
11 sxiv
22 ====
33
4−**Simple (or small or suckless) X Image Viewer**
4+**Simple X Image Viewer**
55
66 sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are
77 imlib2 and giflib. The primary goal for writing sxiv is to create an image
@@ -20,7 +20,7 @@ Features
2020 * Ability to cache thumbnails for fast re-loading
2121 * Basic support for multi-frame images
2222 * Load all frames from GIF files and play GIF animations
23−* Display image information in window title
23+* Display image information in status bar
2424
2525
2626 Screenshots
A image-info View
@@ -0,0 +1,17 @@
1+#!/bin/sh
2+
3+# Example for ~/.sxiv/exec/image-info
4+# Called by sxiv(1) whenever an image gets loaded,
5+# with the name of the image file as its first argument.
6+# The output is displayed in sxiv's status bar.
7+
8+filename=$(basename "$1")
9+filesize=$(du -h "$1" | cut -f 1)
10+
11+geometry=$(identify -format '%wx%h' "$1")
12+
13+tags=$(exiv2 -q pr -pi "$1" | awk '$1~"Keywords" { printf("%s,", $4); }')
14+tags=${tags:+|}${tags%,}
15+
16+echo "[$filesize|$geometry$tags] $filename"
17+
M main.c View
@@ -39,8 +39,10 @@
3939 #include "config.h"
4040
4141 enum {
42− INFO_STR_LEN = 256,
43− FILENAME_CNT = 1024
42+ BAR_L_LEN = 512,
43+ BAR_R_LEN = 64,
44+ FILENAME_CNT = 1024,
45+ TITLE_LEN = 256
4446 };
4547
4648 typedef struct {
@@ -63,15 +65,18 @@ win_t win;
6365 fileinfo_t *files;
6466 int filecnt, fileidx;
6567 int alternate;
66−size_t filesize;
6768
6869 int prefix;
6970
7071 bool resized = false;
7172
72−char win_bar_l[INFO_STR_LEN];
73−char win_bar_r[INFO_STR_LEN];
74−char win_title[INFO_STR_LEN];
73+const char * const INFO_SCRIPT = ".sxiv/exec/image-info";
74+char *info_script;
75+
76+struct {
77+ char l[BAR_L_LEN];
78+ char r[BAR_R_LEN];
79+} bar;
7580
7681 timeout_t timeouts[] = {
7782 { { 0, 0 }, false, redraw },
@@ -202,9 +207,37 @@ bool check_timeouts(struct timeval *t) {
202207 return tmin > 0;
203208 }
204209
205−void load_image(int new) {
206− struct stat fstats;
210+void read_info(void) {
211+ char cmd[4096];
212+ FILE *outp;
213+ int c, i = 0, n = sizeof(bar.l) - 1;
214+ bool lastsep = false;
215+
216+ if (info_script != NULL) {
217+ snprintf(cmd, sizeof(cmd), "%s \"%s\"", info_script, files[fileidx].name);
218+ outp = popen(cmd, "r");
219+ if (outp == NULL)
220+ goto end;
221+ while (i < n && (c = fgetc(outp)) != EOF) {
222+ if (c == '\n') {
223+ if (!lastsep) {
224+ bar.l[i++] = ' ';
225+ lastsep = true;
226+ }
227+ } else {
228+ bar.l[i++] = c;
229+ lastsep = false;
230+ }
231+ }
232+ pclose(outp);
233+ }
234+end:
235+ if (lastsep)
236+ i--;
237+ bar.l[i] = '\0';
238+}
207239
240+void load_image(int new) {
208241 if (new < 0 || new >= filecnt)
209242 return;
210243
@@ -220,10 +253,8 @@ void load_image(int new) {
220253 files[new].loaded = true;
221254 alternate = fileidx;
222255 fileidx = new;
223− if (stat(files[new].path, &fstats) == 0)
224− filesize = fstats.st_size;
225− else
226− filesize = 0;
256+
257+ read_info();
227258
228259 if (img.multi.cnt > 0 && img.multi.animate)
229260 set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
@@ -232,60 +263,51 @@ void load_image(int new) {
232263 }
233264
234265 void update_info(void) {
235− int i, fw, pw, fi, ln, rn;
236− char frame_info[16];
237− const char *size_unit;
238− float size = filesize;
266+ unsigned int i, fn, fw, n, len = sizeof(bar.r);
267+ int sel;
268+ char *t = bar.r, title[TITLE_LEN];
269+ bool ow_info;
239270
240− pw = 0;
241− for (i = filecnt; i > 0; i /= 10)
242− pw++;
271+ for (fw = 0, i = filecnt; i > 0; fw++, i /= 10);
272+ sel = mode == MODE_IMAGE ? fileidx : tns.sel;
243273
244274 if (mode == MODE_THUMB) {
245− if (tns.cnt != filecnt) {
246− snprintf(win_bar_l, sizeof win_bar_l, "Loading... %0*d/%d",
247− pw, tns.cnt, filecnt);
275+ win_set_title(&win, "sxiv");
276+
277+ if (tns.cnt == filecnt) {
278+ n = snprintf(t, len, "%0*d/%d", fw, sel + 1, filecnt);
279+ ow_info = true;
248280 } else {
249− fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s",
250− pw, tns.sel + 1, filecnt, BAR_SEPARATOR);
251− ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
252− files[tns.sel].name) + fi;
253− if (win_textwidth(win_bar_l, ln, true) > win.w)
254− snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
255− files[tns.sel].base);
281+ snprintf(bar.l, sizeof(bar.l), "Loading... %0*d/%d",
282+ fw, tns.cnt, filecnt);
283+ bar.r[0] = '\0';
284+ ow_info = false;
256285 }
257− win_set_title(&win, "sxiv");
258− win_set_bar_info(&win, win_bar_l, NULL);
259286 } else {
260− size_readable(&size, &size_unit);
287+ snprintf(title, sizeof(title), "sxiv - %s", files[sel].name);
288+ win_set_title(&win, title);
289+
290+ n = snprintf(t, len, "%3d%% ", (int) (img.zoom * 100.0));
261291 if (img.multi.cnt > 0) {
262− fw = 0;
263− for (i = img.multi.cnt; i > 0; i /= 10)
264− fw++;
265− snprintf(frame_info, sizeof frame_info, "%s%0*d/%d",
266− BAR_SEPARATOR, fw, img.multi.sel+1, img.multi.cnt);
267− } else {
268− frame_info[0] = '\0';
292+ for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
293+ n += snprintf(t + n, len - n, "(%0*d/%d) ",
294+ fn, img.multi.sel + 1, img.multi.cnt);
269295 }
270− fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s",
271− pw, fileidx + 1, filecnt, BAR_SEPARATOR);
272− ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
273− files[fileidx].name) + fi;
274− rn = snprintf(win_bar_r, sizeof win_bar_r, "%.2f%s%s%dx%d%s%3d%%%s",
275− size, size_unit, BAR_SEPARATOR, img.w, img.h, BAR_SEPARATOR,
276− (int) (img.zoom * 100.0), frame_info);
277−
278− if (win_textwidth(win_bar_l, ln, true) +
279− win_textwidth(win_bar_r, rn, true) > win.w)
296+ n += snprintf(t + n, len - n, "%0*d/%d", fw, sel + 1, filecnt);
297+ ow_info = bar.l[0] == '\0';
298+ }
299+ if (ow_info) {
300+ fn = strlen(files[sel].name);
301+ if (fn < sizeof(bar.l) &&
302+ win_textwidth(files[sel].name, fn, true) +
303+ win_textwidth(bar.r, n, true) < win.w)
280304 {
281− snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
282− files[fileidx].base);
305+ strncpy(bar.l, files[sel].name, sizeof(bar.l));
306+ } else {
307+ strncpy(bar.l, files[sel].base, sizeof(bar.l));
283308 }
284− win_set_bar_info(&win, win_bar_l, win_bar_r);
285−
286− snprintf(win_title, sizeof win_title, "sxiv - %s", files[fileidx].name);
287− win_set_title(&win, win_title);
288309 }
310+ win_set_bar_info(&win, bar.l, bar.r);
289311 }
290312
291313 void redraw(void) {
@@ -519,6 +541,7 @@ int main(int argc, char **argv) {
519541 size_t n;
520542 ssize_t len;
521543 char *filename;
544+ const char *homedir;
522545 struct stat fstats;
523546 r_dir_t dir;
524547
@@ -595,6 +618,18 @@ int main(int argc, char **argv) {
595618 win_init(&win);
596619 img_init(&img, &win);
597620
621+ if ((homedir = getenv("HOME")) == NULL) {
622+ warn("could not locate home directory");
623+ } else {
624+ len = strlen(homedir) + strlen(INFO_SCRIPT) + 2;
625+ info_script = (char*) s_malloc(len);
626+ snprintf(info_script, len, "%s/%s", homedir, INFO_SCRIPT);
627+ if (access(info_script, X_OK) != 0) {
628+ free(info_script);
629+ info_script = NULL;
630+ }
631+ }
632+
598633 if (options->thumb_mode) {
599634 mode = MODE_THUMB;
600635 tns_init(&tns, filecnt, &win);
M sxiv.1 View
@@ -1,6 +1,6 @@
11 .TH SXIV 1 sxiv\-VERSION
22 .SH NAME
3−sxiv \- Simple (or small or suckless) X Image Viewer
3+sxiv \- Simple X Image Viewer
44 .SH SYNOPSIS
55 .B sxiv
66 .RB [ \-bcdFfhpqrstvZ ]
@@ -306,9 +306,18 @@ Pan image left.
306306 .TP
307307 .B Shift+ScrollDown
308308 Pan image right.
309+.SH STATUS BAR
310+The information displayed on the left side of the status bar can be replaced
311+with the output of a user-provided script, which is called by sxiv whenever an
312+image gets loaded. The path of this script is
313+.I ~/.sxiv/exec/image-info
314+and the first argument to this script is the path of the loaded image.
315+.P
316+There is also an example script installed together with sxiv as
317+.IR PREFIX/share/sxiv/exec/image-info .
309318 .SH THUMBNAIL CACHING
310319 To enable thumbnail caching, please make sure to create the directory
311−.I ~/.sxiv/
320+.I ~/.sxiv/cache/
312321 with write permissions. sxiv will then store all thumbnails inside this
313322 directory, but it will not create this directory by itself. It rather uses the
314323 existance of this directory as an affirmation, that the user wants thumbnails
@@ -321,30 +330,23 @@ Additionally, run the following command afterwards inside the cache directory
321330 to remove empty subdirectories:
322331 .P
323332 .RS
324−find \-type d \-empty \-delete
325−.RE
326−.P
327−If the version of
328−.I find
329−installed on your local system does not support the \-delete option, then you
330−can also try the following command:
331−.P
332−.RS
333333 find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\;
334334 .RE
335335 .SH AUTHOR
336336 .EX
337−Bert Muennich <ber.t at gmx.com>
337+Bert Muennich <be.muennich @ gmail.com>
338338 .EE
339339 .SH CONTRIBUTORS
340340 .EX
341341 Bastien Dejean <nihilhill at gmail.com>
342342 Dave Reisner <d at falconindy.com>
343343 Fung SzeTat <sthorde at gmail.com>
344−.EX
344+.EE
345345 .SH HOMEPAGE
346−.TP
346+.EX
347+http://muennich.github.com/sxiv
347348 https://github.com/muennich/sxiv
349+.EE
348350 .SH SEE ALSO
349351 .BR feh (1),
350352 .BR qiv (1)
M thumbs.c View
@@ -31,8 +31,10 @@
3131 #include "util.h"
3232 #include "config.h"
3333
34−const int thumb_dim = THUMB_SIZE + 10;
35−char *cache_dir = NULL;
34+static const int thumb_dim = THUMB_SIZE + 10;
35+
36+static const char * const CACHE_DIR = ".sxiv/cache";
37+static char *cache_dir = NULL;
3638
3739 bool tns_cache_enabled(void) {
3840 struct stat stats;
@@ -175,9 +177,9 @@ void tns_init(tns_t *tns, int cnt, win_t *win) {
175177 if ((homedir = getenv("HOME")) != NULL) {
176178 if (cache_dir != NULL)
177179 free(cache_dir);
178− len = strlen(homedir) + 10;
179− cache_dir = (char*) s_malloc(len * sizeof(char));
180− snprintf(cache_dir, len, "%s/.sxiv", homedir);
180+ len = strlen(homedir) + strlen(CACHE_DIR) + 2;
181+ cache_dir = (char*) s_malloc(len);
182+ snprintf(cache_dir, len, "%s/%s", homedir, CACHE_DIR);
181183 } else {
182184 warn("could not locate thumbnail cache directory");
183185 }
M window.c View
@@ -42,13 +42,16 @@ static GC gc;
4242
4343 Atom wm_delete_win;
4444
45−struct {
45+static struct {
4646 int ascent;
4747 int descent;
4848 XFontStruct *xfont;
4949 XFontSet set;
5050 } font;
5151
52+static int fontheight;
53+static int barheight;
54+
5255 void win_init_font(Display *dpy, const char *fontstr) {
5356 int n;
5457 char *def, **missing;
@@ -77,6 +80,8 @@ void win_init_font(Display *dpy, const char *fontstr) {
7780 font.ascent = font.xfont->ascent;
7881 font.descent = font.xfont->descent;
7982 }
83+ fontheight = font.ascent + font.descent;
84+ barheight = fontheight + 2 * V_TEXT_PAD;
8085 }
8186
8287 unsigned long win_alloc_color(win_t *win, const char *name) {
@@ -85,8 +90,8 @@ unsigned long win_alloc_color(win_t *win, const char *name) {
8590 if (win == NULL)
8691 return 0UL;
8792 if (XAllocNamedColor(win->env.dpy,
88− DefaultColormap(win->env.dpy, win->env.scr),
89− name, &col, &col) == 0)
93+ DefaultColormap(win->env.dpy, win->env.scr),
94+ name, &col, &col) == 0)
9095 {
9196 die("could not allocate color: %s", name);
9297 }
@@ -99,6 +104,8 @@ void win_init(win_t *win) {
99104 if (win == NULL)
100105 return;
101106
107+ memset(win, 0, sizeof(win_t));
108+
102109 e = &win->env;
103110 if ((e->dpy = XOpenDisplay(NULL)) == NULL)
104111 die("could not open display");
@@ -110,19 +117,12 @@ void win_init(win_t *win) {
110117 e->cmap = DefaultColormap(e->dpy, e->scr);
111118 e->depth = DefaultDepth(e->dpy, e->scr);
112119
113− win->white = WhitePixel(e->dpy, e->scr);
114− win->bgcol = win_alloc_color(win, WIN_BG_COLOR);
115− win->fscol = win_alloc_color(win, WIN_FS_COLOR);
116− win->selcol = win_alloc_color(win, SEL_COLOR);
117− win->barbgcol = win_alloc_color(win, BAR_BG_COLOR);
118− win->barfgcol = win_alloc_color(win, BAR_FG_COLOR);
119−
120− win->xwin = 0;
121− win->pm = 0;
122− win->fullscreen = false;
123− win->barh = 0;
124− win->lbar = NULL;
125− win->rbar = NULL;
120+ win->white = WhitePixel(e->dpy, e->scr);
121+ win->bgcol = win_alloc_color(win, WIN_BG_COLOR);
122+ win->fscol = win_alloc_color(win, WIN_FS_COLOR);
123+ win->selcol = win_alloc_color(win, SEL_COLOR);
124+ win->bar.bgcol = win_alloc_color(win, BAR_BG_COLOR);
125+ win->bar.fgcol = win_alloc_color(win, BAR_FG_COLOR);
126126
127127 if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
128128 warn("no locale support");
@@ -141,8 +141,8 @@ void win_set_sizehints(win_t *win) {
141141 sizehints.flags = PMinSize | PMaxSize;
142142 sizehints.min_width = win->w;
143143 sizehints.max_width = win->w;
144− sizehints.min_height = win->h + win->barh;
145− sizehints.max_height = win->h + win->barh;
144+ sizehints.min_height = win->h + win->bar.h;
145+ sizehints.max_height = win->h + win->bar.h;
146146 XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints);
147147 }
148148
@@ -215,8 +215,8 @@ void win_open(win_t *win) {
215215 XSetWMProtocols(e->dpy, win->xwin, &wm_delete_win, 1);
216216
217217 if (!options->hide_bar) {
218− win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD;
219− win->h -= win->barh;
218+ win->bar.h = barheight;
219+ win->h -= win->bar.h;
220220 }
221221
222222 if (options->fixed_win)
@@ -249,8 +249,8 @@ bool win_configure(win_t *win, XConfigureEvent *c) {
249249
250250 if (win == NULL || c == NULL)
251251 return false;
252−
253− if ((changed = win->w != c->width || win->h + win->barh != c->height)) {
252+
253+ if ((changed = win->w != c->width || win->h + win->bar.h != c->height)) {
254254 if (win->pm != None) {
255255 XFreePixmap(win->env.dpy, win->pm);
256256 win->pm = None;
@@ -260,7 +260,7 @@ bool win_configure(win_t *win, XConfigureEvent *c) {
260260 win->x = c->x;
261261 win->y = c->y;
262262 win->w = c->width;
263− win->h = c->height - win->barh;
263+ win->h = c->height - win->bar.h;
264264 win->bw = c->border_width;
265265
266266 return changed;
@@ -283,13 +283,13 @@ bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) {
283283 w = MIN(w, win->env.scrw - 2 * win->bw);
284284 h = MIN(h, win->env.scrh - 2 * win->bw);
285285
286− if (win->x == x && win->y == y && win->w == w && win->h + win->barh == h)
286+ if (win->x == x && win->y == y && win->w == w && win->h + win->bar.h == h)
287287 return false;
288288
289289 win->x = x;
290290 win->y = y;
291291 win->w = w;
292− win->h = h - win->barh;
292+ win->h = h - win->bar.h;
293293
294294 if (options->fixed_win)
295295 win_set_sizehints(win);
@@ -327,12 +327,12 @@ void win_toggle_bar(win_t *win) {
327327 if (win == NULL || win->xwin == None)
328328 return;
329329
330− if (win->barh != 0) {
331− win->h += win->barh;
332− win->barh = 0;
330+ if (win->bar.h != 0) {
331+ win->h += win->bar.h;
332+ win->bar.h = 0;
333333 } else {
334− win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD;
335− win->h -= win->barh;
334+ win->bar.h = barheight;
335+ win->h -= win->bar.h;
336336 }
337337 }
338338
@@ -343,7 +343,7 @@ void win_clear(win_t *win) {
343343 if (win == NULL || win->xwin == None)
344344 return;
345345
346− h = win->h + win->barh;
346+ h = win->h + win->bar.h;
347347 e = &win->env;
348348
349349 if (win->pm == None)
@@ -354,53 +354,56 @@ void win_clear(win_t *win) {
354354 }
355355
356356 void win_draw_bar(win_t *win) {
357+ int len, olen, x, y, w, tw;
358+ char rest[3];
359+ const char *dots = "...";
357360 win_env_t *e;
358− int len, x, y, w, tw = 0, seplen;
359− const char *rt;
360361
361362 if (win == NULL || win->xwin == None || win->pm == None)
362363 return;
363364
364365 e = &win->env;
365− x = H_TEXT_PAD;
366366 y = win->h + font.ascent + V_TEXT_PAD;
367− w = win->w - 2 * H_TEXT_PAD;
367+ w = win->w;
368368
369− XSetForeground(e->dpy, gc, win->barbgcol);
370− XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->barh);
369+ XSetForeground(e->dpy, gc, win->bar.bgcol);
370+ XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->bar.h);
371371
372− XSetForeground(e->dpy, gc, win->barfgcol);
373− XSetBackground(e->dpy, gc, win->barbgcol);
372+ XSetForeground(e->dpy, gc, win->bar.fgcol);
373+ XSetBackground(e->dpy, gc, win->bar.bgcol);
374374
375− if (win->lbar != NULL) {
376− len = strlen(win->lbar);
377− while (len > 0 && (tw = win_textwidth(win->lbar, len, false)) > w)
378− len--;
379− w -= tw + 2 * H_TEXT_PAD;
380− if (font.set)
381− XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->lbar, len);
382− else
383− XDrawString(e->dpy, win->pm, gc, x, y, win->lbar, len);
384− }
385− if (win->rbar != NULL) {
386− len = strlen(win->rbar);
387− seplen = strlen(BAR_SEPARATOR);
388− rt = win->rbar;
389− while (len > 0 && (tw = win_textwidth(rt, len, false)) > w) {
390− rt = strstr(rt, BAR_SEPARATOR);
391− if (rt != NULL) {
392− rt += seplen;
393− len = strlen(rt);
394− } else {
395− len = 0;
396− }
375+ if (win->bar.r != NULL) {
376+ len = strlen(win->bar.r);
377+ if (len > 0) {
378+ if ((tw = win_textwidth(win->bar.r, len, true)) > w)
379+ return;
380+ x = win->w - tw + H_TEXT_PAD;
381+ w -= tw;
382+ if (font.set)
383+ XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.r, len);
384+ else
385+ XDrawString(e->dpy, win->pm, gc, x, y, win->bar.r, len);
397386 }
387+ }
388+ if (win->bar.l != NULL) {
389+ olen = len = strlen(win->bar.l);
390+ while (len > 0 && (tw = win_textwidth(win->bar.l, len, true)) > w)
391+ len--;
398392 if (len > 0) {
399− x = win->w - tw - H_TEXT_PAD;
393+ if (len != olen) {
394+ w = strlen(dots);
395+ if (len <= w)
396+ return;
397+ memcpy(rest, win->bar.l + len - w, w);
398+ memcpy(win->bar.l + len - w, dots, w);
399+ }
400+ x = H_TEXT_PAD;
400401 if (font.set)
401− XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, rt, len);
402+ XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.l, len);
402403 else
403− XDrawString(e->dpy, win->pm, gc, x, y, rt, len);
404+ XDrawString(e->dpy, win->pm, gc, x, y, win->bar.l, len);
405+ if (len != olen)
406+ memcpy(win->bar.l + len - w, rest, w);
404407 }
405408 }
406409 }
@@ -409,11 +412,11 @@ void win_draw(win_t *win) {
409412 if (win == NULL || win->xwin == None || win->pm == None)
410413 return;
411414
412− if (win->barh > 0)
415+ if (win->bar.h > 0)
413416 win_draw_bar(win);
414417
415418 XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
416− 0, 0, win->w, win->h + win->barh, 0, 0);
419+ 0, 0, win->w, win->h + win->bar.h, 0, 0);
417420 }
418421
419422 void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h,
@@ -466,10 +469,10 @@ void win_set_title(win_t *win, const char *title) {
466469 PropModeReplace, (unsigned char *) title, strlen(title));
467470 }
468471
469−void win_set_bar_info(win_t *win, const char *li, const char *ri) {
472+void win_set_bar_info(win_t *win, char *linfo, char *rinfo) {
470473 if (win != NULL) {
471− win->lbar = li;
472− win->rbar = ri;
474+ win->bar.l = linfo;
475+ win->bar.r = rinfo;
473476 }
474477 }
475478
M window.h View
@@ -23,8 +23,6 @@
2323
2424 #include "types.h"
2525
26−#define BAR_SEPARATOR " | "
27−
2826 typedef struct {
2927 Display *dpy;
3028 int scr;
@@ -42,21 +40,23 @@ typedef struct {
4240 unsigned long bgcol;
4341 unsigned long fscol;
4442 unsigned long selcol;
45− unsigned long barbgcol;
46− unsigned long barfgcol;
4743 Pixmap pm;
4844
4945 int x;
5046 int y;
5147 unsigned int w;
5248 unsigned int h; /* = win height - bar height */
53− unsigned int barh;
5449 unsigned int bw;
5550
5651 bool fullscreen;
5752
58− const char *lbar;
59− const char *rbar;
53+ struct {
54+ unsigned int h;
55+ char *l;
56+ char *r;
57+ unsigned long bgcol;
58+ unsigned long fgcol;
59+ } bar;
6060 } win_t;
6161
6262 extern Atom wm_delete_win;
@@ -80,7 +80,7 @@ void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int,
8080 int win_textwidth(const char*, unsigned int, bool);
8181
8282 void win_set_title(win_t*, const char*);
83−void win_set_bar_info(win_t*, const char*, const char*);
83+void win_set_bar_info(win_t*, char*, char*);
8484 void win_set_cursor(win_t*, cursor_t);
8585
8686 #endif /* WINDOW_H */