Krolyxon
Commit a23636d

Branches

Refs →

nsxivcommands.c

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