A Simple X Image Viewer
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

246 wiersze
5.2 KiB

  1. /* sxiv: main.c
  2. * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <sys/stat.h>
  22. #include "events.h"
  23. #include "image.h"
  24. #include "options.h"
  25. #include "thumbs.h"
  26. #include "util.h"
  27. #include "window.h"
  28. enum {
  29. TITLE_LEN = 256,
  30. FNAME_CNT = 1024
  31. };
  32. appmode_t mode;
  33. img_t img;
  34. tns_t tns;
  35. win_t win;
  36. char **filenames;
  37. int filecnt, fileidx;
  38. size_t filesize;
  39. char win_title[TITLE_LEN];
  40. void cleanup() {
  41. static int in = 0;
  42. if (!in++) {
  43. img_close(&img, 0);
  44. tns_free(&tns);
  45. win_close(&win);
  46. }
  47. }
  48. int check_add_file(char *filename) {
  49. if (!filename)
  50. return 0;
  51. if (access(filename, R_OK)) {
  52. warn("could not open file: %s", filename);
  53. return 0;
  54. } else {
  55. if (fileidx == filecnt) {
  56. filecnt *= 2;
  57. filenames = (char**) s_realloc(filenames, filecnt * sizeof(char*));
  58. }
  59. filenames[fileidx++] = filename;
  60. return 1;
  61. }
  62. }
  63. void remove_file(int n, unsigned char silent) {
  64. if (n < 0 || n >= filecnt)
  65. return;
  66. if (filecnt == 1) {
  67. if (!silent)
  68. fprintf(stderr, "sxiv: no more files to display, aborting\n");
  69. cleanup();
  70. exit(!silent);
  71. }
  72. if (n + 1 < filecnt)
  73. memmove(filenames + n, filenames + n + 1, (filecnt - n - 1) *
  74. sizeof(char*));
  75. if (n + 1 < tns.cnt) {
  76. memmove(tns.thumbs + n, tns.thumbs + n + 1, (tns.cnt - n - 1) *
  77. sizeof(thumb_t));
  78. memset(tns.thumbs + tns.cnt - 1, 0, sizeof(thumb_t));
  79. }
  80. filecnt--;
  81. if (n < tns.cnt)
  82. tns.cnt--;
  83. }
  84. void load_image(int new) {
  85. struct stat fstats;
  86. if (new < 0 || new >= filecnt)
  87. return;
  88. /* cursor is reset in redraw() */
  89. win_set_cursor(&win, CURSOR_WATCH);
  90. img_close(&img, 0);
  91. while (!img_load(&img, filenames[new])) {
  92. remove_file(new, 0);
  93. if (new >= filecnt)
  94. new = filecnt - 1;
  95. }
  96. fileidx = new;
  97. if (!stat(filenames[new], &fstats))
  98. filesize = fstats.st_size;
  99. else
  100. filesize = 0;
  101. }
  102. void update_title() {
  103. int n;
  104. float size;
  105. const char *unit;
  106. if (mode == MODE_THUMBS) {
  107. n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] %s",
  108. tns.cnt ? tns.sel + 1 : 0, tns.cnt,
  109. tns.cnt ? filenames[tns.sel] : "");
  110. } else {
  111. size = filesize;
  112. size_readable(&size, &unit);
  113. n = snprintf(win_title, TITLE_LEN,
  114. "sxiv: [%d/%d] <%d%%> <%dx%d> (%.2f%s) %s",
  115. fileidx + 1, filecnt, (int) (img.zoom * 100.0), img.w, img.h,
  116. size, unit, filenames[fileidx]);
  117. }
  118. if (n >= TITLE_LEN) {
  119. for (n = 0; n < 3; n++)
  120. win_title[TITLE_LEN - n - 2] = '.';
  121. }
  122. win_set_title(&win, win_title);
  123. }
  124. int fncmp(const void *a, const void *b) {
  125. return strcoll(*((char* const*) a), *((char* const*) b));
  126. }
  127. int main(int argc, char **argv) {
  128. int i, len, start;
  129. size_t n;
  130. char *filename = NULL;
  131. struct stat fstats;
  132. r_dir_t dir;
  133. parse_options(argc, argv);
  134. if (options->clean_cache) {
  135. tns_init(&tns, 0);
  136. tns_clean_cache(&tns);
  137. exit(0);
  138. }
  139. if (!options->filecnt) {
  140. print_usage();
  141. exit(1);
  142. }
  143. if (options->recursive || options->from_stdin)
  144. filecnt = FNAME_CNT;
  145. else
  146. filecnt = options->filecnt;
  147. filenames = (char**) s_malloc(filecnt * sizeof(char*));
  148. fileidx = 0;
  149. /* build file list: */
  150. if (options->from_stdin) {
  151. while ((len = getline(&filename, &n, stdin)) > 0) {
  152. if (filename[len-1] == '\n')
  153. filename[len-1] = '\0';
  154. if (!*filename || !check_add_file(filename))
  155. free(filename);
  156. filename = NULL;
  157. }
  158. } else {
  159. for (i = 0; i < options->filecnt; i++) {
  160. filename = options->filenames[i];
  161. if (stat(filename, &fstats) || !S_ISDIR(fstats.st_mode)) {
  162. check_add_file(filename);
  163. } else {
  164. if (!options->recursive) {
  165. warn("ignoring directory: %s", filename);
  166. continue;
  167. }
  168. if (r_opendir(&dir, filename)) {
  169. warn("could not open directory: %s", filename);
  170. continue;
  171. }
  172. start = fileidx;
  173. while ((filename = r_readdir(&dir))) {
  174. if (!check_add_file(filename))
  175. free((void*) filename);
  176. }
  177. r_closedir(&dir);
  178. if (fileidx - start > 1)
  179. qsort(filenames + start, fileidx - start, sizeof(char*), fncmp);
  180. }
  181. }
  182. }
  183. if (!fileidx) {
  184. fprintf(stderr, "sxiv: no valid image file given, aborting\n");
  185. exit(1);
  186. }
  187. filecnt = fileidx;
  188. fileidx = options->startnum < filecnt ? options->startnum : 0;
  189. win_init(&win);
  190. img_init(&img, &win);
  191. if (options->thumbnails) {
  192. mode = MODE_THUMBS;
  193. tns_init(&tns, filecnt);
  194. while (!tns_load(&tns, 0, filenames[0], 0))
  195. remove_file(0, 0);
  196. tns.cnt = 1;
  197. } else {
  198. mode = MODE_NORMAL;
  199. tns.thumbs = NULL;
  200. load_image(fileidx);
  201. }
  202. win_open(&win);
  203. run();
  204. cleanup();
  205. return 0;
  206. }