nsxiv090ee54
Save rotated png-files with S-key
+81 −50
6 files changed
- M Makefile +1 −1
- M image.c +33 −4
- M image.h +3 −0
- M main.c +28 −40
- M thumbs.c +14 −4
- M thumbs.h +2 −1
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | all: sxiv | |
| 2 | 2 | ||
| 3 | − | VERSION=0.7 | |
| 3 | + | VERSION=git-20110227 | |
| 4 | 4 | ||
| 5 | 5 | CC?=gcc | |
| 6 | 6 | PREFIX?=/usr/local | |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 17 | 17 | */ | |
| 18 | 18 | ||
| 19 | + | #include <string.h> | |
| 19 | 20 | #include <unistd.h> | |
| 20 | 21 | ||
| 21 | 22 | #include "config.h" | |
| @@ -28,6 +29,9 @@ int zl_cnt; | |||
| 28 | 29 | float zoom_min; | |
| 29 | 30 | float zoom_max; | |
| 30 | 31 | ||
| 32 | + | const short ori_left[8] = { 8, 7, 6, 5, 2, 1, 4, 3 }; | |
| 33 | + | const short ori_right[8] = { 6, 5, 8, 7, 4, 3, 2, 1 }; | |
| 34 | + | ||
| 31 | 35 | Imlib_Image *im_broken; | |
| 32 | 36 | ||
| 33 | 37 | void img_init(img_t *img, win_t *win) { | |
| @@ -90,8 +94,8 @@ int img_load(img_t *img, const char *filename) { | |||
| 90 | 94 | img->scalemode = SCALE_DOWN; | |
| 91 | 95 | } | |
| 92 | 96 | ||
| 93 | − | img->re = 0; | |
| 94 | − | img->checkpan = 0; | |
| 97 | + | img->ori = img->o_ori = 1; | |
| 98 | + | img->re = img->checkpan = 0; | |
| 95 | 99 | ||
| 96 | 100 | img->w = imlib_image_get_width(); | |
| 97 | 101 | img->h = imlib_image_get_height(); | |
| @@ -99,6 +103,25 @@ int img_load(img_t *img, const char *filename) { | |||
| 99 | 103 | return 1; | |
| 100 | 104 | } | |
| 101 | 105 | ||
| 106 | + | int img_save(img_t *img) { | |
| 107 | + | const char *fmt; | |
| 108 | + | ||
| 109 | + | if (!img || !img->im) | |
| 110 | + | return 0; | |
| 111 | + | ||
| 112 | + | imlib_context_set_image(img->im); | |
| 113 | + | ||
| 114 | + | if (img->ori != img->o_ori) { | |
| 115 | + | fmt = imlib_image_format(); | |
| 116 | + | if (strcmp(fmt, "png") == 0) { | |
| 117 | + | imlib_save_image(imlib_image_get_filename()); | |
| 118 | + | return 1; | |
| 119 | + | } | |
| 120 | + | } | |
| 121 | + | ||
| 122 | + | return 0; | |
| 123 | + | } | |
| 124 | + | ||
| 102 | 125 | void img_close(img_t *img) { | |
| 103 | 126 | if (img && img->im) { | |
| 104 | 127 | imlib_context_set_image(img->im); | |
| @@ -341,11 +364,17 @@ void img_rotate(img_t *img, win_t *win, int d) { | |||
| 341 | 364 | } | |
| 342 | 365 | ||
| 343 | 366 | void img_rotate_left(img_t *img, win_t *win) { | |
| 344 | − | img_rotate(img, win, 3); | |
| 367 | + | if (img) { | |
| 368 | + | img_rotate(img, win, 3); | |
| 369 | + | img->ori = ori_left[img->ori]; | |
| 370 | + | } | |
| 345 | 371 | } | |
| 346 | 372 | ||
| 347 | 373 | void img_rotate_right(img_t *img, win_t *win) { | |
| 348 | − | img_rotate(img, win, 1); | |
| 374 | + | if (img) { | |
| 375 | + | img_rotate(img, win, 1); | |
| 376 | + | img->ori = ori_right[img->ori]; | |
| 377 | + | } | |
| 349 | 378 | } | |
| 350 | 379 | ||
| 351 | 380 | void img_toggle_antialias(img_t *img) { | |
| @@ -41,6 +41,8 @@ typedef struct img_s { | |||
| 41 | 41 | ||
| 42 | 42 | float zoom; | |
| 43 | 43 | scalemode_t scalemode; | |
| 44 | + | short ori; | |
| 45 | + | short o_ori; | |
| 44 | 46 | ||
| 45 | 47 | unsigned char re; | |
| 46 | 48 | unsigned char checkpan; | |
| @@ -57,6 +59,7 @@ void img_free(img_t*); | |||
| 57 | 59 | ||
| 58 | 60 | int img_check(const char*); | |
| 59 | 61 | int img_load(img_t*, const char*); | |
| 62 | + | int img_save(img_t*); | |
| 60 | 63 | void img_close(img_t*); | |
| 61 | 64 | ||
| 62 | 65 | void img_render(img_t*, win_t*); | |
| @@ -69,10 +69,11 @@ void cleanup() { | |||
| 69 | 69 | } | |
| 70 | 70 | } | |
| 71 | 71 | ||
| 72 | − | int load_image() { | |
| 72 | + | int load_image(int new) { | |
| 73 | 73 | struct stat fstats; | |
| 74 | 74 | ||
| 75 | 75 | img_close(&img); | |
| 76 | + | fileidx = new; | |
| 76 | 77 | ||
| 77 | 78 | if (!stat(filenames[fileidx], &fstats)) | |
| 78 | 79 | filesize = fstats.st_size; | |
| @@ -140,7 +141,7 @@ int main(int argc, char **argv) { | |||
| 140 | 141 | } else { | |
| 141 | 142 | mode = MODE_NORMAL; | |
| 142 | 143 | tns.thumbs = NULL; | |
| 143 | − | load_image(); | |
| 144 | + | load_image(fileidx); | |
| 144 | 145 | img_render(&img, &win); | |
| 145 | 146 | } | |
| 146 | 147 | ||
| @@ -307,41 +308,29 @@ void on_keypress(XKeyEvent *kev) { | |||
| 307 | 308 | /* navigate image list */ | |
| 308 | 309 | case XK_n: | |
| 309 | 310 | case XK_space: | |
| 310 | − | if (fileidx + 1 < filecnt) { | |
| 311 | − | ++fileidx; | |
| 312 | − | changed = load_image(); | |
| 313 | − | } | |
| 311 | + | if (fileidx + 1 < filecnt) | |
| 312 | + | changed = load_image(fileidx + 1); | |
| 314 | 313 | break; | |
| 315 | 314 | case XK_p: | |
| 316 | 315 | case XK_BackSpace: | |
| 317 | − | if (fileidx > 0) { | |
| 318 | − | --fileidx; | |
| 319 | − | changed = load_image(); | |
| 320 | − | } | |
| 316 | + | if (fileidx > 0) | |
| 317 | + | changed = load_image(fileidx - 1); | |
| 321 | 318 | break; | |
| 322 | 319 | case XK_bracketleft: | |
| 323 | − | if (fileidx != 0) { | |
| 324 | − | fileidx = MAX(0, fileidx - 10); | |
| 325 | − | changed = load_image(); | |
| 326 | − | } | |
| 320 | + | if (fileidx != 0) | |
| 321 | + | changed = load_image(MAX(0, fileidx - 10)); | |
| 327 | 322 | break; | |
| 328 | 323 | case XK_bracketright: | |
| 329 | − | if (fileidx != filecnt - 1) { | |
| 330 | − | fileidx = MIN(fileidx + 10, filecnt - 1); | |
| 331 | − | changed = load_image(); | |
| 332 | − | } | |
| 324 | + | if (fileidx != filecnt - 1) | |
| 325 | + | changed = load_image(MIN(fileidx + 10, filecnt - 1)); | |
| 333 | 326 | break; | |
| 334 | 327 | case XK_g: | |
| 335 | − | if (fileidx != 0) { | |
| 336 | − | fileidx = 0; | |
| 337 | − | changed = load_image(); | |
| 338 | − | } | |
| 328 | + | if (fileidx != 0) | |
| 329 | + | changed = load_image(0); | |
| 339 | 330 | break; | |
| 340 | 331 | case XK_G: | |
| 341 | − | if (fileidx != filecnt - 1) { | |
| 342 | − | fileidx = filecnt - 1; | |
| 343 | − | changed = load_image(); | |
| 344 | − | } | |
| 332 | + | if (fileidx != filecnt - 1) | |
| 333 | + | changed = load_image(filecnt - 1); | |
| 345 | 334 | break; | |
| 346 | 335 | ||
| 347 | 336 | /* zooming */ | |
| @@ -418,7 +407,11 @@ void on_keypress(XKeyEvent *kev) { | |||
| 418 | 407 | changed = 1; | |
| 419 | 408 | break; | |
| 420 | 409 | case XK_r: | |
| 421 | − | changed = load_image(); | |
| 410 | + | changed = load_image(fileidx); | |
| 411 | + | break; | |
| 412 | + | case XK_S: | |
| 413 | + | if (img_save(&img)) | |
| 414 | + | tns_load(&tns, &win, fileidx, filenames[fileidx]); | |
| 422 | 415 | break; | |
| 423 | 416 | } | |
| 424 | 417 | } else { | |
| @@ -426,8 +419,7 @@ void on_keypress(XKeyEvent *kev) { | |||
| 426 | 419 | switch (ksym) { | |
| 427 | 420 | /* open selected image */ | |
| 428 | 421 | case XK_Return: | |
| 429 | − | fileidx = tns.sel; | |
| 430 | − | load_image(); | |
| 422 | + | load_image(tns.sel); | |
| 431 | 423 | mode = MODE_NORMAL; | |
| 432 | 424 | win_set_cursor(&win, CURSOR_NONE); | |
| 433 | 425 | changed = 1; | |
| @@ -496,10 +488,8 @@ void on_buttonpress(XButtonEvent *bev) { | |||
| 496 | 488 | if (mode == MODE_NORMAL) { | |
| 497 | 489 | switch (bev->button) { | |
| 498 | 490 | case Button1: | |
| 499 | − | if (fileidx + 1 < filecnt) { | |
| 500 | − | ++fileidx; | |
| 501 | − | changed = load_image(); | |
| 502 | − | } | |
| 491 | + | if (fileidx + 1 < filecnt) | |
| 492 | + | changed = load_image(fileidx + 1); | |
| 503 | 493 | break; | |
| 504 | 494 | case Button2: | |
| 505 | 495 | mox = bev->x; | |
| @@ -509,10 +499,8 @@ void on_buttonpress(XButtonEvent *bev) { | |||
| 509 | 499 | drag = 1; | |
| 510 | 500 | break; | |
| 511 | 501 | case Button3: | |
| 512 | − | if (fileidx > 0) { | |
| 513 | − | --fileidx; | |
| 514 | − | changed = load_image(); | |
| 515 | − | } | |
| 502 | + | if (fileidx > 0) | |
| 503 | + | changed = load_image(fileidx - 1); | |
| 516 | 504 | break; | |
| 517 | 505 | case Button4: | |
| 518 | 506 | if (mask == ControlMask) | |
| @@ -543,8 +531,7 @@ void on_buttonpress(XButtonEvent *bev) { | |||
| 543 | 531 | case Button1: | |
| 544 | 532 | if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { | |
| 545 | 533 | if (sel == tns.sel) { | |
| 546 | − | fileidx = tns.sel; | |
| 547 | − | load_image(); | |
| 534 | + | load_image(tns.sel); | |
| 548 | 535 | mode = MODE_NORMAL; | |
| 549 | 536 | timo_cursor = TO_CURSOR_HIDE; | |
| 550 | 537 | } else { | |
| @@ -600,7 +587,8 @@ void run() { | |||
| 600 | 587 | gettimeofday(&t0, 0); | |
| 601 | 588 | ||
| 602 | 589 | while (!XPending(win.env.dpy) && tns.cnt < filecnt) { | |
| 603 | − | tns_load(&tns, &win, filenames[tns.cnt]); | |
| 590 | + | /* tns.cnt is increased inside tns_load */ | |
| 591 | + | tns_load(&tns, &win, tns.cnt, filenames[tns.cnt]); | |
| 604 | 592 | gettimeofday(&t1, 0); | |
| 605 | 593 | if (TV_TO_DOUBLE(t1) - TV_TO_DOUBLE(t0) >= 0.25) | |
| 606 | 594 | break; | |
| @@ -35,6 +35,7 @@ void tns_init(tns_t *tns, int cnt) { | |||
| 35 | 35 | tns->cnt = tns->first = tns->sel = 0; | |
| 36 | 36 | tns->thumbs = (thumb_t*) s_malloc(cnt * sizeof(thumb_t)); | |
| 37 | 37 | memset(tns->thumbs, 0, cnt * sizeof(thumb_t)); | |
| 38 | + | tns->cap = cnt; | |
| 38 | 39 | tns->dirty = 0; | |
| 39 | 40 | } | |
| 40 | 41 | ||
| @@ -51,7 +52,7 @@ void tns_free(tns_t *tns, win_t *win) { | |||
| 51 | 52 | tns->thumbs = NULL; | |
| 52 | 53 | } | |
| 53 | 54 | ||
| 54 | − | void tns_load(tns_t *tns, win_t *win, const char *filename) { | |
| 55 | + | void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { | |
| 55 | 56 | int w, h; | |
| 56 | 57 | float z, zw, zh; | |
| 57 | 58 | thumb_t *t; | |
| @@ -60,10 +61,17 @@ void tns_load(tns_t *tns, win_t *win, const char *filename) { | |||
| 60 | 61 | if (!tns || !win || !filename) | |
| 61 | 62 | return; | |
| 62 | 63 | ||
| 63 | − | if ((im = imlib_load_image(filename))) | |
| 64 | + | if (n >= tns->cap) | |
| 65 | + | return; | |
| 66 | + | else if (n >= tns->cnt) | |
| 67 | + | tns->cnt = n + 1; | |
| 68 | + | ||
| 69 | + | if ((im = imlib_load_image(filename))) { | |
| 64 | 70 | imlib_context_set_image(im); | |
| 65 | − | else | |
| 71 | + | imlib_image_set_changes_on_disk(); | |
| 72 | + | } else { | |
| 66 | 73 | imlib_context_set_image(im_broken); | |
| 74 | + | } | |
| 67 | 75 | ||
| 68 | 76 | w = imlib_image_get_width(); | |
| 69 | 77 | h = imlib_image_get_height(); | |
| @@ -73,10 +81,12 @@ void tns_load(tns_t *tns, win_t *win, const char *filename) { | |||
| 73 | 81 | if (!im && z > 1.0) | |
| 74 | 82 | z = 1.0; | |
| 75 | 83 | ||
| 76 | − | t = &tns->thumbs[tns->cnt++]; | |
| 84 | + | t = &tns->thumbs[n]; | |
| 77 | 85 | t->w = z * w; | |
| 78 | 86 | t->h = z * h; | |
| 79 | 87 | ||
| 88 | + | if (t->pm) | |
| 89 | + | win_free_pixmap(win, t->pm); | |
| 80 | 90 | t->pm = win_create_pixmap(win, t->w, t->h); | |
| 81 | 91 | imlib_context_set_drawable(t->pm); | |
| 82 | 92 | imlib_context_set_anti_alias(1); | |
| @@ -38,6 +38,7 @@ typedef struct thumb_s { | |||
| 38 | 38 | ||
| 39 | 39 | typedef struct tns_s { | |
| 40 | 40 | thumb_t *thumbs; | |
| 41 | + | int cap; | |
| 41 | 42 | int cnt; | |
| 42 | 43 | int x; | |
| 43 | 44 | int y; | |
| @@ -51,7 +52,7 @@ typedef struct tns_s { | |||
| 51 | 52 | void tns_init(tns_t*, int); | |
| 52 | 53 | void tns_free(tns_t*, win_t*); | |
| 53 | 54 | ||
| 54 | − | void tns_load(tns_t*, win_t*, const char*); | |
| 55 | + | void tns_load(tns_t*, win_t*, int, const char*); | |
| 55 | 56 | ||
| 56 | 57 | void tns_render(tns_t*, win_t*); | |
| 57 | 58 | void tns_highlight(tns_t*, win_t*, int, Bool); | |