loaders: PNG: Handle gamma on 16bpp conversion
[gfxprim.git] / demos / spiv / spiv_help.c
blobaad401055a93035cf41165569053872e36e9fea9
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 above 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, PSD, PNM, PCX, JPEG2000 and CBZ\n"
168 "(as well general ZIP archives with images), and more will come in\n"
169 "the near future.\n"
170 ".PP\n"
171 "Spiv supports variety of video backends (via GFXprim backends)\n"
172 "currently these are X11, Linux Framebuffer, SDL and AAlib. Spiv also\n"
173 "supports wide range of backend pixel types from 1bit Grayscale to 32bit RGB\n"
174 "with optional Floyd-Steinberg dithering (even, for example, from RGB888 to RGB565).\n"
175 ".PP\n"
176 "Spiv implements feh-like image actions, which are short shell scripts with\n"
177 "printf-like modifiers.\n"
178 "See\n.B ACTIONS\nbelow for further information.\n";
180 static const char *man_tail =
181 ".SH BUGS\n"
182 "Bugs happen. If you find one, report it on the GFXprim mailing list at\n"
183 ".I gfxprim@ucw.cz\n"
184 ".SH AUTHORS\n"
185 "Spiv is developed by Cyril Hrubis <metan@ucw.cz>\n"
186 ".PP\nGFXprim was/is developed by:\n"
187 ".PP\n.nf\nCyril Hrubis <metan@ucw.cz>\n"
188 ".nf\nJiri \"BlueBear\" Dluhos <jiri.bluebear.dluhos@gmail.com>\n"
189 ".nf\nTomas Gavenciak <gavento@ucw.cz>\n";
191 static const char *actions_help =
192 ".SH ACTIONS\n"
193 "Actions are short shell scripts with printf-like modifiers, the \n"
194 "modifiers are substituted to current image path, name, etc. and executed\n"
195 "by pressing function keys).\n"
196 ".PP\n"
197 "Actions could be set via command line parameters or written into the\n"
198 "configuration file and support following modifiers:\n";
200 void print_man(void)
202 int i;
204 puts(man_head);
206 printf(".SH KEYBOARD CONTROL\n");
208 for (i = 0; i < help_keys_len; i++) {
209 if (help_keys[i].desc[0] != '\0') {
210 printf(".IP \"%s\"\n", help_keys[i].keys);
211 printf("%s\n", help_keys[i].desc);
215 spiv_config_print_man();
217 puts(".PP\nConfiguration is loaded from /etc/spiv.conf");
218 puts("then ~/.spiv and overriden by command line parameters.\n");
220 puts(actions_help);
222 for (i = 0; i < actions_len; i++)
223 printf(".PP\n.B %%%c\n%s\n", actions[i].modifier, actions[i].desc);
225 puts(".SH EXAMPLES");
227 for (i = 0; i < examples_len; i++)
228 printf(".PP\n.B %s\n.nf\n%s\n\n", examples[i].desc, examples[i].example);
230 puts(man_tail);
233 static int last_line;
235 static int redraw_help(GP_Backend *backend, unsigned int loff, GP_Coord xoff)
237 GP_Pixmap *c = backend->pixmap;
238 GP_Pixel black = GP_RGBToPixmapPixel(0x00, 0x00, 0x00, c);
239 GP_Pixel white = GP_RGBToPixmapPixel(0xff, 0xff, 0xff, c);
240 int i;
242 int spacing = GP_TextHeight(config.style)/10 + 2;
243 int height = GP_TextHeight(config.style);
245 GP_Fill(c, black);
247 GP_Print(c, config.style, 20 + 10 * xoff, 2, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM,
248 white, black, "%s", "Keyboard Controls:");
250 unsigned int max = 0;
252 for (i = 0; i < help_keys_len; i++)
253 max = GP_MAX(max, GP_TextWidth(config.style, help_keys[i].keys));
255 for (i = loff; i < help_keys_len; i++) {
256 GP_Coord h = spacing + (i - loff + 1) * (height + spacing);
258 if (h + height + spacing > (GP_Coord)c->h) {
259 last_line = 0;
260 goto out;
263 GP_Print(c, config.style, 20 + 10 * xoff, h, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM,
264 white, black, "%s", help_keys[i].keys);
265 GP_Print(c, config.style, 20 + 10 * xoff + max, h, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM,
266 white, black, " - %s", help_keys[i].desc);
267 last_line = 1;
270 out:
271 GP_BackendFlip(backend);
272 return i;
275 void draw_help(GP_Backend *backend)
277 int loff = 0, last, xoff = 0;
279 last = redraw_help(backend, loff, xoff);
281 for (;;) {
282 GP_Event ev;
284 while (GP_BackendWaitEvent(backend, &ev)) {
285 switch (ev.type) {
286 case GP_EV_KEY:
287 if (ev.code != GP_EV_KEY_DOWN)
288 continue;
290 switch (ev.val.key.key) {
291 case GP_KEY_DOWN:
292 if (last < help_keys_len)
293 last = redraw_help(backend, ++loff, xoff);
294 break;
295 case GP_KEY_UP:
296 if (loff > 0)
297 last = redraw_help(backend, --loff, xoff);
298 break;
299 case GP_KEY_LEFT:
300 last = redraw_help(backend, loff, --xoff);
301 break;
302 case GP_KEY_RIGHT:
303 last = redraw_help(backend, loff, ++xoff);
304 break;
305 case GP_KEY_PAGE_DOWN:
306 if (last < help_keys_len) {
307 if (last_line)
308 break;
310 loff += last - loff;
311 last = redraw_help(backend, loff, xoff);
313 break;
314 case GP_KEY_PAGE_UP:
315 if (loff > 0) {
316 loff -= last - loff;
317 if (loff < 0)
318 loff = 0;
319 last = redraw_help(backend, loff, xoff);
321 break;
322 default:
323 return;
325 break;
326 case GP_EV_SYS:
327 switch (ev.code) {
328 case GP_EV_SYS_RESIZE:
329 GP_BackendResizeAck(backend);
330 last = redraw_help(backend, loff, xoff);
331 break;
332 case GP_EV_SYS_QUIT:
333 GP_BackendPutEventBack(backend, &ev);
334 return;