@@ -76,18 +76,17 @@ bool cg_switch_mode(arg_t a) | |||
{ | |||
if (mode == MODE_IMAGE) { | |||
if (tns.thumbs == NULL) | |||
tns_init(&tns, filecnt, &win); | |||
tns_init(&tns, filecnt, &win, &fileidx); | |||
img_close(&img, false); | |||
reset_timeout(reset_cursor); | |||
if (img.ss.on) { | |||
img.ss.on = false; | |||
reset_timeout(slideshow); | |||
} | |||
tns.sel = fileidx; | |||
tns.dirty = true; | |||
mode = MODE_THUMB; | |||
} else { | |||
load_image(tns.sel); | |||
load_image(fileidx); | |||
mode = MODE_IMAGE; | |||
} | |||
return true; | |||
@@ -130,11 +129,9 @@ bool cg_reload_image(arg_t a) | |||
load_image(fileidx); | |||
} else { | |||
win_set_cursor(&win, CURSOR_WATCH); | |||
if (!tns_load(&tns, tns.sel, &files[tns.sel], true, false)) { | |||
remove_file(tns.sel, false); | |||
if (!tns_load(&tns, fileidx, &files[fileidx], true, false)) { | |||
remove_file(fileidx, false); | |||
tns.dirty = true; | |||
if (tns.sel >= tns.cnt) | |||
tns.sel = tns.cnt - 1; | |||
} | |||
} | |||
return true; | |||
@@ -146,11 +143,9 @@ bool cg_remove_image(arg_t a) | |||
remove_file(fileidx, true); | |||
load_image(fileidx >= filecnt ? filecnt - 1 : fileidx); | |||
return true; | |||
} else if (tns.sel < tns.cnt) { | |||
remove_file(tns.sel, true); | |||
} else if (fileidx < tns.cnt) { | |||
remove_file(fileidx, true); | |||
tns.dirty = true; | |||
if (tns.sel >= tns.cnt) | |||
tns.sel = tns.cnt - 1; | |||
return true; | |||
} else { | |||
return false; | |||
@@ -162,8 +157,8 @@ bool cg_first(arg_t a) | |||
if (mode == MODE_IMAGE && fileidx != 0) { | |||
load_image(0); | |||
return true; | |||
} else if (mode == MODE_THUMB && tns.sel != 0) { | |||
tns.sel = 0; | |||
} else if (mode == MODE_THUMB && fileidx != 0) { | |||
fileidx = 0; | |||
tns.dirty = true; | |||
return true; | |||
} else { | |||
@@ -178,8 +173,8 @@ bool cg_n_or_last(arg_t a) | |||
if (mode == MODE_IMAGE && fileidx != n) { | |||
load_image(n); | |||
return true; | |||
} else if (mode == MODE_THUMB && tns.sel != n) { | |||
tns.sel = n; | |||
} else if (mode == MODE_THUMB && fileidx != n) { | |||
fileidx = n; | |||
tns.dirty = true; | |||
return true; | |||
} else { | |||
@@ -199,11 +194,9 @@ bool cg_scroll_screen(arg_t a) | |||
bool cg_toggle_image_mark(arg_t a) | |||
{ | |||
int sel = mode == MODE_IMAGE ? fileidx : tns.sel; | |||
files[sel].marked = !files[sel].marked; | |||
files[fileidx].marked = !files[fileidx].marked; | |||
if (mode == MODE_THUMB) | |||
tns_mark(&tns, sel, files[sel].marked); | |||
tns_mark(&tns, fileidx, files[fileidx].marked); | |||
return true; | |||
} | |||
@@ -221,26 +214,23 @@ bool cg_reverse_marks(arg_t a) | |||
bool cg_navigate_marked(arg_t a) | |||
{ | |||
long n = (long) a; | |||
int d, i, cnt, sel, new; | |||
int d, i; | |||
int cnt = mode == MODE_IMAGE ? filecnt : tns.cnt, new = fileidx; | |||
if (mode == MODE_IMAGE) | |||
cnt = filecnt, sel = new = fileidx; | |||
else | |||
cnt = tns.cnt, sel = new = tns.sel; | |||
if (prefix > 0) | |||
n *= prefix; | |||
d = n > 0 ? 1 : -1; | |||
for (i = sel + d; n != 0 && i >= 0 && i < cnt; i += d) { | |||
for (i = fileidx + d; n != 0 && i >= 0 && i < cnt; i += d) { | |||
if (files[i].marked) { | |||
n -= d; | |||
new = i; | |||
} | |||
} | |||
if (new != sel) { | |||
if (new != fileidx) { | |||
if (mode == MODE_IMAGE) { | |||
load_image(new); | |||
} else { | |||
tns.sel = new; | |||
fileidx = new; | |||
tns.dirty = true; | |||
} | |||
return true; | |||
@@ -462,7 +452,7 @@ bool ct_move_sel(arg_t a) | |||
bool ct_reload_all(arg_t a) | |||
{ | |||
tns_free(&tns); | |||
tns_init(&tns, filecnt, &win); | |||
tns_init(&tns, filecnt, &win, &fileidx); | |||
return false; | |||
} | |||
@@ -184,6 +184,8 @@ void remove_file(int n, bool manual) | |||
filecnt--; | |||
if (n < tns.cnt) | |||
tns.cnt--; | |||
if (mode == MODE_THUMB && fileidx >= tns.cnt) | |||
fileidx = tns.cnt - 1; | |||
if (n < alternate) | |||
alternate--; | |||
} | |||
@@ -340,7 +342,6 @@ void load_image(int new) | |||
void update_info(void) | |||
{ | |||
int sel; | |||
unsigned int i, fn, fw, n; | |||
unsigned int llen = sizeof(win.bar.l), rlen = sizeof(win.bar.r); | |||
char *lt = win.bar.l, *rt = win.bar.r, title[TITLE_LEN]; | |||
@@ -348,23 +349,22 @@ void update_info(void) | |||
bool ow_info; | |||
for (fw = 0, i = filecnt; i > 0; fw++, i /= 10); | |||
sel = mode == MODE_IMAGE ? fileidx : tns.sel; | |||
/* update window title */ | |||
if (mode == MODE_THUMB) { | |||
win_set_title(&win, "sxiv"); | |||
} else { | |||
snprintf(title, sizeof(title), "sxiv - %s", files[sel].name); | |||
snprintf(title, sizeof(title), "sxiv - %s", files[fileidx].name); | |||
win_set_title(&win, title); | |||
} | |||
/* update bar contents */ | |||
if (win.bar.h == 0) | |||
return; | |||
mark = files[sel].marked ? "* " : ""; | |||
mark = files[fileidx].marked ? "* " : ""; | |||
if (mode == MODE_THUMB) { | |||
if (tns.loadnext >= filecnt) { | |||
n = snprintf(rt, rlen, "%s%0*d/%d", mark, fw, sel + 1, filecnt); | |||
n = snprintf(rt, rlen, "%s%0*d/%d", mark, fw, fileidx + 1, filecnt); | |||
ow_info = true; | |||
} else { | |||
snprintf(lt, llen, "Loading... %0*d/%d", fw, tns.loadnext, filecnt); | |||
@@ -383,18 +383,18 @@ void update_info(void) | |||
n += snprintf(rt + n, rlen - n, "%0*d/%d | ", | |||
fn, img.multi.sel + 1, img.multi.cnt); | |||
} | |||
n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt); | |||
n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, fileidx + 1, filecnt); | |||
ow_info = info.cmd == NULL; | |||
} | |||
if (ow_info) { | |||
fn = strlen(files[sel].name); | |||
fn = strlen(files[fileidx].name); | |||
if (fn < llen && | |||
win_textwidth(files[sel].name, fn, true) + | |||
win_textwidth(files[fileidx].name, fn, true) + | |||
win_textwidth(rt, n, true) < win.w) | |||
{ | |||
strncpy(lt, files[sel].name, llen); | |||
strncpy(lt, files[fileidx].name, llen); | |||
} else { | |||
strncpy(lt, files[sel].base, llen); | |||
strncpy(lt, files[fileidx].base, llen); | |||
} | |||
} | |||
} | |||
@@ -464,7 +464,7 @@ void clear_resize(void) | |||
void run_key_handler(const char *key, unsigned int mask) | |||
{ | |||
pid_t pid; | |||
int retval, status, n = mode == MODE_IMAGE ? fileidx : tns.sel; | |||
int retval, status; | |||
char kstr[32], oldbar[sizeof(win.bar.l)]; | |||
bool restore_bar = mode == MODE_IMAGE && info.cmd != NULL; | |||
struct stat oldst, newst; | |||
@@ -489,10 +489,10 @@ void run_key_handler(const char *key, unsigned int mask) | |||
strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l)); | |||
win_draw(&win); | |||
win_set_cursor(&win, CURSOR_WATCH); | |||
stat(files[n].path, &oldst); | |||
stat(files[fileidx].path, &oldst); | |||
if ((pid = fork()) == 0) { | |||
execl(keyhandler.cmd, keyhandler.cmd, kstr, files[n].path, NULL); | |||
execl(keyhandler.cmd, keyhandler.cmd, kstr, files[fileidx].path, NULL); | |||
warn("could not exec key handler"); | |||
exit(EXIT_FAILURE); | |||
} else if (pid < 0) { | |||
@@ -504,7 +504,7 @@ void run_key_handler(const char *key, unsigned int mask) | |||
if (WIFEXITED(status) == 0 || retval != 0) | |||
warn("key handler exited with non-zero return value: %d", retval); | |||
if (stat(files[n].path, &newst) == 0 && | |||
if (stat(files[fileidx].path, &newst) == 0 && | |||
memcmp(&oldst.st_mtime, &newst.st_mtime, sizeof(oldst.st_mtime)) == 0) | |||
{ | |||
/* file has not changed */ | |||
@@ -518,13 +518,11 @@ void run_key_handler(const char *key, unsigned int mask) | |||
img_close(&img, true); | |||
load_image(fileidx); | |||
} | |||
if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) && | |||
if (!tns_load(&tns, fileidx, &files[fileidx], true, mode == MODE_IMAGE) && | |||
mode == MODE_THUMB) | |||
{ | |||
remove_file(tns.sel, false); | |||
remove_file(fileidx, false); | |||
tns.dirty = true; | |||
if (tns.sel >= tns.cnt) | |||
tns.sel = tns.cnt - 1; | |||
} | |||
end: | |||
if (restore_bar) | |||
@@ -610,16 +608,16 @@ void on_buttonpress(XButtonEvent *bev) | |||
switch (bev->button) { | |||
case Button1: | |||
if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { | |||
if (sel != tns.sel) { | |||
tns_highlight(&tns, tns.sel, false); | |||
if (sel != fileidx) { | |||
tns_highlight(&tns, fileidx, false); | |||
tns_highlight(&tns, sel, true); | |||
tns.sel = sel; | |||
fileidx = sel; | |||
firstclick = bev->time; | |||
redraw(); | |||
} else if (bev->time - firstclick <= TO_DOUBLE_CLICK) { | |||
mode = MODE_IMAGE; | |||
set_timeout(reset_cursor, TO_CURSOR_HIDE, true); | |||
load_image(tns.sel); | |||
load_image(fileidx); | |||
redraw(); | |||
} else { | |||
firstclick = bev->time; | |||
@@ -665,8 +663,6 @@ void run(void) | |||
tns.cnt++; | |||
} else { | |||
remove_file(tns.loadnext, false); | |||
if (tns.sel > 0 && tns.sel >= tns.cnt) | |||
tns.sel--; | |||
} | |||
while (tns.loadnext < filecnt && tns.thumbs[tns.loadnext].loaded) | |||
tns.loadnext++; | |||
@@ -766,7 +762,7 @@ int main(int argc, char **argv) | |||
parse_options(argc, argv); | |||
if (options->clean_cache) { | |||
tns_init(&tns, 0, NULL); | |||
tns_init(&tns, 0, NULL, NULL); | |||
tns_clean_cache(&tns); | |||
exit(EXIT_SUCCESS); | |||
} | |||
@@ -859,7 +855,7 @@ int main(int argc, char **argv) | |||
if (options->thumb_mode) { | |||
mode = MODE_THUMB; | |||
tns_init(&tns, filecnt, &win); | |||
tns_init(&tns, filecnt, &win, &fileidx); | |||
while (!tns_load(&tns, 0, &files[0], false, false)) | |||
remove_file(0, false); | |||
tns.cnt = 1; | |||
@@ -150,7 +150,7 @@ void tns_clean_cache(tns_t *tns) | |||
} | |||
void tns_init(tns_t *tns, int cnt, win_t *win) | |||
void tns_init(tns_t *tns, int cnt, win_t *win, int *sel) | |||
{ | |||
int len; | |||
const char *homedir, *dsuffix = ""; | |||
@@ -165,7 +165,8 @@ void tns_init(tns_t *tns, int cnt, win_t *win) | |||
tns->thumbs = NULL; | |||
} | |||
tns->cap = cnt; | |||
tns->cnt = tns->loadnext = tns->first = tns->sel = 0; | |||
tns->cnt = tns->loadnext = tns->first = 0; | |||
tns->sel = sel; | |||
tns->win = win; | |||
tns->dirty = false; | |||
@@ -338,21 +339,21 @@ void tns_check_view(tns_t *tns, bool scrolled) | |||
return; | |||
tns->first -= tns->first % tns->cols; | |||
r = tns->sel % tns->cols; | |||
r = *tns->sel % tns->cols; | |||
if (scrolled) { | |||
/* move selection into visible area */ | |||
if (tns->sel >= tns->first + tns->cols * tns->rows) | |||
tns->sel = tns->first + r + tns->cols * (tns->rows - 1); | |||
else if (tns->sel < tns->first) | |||
tns->sel = tns->first + r; | |||
if (*tns->sel >= tns->first + tns->cols * tns->rows) | |||
*tns->sel = tns->first + r + tns->cols * (tns->rows - 1); | |||
else if (*tns->sel < tns->first) | |||
*tns->sel = tns->first + r; | |||
} else { | |||
/* scroll to selection */ | |||
if (tns->first + tns->cols * tns->rows <= tns->sel) { | |||
tns->first = tns->sel - r - tns->cols * (tns->rows - 1); | |||
if (tns->first + tns->cols * tns->rows <= *tns->sel) { | |||
tns->first = *tns->sel - r - tns->cols * (tns->rows - 1); | |||
tns->dirty = true; | |||
} else if (tns->first > tns->sel) { | |||
tns->first = tns->sel - r; | |||
} else if (tns->first > *tns->sel) { | |||
tns->first = *tns->sel - r; | |||
tns->dirty = true; | |||
} | |||
} | |||
@@ -409,7 +410,7 @@ void tns_render(tns_t *tns) | |||
} | |||
} | |||
tns->dirty = false; | |||
tns_highlight(tns, tns->sel, true); | |||
tns_highlight(tns, *tns->sel, true); | |||
} | |||
void tns_mark(tns_t *tns, int n, bool mark) | |||
@@ -423,7 +424,7 @@ void tns_mark(tns_t *tns, int n, bool mark) | |||
win_t *win = tns->win; | |||
int x = t->x, y = t->y, w = t->w, h = t->h; | |||
if (mark || n == tns->sel) | |||
if (mark || n == *tns->sel) | |||
col = win->selcol; | |||
else if (win->fullscreen) | |||
col = win->fscol; | |||
@@ -473,33 +474,33 @@ bool tns_move_selection(tns_t *tns, direction_t dir, int cnt) | |||
if (tns == NULL || tns->thumbs == NULL) | |||
return false; | |||
old = tns->sel; | |||
old = *tns->sel; | |||
cnt = cnt > 1 ? cnt : 1; | |||
switch (dir) { | |||
case DIR_UP: | |||
tns->sel = MAX(tns->sel - cnt * tns->cols, tns->sel % tns->cols); | |||
*tns->sel = MAX(*tns->sel - cnt * tns->cols, *tns->sel % tns->cols); | |||
break; | |||
case DIR_DOWN: | |||
max = tns->cols * ((tns->cnt - 1) / tns->cols) + | |||
MIN((tns->cnt - 1) % tns->cols, tns->sel % tns->cols); | |||
tns->sel = MIN(tns->sel + cnt * tns->cols, max); | |||
MIN((tns->cnt - 1) % tns->cols, *tns->sel % tns->cols); | |||
*tns->sel = MIN(*tns->sel + cnt * tns->cols, max); | |||
break; | |||
case DIR_LEFT: | |||
tns->sel = MAX(tns->sel - cnt, 0); | |||
*tns->sel = MAX(*tns->sel - cnt, 0); | |||
break; | |||
case DIR_RIGHT: | |||
tns->sel = MIN(tns->sel + cnt, tns->cnt - 1); | |||
*tns->sel = MIN(*tns->sel + cnt, tns->cnt - 1); | |||
break; | |||
} | |||
if (tns->sel != old) { | |||
if (*tns->sel != old) { | |||
tns_highlight(tns, old, false); | |||
tns_check_view(tns, false); | |||
if (!tns->dirty) | |||
tns_highlight(tns, tns->sel, true); | |||
tns_highlight(tns, *tns->sel, true); | |||
} | |||
return tns->sel != old; | |||
return *tns->sel != old; | |||
} | |||
bool tns_scroll(tns_t *tns, direction_t dir, bool screen) | |||
@@ -41,7 +41,7 @@ typedef struct { | |||
int cnt; | |||
int loadnext; | |||
int first; | |||
int sel; | |||
int *sel; | |||
win_t *win; | |||
int x; | |||
@@ -54,7 +54,7 @@ typedef struct { | |||
void tns_clean_cache(tns_t*); | |||
void tns_init(tns_t*, int, win_t*); | |||
void tns_init(tns_t*, int, win_t*, int*); | |||
void tns_free(tns_t*); | |||
bool tns_load(tns_t*, int, const fileinfo_t*, bool, bool); | |||