Krolyxon
Commit e3b68ef

Branches

Refs →

nsxivcommands.c

440 lines · 7.9 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 <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22#include <sys/wait.h>
23
24#include "commands.h"
25#include "image.h"
26#include "options.h"
27#include "thumbs.h"
28#include "util.h"
29
30#define _IMAGE_CONFIG
31#include "config.h"
32
33void remove_file(int, bool);
34void load_image(int);
35void open_info(void);
36int ptr_third_x(void);
37void redraw(void);
38void reset_cursor(void);
39void animate(void);
40void slideshow(void);
41void set_timeout(timeout_f, int, bool);
42void reset_timeout(timeout_f);
43
44extern appmode_t mode;
45extern img_t img;
46extern tns_t tns;
47extern win_t win;
48
49extern fileinfo_t *files;
50extern int filecnt, fileidx;
51extern int alternate;
52extern int markcnt;
53
54extern int prefix;
55extern bool extprefix;
56
57bool cg_quit(arg_t _)
58{
59 unsigned int i;
60
61 if (options->to_stdout && markcnt > 0) {
62 for (i = 0; i < filecnt; i++) {
63 if (files[i].flags & FF_MARK)
64 printf("%s\n", files[i].name);
65 }
66 }
67 exit(EXIT_SUCCESS);
68}
69
70bool cg_switch_mode(arg_t _)
71{
72 if (mode == MODE_IMAGE) {
73 if (tns.thumbs == NULL)
74 tns_init(&tns, files, &filecnt, &fileidx, &win);
75 img_close(&img, false);
76 reset_timeout(reset_cursor);
77 if (img.ss.on) {
78 img.ss.on = false;
79 reset_timeout(slideshow);
80 }
81 tns.dirty = true;
82 mode = MODE_THUMB;
83 } else {
84 load_image(fileidx);
85 mode = MODE_IMAGE;
86 }
87 return true;
88}
89
90bool cg_toggle_fullscreen(arg_t _)
91{
92 win_toggle_fullscreen(&win);
93 /* redraw after next ConfigureNotify event */
94 set_timeout(redraw, TO_REDRAW_RESIZE, false);
95 if (mode == MODE_IMAGE)
96 img.checkpan = img.dirty = true;
97 else
98 tns.dirty = true;
99 return false;
100}
101
102bool cg_toggle_bar(arg_t _)
103{
104 win_toggle_bar(&win);
105 if (mode == MODE_IMAGE) {
106 img.checkpan = img.dirty = true;
107 if (win.bar.h > 0)
108 open_info();
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 files[fileidx].flags ^= FF_MARK;
198 markcnt += files[fileidx].flags & FF_MARK ? 1 : -1;
199 if (mode == MODE_THUMB)
200 tns_mark(&tns, fileidx, !!(files[fileidx].flags & FF_MARK));
201 return true;
202}
203
204bool cg_reverse_marks(arg_t _)
205{
206 int i;
207
208 for (i = 0; i < filecnt; i++) {
209 files[i].flags ^= FF_MARK;
210 markcnt += files[i].flags & FF_MARK ? 1 : -1;
211 }
212 if (mode == MODE_THUMB)
213 tns.dirty = true;
214 return true;
215}
216
217bool cg_unmark_all(arg_t _)
218{
219 int i;
220
221 for (i = 0; i < filecnt; i++)
222 files[i].flags &= ~FF_MARK;
223 markcnt = 0;
224 if (mode == MODE_THUMB)
225 tns.dirty = true;
226 return true;
227}
228
229bool cg_navigate_marked(arg_t n)
230{
231 int d, i;
232 int new = fileidx;
233
234 if (prefix > 0)
235 n *= prefix;
236 d = n > 0 ? 1 : -1;
237 for (i = fileidx + d; n != 0 && i >= 0 && i < filecnt; i += d) {
238 if (files[i].flags & FF_MARK) {
239 n -= d;
240 new = i;
241 }
242 }
243 if (new != fileidx) {
244 if (mode == MODE_IMAGE) {
245 load_image(new);
246 } else {
247 fileidx = new;
248 tns.dirty = true;
249 }
250 return true;
251 } else {
252 return false;
253 }
254}
255
256bool cg_change_gamma(arg_t d)
257{
258 if (img_change_gamma(&img, d * (prefix > 0 ? prefix : 1))) {
259 if (mode == MODE_THUMB)
260 tns.dirty = true;
261 return true;
262 } else {
263 return false;
264 }
265}
266
267bool ci_navigate(arg_t n)
268{
269 if (prefix > 0)
270 n *= prefix;
271 n += fileidx;
272 if (n < 0)
273 n = 0;
274 if (n >= filecnt)
275 n = filecnt - 1;
276
277 if (n != fileidx) {
278 load_image(n);
279 return true;
280 } else {
281 return false;
282 }
283}
284
285bool ci_cursor_navigate(arg_t _)
286{
287 return ci_navigate(ptr_third_x() - 1);
288}
289
290bool ci_alternate(arg_t _)
291{
292 load_image(alternate);
293 return true;
294}
295
296bool ci_navigate_frame(arg_t d)
297{
298 if (prefix > 0)
299 d *= prefix;
300 return !img.multi.animate && img_frame_navigate(&img, d);
301}
302
303bool ci_toggle_animation(arg_t _)
304{
305 bool dirty = false;
306
307 if (img.multi.cnt > 0) {
308 img.multi.animate = !img.multi.animate;
309 if (img.multi.animate) {
310 dirty = img_frame_animate(&img);
311 set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
312 } else {
313 reset_timeout(animate);
314 }
315 }
316 return dirty;
317}
318
319bool ci_scroll(arg_t dir)
320{
321 return img_pan(&img, dir, prefix);
322}
323
324bool ci_scroll_to_edge(arg_t dir)
325{
326 return img_pan_edge(&img, dir);
327}
328
329bool ci_drag(arg_t _)
330{
331 int x, y;
332 float px, py;
333 XEvent e;
334
335 if ((int)(img.w * img.zoom) <= win.w && (int)(img.h * img.zoom) <= win.h)
336 return false;
337
338 win_set_cursor(&win, CURSOR_DRAG);
339
340 win_cursor_pos(&win, &x, &y);
341
342 for (;;) {
343 px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8)
344 * (win.w - img.w * img.zoom);
345 py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8)
346 * (win.h - img.h * img.zoom);
347
348 if (img_pos(&img, px, py)) {
349 img_render(&img);
350 win_draw(&win);
351 }
352 XMaskEvent(win.env.dpy,
353 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
354 if (e.type == ButtonPress || e.type == ButtonRelease)
355 break;
356 while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
357 x = e.xmotion.x;
358 y = e.xmotion.y;
359 }
360 set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
361 reset_cursor();
362
363 return true;
364}
365
366bool ci_set_zoom(arg_t zl)
367{
368 return img_zoom(&img, (prefix ? prefix : zl) / 100.0);
369}
370
371bool ci_fit_to_win(arg_t sm)
372{
373 return img_fit_win(&img, sm);
374}
375
376bool ci_rotate(arg_t degree)
377{
378 img_rotate(&img, degree);
379 return true;
380}
381
382bool ci_flip(arg_t dir)
383{
384 img_flip(&img, dir);
385 return true;
386}
387
388bool ci_toggle_antialias(arg_t _)
389{
390 img_toggle_antialias(&img);
391 return true;
392}
393
394bool ci_toggle_alpha(arg_t _)
395{
396 img.alpha = !img.alpha;
397 img.dirty = true;
398 return true;
399}
400
401bool ci_slideshow(arg_t _)
402{
403 if (prefix > 0) {
404 img.ss.on = true;
405 img.ss.delay = prefix * 10;
406 set_timeout(slideshow, img.ss.delay * 100, true);
407 } else if (img.ss.on) {
408 img.ss.on = false;
409 reset_timeout(slideshow);
410 } else {
411 img.ss.on = true;
412 }
413 return true;
414}
415
416bool ct_move_sel(arg_t dir)
417{
418 return tns_move_selection(&tns, dir, prefix);
419}
420
421bool ct_reload_all(arg_t _)
422{
423 tns_free(&tns);
424 tns_init(&tns, files, &filecnt, &fileidx, &win);
425 tns.dirty = true;
426 return true;
427}
428
429
430#undef G_CMD
431#define G_CMD(c) { -1, cg_##c },
432#undef I_CMD
433#define I_CMD(c) { MODE_IMAGE, ci_##c },
434#undef T_CMD
435#define T_CMD(c) { MODE_THUMB, ct_##c },
436
437const cmd_t cmds[CMD_COUNT] = {
438#include "commands.lst"
439};
440