Krolyxon
Commit 1449bfc

Branches

Refs →

nsxivcommands.c

450 lines · 8.1 KB · C

1/* Copyright 2011, 2012, 2014 Bert Muennich
2 *
3 * This file is a part of nsxiv.
4 *
5 * nsxiv is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License,
8 * or (at your option) any later version.
9 *
10 * nsxiv is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with nsxiv. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "nsxiv.h"
20#define _IMAGE_CONFIG
21#include "config.h"
22
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/wait.h>
27
28void remove_file(int, bool);
29void load_image(int);
30bool mark_image(int, bool);
31void close_info(void);
32void open_info(void);
33int ptr_third_x(void);
34void redraw(void);
35void reset_cursor(void);
36void animate(void);
37void slideshow(void);
38void set_timeout(timeout_f, int, bool);
39void reset_timeout(timeout_f);
40void handle_key_handler(bool);
41
42extern appmode_t mode;
43extern img_t img;
44extern tns_t tns;
45extern win_t win;
46
47extern fileinfo_t *files;
48extern int filecnt, fileidx;
49extern int alternate;
50extern int markcnt;
51extern int markidx;
52
53extern int prefix;
54extern bool extprefix;
55
56bool cg_quit(arg_t _)
57{
58 unsigned int i;
59
60 if (options->to_stdout && markcnt > 0) {
61 for (i = 0; i < filecnt; i++) {
62 if (files[i].flags & FF_MARK)
63 printf("%s%c", files[i].name, options->stdout_separator);
64 }
65 }
66 exit(EXIT_SUCCESS);
67}
68
69bool cg_switch_mode(arg_t _)
70{
71 if (mode == MODE_IMAGE) {
72 if (tns.thumbs == NULL)
73 tns_init(&tns, files, &filecnt, &fileidx, &win);
74 img_close(&img, false);
75 reset_timeout(reset_cursor);
76 if (img.ss.on) {
77 img.ss.on = false;
78 reset_timeout(slideshow);
79 }
80 tns.dirty = true;
81 mode = MODE_THUMB;
82 } else {
83 load_image(fileidx);
84 mode = MODE_IMAGE;
85 }
86 return true;
87}
88
89bool cg_toggle_fullscreen(arg_t _)
90{
91 win_toggle_fullscreen(&win);
92 /* redraw after next ConfigureNotify event */
93 set_timeout(redraw, TO_REDRAW_RESIZE, false);
94 if (mode == MODE_IMAGE)
95 img.checkpan = img.dirty = true;
96 else
97 tns.dirty = true;
98 return false;
99}
100
101bool cg_toggle_bar(arg_t _)
102{
103 win_toggle_bar(&win);
104 if (mode == MODE_IMAGE) {
105 if (win.bar.h > 0)
106 open_info();
107 else
108 close_info();
109 img.checkpan = img.dirty = true;
110 } else {
111 tns.dirty = true;
112 }
113 return true;
114}
115
116bool cg_prefix_external(arg_t _)
117{
118 handle_key_handler(true);
119 return false;
120}
121
122bool cg_reload_image(arg_t _)
123{
124 if (mode == MODE_IMAGE) {
125 load_image(fileidx);
126 } else {
127 win_set_cursor(&win, CURSOR_WATCH);
128 if (!tns_load(&tns, fileidx, true, false)) {
129 remove_file(fileidx, false);
130 tns.dirty = true;
131 }
132 }
133 return true;
134}
135
136bool cg_remove_image(arg_t _)
137{
138 remove_file(fileidx, true);
139 if (mode == MODE_IMAGE)
140 load_image(fileidx);
141 else
142 tns.dirty = true;
143 return true;
144}
145
146bool cg_first(arg_t _)
147{
148 if (mode == MODE_IMAGE && fileidx != 0) {
149 load_image(0);
150 return true;
151 } else if (mode == MODE_THUMB && fileidx != 0) {
152 fileidx = 0;
153 tns.dirty = true;
154 return true;
155 } else {
156 return false;
157 }
158}
159
160bool cg_n_or_last(arg_t _)
161{
162 int n = prefix != 0 && prefix - 1 < filecnt ? prefix - 1 : filecnt - 1;
163
164 if (mode == MODE_IMAGE && fileidx != n) {
165 load_image(n);
166 return true;
167 } else if (mode == MODE_THUMB && fileidx != n) {
168 fileidx = n;
169 tns.dirty = true;
170 return true;
171 } else {
172 return false;
173 }
174}
175
176bool cg_scroll_screen(arg_t dir)
177{
178 if (mode == MODE_IMAGE)
179 return img_pan(&img, dir, -1);
180 else
181 return tns_scroll(&tns, dir, true);
182}
183
184bool cg_zoom(arg_t d)
185{
186 if (mode == MODE_THUMB)
187 return tns_zoom(&tns, d);
188 else
189 return img_zoom(&img, d);
190}
191
192bool cg_toggle_image_mark(arg_t _)
193{
194 return mark_image(fileidx, !(files[fileidx].flags & FF_MARK));
195}
196
197bool cg_reverse_marks(arg_t _)
198{
199 int i;
200
201 for (i = 0; i < filecnt; i++) {
202 files[i].flags ^= FF_MARK;
203 markcnt += files[i].flags & FF_MARK ? 1 : -1;
204 }
205 if (mode == MODE_THUMB)
206 tns.dirty = true;
207 return true;
208}
209
210bool cg_mark_range(arg_t _)
211{
212 int d = markidx < fileidx ? 1 : -1, end, i;
213 bool dirty = false, on = !!(files[markidx].flags & FF_MARK);
214
215 for (i = markidx + d, end = fileidx + d; i != end; i += d)
216 dirty |= mark_image(i, on);
217 return dirty;
218}
219
220bool cg_unmark_all(arg_t _)
221{
222 int i;
223
224 for (i = 0; i < filecnt; i++)
225 files[i].flags &= ~FF_MARK;
226 markcnt = 0;
227 if (mode == MODE_THUMB)
228 tns.dirty = true;
229 return true;
230}
231
232bool cg_navigate_marked(arg_t n)
233{
234 int d, i;
235 int new = fileidx;
236
237 if (prefix > 0)
238 n *= prefix;
239 d = n > 0 ? 1 : -1;
240 for (i = fileidx + d; n != 0 && i >= 0 && i < filecnt; i += d) {
241 if (files[i].flags & FF_MARK) {
242 n -= d;
243 new = i;
244 }
245 }
246 if (new != fileidx) {
247 if (mode == MODE_IMAGE) {
248 load_image(new);
249 } else {
250 fileidx = new;
251 tns.dirty = true;
252 }
253 return true;
254 } else {
255 return false;
256 }
257}
258
259bool cg_change_gamma(arg_t d)
260{
261 if (img_change_gamma(&img, d * (prefix > 0 ? prefix : 1))) {
262 if (mode == MODE_THUMB)
263 tns.dirty = true;
264 return true;
265 } else {
266 return false;
267 }
268}
269
270bool ci_navigate(arg_t n)
271{
272 if (prefix > 0)
273 n *= prefix;
274 n += fileidx;
275 if (n < 0)
276 n = 0;
277 if (n >= filecnt)
278 n = filecnt - 1;
279
280 if (n != fileidx) {
281 load_image(n);
282 return true;
283 } else {
284 return false;
285 }
286}
287
288bool ci_cursor_navigate(arg_t _)
289{
290 return ci_navigate(ptr_third_x() - 1);
291}
292
293bool ci_alternate(arg_t _)
294{
295 load_image(alternate);
296 return true;
297}
298
299bool ci_navigate_frame(arg_t d)
300{
301 if (prefix > 0)
302 d *= prefix;
303 return !img.multi.animate && img_frame_navigate(&img, d);
304}
305
306bool ci_toggle_animation(arg_t _)
307{
308 bool dirty = false;
309
310 if (img.multi.cnt > 0) {
311 img.multi.animate = !img.multi.animate;
312 if (img.multi.animate) {
313 dirty = img_frame_animate(&img);
314 set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
315 } else {
316 reset_timeout(animate);
317 }
318 }
319 return dirty;
320}
321
322bool ci_scroll(arg_t dir)
323{
324 return img_pan(&img, dir, prefix);
325}
326
327bool ci_scroll_to_edge(arg_t dir)
328{
329 return img_pan_edge(&img, dir);
330}
331
332bool ci_drag(arg_t mode)
333{
334 int x, y, ox, oy;
335 float px, py;
336 XEvent e;
337
338 if ((int)(img.w * img.zoom) <= win.w && (int)(img.h * img.zoom) <= win.h)
339 return false;
340
341 win_set_cursor(&win, CURSOR_DRAG);
342 win_cursor_pos(&win, &x, &y);
343 ox = x;
344 oy = y;
345
346 while (true) {
347 if (mode == DRAG_ABSOLUTE) {
348 px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8)
349 * (win.w - img.w * img.zoom);
350 py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8)
351 * (win.h - img.h * img.zoom);
352 } else {
353 px = img.x + x - ox;
354 py = img.y + y - oy;
355 }
356
357 if (img_pos(&img, px, py)) {
358 img_render(&img);
359 win_draw(&win);
360 }
361 XMaskEvent(win.env.dpy,
362 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
363 if (e.type == ButtonPress || e.type == ButtonRelease)
364 break;
365 while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
366 ox = x;
367 oy = y;
368 x = e.xmotion.x;
369 y = e.xmotion.y;
370 }
371 set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
372 reset_cursor();
373
374 return true;
375}
376
377bool ci_set_zoom(arg_t zl)
378{
379 return img_zoom_to(&img, (prefix ? prefix : zl) / 100.0);
380}
381
382bool ci_fit_to_win(arg_t sm)
383{
384 return img_fit_win(&img, sm);
385}
386
387bool ci_rotate(arg_t degree)
388{
389 img_rotate(&img, degree);
390 return true;
391}
392
393bool ci_flip(arg_t dir)
394{
395 img_flip(&img, dir);
396 return true;
397}
398
399bool ci_toggle_antialias(arg_t _)
400{
401 img_toggle_antialias(&img);
402 return true;
403}
404
405bool ci_toggle_alpha(arg_t _)
406{
407 img.alpha = !img.alpha;
408 img.dirty = true;
409 return true;
410}
411
412bool ci_slideshow(arg_t _)
413{
414 if (prefix > 0) {
415 img.ss.on = true;
416 img.ss.delay = prefix * 10;
417 set_timeout(slideshow, img.ss.delay * 100, true);
418 } else if (img.ss.on) {
419 img.ss.on = false;
420 reset_timeout(slideshow);
421 } else {
422 img.ss.on = true;
423 }
424 return true;
425}
426
427bool ct_move_sel(arg_t dir)
428{
429 return tns_move_selection(&tns, dir, prefix);
430}
431
432bool ct_reload_all(arg_t _)
433{
434 tns_free(&tns);
435 tns_init(&tns, files, &filecnt, &fileidx, &win);
436 tns.dirty = true;
437 return true;
438}
439
440
441#undef G_CMD
442#define G_CMD(c) { -1, cg_##c },
443#undef I_CMD
444#define I_CMD(c) { MODE_IMAGE, ci_##c },
445#undef T_CMD
446#define T_CMD(c) { MODE_THUMB, ct_##c },
447
448const cmd_t cmds[CMD_COUNT] = {
449#include "commands.lst"
450};