Merge branch 'userinfo'

This commit is contained in:
Bert Münnich 2013-01-27 18:03:07 +01:00
commit aa6ccf42b8
8 changed files with 221 additions and 158 deletions

View File

@ -1,4 +1,4 @@
VERSION = git-20130112 VERSION = git-20130127
PREFIX = /usr/local PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man MANPREFIX = $(PREFIX)/share/man
@ -32,9 +32,13 @@ install: all
cp sxiv $(DESTDIR)$(PREFIX)/bin/ cp sxiv $(DESTDIR)$(PREFIX)/bin/
chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv
mkdir -p $(DESTDIR)$(MANPREFIX)/man1 mkdir -p $(DESTDIR)$(MANPREFIX)/man1
sed "s/VERSION/$(VERSION)/g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec
cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
uninstall: uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/sxiv rm -f $(DESTDIR)$(PREFIX)/bin/sxiv
rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
rm -rf $(DESTDIR)$(PREFIX)/share/sxiv

View File

@ -1,7 +1,7 @@
sxiv sxiv
==== ====
**Simple (or small or suckless) X Image Viewer** **Simple X Image Viewer**
sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are
imlib2 and giflib. The primary goal for writing sxiv is to create an image imlib2 and giflib. The primary goal for writing sxiv is to create an image
@ -20,7 +20,7 @@ Features
* Ability to cache thumbnails for fast re-loading * Ability to cache thumbnails for fast re-loading
* Basic support for multi-frame images * Basic support for multi-frame images
* Load all frames from GIF files and play GIF animations * Load all frames from GIF files and play GIF animations
* Display image information in window title * Display image information in status bar
Screenshots Screenshots

17
image-info Normal file
View File

@ -0,0 +1,17 @@
#!/bin/sh
# Example for ~/.sxiv/exec/image-info
# Called by sxiv(1) whenever an image gets loaded,
# with the name of the image file as its first argument.
# The output is displayed in sxiv's status bar.
filename=$(basename "$1")
filesize=$(du -h "$1" | cut -f 1)
geometry=$(identify -format '%wx%h' "$1")
tags=$(exiv2 -q pr -pi "$1" | awk '$1~"Keywords" { printf("%s,", $4); }')
tags=${tags:+|}${tags%,}
echo "[$filesize|$geometry$tags] $filename"

147
main.c
View File

