Krolyxon
Commit 87a1ace

Branches

Refs →

nsxivcommands.c

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