Krolyxon
Commit 8b3ae50

Branches

Refs →

nsxivcommands.c

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