Permalink
Browse files

Merge branch 'userinfo'

  • Loading branch information...
2 parents 3a0a1ae + 9c0a53b commit aa6ccf42b8aace05154bf2eebcba8695524b0b17 @muennich committed Jan 27, 2013
Showing with 218 additions and 155 deletions.
  1. +6 −2 Makefile
  2. +2 −2 README.md
  3. +17 −0 image-info
  4. +90 −55 main.c
  5. +16 −14 sxiv.1
  6. +7 −5 thumbs.c
  7. +72 −69 window.c
  8. +8 −8 window.h
View
@@ -1,4 +1,4 @@
-VERSION = git-20130112
+VERSION = git-20130127
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
@@ -32,9 +32,13 @@ install: all
cp sxiv $(DESTDIR)$(PREFIX)/bin/
chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv
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
+ 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:
rm -f $(DESTDIR)$(PREFIX)/bin/sxiv
rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
+ rm -rf $(DESTDIR)$(PREFIX)/share/sxiv
View
@@ -1,7 +1,7 @@
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
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
* Basic support for multi-frame images
* Load all frames from GIF files and play GIF animations
-* Display image information in window title
+* Display image information in status bar
Screenshots
View
@@ -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"
+
View
145 main.c
@@ -39,8 +39,10 @@
#include "config.h"
enum {
- INFO_STR_LEN = 256,
- FILENAME_CNT = 1024
+ BAR_L_LEN = 512,
+ BAR_R_LEN = 64,
+ FILENAME_CNT = 1024,
+ TITLE_LEN = 256
};
typedef struct {
@@ -63,15 +65,18 @@ win_t win;
fileinfo_t *files;
int filecnt, fileidx;
int alternate;
-size_t filesize;
int prefix;
bool resized = false;
-char win_bar_l[INFO_STR_LEN];
-char win_bar_r[INFO_STR_LEN];
-char win_title[INFO_STR_LEN];
+const char * const INFO_SCRIPT = ".sxiv/exec/image-info";
+char *info_script;
+
+struct {
+ char l[BAR_L_LEN];
+ char r[BAR_R_LEN];
+} bar;
timeout_t timeouts[] = {
{ { 0, 0 }, false, redraw },
@@ -202,9 +207,37 @@ bool check_timeouts(struct timeval *t) {
return tmin > 0;
}
-void load_image(int new) {
- struct stat fstats;
+void read_info(void) {
+ 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)
return;
@@ -220,10 +253,8 @@ void load_image(int new) {
files[new].loaded = true;
alternate = fileidx;
fileidx = new;
- if (stat(files[new].path, &fstats) == 0)
- filesize = fstats.st_size;
- else
- filesize = 0;
+
+ read_info();
if (img.multi.cnt > 0 && img.multi.animate)
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
@@ -232,60 +263,51 @@ void load_image(int new) {
}
void update_info(void) {
- int i, fw, pw, fi, ln, rn;
- char frame_info[16];
- const char *size_unit;
- float size = filesize;
+ unsigned int i, fn, fw, n, len = sizeof(bar.r);
+ int sel;
+ char *t = bar.r, title[TITLE_LEN];
+ bool ow_info;
- pw = 0;
- for (i = filecnt; i > 0; i /= 10)
- pw++;
+ for (fw = 0, i = filecnt; i > 0; fw++, i /= 10);
+ sel = mode == MODE_IMAGE ? fileidx : tns.sel;
if (mode == MODE_THUMB) {
- if (tns.cnt != filecnt) {
- snprintf(win_bar_l, sizeof win_bar_l, "Loading... %0*d/%d",
- pw, tns.cnt, filecnt);
+ win_set_title(&win, "sxiv");
+
+ if (tns.cnt == filecnt) {
+ n = snprintf(t, len, "%0*d/%d", fw, sel + 1, filecnt);
+ ow_info = true;
} 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);
+ snprintf(bar.l, sizeof(bar.l), "Loading... %0*d/%d",
+ fw, tns.cnt, filecnt);
+ bar.r[0] = '\0';
+ ow_info = false;
}
- win_set_title(&win, "sxiv");
- win_set_bar_info(&win, win_bar_l, NULL);
} else {
- size_readable(&size, &size_unit);
+ 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) {
- fw = 0;
- for (i = img.multi.cnt; i > 0; i /= 10)
- fw++;
- 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';
+ for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
+ n += snprintf(t + n, len - n, "(%0*d/%d) ",
+ fn, img.multi.sel + 1, img.multi.cnt);
}
- fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s",
- pw, fileidx + 1, filecnt, BAR_SEPARATOR);
- ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
- files[fileidx].name) + fi;
- rn = snprintf(win_bar_r, sizeof win_bar_r, "%.2f%s%s%dx%d%s%3d%%%s",
- size, size_unit, BAR_SEPARATOR, img.w, img.h, BAR_SEPARATOR,
- (int) (img.zoom * 100.0), frame_info);
-
- if (win_textwidth(win_bar_l, ln, true) +
- win_textwidth(win_bar_r, rn, true) > win.w)
+ n += snprintf(t + n, len - n, "%0*d/%d", fw, sel + 1, filecnt);
+ ow_info = bar.l[0] == '\0';
+ }
+ if (ow_info) {
+ fn = strlen(files[sel].name);
+ if (fn < sizeof(bar.l) &&
+ win_textwidth(files[sel].name, fn, true) +
+ win_textwidth(bar.r, n, true) < win.w)
{
- snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s",
- files[fileidx].base);
+ strncpy(bar.l, files[sel].name, sizeof(bar.l));
+ } 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) {
@@ -519,6 +541,7 @@ int main(int argc, char **argv) {
size_t n;
ssize_t len;
char *filename;
+ const char *homedir;
struct stat fstats;
r_dir_t dir;
@@ -595,6 +618,18 @@ int main(int argc, char **argv) {
win_init(&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) {
mode = MODE_THUMB;
tns_init(&tns, filecnt, &win);
View
30 sxiv.1
@@ -1,6 +1,6 @@
.TH SXIV 1 sxiv\-VERSION
.SH NAME
-sxiv \- Simple (or small or suckless) X Image Viewer
+sxiv \- Simple X Image Viewer
.SH SYNOPSIS
.B sxiv
.RB [ \-bcdFfhpqrstvZ ]
@@ -306,9 +306,18 @@ Pan image left.
.TP
.B Shift+ScrollDown
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
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
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
@@ -321,30 +330,23 @@ Additionally, run the following command afterwards inside the cache directory
to remove empty subdirectories:
.P
.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 {} \\;
.RE
.SH AUTHOR
.EX
-Bert Muennich <ber.t at gmx.com>
+Bert Muennich <be.muennich @ gmail.com>
.EE
.SH CONTRIBUTORS
.EX
Bastien Dejean <nihilhill at gmail.com>
Dave Reisner <d at falconindy.com>
Fung SzeTat <sthorde at gmail.com>
-.EX
+.EE
.SH HOMEPAGE
-.TP
+.EX
+http://muennich.github.com/sxiv
https://github.com/muennich/sxiv
+.EE
.SH SEE ALSO
.BR feh (1),
.BR qiv (1)
View
@@ -31,8 +31,10 @@
#include "util.h"
#include "config.h"
-const int thumb_dim = THUMB_SIZE + 10;
-char *cache_dir = NULL;
+static const int thumb_dim = THUMB_SIZE + 10;
+
+static const char * const CACHE_DIR = ".sxiv/cache";
+static char *cache_dir = NULL;
bool tns_cache_enabled(void) {
struct stat stats;
@@ -175,9 +177,9 @@ void tns_init(tns_t *tns, int cnt, win_t *win) {
if ((homedir = getenv("HOME")) != NULL) {
if (cache_dir != NULL)
free(cache_dir);
- len = strlen(homedir) + 10;
- cache_dir = (char*) s_malloc(len * sizeof(char));
- snprintf(cache_dir, len, "%s/.sxiv", homedir);
+ len = strlen(homedir) + strlen(CACHE_DIR) + 2;
+ cache_dir = (char*) s_malloc(len);
+ snprintf(cache_dir, len, "%s/%s", homedir, CACHE_DIR);
} else {
warn("could not locate thumbnail cache directory");
}
Oops, something went wrong.

0 comments on commit aa6ccf4

Please sign in to comment.