Krolyxon
Commit b845827

Branches

Refs →

nsxivb845827

Added text bar on bottom of window

Author
Bert Münnich
Date
2012-02-12 19:00 +0100
Parent
8fc7cb7
Commit
b8458271fba9929831dcc71d86c205fb52578e3a

+211 −64

8 files changed

  1. M Makefile +1 −1
  2. M config.def.h +12 −5
  3. M image.c +0 −2
  4. M main.c +38 −29
  5. M thumbs.c +0 −1
  6. M types.h +1 −0
  7. M window.c +152 −26
  8. M window.h +7 −0
M Makefile View
@@ -1,4 +1,4 @@
1−VERSION = git-20120211
1+VERSION = git-20120212
22
33 CC = gcc
44 CFLAGS = -ansi -Wall -pedantic -O2
M config.def.h View
@@ -6,11 +6,18 @@ enum {
66 WIN_HEIGHT = 600
77 };
88
9−/* default color for window background: */
10−static const char * const BG_COLOR = "#777777";
11−/* default color for thumbnail selection: */
12−static const char * const SEL_COLOR = "#DDDDDD";
13−/* (see X(7) section "COLOR NAMES" for valid values) */
9+/* bar font:
10+ * (see X(7) section "FONT NAMES" for valid values)
11+ */
12+static const char * const BAR_FONT = "6x13";
13+
14+/* colors:
15+ * (see X(7) section "COLOR NAMES" for valid values)
16+ */
17+static const char * const WIN_BG_COLOR = "#777777";
18+static const char * const SEL_COLOR = "#DDDDDD";
19+static const char * const BAR_BG_COLOR = "#222222";
20+static const char * const BAR_FG_COLOR = "#EEEEEE";
1421
1522 #endif
1623 #ifdef _IMAGE_CONFIG
M image.c View
@@ -414,8 +414,6 @@ void img_render(img_t *img) {
414414 imlib_context_set_drawable(win->pm);
415415 imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh);
416416
417− win_draw(win);
418−
419417 img->dirty = false;
420418 }
421419
M main.c View
@@ -22,6 +22,7 @@
2222 #include <stdlib.h>
2323 #include <stdio.h>
2424 #include <string.h>
25+#include <libgen.h>
2526 #include <unistd.h>
2627 #include <sys/stat.h>
2728 #include <sys/time.h>
@@ -38,8 +39,8 @@
3839 #include "config.h"
3940
4041 enum {
41− TITLE_LEN = 256,
42− FNAME_CNT = 1024
42+ INFO_STR_LEN = 256,
43+ FILENAME_CNT = 1024
4344 };
4445
4546 typedef struct {
@@ -64,7 +65,9 @@ size_t filesize;
6465
6566 int prefix;
6667
67−char win_title[TITLE_LEN];
68+char win_bar_l[INFO_STR_LEN];
69+char win_bar_r[INFO_STR_LEN];
70+char win_title[INFO_STR_LEN];
6871
6972 timeout_t timeouts[] = {
7073 { { 0, 0 }, false, redraw },
@@ -105,6 +108,7 @@ void check_add_file(char *filename) {
105108 }
106109 files[fileidx].loaded = false;
107110 files[fileidx].name = s_strdup(filename);
111+ files[fileidx].base = s_strdup(basename(filename));
108112 if (*filename == '/')
109113 files[fileidx].path = files[fileidx].name;
110114 fileidx++;
@@ -216,39 +220,43 @@ void load_image(int new) {
216220 reset_timeout(animate);
217221 }
218222
219−void update_title(void) {
220− int n;
223+void update_info(void) {
224+ unsigned int i, fw, pw;
221225 char frame_info[16];
222− float size;
223226 const char *size_unit;
227+ float size = filesize;
228+
229+ pw = 0;
230+ for (i = filecnt; i > 0; i /= 10)
231+ pw++;
224232
225233 if (mode == MODE_THUMB) {
226− n = snprintf(win_title, TITLE_LEN, "sxiv: %d/%d %s",
227− tns.cnt ? tns.sel + 1 : 0, tns.cnt,
228− tns.cnt ? files[tns.sel].name : "");
234+ snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d %s",
235+ pw, tns.cnt > 0 ? tns.sel + 1 : 0, filecnt,
236+ tns.cnt > 0 ? files[tns.sel].base : "");
237+ win_bar_r[0] = '\0';
238+ snprintf(win_title, sizeof win_title, "sxiv");
229239 } else {
230− size = filesize;
231240 size_readable(&size, &size_unit);
232−
233− if (img.multi.cnt > 0)
234− snprintf(frame_info, sizeof(frame_info), " (%d/%d)",
235− img.multi.sel + 1, img.multi.cnt);
236− else
241+ if (img.multi.cnt > 0) {
242+ fw = 0;
243+ for (i = img.multi.cnt; i > 0; i /= 10)
244+ fw++;
245+ snprintf(frame_info, sizeof frame_info, " %0*d/%d",
246+ fw, img.multi.sel + 1, img.multi.cnt);
247+ } else {
237248 frame_info[0] = '\0';
238−
239− n = snprintf(win_title, TITLE_LEN,
240− "sxiv: %d/%d%s %dx%d %d%% %.2f%s %s",
241− fileidx + 1, filecnt, frame_info, img.w, img.h,
242− (int) (img.zoom * 100.0), size, size_unit,
243− files[fileidx].name);
244− }
245−
246− if (n >= TITLE_LEN) {
247− for (n = 0; n < 3; n++)
248− win_title[TITLE_LEN - n - 2] = '.';
249+ }
250+ snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d %s",
251+ pw, fileidx + 1, filecnt, files[fileidx].base);
252+ snprintf(win_bar_r, sizeof win_bar_r, "%.2f%s %dx%d %3d%%%s",
253+ size, size_unit, img.w, img.h, (int) (img.zoom * 100.0),
254+ frame_info);
255+ snprintf(win_title, sizeof win_title, "sxiv - %s",
256+ files[fileidx].name);
249257 }
250−
251258 win_set_title(&win, win_title);
259+ win_set_bar_info(&win, win_bar_l, win_bar_r);
252260 }
253261
254262 void redraw(void) {
@@ -256,7 +264,8 @@ void redraw(void) {
256264 img_render(&img);
257265 else
258266 tns_render(&tns);
259− update_title();
267+ update_info();
268+ win_draw(&win);
260269 reset_timeout(redraw);
261270 reset_cursor();
262271 }
@@ -466,7 +475,7 @@ int main(int argc, char **argv) {
466475 }
467476
468477 if (options->recursive || options->from_stdin)
469− filecnt = FNAME_CNT;
478+ filecnt = FILENAME_CNT;
470479 else
471480 filecnt = options->filecnt;
472481
M thumbs.c View
@@ -385,7 +385,6 @@ void tns_highlight(tns_t *tns, int n, bool hl) {
385385 win_draw_rect(win, win->pm, x - 3, y - 3, THUMB_SIZE + 6, THUMB_SIZE + 6,
386386 false, 2, col);
387387 }
388− win_draw(win);
389388 }
390389
391390 bool tns_move_selection(tns_t *tns, direction_t dir) {
M types.h View
@@ -34,6 +34,7 @@ typedef enum {
3434 typedef struct {
3535 const char *name; /* as given by user */
3636 const char *path; /* always absolute */
37+ const char *base;
3738 bool loaded;
3839 } fileinfo_t;
3940
M window.c View
@@ -20,6 +20,7 @@
2020 #define _WINDOW_CONFIG
2121
2222 #include <string.h>
23+#include <locale.h>
2324 #include <X11/Xutil.h>
2425 #include <X11/cursorfont.h>
2526
@@ -28,6 +29,11 @@
2829 #include "window.h"
2930 #include "config.h"
3031
32+enum {
33+ H_TEXT_PAD = 5,
34+ V_TEXT_PAD = 1
35+};
36+
3137 static Cursor carrow;
3238 static Cursor cnone;
3339 static Cursor chand;
@@ -36,9 +42,62 @@ static GC gc;
3642
3743 Atom wm_delete_win;
3844
45+struct {
46+ int ascent;
47+ int descent;
48+ XFontStruct *xfont;
49+ XFontSet set;
50+} font;
51+
52+void win_init_font(Display *dpy, const char *fontstr) {
53+ int n;
54+ char *def, **missing;
55+
56+ font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
57+ if (missing) {
58+ while (n--)
59+ warn("missing fontset: %s", missing[n]);
60+ XFreeStringList(missing);
61+ }
62+ if (font.set) {
63+ XFontStruct **xfonts;
64+ char **font_names;
65+
66+ font.ascent = font.descent = 0;
67+ XExtentsOfFontSet(font.set);
68+ n = XFontsOfFontSet(font.set, &xfonts, &font_names);
69+ while (n--) {
70+ font.ascent = MAX(font.ascent, (*xfonts)->ascent);
71+ font.descent = MAX(font.descent,(*xfonts)->descent);
72+ xfonts++;
73+ }
74+ } else {
75+ if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL &&
76+ (font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL)
77+ {
78+ die("could not load font: %s", fontstr);
79+ }
80+ font.ascent = font.xfont->ascent;
81+ font.descent = font.xfont->descent;
82+ }
83+}
84+
85+unsigned long win_alloc_color(win_t *win, const char *name) {
86+ XColor col;
87+
88+ if (win == NULL)
89+ return 0UL;
90+ if (XAllocNamedColor(win->env.dpy,
91+ DefaultColormap(win->env.dpy, win->env.scr),
92+ name, &col, &col) == 0)
93+ {
94+ die("could not allocate color: %s", name);
95+ }
96+ return col.pixel;
97+}
98+
3999 void win_init(win_t *win) {
40100 win_env_t *e;
41− XColor col;
42101
43102 if (win == NULL)
44103 return;
@@ -57,25 +116,21 @@ void win_init(win_t *win) {
57116 win->black = BlackPixel(e->dpy, e->scr);
58117 win->white = WhitePixel(e->dpy, e->scr);
59118
60− if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), BG_COLOR,
61− &col, &col) != 0)
62− {
63− win->bgcol = col.pixel;
64− } else {
65− die("could not allocate color: %s", BG_COLOR);
66− }
67−
68− if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), SEL_COLOR,
69− &col, &col) != 0)
70− {
71− win->selcol = col.pixel;
72− } else {
73− die("could not allocate color: %s", SEL_COLOR);
74− }
119+ win->bgcol = win_alloc_color(win, WIN_BG_COLOR);
120+ win->selcol = win_alloc_color(win, SEL_COLOR);
121+ win->barbgcol = win_alloc_color(win, BAR_BG_COLOR);
122+ win->barfgcol = win_alloc_color(win, BAR_FG_COLOR);
75123
76124 win->xwin = 0;
77125 win->pm = 0;
78126 win->fullscreen = false;
127+ win->lbar = NULL;
128+ win->rbar = NULL;
129+
130+ if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
131+ warn("no locale support");
132+
133+ win_init_font(e->dpy, BAR_FONT);
79134 }
80135
81136 void win_set_sizehints(win_t *win) {
@@ -87,8 +142,8 @@ void win_set_sizehints(win_t *win) {
87142 sizehints.flags = PMinSize | PMaxSize;
88143 sizehints.min_width = win->w;
89144 sizehints.max_width = win->w;
90− sizehints.min_height = win->h;
91− sizehints.max_height = win->h;
145+ sizehints.min_height = win->h + win->barh;
146+ sizehints.max_height = win->h + win->barh;
92147 XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints);
93148 }
94149
@@ -157,6 +212,9 @@ void win_open(win_t *win) {
157212 classhint.res_class = "sxiv";
158213 XSetClassHint(e->dpy, win->xwin, &classhint);
159214
215+ win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD;
216+ win->h -= win->barh;
217+
160218 if (options->fixed_win)
161219 win_set_sizehints(win);
162220
@@ -191,12 +249,12 @@ bool win_configure(win_t *win, XConfigureEvent *c) {
191249 if (win == NULL)
192250 return false;
193251
194− changed = win->w != c->width || win->h != c->height;
252+ changed = win->w != c->width || win->h + win->barh != c->height;
195253
196254 win->x = c->x;
197255 win->y = c->y;
198256 win->w = c->width;
199− win->h = c->height;
257+ win->h = c->height - win->barh;
200258 win->bw = c->border_width;
201259
202260 return changed;
@@ -211,18 +269,18 @@ bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) {
211269 w = MIN(w, win->env.scrw - 2 * win->bw);
212270 h = MIN(h, win->env.scrh - 2 * win->bw);
213271
214− if (win->x == x && win->y == y && win->w == w && win->h == h)
272+ if (win->x == x && win->y == y && win->w == w && win->h + win->barh == h)
215273 return false;
216274
217275 win->x = x;
218276 win->y = y;
219277 win->w = w;
220− win->h = h;
278+ win->h = h - win->barh;
221279
222280 if (options->fixed_win)
223281 win_set_sizehints(win);
224282
225− XMoveResizeWindow(win->env.dpy, win->xwin, win->x, win->y, win->w, win->h);
283+ XMoveResizeWindow(win->env.dpy, win->xwin, x, y, w, h);
226284
227285 return true;
228286 }
@@ -253,26 +311,87 @@ void win_toggle_fullscreen(win_t *win) {
253311
254312 void win_clear(win_t *win) {
255313 win_env_t *e;
256− XGCValues gcval;
257314
258315 if (win == NULL || win->xwin == None)
259316 return;
260317
261318 e = &win->env;
262− gcval.foreground = win->fullscreen ? win->black : win->bgcol;
263319
264320 if (win->pm != None)
265321 XFreePixmap(e->dpy, win->pm);
266322 win->pm = XCreatePixmap(e->dpy, win->xwin, e->scrw, e->scrh, e->depth);
267323
268− XChangeGC(e->dpy, gc, GCForeground, &gcval);
324+ XSetForeground(e->dpy, gc, win->fullscreen ? win->black : win->bgcol);
269325 XFillRectangle(e->dpy, win->pm, gc, 0, 0, e->scrw, e->scrh);
270326 }
271327
328+int win_textwidth(const char *text, unsigned int len) {
329+ XRectangle r;
330+
331+ if (font.set) {
332+ XmbTextExtents(font.set, text, len, NULL, &r);
333+ return r.width;
334+ } else {
335+ return XTextWidth(font.xfont, text, len);
336+ }
337+}
338+void win_draw_bar(win_t *win) {
339+ win_env_t *e;
340+ int len, x, y, w, tw = 0;
341+ const char *rt;
342+
343+ if (win == NULL || win->xwin == None)
344+ return;
345+
346+ e = &win->env;
347+ x = H_TEXT_PAD;
348+ y = win->h + font.ascent + V_TEXT_PAD;
349+ w = win->w - 2 * H_TEXT_PAD;
350+
351+ XSetForeground(e->dpy, gc, win->barbgcol);
352+ XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->barh);
353+
354+ XSetForeground(e->dpy, gc, win->barfgcol);
355+ XSetBackground(e->dpy, gc, win->barbgcol);
356+
357+ if (win->lbar != NULL) {
358+ len = strlen(win->lbar);
359+ while (len > 0 && (tw = win_textwidth(win->lbar, len)) > w)
360+ len--;
361+ w -= tw + 2 * H_TEXT_PAD;
362+ if (font.set)
363+ XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->lbar, len);
364+ else
365+ XDrawString(e->dpy, win->pm, gc, x, y, win->lbar, len);
366+ }
367+ if (win->rbar != NULL) {
368+ len = strlen(win->rbar);
369+ rt = win->rbar;
370+ while (len > 0 && (tw = win_textwidth(rt, len)) > w) {
371+ rt = strstr(rt, " ");
372+ if (rt != NULL) {
373+ rt += 2;
374+ len = strlen(rt);
375+ } else {
376+ len = 0;
377+ }
378+ }
379+ if (len > 0) {
380+ x = win->w - tw - H_TEXT_PAD;
381+ if (font.set)
382+ XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, rt, len);
383+ else
384+ XDrawString(e->dpy, win->pm, gc, x, y, rt, len);
385+ }
386+ }
387+}
388+
272389 void win_draw(win_t *win) {
273390 if (win == NULL || win->xwin == None)
274391 return;
275392
393+ win_draw_bar(win);
394+
276395 XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->pm);
277396 XClearWindow(win->env.dpy, win->xwin);
278397 }
@@ -314,6 +433,13 @@ void win_set_title(win_t *win, const char *title) {
314433 PropModeReplace, (unsigned char *) title, strlen(title));
315434 }
316435
436+void win_set_bar_info(win_t *win, const char *li, const char *ri) {
437+ if (win != NULL) {
438+ win->lbar = li;
439+ win->rbar = ri;
440+ }
441+}
442+
317443 void win_set_cursor(win_t *win, cursor_t cursor) {
318444 if (win == NULL || win->xwin == None)
319445 return;
M window.h View
@@ -40,15 +40,21 @@ typedef struct {
4040 unsigned long white;
4141 unsigned long bgcol;
4242 unsigned long selcol;
43+ unsigned long barbgcol;
44+ unsigned long barfgcol;
4345 Pixmap pm;
4446
4547 int x;
4648 int y;
4749 unsigned int w;
4850 unsigned int h;
51+ unsigned int barh;
4952 unsigned int bw;
5053
5154 bool fullscreen;
55+
56+ const char *lbar;
57+ const char *rbar;
5258 } win_t;
5359
5460 extern Atom wm_delete_win;
@@ -68,6 +74,7 @@ void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int,
6874 unsigned long);
6975
7076 void win_set_title(win_t*, const char*);
77+void win_set_bar_info(win_t*, const char*, const char*);
7178 void win_set_cursor(win_t*, cursor_t);
7279
7380 #endif /* WINDOW_H */