Krolyxon
Commit a4b90ae

Branches

Refs →

nsxivcommands.c

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