Krolyxon
Commit 1480260

Branches

Refs →

nsxivcommands.c

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