Krolyxon
Commit ff013dd

Branches

Refs →

nsxivmain.c

258 lines · 5.6 KB · C

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
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22#include <sys/stat.h>
23
24#include "events.h"
25#include "image.h"
26#include "options.h"
27#include "thumbs.h"
28#include "types.h"
29#include "util.h"
30#include "window.h"
31
32enum {
33 TITLE_LEN = 256,
34 FNAME_CNT = 1024
35};
36
37appmode_t mode;
38img_t img;
39tns_t tns;
40win_t win;
41
42fileinfo_t *files;
43int filecnt, fileidx;
44size_t filesize;
45
46char win_title[TITLE_LEN];
47
48void cleanup() {
49 static int in = 0;
50
51 if (!in++) {
52 img_close(&img, 0);
53 tns_free(&tns);
54 win_close(&win);
55 }
56}
57
58void check_add_file(char *filename) {
59 if (!filename || !*filename)
60 return;
61
62 if (access(filename, R_OK)) {
63 warn("could not open file: %s", filename);
64 return;
65 }
66
67 if (fileidx == filecnt) {
68 filecnt *= 2;
69 files = (fileinfo_t*) s_realloc(files, filecnt * sizeof(fileinfo_t));
70 }
71 if (*filename != '/') {
72 files[fileidx].path = absolute_path(filename);
73 if (!files[fileidx].path) {
74 warn("could not get absolute path of file: %s\n", filename);
75 return;
76 }
77 }
78 files[fileidx].name = s_strdup(filename);
79 if (*filename == '/')
80 files[fileidx].path = files[fileidx].name;
81 fileidx++;
82}
83
84void remove_file(int n, unsigned char silent) {
85 if (n < 0 || n >= filecnt)
86 return;
87
88 if (filecnt == 1) {
89 if (!silent)
90 fprintf(stderr, "sxiv: no more files to display, aborting\n");
91 cleanup();
92 exit(!silent);
93 }
94
95 if (n + 1 < filecnt) {
96 if (files[n].path != files[n].name)
97 free((void*) files[n].path);
98 free((void*) files[n].name);
99 memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(fileinfo_t));
100 }
101 if (n + 1 < tns.cnt) {
102 memmove(tns.thumbs + n, tns.thumbs + n + 1, (tns.cnt - n - 1) *
103 sizeof(thumb_t));
104 memset(tns.thumbs + tns.cnt - 1, 0, sizeof(thumb_t));
105 }
106
107 filecnt--;
108 if (n < tns.cnt)
109 tns.cnt--;
110}
111
112void load_image(int new) {
113 struct stat fstats;
114
115 if (new < 0 || new >= filecnt)
116 return;
117
118 /* cursor is reset in redraw() */
119 win_set_cursor(&win, CURSOR_WATCH);
120 img_close(&img, 0);
121
122 while (!img_load(&img, &files[new])) {
123 remove_file(new, 0);
124 if (new >= filecnt)
125 new = filecnt - 1;
126 }
127
128 fileidx = new;
129 if (!stat(files[new].path, &fstats))
130 filesize = fstats.st_size;
131 else
132 filesize = 0;
133}
134
135void update_title() {
136 int n;
137 float size;
138 const char *unit;
139
140 if (mode == MODE_THUMBS) {
141 n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] %s",
142 tns.cnt ? tns.sel + 1 : 0, tns.cnt,
143 tns.cnt ? files[tns.sel].name : "");
144 } else {
145 size = filesize;
146 size_readable(&size, &unit);
147 n = snprintf(win_title, TITLE_LEN,
148 "sxiv: [%d/%d] <%d%%> <%dx%d> (%.2f%s) %s",
149 fileidx + 1, filecnt, (int) (img.zoom * 100.0), img.w, img.h,
150 size, unit, files[fileidx].name);
151 }
152
153 if (n >= TITLE_LEN) {
154 for (n = 0; n < 3; n++)
155 win_title[TITLE_LEN - n - 2] = '.';
156 }
157
158 win_set_title(&win, win_title);
159}
160
161int fncmp(const void *a, const void *b) {
162 return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name);
163}
164
165int main(int argc, char **argv) {
166 int i, len, start;
167 size_t n;
168 char *filename;
169 struct stat fstats;
170 r_dir_t dir;
171
172 parse_options(argc, argv);
173
174 if (options->clean_cache) {
175 tns_init(&tns, 0);
176 tns_clean_cache(&tns);
177 exit(0);
178 }
179
180 if (!options->filecnt) {
181 print_usage();
182 exit(1);
183 }
184
185 if (options->recursive || options->from_stdin)
186 filecnt = FNAME_CNT;
187 else
188 filecnt = options->filecnt;
189
190 files = (fileinfo_t*) s_malloc(filecnt * sizeof(fileinfo_t));
191 fileidx = 0;
192
193 /* build file list: */
194 if (options->from_stdin) {
195 filename = NULL;
196 while ((len = getline(&filename, &n, stdin)) > 0) {
197 if (filename[len-1] == '\n')
198 filename[len-1] = '\0';
199 check_add_file(filename);
200 }
201 } else {
202 for (i = 0; i < options->filecnt; i++) {
203 filename = options->filenames[i];
204
205 if (stat(filename, &fstats) || !S_ISDIR(fstats.st_mode)) {
206 check_add_file(filename);
207 } else {
208 if (!options->recursive) {
209 warn("ignoring directory: %s", filename);
210 continue;
211 }
212 if (r_opendir(&dir, filename)) {
213 warn("could not open directory: %s", filename);
214 continue;
215 }
216 start = fileidx;
217 printf("reading dir: %s\n", filename);
218 while ((filename = r_readdir(&dir))) {
219 check_add_file(filename);
220 free((void*) filename);
221 }
222 r_closedir(&dir);
223 if (fileidx - start > 1)
224 qsort(files + start, fileidx - start, sizeof(fileinfo_t), fncmp);
225 }
226 }
227 }
228
229 if (!fileidx) {
230 fprintf(stderr, "sxiv: no valid image file given, aborting\n");
231 exit(1);
232 }
233
234 filecnt = fileidx;
235 fileidx = options->startnum < filecnt ? options->startnum : 0;
236
237 win_init(&win);
238 img_init(&img, &win);
239
240 if (options->thumbnails) {
241 mode = MODE_THUMBS;
242 tns_init(&tns, filecnt);
243 while (!tns_load(&tns, 0, &files[0], 0))
244 remove_file(0, 0);
245 tns.cnt = 1;
246 } else {
247 mode = MODE_NORMAL;
248 tns.thumbs = NULL;
249 load_image(fileidx);
250 }
251
252 win_open(&win);
253
254 run();
255 cleanup();
256
257 return 0;
258}