Krolyxon
Commit 1d74938

Branches

Refs →

nsxivcommands.c

400 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#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 it_move(arg_t a) {
151 direction_t dir = (direction_t) a;
152
153 if (mode == MODE_IMAGE)
154 return img_pan(&img, &win, dir, 0);
155 else
156 return tns_move_selection(&tns, &win, dir);
157}
158
159int i_pan_screen(arg_t a) {
160 direction_t dir = (direction_t) a;
161
162 if (mode == MODE_IMAGE)
163 return img_pan(&img, &win, dir, 1);
164 else
165 return 0;
166}
167
168int i_pan_edge(arg_t a) {
169 direction_t dir = (direction_t) a;
170
171 if (mode == MODE_IMAGE)
172 return img_pan_edge(&img, &win, dir);
173 else
174 return 0;
175}
176
177/* Xlib helper function for i_drag() */
178Bool is_motionnotify(Display *d, XEvent *e, XPointer a) {
179 return e != NULL && e->type == MotionNotify;
180}
181
182int i_drag(arg_t a) {
183 int dx = 0, dy = 0, i, ox, oy, x, y;
184 unsigned int ui;
185 Bool dragging = True, next = False;
186 XEvent e;
187 Window w;
188
189 if (mode != MODE_IMAGE)
190 return 0;
191 if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
192 return 0;
193
194 win_set_cursor(&win, CURSOR_HAND);
195
196 while (dragging) {
197 if (!next)
198 XMaskEvent(win.env.dpy,
199 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
200 switch (e.type) {
201 case ButtonPress:
202 case ButtonRelease:
203 dragging = False;
204 break;
205 case MotionNotify:
206 x = e.xmotion.x;
207 y = e.xmotion.y;
208 if (x >= 0 && x <= win.w && y >= 0 && y <= win.h) {
209 dx += x - ox;
210 dy += y - oy;
211 }
212 ox = x;
213 oy = y;
214 break;
215 }
216 if (dragging)
217 next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None);
218 if ((!dragging || !next) && (dx != 0 || dy != 0)) {
219 if (img_move(&img, &win, dx, dy))
220 img_render(&img, &win);
221 dx = dy = 0;
222 }
223 }
224
225 win_set_cursor(&win, CURSOR_ARROW);
226 timo_cursor = TO_CURSOR_HIDE;
227 timo_redraw = 0;
228
229 return 0;
230}
231
232int i_zoom(arg_t a) {
233 int scale = (int) a;
234
235 if (mode != MODE_IMAGE)
236 return 0;
237 if (scale > 0)
238 return img_zoom_in(&img, &win);
239 else if (scale < 0)
240 return img_zoom_out(&img, &win);
241 else
242 return img_zoom(&img, &win, 1.0);
243}
244
245int i_fit_to_win(arg_t a) {
246 int ret;
247
248 if (mode == MODE_IMAGE) {
249 if ((ret = img_fit_win(&img, &win)))
250 img_center(&img, &win);
251 return ret;
252 } else {
253 return 0;
254 }
255}
256
257int i_fit_to_img(arg_t a) {
258 int ret, x, y;
259 unsigned int w, h;
260
261 if (mode == MODE_IMAGE) {
262 x = MAX(0, win.x + img.x);
263 y = MAX(0, win.y + img.y);
264 w = img.w * img.zoom;
265 h = img.h * img.zoom;
266 if ((ret = win_moveresize(&win, x, y, w, h))) {
267 img.x = x - win.x;
268 img.y = y - win.y;
269 }
270 return ret;
271 } else {
272 return 0;
273 }
274}
275
276int i_rotate(arg_t a) {
277 direction_t dir = (direction_t) a;
278
279 if (mode == MODE_IMAGE) {
280 if (dir == DIR_LEFT) {
281 img_rotate_left(&img, &win);
282 return 1;
283 } else if (dir == DIR_RIGHT) {
284 img_rotate_right(&img, &win);
285 return 1;
286 }
287 }
288 return 0;
289}
290
291int i_toggle_antialias(arg_t a) {
292 if (mode == MODE_IMAGE) {
293 img_toggle_antialias(&img);
294 return 1;
295 } else {
296 return 0;
297 }
298}
299
300int i_toggle_alpha(arg_t a) {
301 if (mode == MODE_IMAGE) {
302 img.alpha ^= 1;
303 return 1;
304 } else {
305 return 0;
306 }
307}
308
309int it_open_with(arg_t a) {
310 const char *prog = (const char*) a;
311 pid_t pid;
312
313 if (!prog || !*prog)
314 return 0;
315
316 if((pid = fork()) == 0) {
317 execlp(prog, prog,
318 files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL);
319 warn("could not exec: %s", prog);
320 exit(1);
321 } else if (pid < 0) {
322 warn("could not for. program was: %s", prog);
323 }
324
325 return 0;
326}
327
328int it_shell_cmd(arg_t a) {
329 const char *cline = (const char*) a;
330 char *cn, *cmdline;
331 const char *co, *fpath;
332 int fpcnt, fplen, status;
333 pid_t pid;
334
335 if (!cline || !*cline)
336 return 0;
337
338 /* build command line: */
339 fpcnt = 0;
340 co = cline - 1;
341 while ((co = strchr(co + 1, '#')))
342 fpcnt++;
343 if (!fpcnt)
344 return 0;
345 fpath = files[mode == MODE_IMAGE ? fileidx : tns.sel].path;
346 fplen = strlen(fpath);
347 cn = cmdline = (char*) s_malloc((strlen(cline) + fpcnt * (fplen + 2)) *
348 sizeof(char));
349 /* replace all '#' with filename: */
350 for (co = cline; *co; co++) {
351 if (*co == '#') {
352 *cn++ = '"';
353 strcpy(cn, fpath);
354 cn += fplen;
355 *cn++ = '"';
356 } else {
357 *cn++ = *co;
358 }
359 }
360 *cn = '\0';
361
362 win_set_cursor(&win, CURSOR_WATCH);
363
364 if ((pid = fork()) == 0) {
365 execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
366 warn("could not exec: /bin/sh");
367 exit(1);
368 } else if (pid < 0) {
369 warn("could not fork. command line was: %s", cmdline);
370 goto end;
371 }
372
373 waitpid(pid, &status, 0);
374 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
375 warn("child exited with non-zero return value: %d. command line was: %s",
376 WEXITSTATUS(status), cmdline);
377
378 if (mode == MODE_IMAGE) {
379 if (fileidx < tns.cnt)
380 tns_load(&tns, fileidx, &files[fileidx], False, True);
381 img_close(&img, 1);
382 load_image(fileidx);
383 } else {
384 if (!tns_load(&tns, tns.sel, &files[tns.sel], True, False)) {
385 remove_file(tns.sel, 0);
386 tns.dirty = 1;
387 if (tns.sel >= tns.cnt)
388 tns.sel = tns.cnt - 1;
389 }
390 }
391
392end:
393 if (mode == MODE_THUMB)
394 win_set_cursor(&win, CURSOR_ARROW);
395 /* else: cursor gets reset in redraw() */
396
397 free(cmdline);
398
399 return 1;
400}