demos: Fix and cleanup GP_BackendInit() + docs.
[gfxprim/pasky.git] / demos / spiv / spiv_help.c
blob0f9e222b3f6753cf49b6f6b59c5ff9be6a9d9b2a
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim 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 GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <stdio.h>
24 #include <GP.h>
26 #include "spiv_config.h"
27 #include "spiv_help.h"
29 struct key_help {
30 const char *keys;
31 const char *desc;
34 #define KEYS_MAX "13"
36 static struct key_help help_keys[] = {
37 {"Esc, Enter, Q", "Quit spiv"},
38 {"Space", "Move to the next image"},
39 {"BackSpace", "Move to the prev image"},
40 {"PgDown", "Move to the start of directory"},
41 {"PgUp", "Move to the end of directory"},
42 {"Home", "Move to the first image"},
43 {"End", "Move to the last image"},
44 {"R", "Rotate by 90 degrees clockwise"},
45 {"E", "Rotate by 90 degrees counterclockwise"},
46 {"W", "Toggle fixed, resizable window"},
47 {"D", "Turn on/off downscale when image is larger than win"},
48 {"U", "Turn on/off upscale when image is smaller than win"},
49 {"H", "Show help"},
50 {"I", "Toggle show info box"},
51 {"P", "Toggle show progress"},
52 {"S", "Start/stop slideshow"},
53 {"", ""},
54 {"F1-F10", "Execute action 1 - 10"},
55 {"", ""},
56 {"<, KP Minus", "Zoom out by 50% (by 10% with Shift)"},
57 {">, KP Plus", "Zoom in by 50% (by 10% with Shift)"},
58 {"1", "Resize to the image size"},
59 {"2", "Resize to a half of the image size"},
60 {"3", "Resize to one third of the image size"},
61 {"9", "Resize to one ninth of the image size"},
62 {"...", ""},
63 {"0", "Resize to one tenth of the image size"},
64 {"Shift 2", "Resize twice of the image size"},
65 {"Shift 3", "Resize three times of the image size"},
66 {"...", ""},
67 {"Up", "Move image by 10px up (by 1 with Shift)"},
68 {"Down", "Move image by 10px down (by 1 with Shift)"},
69 {"Left", "Move image by 10px left (by 1 with Shift)"},
70 {"Right", "Move image by 10px right (by 1 with Shift)"},
71 {"", ""},
72 {"]", "Change to next resampling method"},
73 {"[", "Change to prev resampling method"},
74 {"L", "Toggle low pass filter"},
75 {"C", "Drop image cache"},
78 static const int help_keys_len = sizeof(help_keys) / sizeof(*help_keys);
80 struct examples {
81 const char *example;
82 const char *desc;
85 static const struct examples examples[] = {
86 {"spiv *.jpg",
87 "Shows all jpeg images in current directory"},
88 {"spiv images.zip",
89 "Shows all images stored in zip file"},
90 {"spiv .",
91 "Shows all loadable images in current directory"},
92 {"spiv -s 5 vacation/",
93 "Runs slideshow with 5 second delay"},
94 {"spiv -1 'cp %F sorted' images/",
95 "Copies currently loaded image into directory 'sorted/' on pressing F1"},
96 {"spiv -e G1 -d images/",
97 "Emulates 1-bit Grayscale display and turns on Floyd-Steinberg dithering"},
98 {"spiv -b 'X11:use_root' -t 10 images/",
99 "Runs slideshow using X root window as backend window"},
100 {"spiv -b 'X11:create_root' -t 10 images/",
101 "Same as abowe but works in KDE\n"}
104 static const int examples_len = sizeof(examples) / sizeof(*examples);
106 struct actions {
107 const char modifier;
108 const char *desc;
111 static struct actions actions[] = {
112 {'f', "Path to current image"},
113 {'F', "Shell escaped path to current image"},
114 {'n', "Current image filename without extension"},
115 {'N', "Shell escaped image filename without extension"},
116 {'e', "Current image file extension"},
119 static const int actions_len = sizeof(actions) / sizeof(*actions);
121 void print_help(void)
123 int i;
125 printf("Usage: spiv [opts] images or dirs with images\n");
126 spiv_config_print_help();
128 printf(" Action shell command modifiers:\n");
130 for (i = 0; i < actions_len; i++)
131 printf(" %%%c %s\n", actions[i].modifier, actions[i].desc);
133 printf("\n");
135 printf("Keyboard controls:\n\n");
137 for (i = 0; i < help_keys_len; i++) {
138 if (help_keys[i].desc[0] == '\0') {
139 printf(" %s\n", help_keys[i].keys);
140 } else {
141 printf(" %-"KEYS_MAX"s - %s\n",
142 help_keys[i].keys, help_keys[i].desc);
146 puts("");
148 printf("Example usage:\n\n");
150 for (i = 0; i < examples_len; i++)
151 printf("%s\n\t%s\n", examples[i].example, examples[i].desc);
154 const char *man_head =
155 ".TH spiv 1 2013 GFXprim \"Simple yet Powerful Image Viewer\"\n\n"
156 ".SH NAME\n"
157 "spiv \\- Simple yet Powerful Image Viewer\n"
158 ".SH SYNOPSIS\n"
159 ".B spiv\n"
160 "[options] images|dirs\n"
161 ".SH DESCRIPTION\n"
162 ".B spiv\n"
163 "is a fast, lightweight and minimalistic image viewer build on the\n"
164 "top of the GFXprim library.\n"
165 ".PP\n"
166 "Spiv supports wide range of image formats, currently supported are\n"
167 "JPEG, PNG, GIF, BMP, TIFF, PSP, PPM, JP2 and CBZ (as well general\n"
168 "ZIP archives with images), and more will come in the near future.\n"
169 ".PP\n"
170 "Spiv supports variety of video backends (via GFXprim backends)\n"
171 "currently these are X11, Linux Framebuffer, SDL and AAlib. Spiv also\n"
172 "supports wide range of backend pixel types from 1bit Grayscale to 32bit RGB\n"
173 "with optional Floyd-Steinberg dithering (even, for example, from RGB888 to RGB565).\n"
174 ".PP\n"
175 "Spiv implements feh-like image actions, which are short shell scripts with\n"
176 "printf-like modifiers.\n"
177 "See\n.B ACTIONS\nbellow for further information.\n";
179 static const char *man_tail =
180 ".SH BUGS\n"
181 "Bugs happen. If you find one, report it on the GFXprim mailing list at\n"
182 ".I gfxprim@ucw.cz\n"
183 ".SH AUTHORS\n"
184 "Spiv is developed by Cyril Hrubis <chrubis@ucw.cz>\n"
185 ".PP\nGFXprim was/is developed by:\n"
186 ".PP\n.nf\nCyril Hrubis <chrubis@ucw.cz>\n"
187 ".nf\nJiri \"BlueBear\" Dluhos <jiri.bluebear.dluhos@gmail.com>\n"
188 ".nf\nTomas Gavenciak <gavento@ucw.cz>\n";
190 static const char *actions_help =
191 ".SH ACTIONS\n"
192 "Actions are short shell scripts with printf-like modifiers, the \n"
193 "modifiers are substituted to current image path, name, etc. and executed\n"
194 "by pressing function keys).\n"
195 ".PP\n"
196 "Actions could be set via command line parameters or written into the\n"
197 "configuration file and support following modifiers:\n";
199 void print_man(void)
201 int i;
203 puts(man_head);
205 printf(".SH KEYBOARD CONTROL\n");
207 for (i = 0; i < help_keys_len; i++) {
208 if (help_keys[i].desc[0] != '\0') {
209 printf(".IP \"%s\"\n", help_keys[i].keys);
210 printf("%s\n", help_keys[i].desc);
214 spiv_config_print_man();
216 puts(".PP\nConfiguration is loaded from /etc/spiv.conf");
217 puts("then ~/.spiv and overriden by command line parameters.\n");
219 puts(actions_help);
221 for (i = 0; i < actions_len; i++)
222 printf(".PP\n.B %%%c\n%s\n", actions[i].modifier, actions[i].desc);
224 puts(".SH EXAMPLES");
226 for (i = 0; i < examples_len; i++)
227 printf(".PP\n.B %s\n.nf\n%s\n\n", examples[i].desc, examples[i].example);
229 puts(man_tail);
232 static int redraw_help(GP_Backend *backend, unsigned int loff, GP_Coord xoff)
234 GP_Context *c = backend->context;
235 GP_Pixel black = GP_ColorToContextPixel(GP_COL_BLACK, c);
236 GP_Pixel white = GP_ColorToContextPixel(GP_COL_WHITE, c);
237 int i;
239 GP_Fill(c, black);
241 GP_Print(c, NULL, 20 + 10 * xoff, 2, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM,
242 white, black, "%s", "Keyboard Controls:");
244 for (i = loff; i < help_keys_len; i++) {
245 GP_Coord h = 2 + (i - loff + 1) * 15;
247 if (h + 2 >= (GP_Coord)c->h)
248 goto out;
250 GP_Print(c, NULL, 20 + 10 * xoff, h, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM,
251 white, black, "%-"KEYS_MAX"s - %s", help_keys[i].keys, help_keys[i].desc);
254 out:
255 GP_BackendFlip(backend);
256 return i;
259 static int max_lines(GP_Backend *backend)
261 return (backend->context->h - 4) / 15;
264 void draw_help(GP_Backend *backend)
266 int loff = 0, last, xoff = 0;
268 last = redraw_help(backend, loff, xoff);
270 for (;;) {
271 GP_Event ev;
273 while (GP_BackendWaitEvent(backend, &ev)) {
274 switch (ev.type) {
275 case GP_EV_KEY:
276 if (ev.code != GP_EV_KEY_DOWN)
277 continue;
279 switch (ev.val.key.key) {
280 case GP_KEY_DOWN:
281 if (last < help_keys_len)
282 last = redraw_help(backend, ++loff, xoff);
283 break;
284 case GP_KEY_UP:
285 if (loff > 0)
286 last = redraw_help(backend, --loff, xoff);
287 break;
288 case GP_KEY_LEFT:
289 last = redraw_help(backend, loff, --xoff);
290 break;
291 case GP_KEY_RIGHT:
292 last = redraw_help(backend, loff, ++xoff);
293 break;
294 case GP_KEY_PAGE_DOWN:
295 if (last < help_keys_len) {
296 if (loff + max_lines(backend) >= help_keys_len)
297 break;
299 loff += max_lines(backend);
301 last = redraw_help(backend, loff, xoff);
303 break;
304 case GP_KEY_PAGE_UP:
305 if (loff > 0) {
306 loff -= max_lines(backend);
307 if (loff < 0)
308 loff = 0;
309 last = redraw_help(backend, loff, xoff);
311 break;
312 default:
313 return;
315 break;
316 case GP_EV_SYS:
317 switch (ev.code) {
318 case GP_EV_SYS_RESIZE:
319 GP_BackendResizeAck(backend);
320 last = redraw_help(backend, loff, xoff);
321 break;
322 case GP_EV_SYS_QUIT:
323 GP_BackendPutEventBack(backend, &ev);
324 return;