dotfiles

personal configuration files and scripts
git clone https://tongong.net/git/dotfiles.git
Log | Files | Refs | README

commands.c (8326B)


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