| @@ -56,7 +56,7 @@ char* tns_cache_filepath(const char *filepath) |
| 56 | 56 | | return cfile; |
| 57 | 57 | | } |
| 58 | 58 | | |
| 59 | | − | Imlib_Image tns_cache_load(const char *filepath) |
| 59 | + | Imlib_Image tns_cache_load(const char *filepath, bool *outdated) |
| 60 | 60 | | { |
| 61 | 61 | | char *cfile; |
| 62 | 62 | | struct stat cstats, fstats; |
| @@ -68,8 +68,12 @@ Imlib_Image tns_cache_load(const char *filepath) |
| 68 | 68 | | return NULL; |
| 69 | 69 | | |
| 70 | 70 | | if ((cfile = tns_cache_filepath(filepath)) != NULL) { |
| 71 | | − | if (stat(cfile, &cstats) == 0 && cstats.st_mtime == fstats.st_mtime) |
| 72 | | − | im = imlib_load_image(cfile); |
| 71 | + | if (stat(cfile, &cstats) == 0) { |
| 72 | + | if (cstats.st_mtime == fstats.st_mtime) |
| 73 | + | im = imlib_load_image(cfile); |
| 74 | + | else |
| 75 | + | *outdated = true; |
| 76 | + | } |
| 73 | 77 | | free(cfile); |
| 74 | 78 | | } |
| 75 | 79 | | return im; |
| @@ -165,8 +169,8 @@ void tns_init(tns_t *tns, const fileinfo_t *files, int cnt, int *sel, win_t *win |
| 165 | 169 | | tns->thumbs = NULL; |
| 166 | 170 | | } |
| 167 | 171 | | tns->files = files; |
| 168 | | − | tns->cap = cnt; |
| 169 | | − | tns->cnt = tns->loadnext = tns->first = 0; |
| 172 | + | tns->cnt = cnt; |
| 173 | + | tns->loadnext = tns->first = tns->end = tns->r_first = tns->r_end = 0; |
| 170 | 174 | | tns->sel = sel; |
| 171 | 175 | | tns->win = win; |
| 172 | 176 | | tns->dirty = false; |
| @@ -218,7 +222,7 @@ bool tns_load(tns_t *tns, int n, bool force) |
| 218 | 222 | | |
| 219 | 223 | | if (tns == NULL || tns->thumbs == NULL) |
| 220 | 224 | | return false; |
| 221 | | − | if (n < 0 || n >= tns->cap) |
| 225 | + | if (n < 0 || n >= tns->cnt) |
| 222 | 226 | | return false; |
| 223 | 227 | | file = &tns->files[n]; |
| 224 | 228 | | if (file->name == NULL || file->path == NULL) |
| @@ -231,7 +235,7 @@ bool tns_load(tns_t *tns, int n, bool force) |
| 231 | 235 | | imlib_free_image(); |
| 232 | 236 | | } |
| 233 | 237 | | |
| 234 | | − | if (!force && (im = tns_cache_load(file->path)) != NULL) { |
| 238 | + | if (!force && (im = tns_cache_load(file->path, &force)) != NULL) { |
| 235 | 239 | | cache_hit = true; |
| 236 | 240 | | } else { |
| 237 | 241 | | #if HAVE_LIBEXIF |
| @@ -323,11 +327,28 @@ bool tns_load(tns_t *tns, int n, bool force) |
| 323 | 327 | | if (!cache_hit) |
| 324 | 328 | | tns_cache_write(t, file, true); |
| 325 | 329 | | |
| 326 | | − | t->loaded = true; |
| 327 | 330 | | tns->dirty = true; |
| 328 | 331 | | return true; |
| 329 | 332 | | } |
| 330 | 333 | | |
| 334 | + | void tns_unload(tns_t *tns, int n) |
| 335 | + | { |
| 336 | + | thumb_t *t; |
| 337 | + | |
| 338 | + | if (tns == NULL || tns->thumbs == NULL) |
| 339 | + | return; |
| 340 | + | if (n < 0 || n >= tns->cnt) |
| 341 | + | return; |
| 342 | + | |
| 343 | + | t = &tns->thumbs[n]; |
| 344 | + | |
| 345 | + | if (t->im != NULL) { |
| 346 | + | imlib_context_set_image(t->im); |
| 347 | + | imlib_free_image(); |
| 348 | + | t->im = NULL; |
| 349 | + | } |
| 350 | + | } |
| 351 | + | |
| 331 | 352 | | void tns_check_view(tns_t *tns, bool scrolled) |
| 332 | 353 | | { |
| 333 | 354 | | int r; |
| @@ -385,20 +406,31 @@ void tns_render(tns_t *tns) |
| 385 | 406 | | if (r > 0) |
| 386 | 407 | | cnt -= r % tns->cols; |
| 387 | 408 | | } |
| 388 | | − | |
| 389 | 409 | | r = cnt % tns->cols ? 1 : 0; |
| 390 | 410 | | tns->x = x = (win->w - MIN(cnt, tns->cols) * thumb_dim) / 2 + 5; |
| 391 | 411 | | tns->y = y = (win->h - (cnt / tns->cols + r) * thumb_dim) / 2 + 5; |
| 412 | + | tns->loadnext = tns->cnt; |
| 413 | + | tns->end = tns->first + cnt; |
| 392 | 414 | | |
| 393 | | − | for (i = 0; i < cnt; i++) { |
| 394 | | − | t = &tns->thumbs[tns->first + i]; |
| 395 | | − | t->x = x + (THUMB_SIZE - t->w) / 2; |
| 396 | | − | t->y = y + (THUMB_SIZE - t->h) / 2; |
| 397 | | − | imlib_context_set_image(t->im); |
| 398 | | − | imlib_render_image_part_on_drawable_at_size(0, 0, t->w, t->h, |
| 399 | | − | t->x, t->y, t->w, t->h); |
| 400 | | − | if (tns->files[tns->first + i].marked) |
| 401 | | − | tns_mark(tns, tns->first + i, true); |
| 415 | + | for (i = tns->r_first; i < tns->r_end; i++) { |
| 416 | + | if ((i < tns->first || i >= tns->end) && tns->thumbs[i].im != NULL) |
| 417 | + | tns_unload(tns, i); |
| 418 | + | } |
| 419 | + | tns->r_first = tns->first; |
| 420 | + | tns->r_end = tns->end; |
| 421 | + | |
| 422 | + | for (i = tns->first; i < tns->end; i++) { |
| 423 | + | t = &tns->thumbs[i]; |
| 424 | + | if (t->im != NULL) { |
| 425 | + | t->x = x + (THUMB_SIZE - t->w) / 2; |
| 426 | + | t->y = y + (THUMB_SIZE - t->h) / 2; |
| 427 | + | imlib_context_set_image(t->im); |
| 428 | + | imlib_render_image_on_drawable_at_size(t->x, t->y, t->w, t->h); |
| 429 | + | if (tns->files[i].marked) |
| 430 | + | tns_mark(tns, i, true); |
| 431 | + | } else { |
| 432 | + | tns->loadnext = MIN(tns->loadnext, i); |
| 433 | + | } |
| 402 | 434 | | if ((i + 1) % tns->cols == 0) { |
| 403 | 435 | | x = tns->x; |
| 404 | 436 | | y += thumb_dim; |
| @@ -415,7 +447,7 @@ void tns_mark(tns_t *tns, int n, bool mark) |
| 415 | 447 | | if (tns == NULL || tns->thumbs == NULL || tns->win == NULL) |
| 416 | 448 | | return; |
| 417 | 449 | | |
| 418 | | − | if (n >= 0 && n < tns->cnt) { |
| 450 | + | if (n >= 0 && n < tns->cnt && tns->thumbs[n].im != NULL) { |
| 419 | 451 | | win_t *win = tns->win; |
| 420 | 452 | | thumb_t *t = &tns->thumbs[n]; |
| 421 | 453 | | unsigned long col = win->fullscreen ? win->fscol : win->bgcol; |
| @@ -440,7 +472,7 @@ void tns_highlight(tns_t *tns, int n, bool hl) |
| 440 | 472 | | if (tns == NULL || tns->thumbs == NULL || tns->win == NULL) |
| 441 | 473 | | return; |
| 442 | 474 | | |
| 443 | | − | if (n >= 0 && n < tns->cnt) { |
| 475 | + | if (n >= 0 && n < tns->cnt && tns->thumbs[n].im != NULL) { |
| 444 | 476 | | win_t *win = tns->win; |
| 445 | 477 | | thumb_t *t = &tns->thumbs[n]; |
| 446 | 478 | | unsigned long col; |