Krolyxon
Commit 3e4f63e

Branches

Refs →

nsxivmain.c

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