Krolyxon
Commit 9fa0bbc

Branches

Refs →

nsxivcommands.c

407 lines · 8.0 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 hide_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 win_set_cursor(&win, CURSOR_ARROW);
60 reset_timeout(hide_cursor);
61 tns.sel = fileidx;
62 tns.dirty = 1;
63 mode = MODE_THUMB;
64 } else {
65 load_image(tns.sel);
66 mode = MODE_IMAGE;
67 }
68 return 1;
69}
70
71int it_toggle_fullscreen(arg_t a) {
72 win_toggle_fullscreen(&win);
73 set_timeout(redraw, TO_REDRAW_RESIZE, 0);
74 if (mode == MODE_IMAGE)
75 img.checkpan = 1;
76 else
77 tns.dirty = 1;
78 return 0;
79}
80
81int it_reload_image(arg_t a) {
82 if (mode == MODE_IMAGE) {
83 load_image(fileidx);
84 } else if (!tns_load(&tns, tns.sel, &files[tns.sel], True, False)) {
85 remove_file(tns.sel, 0);
86 tns.dirty = 1;
87 if (tns.sel >= tns.cnt)
88 tns.sel = tns.cnt - 1;
89 }
90 return 1;
91}
92
93int it_remove_image(arg_t a) {
94 if (mode == MODE_IMAGE) {
95 remove_file(fileidx, 1);
96 load_image(fileidx >= filecnt ? filecnt - 1 : fileidx);
97 return 1;
98 } else if (tns.sel < tns.cnt) {
99 remove_file(tns.sel, 1);
100 tns.dirty = 1;
101 if (tns.sel >= tns.cnt)
102 tns.sel = tns.cnt - 1;
103 return 1;
104 } else {
105 return 0;
106 }
107}
108
109int i_navigate(arg_t a) {
110 int n = (int) a;
111
112 if (mode == MODE_IMAGE) {
113 n += fileidx;
114 if (n < 0)
115 n = 0;
116 if (n >= filecnt)
117 n = filecnt - 1;
118
119 if (n != fileidx) {
120 load_image(n);
121 return 1;
122 }
123 }
124 return 0;
125}
126
127int it_first(arg_t a) {
128 if (mode == MODE_IMAGE && fileidx != 0) {
129 load_image(0);
130 return 1;
131 } else if (mode == MODE_THUMB && tns.sel != 0) {
132 tns.sel = 0;
133 tns.dirty = 1;
134 return 1;
135 } else {
136 return 0;
137 }
138}
139
140int it_last(arg_t a) {
141 if (mode == MODE_IMAGE && fileidx != filecnt - 1) {
142 load_image(filecnt - 1);
143 return 1;
144 } else if (mode == MODE_THUMB && tns.sel != tns.cnt - 1) {
145 tns.sel = tns.cnt - 1;
146 tns.dirty = 1;
147 return 1;
148 } else {
149 return 0;
150 }
151}
152
153int i_navigate_frame(arg_t a) {
154 if (mode == MODE_IMAGE && !img.multi.animate)
155 return img_frame_navigate(&img, (int) a);
156 else
157 return 0;
158}
159
160int i_toggle_animation(arg_t a) {
161 int delay;
162
163 if (mode != MODE_IMAGE)
164 return 0;
165
166 if (img.multi.animate) {
167 reset_timeout(animate);
168 img.multi.animate = 0;
169 return 0;
170 } else {
171 delay = img_frame_animate(&img, 1);
172 set_timeout(animate, delay, 1);
173 return 1;
174 }
175}
176
177int it_move(arg_t a) {
178 direction_t dir = (direction_t) a;
179
180 if (mode == MODE_IMAGE)
181 return img_pan(&img, &win, dir, 0);
182 else
183 return tns_move_selection(&tns, &win, dir);
184}
185
186int i_pan_screen(arg_t a) {
187 direction_t dir = (direction_t) a;
188
189 if (mode == MODE_IMAGE)
190 return img_pan(&img, &win, dir, 1);
191 else
192 return 0;
193}
194
195int i_pan_edge(arg_t a) {
196 direction_t dir = (direction_t) a;
197
198 if (mode == MODE_IMAGE)
199 return img_pan_edge(&img, &win, dir);
200 else
201 return 0;
202}
203
204/* Xlib helper function for i_drag() */
205Bool is_motionnotify(Display *d, XEvent *e, XPointer a) {
206 return e != NULL && e->type == MotionNotify;
207}
208
209int i_drag(arg_t a) {
210 int dx = 0, dy = 0, i, ox, oy, x, y;
211 unsigned int ui;
212 Bool dragging = True, next = False;
213 XEvent e;
214 Window w;
215
216 if (mode != MODE_IMAGE)
217 return 0;
218 if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
219 return 0;
220
221 win_set_cursor(&win, CURSOR_HAND);
222
223 while (dragging) {
224 if (!next)
225 XMaskEvent(win.env.dpy,
226 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
227 switch (e.type) {
228 case ButtonPress:
229 case ButtonRelease:
230 dragging = False;
231 break;
232 case MotionNotify:
233 x = e.xmotion.x;
234 y = e.xmotion.y;
235 if (x >= 0 && x <= win.w && y >= 0 && y <= win.h) {
236 dx += x - ox;
237 dy += y - oy;
238 }
239 ox = x;
240 oy = y;
241 break;
242 }
243 if (dragging)
244 next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None);
245 if ((!dragging || !next) && (dx != 0 || dy != 0)) {
246 if (img_move(&img, &win, dx, dy))
247 img_render(&img, &win);
248 dx = dy = 0;
249 }
250 }
251
252 win_set_cursor(&win, CURSOR_ARROW);
253 set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
254 reset_timeout(redraw);
255
256 return 0;
257}
258
259int i_zoom(arg_t a) {
260 int scale = (int) a;
261
262 if (mode != MODE_IMAGE)
263 return 0;
264
265 if (scale > 0)
266 return img_zoom_in(&img, &win);
267 else if (scale < 0)
268 return img_zoom_out(&img, &win);
269 else
270 return img_zoom(&img, &win, 1.0);
271}
272
273int i_fit_to_win(arg_t a) {
274 int ret;
275
276 if (mode == MODE_IMAGE) {
277 if ((ret = img_fit_win(&img, &win)))
278 img_center(&img, &win);
279 return ret;
280 } else {
281 return 0;
282 }
283}
284
285int i_fit_to_img(arg_t a) {
286 int ret, x, y;
287 unsigned int w, h;
288
289 if (mode == MODE_IMAGE) {
290 x = MAX(0, win.x + img.x);
291 y = MAX(0, win.y + img.y);
292 w = img.w * img.zoom;
293 h = img.h * img.zoom;
294 if ((ret = win_moveresize(&win, x, y, w, h))) {
295 img.x = x - win.x;
296 img.y = y - win.y;
297 }
298 return ret;
299 } else {
300 return 0;
301 }
302}
303
304int i_rotate(arg_t a) {
305 direction_t dir = (direction_t) a;
306
307 if (mode == MODE_IMAGE) {
308 if (dir == DIR_LEFT) {
309 img_rotate_left(&img, &win);
310 return 1;
311 } else if (dir == DIR_RIGHT) {
312 img_rotate_right(&img, &win);
313 return 1;
314 }
315 }
316 return 0;
317}
318
319int i_toggle_antialias(arg_t a) {
320 if (mode == MODE_IMAGE) {
321 img_toggle_antialias(&img);
322 return 1;
323 } else {
324 return 0;
325 }
326}
327
328int i_toggle_alpha(arg_t a) {
329 if (mode == MODE_IMAGE) {
330 img.alpha ^= 1;
331 return 1;
332 } else {
333 return 0;
334 }
335}
336
337int it_open_with(arg_t a) {
338 const char *prog = (const char*) a;
339 pid_t pid;
340
341 if (!prog || !*prog)
342 return 0;
343
344 if((pid = fork()) == 0) {
345 execlp(prog, prog,
346 files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL);
347 warn("could not exec: %s", prog);
348 exit(1);
349 } else if (pid < 0) {
350 warn("could not fork. program was: %s", prog);
351 }
352
353 return 0;
354}
355
356int it_shell_cmd(arg_t a) {
357 int n, status;
358 const char *cmdline = (const char*) a;
359 pid_t pid;
360
361 if (!cmdline || !*cmdline)
362 return 0;
363
364 n = mode == MODE_IMAGE ? fileidx : tns.sel;
365
366 if (setenv("SXIV_IMG", files[n].path, 1) < 0) {
367 warn("could not change env.-variable: SXIV_IMG. command line was: %s",
368 cmdline);
369 return 0;
370 }
371
372 win_set_cursor(&win, CURSOR_WATCH);
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 goto end;
381 }
382
383 waitpid(pid, &status, 0);
384 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
385 warn("child exited with non-zero return value: %d. command line was: %s",
386 WEXITSTATUS(status), cmdline);
387
388 if (mode == MODE_IMAGE) {
389 img_close(&img, 1);
390 load_image(fileidx);
391 }
392 if (!tns_load(&tns, n, &files[n], True, mode == MODE_IMAGE) &&
393 mode == MODE_THUMB)
394 {
395 remove_file(tns.sel, 0);
396 tns.dirty = 1;
397 if (tns.sel >= tns.cnt)
398 tns.sel = tns.cnt - 1;
399 }
400
401end:
402 if (mode == MODE_THUMB)
403 win_set_cursor(&win, CURSOR_ARROW);
404 /* else: cursor gets reset in redraw() */
405
406 return 1;
407}