Krolyxon
Commit 5105127

Branches

Refs →

nsxivcommands.c

447 lines · 8.8 KB · C

1/* sxiv: commands.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 it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#define _POSIX_C_SOURCE 200112L
20
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include <sys/wait.h>
25
26#include "commands.h"
27#include "image.h"
28#include "thumbs.h"
29#include "types.h"
30#include "util.h"
31
32void cleanup();
33void remove_file(int, unsigned char);
34void load_image(int);
35void redraw();
36void reset_cursor();
37void animate();
38void slideshow();
39void set_timeout(timeout_f, int, int);
40void reset_timeout(timeout_f);
41
42extern appmode_t mode;
43extern img_t img;
44extern tns_t tns;
45extern win_t win;
46
47extern fileinfo_t *files;
48extern int filecnt, fileidx;
49
50int it_quit(arg_t a) {
51 cleanup();
52 exit(0);
53}
54
55int it_switch_mode(arg_t a) {
56 if (mode == MODE_IMAGE) {
57 if (!tns.thumbs)
58 tns_init(&tns, filecnt);
59 img_close(&img, 0);
60 reset_timeout(reset_cursor);
61 if (img.slideshow) {
62 img.slideshow = 0;
63 reset_timeout(slideshow);
64 }
65 tns.sel = fileidx;
66 tns.dirty = 1;
67 mode = MODE_THUMB;
68 } else {
69 load_image(tns.sel);
70 mode = MODE_IMAGE;
71 }
72 return 1;
73}
74
75int it_toggle_fullscreen(arg_t a) {
76 win_toggle_fullscreen(&win);
77 set_timeout(redraw, TO_REDRAW_RESIZE, 0);
78 if (mode == MODE_IMAGE)
79 img.checkpan = 1;
80 else
81 tns.dirty = 1;
82 return 0;
83}
84
85int it_reload_image(arg_t a) {
86 if (mode == MODE_IMAGE) {
87 load_image(fileidx);
88 } else {
89 win_set_cursor(&win, CURSOR_WATCH);
90 if (!tns_load(&tns, tns.sel, &files[tns.sel], True, False)) {
91 remove_file(tns.sel, 0);
92 tns.dirty = 1;
93 if (tns.sel >= tns.cnt)
94 tns.sel = tns.cnt - 1;
95 }
96 }
97 return 1;
98}
99
100int it_remove_image(arg_t a) {
101 if (mode == MODE_IMAGE) {
102 remove_file(fileidx, 1);
103 load_image(fileidx >= filecnt ? filecnt - 1 : fileidx);
104 return 1;
105 } else if (tns.sel < tns.cnt) {
106 remove_file(tns.sel, 1);
107 tns.dirty = 1;
108 if (tns.sel >= tns.cnt)
109 tns.sel = tns.cnt - 1;
110 return 1;
111 } else {
112 return 0;
113 }
114}
115
116int i_navigate(arg_t a) {
117 long n = (long) a;
118
119 if (mode == MODE_IMAGE) {
120 n += fileidx;
121 if (n < 0)
122 n = 0;
123 if (n >= filecnt)
124 n = filecnt - 1;
125
126 if (n != fileidx) {
127 load_image(n);
128 return 1;
129 }
130 }
131 return 0;
132}
133
134int it_first(arg_t a) {
135 if (mode == MODE_IMAGE && fileidx != 0) {
136 load_image(0);
137 return 1;
138 } else if (mode == MODE_THUMB && tns.sel != 0) {
139 tns.sel = 0;
140 tns.dirty = 1;
141 return 1;
142 } else {
143 return 0;
144 }
145}
146
147int it_last(arg_t a) {
148 if (mode == MODE_IMAGE && fileidx != filecnt - 1) {
149 load_image(filecnt - 1);
150 return 1;
151 } else if (mode == MODE_THUMB && tns.sel != tns.cnt - 1) {
152 tns.sel = tns.cnt - 1;
153 tns.dirty = 1;
154 return 1;
155 } else {
156 return 0;
157 }
158}
159
160int i_navigate_frame(arg_t a) {
161 if (mode == MODE_IMAGE && !img.multi.animate)
162 return img_frame_navigate(&img, (long) a);
163 else
164 return 0;
165}
166
167int i_toggle_animation(arg_t a) {
168 int delay;
169
170 if (mode != MODE_IMAGE)
171 return 0;
172
173 if (img.multi.animate) {
174 reset_timeout(animate);
175 img.multi.animate = 0;
176 } else {
177 delay = img_frame_animate(&img, 1);
178 set_timeout(animate, delay, 1);
179 }
180 return 1;
181}
182
183int it_move(arg_t a) {
184 direction_t dir = (direction_t) a;
185
186 if (mode == MODE_IMAGE)
187 return img_pan(&img, &win, dir, 0);
188 else
189 return tns_move_selection(&tns, &win, dir);
190}
191
192int i_pan_screen(arg_t a) {
193 direction_t dir = (direction_t) a;
194
195 if (mode == MODE_IMAGE)
196 return img_pan(&img, &win, dir, 1);
197 else
198 return 0;
199}
200
201int i_pan_edge(arg_t a) {
202 direction_t dir = (direction_t) a;
203
204 if (mode == MODE_IMAGE)
205 return img_pan_edge(&img, &win, dir);
206 else
207 return 0;
208}
209
210/* Xlib helper function for i_drag() */
211Bool is_motionnotify(Display *d, XEvent *e, XPointer a) {
212 return e != NULL && e->type == MotionNotify;
213}
214
215int i_drag(arg_t a) {
216 int dx = 0, dy = 0, i, ox, oy, x, y;
217 unsigned int ui;
218 Bool dragging = True, next = False;
219 XEvent e;
220 Window w;
221
222 if (mode != MODE_IMAGE)
223 return 0;
224 if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
225 return 0;
226
227 win_set_cursor(&win, CURSOR_HAND);
228
229 while (dragging) {
230 if (!next)
231 XMaskEvent(win.env.dpy,
232 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
233 switch (e.type) {
234 case ButtonPress:
235 case ButtonRelease:
236 dragging = False;
237 break;
238 case MotionNotify:
239 x = e.xmotion.x;
240 y = e.xmotion.y;
241 if (x >= 0 && x <= win.w && y >= 0 && y <= win.h) {
242 dx += x - ox;
243 dy += y - oy;
244 }
245 ox = x;
246 oy = y;
247 break;
248 }
249 if (dragging)
250 next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None);
251 if ((!dragging || !next) && (dx != 0 || dy != 0)) {
252 if (img_move(&img, &win, dx, dy))
253 img_render(&img, &win);
254 dx = dy = 0;
255 }
256 }
257
258 win_set_cursor(&win, CURSOR_ARROW);
259 set_timeout(reset_cursor, TO_CURSOR_HIDE, 1);
260 reset_timeout(redraw);
261
262 return 0;
263}
264
265int i_zoom(arg_t a) {
266 long scale = (long) a;
267
268 if (mode != MODE_IMAGE)
269 return 0;
270
271 if (scale > 0)
272 return img_zoom_in(&img, &win);
273 else if (scale < 0)
274 return img_zoom_out(&img, &win);
275 else
276 return img_zoom(&img, &win, 1.0);
277}
278
279int i_fit_to_win(arg_t a) {
280 int ret;
281
282 if (mode == MODE_IMAGE) {
283 if ((ret = img_fit_win(&img, &win)))
284 img_center(&img, &win);
285 return ret;
286 } else {
287 return 0;
288 }
289}
290
291int i_fit_to_img(arg_t a) {
292 int ret, x, y;
293 unsigned int w, h;
294
295 if (mode == MODE_IMAGE) {
296 x = MAX(0, win.x + img.x);
297 y = MAX(0, win.y + img.y);
298 w = img.w * img.zoom;
299 h = img.h * img.zoom;
300 if ((ret = win_moveresize(&win, x, y, w, h))) {
301 img.x = x - win.x;
302 img.y = y - win.y;
303 }
304 return ret;
305 } else {
306 return 0;
307 }
308}
309
310int i_rotate(arg_t a) {
311 direction_t dir = (direction_t) a;
312
313 if (mode == MODE_IMAGE) {
314 if (dir == DIR_LEFT) {
315 img_rotate_left(&img, &win);
316 return 1;
317 } else if (dir == DIR_RIGHT) {
318 img_rotate_right(&img, &win);
319 return 1;
320 }
321 }
322 return 0;
323}
324
325int i_toggle_slideshow(arg_t a) {
326 if (mode == MODE_IMAGE) {
327 if (img.slideshow) {
328 img.slideshow = 0;
329 reset_timeout(slideshow);
330 return 1;
331 } else if (fileidx + 1 < filecnt) {
332 img.slideshow = 1;
333 set_timeout(slideshow, img.ss_delay, 1);
334 return 1;
335 }
336 }
337 return 0;
338}
339
340int i_adjust_slideshow(arg_t a) {
341 long d = (long) a;
342 int i, delays[] = { 1, 2, 3, 5, 10, 15, 20, 30, 60, 120, 180, 300, 600 };
343
344 if (mode != MODE_IMAGE || !img.slideshow)
345 return 0;
346
347 if (d < 0) {
348 for (i = ARRLEN(delays) - 2; i >= 0; i--) {
349 if (img.ss_delay > delays[i] * 1000) {
350 img.ss_delay = delays[i] * 1000;
351 return 1;
352 }
353 }
354 } else {
355 for (i = 1; i < ARRLEN(delays); i++) {
356 if (img.ss_delay < delays[i] * 1000) {
357 img.ss_delay = delays[i] * 1000;
358 return 1;
359 }
360 }
361 }
362 return 0;
363}
364
365int i_toggle_antialias(arg_t a) {
366 if (mode == MODE_IMAGE) {
367 img_toggle_antialias(&img);
368 return 1;
369 } else {
370 return 0;
371 }
372}
373
374int it_toggle_alpha(arg_t a) {
375 img.alpha ^= 1;
376 tns.alpha = img.alpha;
377 if (mode == MODE_THUMB)
378 tns.dirty = 1;
379 return 1;
380}
381
382int it_open_with(arg_t a) {
383 const char *prog = (const char*) a;
384 pid_t pid;
385
386 if (!prog || !*prog)
387 return 0;
388
389 if((pid = fork()) == 0) {
390 execlp(prog, prog,
391 files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL);
392 warn("could not exec: %s", prog);
393 exit(1);
394 } else if (pid < 0) {
395 warn("could not fork. program was: %s", prog);
396 }
397
398 return 0;
399}
400
401int it_shell_cmd(arg_t a) {
402 int n, status;
403 const char *cmdline = (const char*) a;
404 pid_t pid;
405
406 if (!cmdline || !*cmdline)
407 return 0;
408
409 n = mode == MODE_IMAGE ? fileidx : tns.sel;
410
411 if (setenv("SXIV_IMG", files[n].path, 1) < 0) {
412 warn("could not set env.-variable: SXIV_IMG. command line was: %s",
413 cmdline);
414 return 0;
415 }
416
417 if ((pid = fork()) == 0) {
418 execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
419 warn("could not exec: /bin/sh. command line was: %s", cmdline);
420 exit(1);
421 } else if (pid < 0) {
422 warn("could not fork. command line was: %s", cmdline);
423 return 0;
424 }
425
426 win_set_cursor(&win, CURSOR_WATCH);
427
428 waitpid(pid, &status, 0);
429 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
430 warn("child exited with non-zero return value: %d. command line was: %s",
431 WEXITSTATUS(status), cmdline);
432
433 if (mode == MODE_IMAGE) {
434 img_close(&img, 1);
435 load_image(fileidx);
436 }
437 if (!tns_load(&tns, n, &files[n], True, mode == MODE_IMAGE) &&
438 mode == MODE_THUMB)
439 {
440 remove_file(tns.sel, 0);
441 tns.dirty = 1;
442 if (tns.sel >= tns.cnt)
443 tns.sel = tns.cnt - 1;
444 }
445
446 return 1;
447}