Krolyxon
Commit 8bf1adc

Branches

Refs →

nsxivcommands.c

447 lines · 8.0 KB · C

1/* Copyright 2011, 2012, 2014 Bert Muennich
2 *
3 * This file is part of sxiv.
4 *
5 * sxiv is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License,
8 * or (at your option) any later version.
9 *
10 * sxiv is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with sxiv. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "sxiv.h"
20#define _IMAGE_CONFIG
21#include "config.h"
22
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/wait.h>
27
28void remove_file(int, bool);
29void load_image(int);
30void close_info(void);
31void open_info(void);
32int ptr_third_x(void);
33void redraw(void);
34void reset_cursor(void);
35void animate(void);
36void slideshow(void);
37void set_timeout(timeout_f, int, bool);
38void reset_timeout(timeout_f);
39
40extern appmode_t mode;
41extern img_t img;
42extern tns_t tns;
43extern win_t win;
44
45extern fileinfo_t *files;
46extern int filecnt, fileidx;
47extern int alternate;
48extern int markcnt;
49
50extern int prefix;
51extern bool extprefix;
52
53bool cg_quit(arg_t _)
54{
55 unsigned int i;
56
57 if (options->to_stdout && markcnt > 0) {
58 for (i = 0; i < filecnt; i++) {
59 if (files[i].flags & FF_MARK)
60 printf("%s\n", files[i].name);
61 }
62 }
63 exit(EXIT_SUCCESS);
64}
65
66bool cg_switch_mode(arg_t _)
67{
68 if (mode == MODE_IMAGE) {
69 if (tns.thumbs == NULL)
70 tns_init(&tns, files, &filecnt, &fileidx, &win);
71 img_close(&img, false);
72 reset_timeout(reset_cursor);
73 if (img.ss.on) {
74 img.ss.on = false;
75 reset_timeout(slideshow);
76 }
77 tns.dirty = true;
78 mode = MODE_THUMB;
79 } else {
80 load_image(fileidx);
81 mode = MODE_IMAGE;
82 }
83 return true;
84}
85
86bool cg_toggle_fullscreen(arg_t _)
87{
88 win_toggle_fullscreen(&win);
89 /* redraw after next ConfigureNotify event */
90 set_timeout(redraw, TO_REDRAW_RESIZE, false);
91 if (mode == MODE_IMAGE)
92 img.checkpan = img.dirty = true;
93 else
94 tns.dirty = true;
95 return false;
96}
97
98bool cg_toggle_bar(arg_t _)
99{
100 win_toggle_bar(&win);
101 if (mode == MODE_IMAGE) {
102 if (win.bar.h > 0)
103 open_info();
104 else
105 close_info();
106 img.checkpan = img.dirty = true;
107 } else {
108 tns.dirty = true;
109 }
110 return true;
111}
112
113bool cg_prefix_external(arg_t _)
114{
115 extprefix = true;
116 return false;
117}
118
119bool cg_reload_image(arg_t _)
120{
121 if (mode == MODE_IMAGE) {
122 load_image(fileidx);
123 } else {
124 win_set_cursor(&win, CURSOR_WATCH);
125 if (!tns_load(&tns, fileidx, true, false)) {
126 remove_file(fileidx, false);
127 tns.dirty = true;
128 }
129 }
130 return true;
131}
132
133bool cg_remove_image(arg_t _)
134{
135 remove_file(fileidx, true);
136 if (mode == MODE_IMAGE)
137 load_image(fileidx);
138 else
139 tns.dirty = true;
140 return true;
141}
142
143bool cg_first(arg_t _)
144{
145 if (mode == MODE_IMAGE && fileidx != 0) {
146 load_image(0);
147 return true;
148 } else if (mode == MODE_THUMB && fileidx != 0) {
149 fileidx = 0;
150 tns.dirty = true;
151 return true;
152 } else {
153 return false;
154 }
155}
156
157bool cg_n_or_last(arg_t _)
158{
159 int n = prefix != 0 && prefix - 1 < filecnt ? prefix - 1 : filecnt - 1;
160
161 if (mode == MODE_IMAGE && fileidx != n) {
162 load_image(n);
163 return true;
164 } else if (mode == MODE_THUMB && fileidx != n) {
165 fileidx = n;
166 tns.dirty = true;
167 return true;
168 } else {
169 return false;
170 }
171}
172
173bool cg_scroll_screen(arg_t dir)
174{
175 if (mode == MODE_IMAGE)
176 return img_pan(&img, dir, -1);
177 else
178 return tns_scroll(&tns, dir, true);
179}
180
181bool cg_zoom(arg_t d)
182{
183 if (mode == MODE_THUMB)
184 return tns_zoom(&tns, d);
185 else if (d > 0)
186 return img_zoom_in(&img);
187 else if (d < 0)
188 return img_zoom_out(&img);
189 else
190 return false;
191}
192
193bool cg_toggle_image_mark(arg_t _)
194{
195 files[fileidx].flags ^= FF_MARK;
196 markcnt += files[fileidx].flags & FF_MARK ? 1 : -1;
197 if (mode == MODE_THUMB)
198 tns_mark(&tns, fileidx, !!(files[fileidx].flags & FF_MARK));
199 return true;
200}
201
202bool cg_reverse_marks(arg_t _)
203{
204 int i;
205
206 for (i = 0; i < filecnt; i++) {
207 files[i].flags ^= FF_MARK;
208 markcnt += files[i].flags & FF_MARK ? 1 : -1;
209 }
210 if (mode == MODE_THUMB)
211 tns.dirty = true;
212 return true;
213}
214
215bool cg_unmark_all(arg_t _)
216{
217 int i;
218
219 for (i = 0; i < filecnt; i++)
220 files[i].flags &= ~FF_MARK;
221 markcnt = 0;
222 if (mode == MODE_THUMB)
223 tns.dirty = true;
224 return true;
225}
226
227bool cg_navigate_marked(arg_t n)
228{
229 int d, i;
230 int new = fileidx;
231
232 if (prefix > 0)
233 n *= prefix;
234 d = n > 0 ? 1 : -1;
235 for (i = fileidx + d; n != 0 && i >= 0 && i < filecnt; i += d) {
236 if (files[i].flags & FF_MARK) {
237 n -= d;
238 new = i;
239 }
240 }
241 if (new != fileidx) {
242 if (mode == MODE_IMAGE) {
243 load_image(new);
244 } else {
245 fileidx = new;
246 tns.dirty = true;
247 }
248 return true;
249 } else {
250 return false;
251 }
252}
253
254bool cg_change_gamma(arg_t d)
255{
256 if (img_change_gamma(&img, d * (prefix > 0 ? prefix : 1))) {
257 if (mode == MODE_THUMB)
258 tns.dirty = true;
259 return true;
260 } else {
261 return false;
262 }
263}
264
265bool ci_navigate(arg_t n)
266{
267 if (prefix > 0)
268 n *= prefix;
269 n += fileidx;
270 if (n < 0)
271 n = 0;
272 if (n >= filecnt)
273 n = filecnt - 1;
274
275 if (n != fileidx) {
276 load_image(n);
277 return true;
278 } else {
279 return false;
280 }
281}
282
283bool ci_cursor_navigate(arg_t _)
284{
285 return ci_navigate(ptr_third_x() - 1);
286}
287
288bool ci_alternate(arg_t _)
289{
290 load_image(alternate);
291 return true;
292}
293
294bool ci_navigate_frame(arg_t d)
295{
296 if (prefix > 0)
297 d *= prefix;
298 return !img.multi.animate && img_frame_navigate(&img, d);
299}
300
301bool ci_toggle_animation(arg_t _)
302{
303 bool dirty = false;
304
305 if (img.multi.cnt > 0) {
306 img.multi.animate = !img.multi.animate;
307 if (img.multi.animate) {
308 dirty = img_frame_animate(&img);
309 set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
310 } else {
311 reset_timeout(animate);
312 }
313 }
314 return dirty;
315}
316
317bool ci_scroll(arg_t dir)
318{
319 return img_pan(&img, dir, prefix);
320}
321
322bool ci_scroll_to_edge(arg_t dir)
323{
324 return img_pan_edge(&img, dir);
325}
326
327bool ci_drag(arg_t mode)
328{
329 int x, y, ox, oy;
330 float px, py;
331 XEvent e;
332
333 if ((int)(img.w * img.zoom) <= win.w && (int)(img.h * img.zoom) <= win.h)
334 return false;
335
336 win_set_cursor(&win, CURSOR_DRAG);
337
338 win_cursor_pos(&win, &x, &y);
339 ox = x;
340 oy = y;
341
342 for (;;) {
343 if (mode == DRAG_ABSOLUTE) {
344 px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8)
345 * (win.w - img.w * img.zoom);
346 py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8)
347 * (win.h - img.h * img.zoom);
348 } else {
349 px = img.x + x - ox;
350 py = img.y + y - oy;
351 }
352
353 if (img_pos(&img, px, py)) {
354 img_render(&img);
355 win_draw(&win);
356 }
357 XMaskEvent(win.env.dpy,
358 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
359 if (e.type == ButtonPress || e.type == ButtonRelease)
360 break;
361 while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
362 ox = x;
363 oy = y;
364 x = e.xmotion.x;
365 y = e.xmotion.y;
366 }
367 set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
368 reset_cursor();
369
370 return true;
371}
372
373bool ci_set_zoom(arg_t zl)
374{
375 return img_zoom(&img, (prefix ? prefix : zl) / 100.0);
376}
377
378bool ci_fit_to_win(arg_t sm)
379{
380 return img_fit_win(&img, sm);
381}
382
383bool ci_rotate(arg_t degree)
384{
385 img_rotate(&img, degree);
386 return true;
387}
388
389bool ci_flip(arg_t dir)
390{
391 img_flip(&img, dir);
392 return true;
393}
394
395bool ci_toggle_antialias(arg_t _)
396{
397 img_toggle_antialias(&img);
398 return true;
399}
400
401bool ci_toggle_alpha(arg_t _)
402{
403 img.alpha = !img.alpha;
404 img.dirty = true;
405 return true;
406}
407
408bool ci_slideshow(arg_t _)
409{
410 if (prefix > 0) {
411 img.ss.on = true;
412 img.ss.delay = prefix * 10;
413 set_timeout(slideshow, img.ss.delay * 100, true);
414 } else if (img.ss.on) {
415 img.ss.on = false;
416 reset_timeout(slideshow);
417 } else {
418 img.ss.on = true;
419 }
420 return true;
421}
422
423bool ct_move_sel(arg_t dir)
424{
425 return tns_move_selection(&tns, dir, prefix);
426}
427
428bool ct_reload_all(arg_t _)
429{
430 tns_free(&tns);
431 tns_init(&tns, files, &filecnt, &fileidx, &win);
432 tns.dirty = true;
433 return true;
434}
435
436
437#undef G_CMD
438#define G_CMD(c) { -1, cg_##c },
439#undef I_CMD
440#define I_CMD(c) { MODE_IMAGE, ci_##c },
441#undef T_CMD
442#define T_CMD(c) { MODE_THUMB, ct_##c },
443
444const cmd_t cmds[CMD_COUNT] = {
445#include "commands.lst"
446};
447