@ -39,8 +39,10 @@
#include "config.h" #include "config.h"
enum { enum {
INFO_STR_LEN = 256, BAR_L_LEN = 512,
FILENAME_CNT = 1024 BAR_R_LEN = 64,
FILENAME_CNT = 1024,
TITLE_LEN = 256
}; };
typedef struct { typedef struct {
@ -63,15 +65,18 @@ win_t win;
fileinfo_t *files; fileinfo_t *files;
int filecnt, fileidx; int filecnt, fileidx;
int alternate; int alternate;
size_t filesize;
int prefix; int prefix;
bool resized = false; bool resized = false;
char win_bar_l[INFO_STR_LEN]; const char * const INFO_SCRIPT = ".sxiv/exec/image-info";
char win_bar_r[INFO_STR_LEN]; char *info_script;
char win_title[INFO_STR_LEN];
struct {
char l[BAR_L_LEN];
char r[BAR_R_LEN];
} bar;
timeout_t timeouts[] = { timeout_t timeouts[] = {
{ { 0, 0 }, false, redraw }, { { 0, 0 }, false, redraw },
@ -202,9 +207,37 @@ bool check_timeouts(struct timeval *t) {
return tmin > 0; return tmin > 0;
} }
void load_image(int new) { void read_info(void) {
struct stat fstats; char cmd[4096];
FILE *outp;
int c, i = 0, n = sizeof(bar.l) - 1;
bool lastsep = false;
if (info_script != NULL) {
snprintf(cmd, sizeof(cmd), "%s \"%s\"", info_script, files[fileidx].name);
outp = popen(cmd, "r");
if (outp == NULL)
goto end;
while (i < n && (c = fgetc(outp)) != EOF) {
if (c == '\n') {
if (!lastsep) {
bar.l[i++] = ' ';
lastsep = true;
}
} else {
bar.l[i++] = c;
lastsep = false;
}
}
pclose(outp);
}
end:
if (lastsep)
i--;
bar.l[i] = '\0';
}
void load_image(int new) {
if (new < 0 || new >= filecnt) if (new < 0 || new >= filecnt)
return; return;
@ -220,10 +253,8 @@ void load_image(int new) {
files[new].loaded = true; files[new].loaded = true;
alternate = fileidx; alternate = fileidx;
fileidx = new; fileidx = new;
if (stat(files[new].path, &fstats) == 0)
filesize = fstats.st_size; read_info();
else
filesize = 0;
if (img.multi.cnt > 0 && img.multi.animate) if (img.multi.cnt > 0 && img.multi.animate)
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
@ -232,60 +263,51 @@ void load_image(int new) {
} }
void update_info(void) { void update_info(void) {
int i, fw, pw, fi, ln, rn; unsigned int i, fn, fw, n, len = sizeof(bar.r);
char frame_info[16]; int sel;
const char *size_unit; char *t = bar.r, title[TITLE_LEN];
float size = filesize; bool ow_info;
pw = 0; for (fw = 0, i = filecnt; i > 0; fw++, i /= 10);
for (i = filecnt; i > 0; i /= 10) sel = mode == MODE_IMAGE ? fileidx : tns.sel;
pw++;
if (mode == MODE_THUMB) { if (mode == MODE_THUMB) {
if (tns.cnt != filecnt) {
snprintf(win_bar_l, sizeof win_bar_l, "Loading... %0*d/%d",
pw, tns.cnt, filecnt);
} else {
fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s",
pw, tns.sel + 1, filecnt, BAR_SEPARATOR);
ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
files[tns.sel].name) + fi;
if (win_textwidth(win_bar_l, ln, true) > win.w)
snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
files[tns.sel].base);
}
win_set_title(&win, "sxiv"); win_set_title(&win, "sxiv");
win_set_bar_info(&win, win_bar_l, NULL);
if (tns.cnt == filecnt) {
n = snprintf(t, len, "%0*d/%d", fw, sel + 1, filecnt);
ow_info = true;
} else { } else {
size_readable(&size, &size_unit); snprintf(bar.l, sizeof(bar.l), "Loading... %0*d/%d",
fw, tns.cnt, filecnt);
bar.r[0] = '\0';
ow_info = false;
}
} else {
snprintf(title, sizeof(title), "sxiv - %s", files[sel].name);
win_set_title(&win, title);
n = snprintf(t, len, "%3d%% ", (int) (img.zoom * 100.0));
if (img.multi.cnt > 0) { if (img.multi.cnt > 0) {
fw = 0; for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
for (i = img.multi.cnt; i > 0; i /= 10) n += snprintf(t + n, len - n, "(%0*d/%d) ",
fw++; fn, img.multi.sel + 1, img.multi.cnt);
snprintf(frame_info, sizeof frame_info, "%s%0*d/%d",
BAR_SEPARATOR, fw, img.multi.sel+1, img.multi.cnt);
} else {
frame_info[0] = '\0';
} }
fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s", n += snprintf(t + n, len - n, "%0*d/%d", fw, sel + 1, filecnt);
pw, fileidx + 1, filecnt, BAR_SEPARATOR); ow_info = bar.l[0] == '\0';
ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", }
files[fileidx].name) + fi; if (ow_info) {
rn = snprintf(win_bar_r, sizeof win_bar_r, "%.2f%s%s%dx%d%s%3d%%%s", fn = strlen(files[sel].name);
size, size_unit, BAR_SEPARATOR, img.w, img.h, BAR_SEPARATOR, if (fn < sizeof(bar.l) &&
(int) (img.zoom * 100.0), frame_info); win_textwidth(files[sel].name, fn, true) +
win_textwidth(bar.r, n, true) < win.w)
if (win_textwidth(win_bar_l, ln, true) +
win_textwidth(win_bar_r, rn, true) > win.w)
{ {
snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", strncpy(bar.l, files[sel].name, sizeof(bar.l));
files[fileidx].base); } else {
strncpy(bar.l, files[sel].base, sizeof(bar.l));
} }
win_set_bar_info(&win, win_bar_l, win_bar_r);
snprintf(win_title, sizeof win_title, "sxiv - %s", files[fileidx].name);
win_set_title(&win, win_title);
} }
win_set_bar_info(&win, bar.l, bar.r);
} }
void redraw(void) { void redraw(void) {
@ -519,6 +541,7 @@ int main(int argc, char **argv) {
size_t n; size_t n;
ssize_t len; ssize_t len;
char *filename; char *filename;
const char *homedir;
struct stat fstats; struct stat fstats;
r_dir_t dir; r_dir_t dir;
@ -595,6 +618,18 @@ int main(int argc, char **argv) {
win_init(&win); win_init(&win);
img_init(&img, &win); img_init(&img, &win);
if ((homedir = getenv("HOME")) == NULL) {
warn("could not locate home directory");
} else {
len = strlen(homedir) + strlen(INFO_SCRIPT) + 2;
info_script = (char*) s_malloc(len);
snprintf(info_script, len, "%s/%s", homedir, INFO_SCRIPT);
if (access(info_script, X_OK) != 0) {
free(info_script);
info_script = NULL;
}
}
if (options->thumb_mode) { if (options->thumb_mode) {
mode = MODE_THUMB; mode = MODE_THUMB;
tns_init(&tns, filecnt, &win); tns_init(&tns, filecnt, &win);

30
sxiv.1
View File

@ -1,6 +1,6 @@
.TH SXIV 1 sxiv\-VERSION .TH SXIV 1 sxiv\-VERSION
.SH NAME .SH NAME
sxiv \- Simple (or small or suckless) X Image Viewer sxiv \- Simple X Image Viewer
.SH SYNOPSIS .SH SYNOPSIS
.B sxiv .B sxiv
.RB [ \-bcdFfhpqrstvZ ] .RB [ \-bcdFfhpqrstvZ ]
@ -306,9 +306,18 @@ Pan image left.
.TP .TP
.B Shift+ScrollDown .B Shift+ScrollDown
Pan image right. Pan image right.
.SH STATUS BAR
The information displayed on the left side of the status bar can be replaced
with the output of a user-provided script, which is called by sxiv whenever an
image gets loaded. The path of this script is
.I ~/.sxiv/exec/image-info
and the first argument to this script is the path of the loaded image.
.P
There is also an example script installed together with sxiv as
.IR PREFIX/share/sxiv/exec/image-info .
.SH THUMBNAIL CACHING .SH THUMBNAIL CACHING
To enable thumbnail caching, please make sure to create the directory To enable thumbnail caching, please make sure to create the directory
.I ~/.sxiv/ .I ~/.sxiv/cache/
with write permissions. sxiv will then store all thumbnails inside this with write permissions. sxiv will then store all thumbnails inside this
directory, but it will not create this directory by itself. It rather uses the directory, but it will not create this directory by itself. It rather uses the
existance of this directory as an affirmation, that the user wants thumbnails 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
to remove empty subdirectories: to remove empty subdirectories:
.P .P
.RS .RS
find \-type d \-empty \-delete
.RE
.P
If the version of
.I find
installed on your local system does not support the \-delete option, then you
can also try the following command:
.P
.RS
find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\; find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\;
.RE .RE
.SH AUTHOR .SH AUTHOR
.EX .EX
Bert Muennich <ber.t at gmx.com> Bert Muennich <be.muennich @ gmail.com>
.EE .EE
.SH CONTRIBUTORS .SH CONTRIBUTORS
.EX .EX
Bastien Dejean <nihilhill at gmail.com> Bastien Dejean <nihilhill at gmail.com>
Dave Reisner <d at falconindy.com> Dave Reisner <d at falconindy.com>
Fung SzeTat <sthorde at gmail.com> Fung SzeTat <sthorde at gmail.com>
.EX .EE
.SH HOMEPAGE .SH HOMEPAGE
.TP .EX
http://muennich.github.com/sxiv
https://github.com/muennich/sxiv https://github.com/muennich/sxiv
.EE
.SH SEE ALSO .SH SEE ALSO
.BR feh (1), .BR feh (1),
.BR qiv (1) .BR qiv (1)

View File

@ -31,8 +31,10 @@
#include "util.h" #include "util.h"
#include "config.h" #include "config.h"
const int thumb_dim = THUMB_SIZE + 10; static const int thumb_dim = THUMB_SIZE + 10;
char *cache_dir = NULL;
static const char * const CACHE_DIR = ".sxiv/cache";
static char *cache_dir = NULL;
bool tns_cache_enabled(void) { bool tns_cache_enabled(void) {
struct stat stats; struct stat stats;
@ -175,9 +177,9 @@ void tns_init(tns_t *tns, int cnt, win_t *win) {
if ((homedir = getenv("HOME")) != NULL) { if ((homedir = getenv("HOME")) != NULL) {
if (cache_dir != NULL) if (cache_dir != NULL)
free(cache_dir); free(cache_dir);
len = strlen(homedir) + 10; len = strlen(homedir) + strlen(CACHE_DIR) + 2;
cache_dir = (char*) s_malloc(len * sizeof(char)); cache_dir = (char*) s_malloc(len);
snprintf(cache_dir, len, "%s/.sxiv", homedir); snprintf(cache_dir, len, "%s/%s", homedir, CACHE_DIR);
} else { } else {
warn("could not locate thumbnail cache directory"); warn("could not locate thumbnail cache directory");
} }

129
window.c
View File

@ -42,13 +42,16 @@ static GC gc;
Atom wm_delete_win; Atom wm_delete_win;
struct { static struct {
int ascent; int ascent;
int descent; int descent;
XFontStruct *xfont; XFontStruct *xfont;
XFontSet set; XFontSet set;
} font; } font;
static int fontheight;
static int barheight;
void win_init_font(Display *dpy, const char *fontstr) { void win_init_font(Display *dpy, const char *fontstr) {
int n; int n;
char *def, **missing; char *def, **missing;
@ -77,6 +80,8 @@ void win_init_font(Display *dpy, const char *fontstr) {
font.ascent = font.xfont->ascent; font.ascent = font.xfont->ascent;
font.descent = font.xfont->descent; font.descent = font.xfont->descent;
} }
fontheight = font.ascent + font.descent;
barheight = fontheight + 2 * V_TEXT_PAD;
} }
unsigned long win_alloc_color(win_t *win, const char *name) { unsigned long win_alloc_color(win_t *win, const char *name) {
@ -99,6 +104,8 @@ void win_init(win_t *win) {
if (win == NULL) if (win == NULL)
return; return;
memset(win, 0, sizeof(win_t));
e = &win->env; e = &win->env;
if ((e->dpy = XOpenDisplay(NULL)) == NULL) if ((e->dpy = XOpenDisplay(NULL)) == NULL)
die("could not open display"); die("could not open display");
@ -114,15 +121,8 @@ void win_init(win_t *win) {
win->bgcol = win_alloc_color(win, WIN_BG_COLOR); win->bgcol = win_alloc_color(win, WIN_BG_COLOR);
win->fscol = win_alloc_color(win, WIN_FS_COLOR); win->fscol = win_alloc_color(win, WIN_FS_COLOR);
win->selcol = win_alloc_color(win, SEL_COLOR); win->selcol = win_alloc_color(win, SEL_COLOR);
win->barbgcol = win_alloc_color(win, BAR_BG_COLOR); win->bar.bgcol = win_alloc_color(win, BAR_BG_COLOR);
win->barfgcol = win_alloc_color(win, BAR_FG_COLOR); win->bar.fgcol = win_alloc_color(win, BAR_FG_COLOR);
win->xwin = 0;
win->pm = 0;
win->fullscreen = false;
win->barh = 0;
win->lbar = NULL;
win->rbar = NULL;
if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
warn("no locale support"); warn("no locale support");
@ -141,8 +141,8 @@ void win_set_sizehints(win_t *win) {
sizehints.flags = PMinSize | PMaxSize; sizehints.flags = PMinSize | PMaxSize;
sizehints.min_width = win->w; sizehints.min_width = win->w;
sizehints.max_width = win->w; sizehints.max_width = win->w;
sizehints.min_height = win->h + win->barh; sizehints.min_height = win->h + win->bar.h;
sizehints.max_height = win->h + win->barh; sizehints.max_height = win->h + win->bar.h;
XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints); XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints);
} }
@ -215,8 +215,8 @@ void win_open(win_t *win) {
XSetWMProtocols(e->dpy, win->xwin, &wm_delete_win, 1); XSetWMProtocols(e->dpy, win->xwin, &wm_delete_win, 1);
if (!options->hide_bar) { if (!options->hide_bar) {
win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD; win->bar.h = barheight;
win->h -= win->barh; win->h -= win->bar.h;
} }
if (options->fixed_win) if (options->fixed_win)
@ -250,7 +250,7 @@ bool win_configure(win_t *win, XConfigureEvent *c) {
if (win == NULL || c == NULL) if (win == NULL || c == NULL)
return false; return false;
if ((changed = win->w != c->width || win->h + win->barh != c->height)) { if ((changed = win->w != c->width || win->h + win->bar.h != c->height)) {
if (win->pm != None) { if (win->pm != None) {
XFreePixmap(win->env.dpy, win->pm); XFreePixmap(win->env.dpy, win->pm);
win->pm = None; win->pm = None;
@ -260,7 +260,7 @@ bool win_configure(win_t *win, XConfigureEvent *c) {
win->x = c->x; win->x = c->x;
win->y = c->y; win->y = c->y;
win->w = c->width; win->w = c->width;
win->h = c->height - win->barh; win->h = c->height - win->bar.h;
win->bw = c->border_width; win->bw = c->border_width;
return changed; return changed;
@ -283,13 +283,13 @@ bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) {
w = MIN(w, win->env.scrw - 2 * win->bw); w = MIN(w, win->env.scrw - 2 * win->bw);
h = MIN(h, win->env.scrh - 2 * win->bw); h = MIN(h, win->env.scrh - 2 * win->bw);
if (win->x == x && win->y == y && win->w == w && win->h + win->barh == h) if (win->x == x && win->y == y && win->w == w && win->h + win->bar.h == h)
return false; return false;
win->x = x; win->x = x;
win->y = y; win->y = y;
win->w = w; win->w = w;
win->h = h - win->barh; win->h = h - win->bar.h;
if (options->fixed_win) if (options->fixed_win)
win_set_sizehints(win); win_set_sizehints(win);
@ -327,12 +327,12 @@ void win_toggle_bar(win_t *win) {
if (win == NULL || win->xwin == None) if (win == NULL || win->xwin == None)
return; return;
if (win->barh != 0) { if (win->bar.h != 0) {
win->h += win->barh; win->h += win->bar.h;
win->barh = 0; win->bar.h = 0;
} else { } else {
win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD; win->bar.h = barheight;
win->h -= win->barh; win->h -= win->bar.h;
} }
} }
@ -343,7 +343,7 @@ void win_clear(win_t *win) {
if (win == NULL || win->xwin == None) if (win == NULL || win->xwin == None)
return; return;
h = win->h + win->barh; h = win->h + win->bar.h;
e = &win->env; e = &win->env;
if (win->pm == None) if (win->pm == None)
@ -354,53 +354,56 @@ void win_clear(win_t *win) {
} }
void win_draw_bar(win_t *win) { void win_draw_bar(win_t *win) {
int len, olen, x, y, w, tw;
char rest[3];
const char *dots = "...";
win_env_t *e; win_env_t *e;
int len, x, y, w, tw = 0, seplen;
const char *rt;
if (win == NULL || win->xwin == None || win->pm == None) if (win == NULL || win->xwin == None || win->pm == None)
return; return;
e = &win->env; e = &win->env;
x = H_TEXT_PAD;
y = win->h + font.ascent + V_TEXT_PAD; y = win->h + font.ascent + V_TEXT_PAD;
w = win->w - 2 * H_TEXT_PAD; w = win->w;
XSetForeground(e->dpy, gc, win->barbgcol); XSetForeground(e->dpy, gc, win->bar.bgcol);
XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->barh); XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->bar.h);
XSetForeground(e->dpy, gc, win->barfgcol); XSetForeground(e->dpy, gc, win->bar.fgcol);
XSetBackground(e->dpy, gc, win->barbgcol); XSetBackground(e->dpy, gc, win->bar.bgcol);
if (win->lbar != NULL) { if (win->bar.r != NULL) {
len = strlen(win->lbar); len = strlen(win->bar.r);
while (len > 0 && (tw = win_textwidth(win->lbar, len, false)) > w)
len--;
w -= tw + 2 * H_TEXT_PAD;
if (font.set)
XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->lbar, len);
else
XDrawString(e->dpy, win->pm, gc, x, y, win->lbar, len);
}
if (win->rbar != NULL) {
len = strlen(win->rbar);
seplen = strlen(BAR_SEPARATOR);
rt = win->rbar;
while (len > 0 && (tw = win_textwidth(rt, len, false)) > w) {
rt = strstr(rt, BAR_SEPARATOR);
if (rt != NULL) {
rt += seplen;
len = strlen(rt);
} else {
len = 0;
}
}
if (len > 0) { if (len > 0) {
x = win->w - tw - H_TEXT_PAD; if ((tw = win_textwidth(win->bar.r, len, true)) > w)
return;
x = win->w - tw + H_TEXT_PAD;
w -= tw;
if (font.set) if (font.set)
XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, rt, len); XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.r, len);
else else
XDrawString(e->dpy, win->pm, gc, x, y, rt, len); XDrawString(e->dpy, win->pm, gc, x, y, win->bar.r, len);
}
}
if (win->bar.l != NULL) {
olen = len = strlen(win->bar.l);
while (len > 0 && (tw = win_textwidth(win->bar.l, len, true)) > w)
len--;
if (len > 0) {
if (len != olen) {
w = strlen(dots);
if (len <= w)
return;
memcpy(rest, win->bar.l + len - w, w);
memcpy(win->bar.l + len - w, dots, w);
}
x = H_TEXT_PAD;
if (font.set)
XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.l, len);
else
XDrawString(e->dpy, win->pm, gc, x, y, win->bar.l, len);
if (len != olen)
memcpy(win->bar.l + len - w, rest, w);
} }
} }
} }
@ -409,11 +412,11 @@ void win_draw(win_t *win) {
if (win == NULL || win->xwin == None || win->pm == None) if (win == NULL || win->xwin == None || win->pm == None)
return; return;
if (win->barh > 0) if (win->bar.h > 0)
win_draw_bar(win); win_draw_bar(win);
XCopyArea(win->env.dpy, win->pm, win->xwin, gc, XCopyArea(win->env.dpy, win->pm, win->xwin, gc,
0, 0, win->w, win->h + win->barh, 0, 0); 0, 0, win->w, win->h + win->bar.h, 0, 0);
} }
void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h, 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) {
PropModeReplace, (unsigned char *) title, strlen(title)); PropModeReplace, (unsigned char *) title, strlen(title));
} }
void win_set_bar_info(win_t *win, const char *li, const char *ri) { void win_set_bar_info(win_t *win, char *linfo, char *rinfo) {
if (win != NULL) { if (win != NULL) {
win->lbar = li; win->bar.l = linfo;
win->rbar = ri; win->bar.r = rinfo;
} }
} }

View File

@ -23,8 +23,6 @@
#include "types.h" #include "types.h"
#define BAR_SEPARATOR " | "
typedef struct { typedef struct {
Display *dpy; Display *dpy;
int scr; int scr;
@ -42,21 +40,23 @@ typedef struct {
unsigned long bgcol; unsigned long bgcol;
unsigned long fscol; unsigned long fscol;
unsigned long selcol; unsigned long selcol;
unsigned long barbgcol;
unsigned long barfgcol;
Pixmap pm; Pixmap pm;
int x; int x;
int y; int y;
unsigned int w; unsigned int w;
unsigned int h; /* = win height - bar height */ unsigned int h; /* = win height - bar height */
unsigned int barh;
unsigned int bw; unsigned int bw;
bool fullscreen; bool fullscreen;
const char *lbar; struct {
const char *rbar; unsigned int h;
char *l;
char *r;
unsigned long bgcol;
unsigned long fgcol;
} bar;
} win_t; } win_t;
extern Atom wm_delete_win; extern Atom wm_delete_win;
@ -80,7 +80,7 @@ void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int,
int win_textwidth(const char*, unsigned int, bool); int win_textwidth(const char*, unsigned int, bool);
void win_set_title(win_t*, const char*); void win_set_title(win_t*, const char*);
void win_set_bar_info(win_t*, const char*, const char*); void win_set_bar_info(win_t*, char*, char*);
void win_set_cursor(win_t*, cursor_t); void win_set_cursor(win_t*, cursor_t);
#endif /* WINDOW_H */ #endif /* WINDOW_H */