Krolyxon
Commit d6a475e

Branches

Refs →

nsxivd6a475e

Simplified status bar, filled by user script

Author
muennich
Date
2013-01-07 14:30 +0100
Committer
Bert Münnich · 2013-01-12 23:40 +0100
Parent
385ba28
Commit
d6a475e4b1c0d5025806c4a6e47c68e46a3c31d9

+170 −132

3 files changed

  1. M main.c +90 −55
  2. M window.c +72 −69
  3. M window.h +8 −8
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 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 */