blob: 01bfe06b687752012c833a521b5ce24dba723f4b [file] [log] [blame]
Steve Kondikae271bc2015-11-15 02:50:53 +01001/****************************************************************************
2 * Copyright (c) 2007-2011,2015 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28/*
29 * $Id: savescreen.c,v 1.27 2015/03/28 23:21:28 tom Exp $
30 *
31 * Demonstrate save/restore functions from the curses library.
32 * Thomas Dickey - 2007/7/14
33 */
34
35#include <test.priv.h>
36
37#if HAVE_SCR_DUMP
38
39#include <sys/types.h>
40#include <sys/stat.h>
41
42#if TIME_WITH_SYS_TIME
43# include <sys/time.h>
44# include <time.h>
45#else
46# if HAVE_SYS_TIME_H
47# include <sys/time.h>
48# else
49# include <time.h>
50# endif
51#endif
52
53static bool use_init = FALSE;
54static bool keep_dumps = FALSE;
55
56static int
57fexists(const char *name)
58{
59 struct stat sb;
60 return (stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFREG);
61}
62
63static void
64setup_next(void)
65{
66 curs_set(1);
67 reset_shell_mode();
68}
69
70static void
71cleanup(char *files[])
72{
73 int n;
74
75 if (!keep_dumps) {
76 for (n = 0; files[n] != 0; ++n) {
77 unlink(files[n]);
78 }
79 }
80}
81
82static int
83load_screen(char *filename)
84{
85 int result;
86
87 if (use_init) {
88 if ((result = scr_init(filename)) != ERR)
89 result = scr_restore(filename);
90 } else {
91 result = scr_set(filename);
92 }
93 return result;
94}
95
96/*
97 * scr_restore() or scr_set() operates on curscr. If we read a character using
98 * getch() that will refresh stdscr, wiping out the result. To avoid that,
99 * copy the data back from curscr to stdscr.
100 */
101static void
102after_load(void)
103{
104 overwrite(curscr, stdscr);
105 doupdate();
106}
107
108static void
109show_what(int which, int last)
110{
111 int y, x, n;
112 time_t now;
113 char *mytime;
114
115 getyx(stdscr, y, x);
116
117 move(0, 0);
118 printw("Saved %d of %d (? for help)", which, last + 1);
119
120 now = time((time_t *) 0);
121 mytime = ctime(&now);
122 for (n = (int) strlen(mytime) - 1; n >= 0; --n) {
123 if (isspace(UChar(mytime[n]))) {
124 mytime[n] = '\0';
125 } else {
126 break;
127 }
128 }
129 mvprintw(0, (COLS - n - 2), " %s", mytime);
130
131 move(y, x);
132
133 refresh();
134}
135
136static int
137get_command(int which, int last)
138{
139 int ch;
140
141 timeout(50);
142
143 do {
144 show_what(which, last);
145 ch = getch();
146 } while (ch == ERR);
147
148 return ch;
149}
150
151static void
152show_help(const char **help)
153{
154 WINDOW *mywin = newwin(LINES, COLS, 0, 0);
155 int n;
156
157 box(mywin, 0, 0);
158 wmove(mywin, 1, 1);
159 for (n = 0; help[n] != 0; ++n) {
160 wmove(mywin, 1 + n, 2);
161 wprintw(mywin, "%.*s", COLS - 4, help[n]);
162 }
163 wgetch(mywin);
164 delwin(mywin);
165 touchwin(stdscr);
166 refresh();
167}
168
169static void
170editor_help(void)
171{
172 static const char *msgs[] =
173 {
174 "You are now in the screen-editor, which allows you to make some",
175 "lines on the screen, as well as save copies of the screen to a",
176 "temporary file",
177 "",
178 "Keys:",
179 " q quit",
180 " n run the screen-loader to show the saved screens",
181 " <space> dump a screen",
182 "",
183 " a toggle between '#' and graphic symbol for drawing",
184 " c change color drawn by line to next in palette",
185 " h,j,k,l or arrows to move around the screen, drawing",
186 };
187 show_help(msgs);
188}
189
190static void
191replay_help(void)
192{
193 static const char *msgs[] =
194 {
195 "You are now in the screen-loader, which allows you to view",
196 "the dumped/restored screens.",
197 "",
198 "Keys:",
199 " q quit",
200 " <space> load the next screen",
201 " <backspace> load the previous screen",
202 };
203 show_help(msgs);
204}
205
206static void
207usage(void)
208{
209 static const char *msg[] =
210 {
211 "Usage: savescreen [-r] files",
212 "",
213 "Options:",
214 " -f file fill/initialize screen using text from this file",
215 " -i use scr_init/scr_restore rather than scr_set",
216 " -k keep the restored dump-files rather than removing them",
217 " -r replay the screen-dump files"
218 };
219 unsigned n;
220 for (n = 0; n < SIZEOF(msg); ++n) {
221 fprintf(stderr, "%s\n", msg[n]);
222 }
223 ExitProgram(EXIT_FAILURE);
224}
225
226int
227main(int argc, char *argv[])
228{
229 int ch;
230 int which = 0;
231 int last;
232 bool replaying = FALSE;
233 bool done = FALSE;
234 char **files;
235 char *fill_by = 0;
236#if USE_WIDEC_SUPPORT
237 cchar_t mycc;
238 int myxx;
239#endif
240
241 setlocale(LC_ALL, "");
242
243 while ((ch = getopt(argc, argv, "f:ikr")) != -1) {
244 switch (ch) {
245 case 'f':
246 fill_by = optarg;
247 break;
248 case 'i':
249 use_init = TRUE;
250 break;
251 case 'k':
252 keep_dumps = TRUE;
253 break;
254 case 'r':
255 replaying = TRUE;
256 break;
257 default:
258 usage();
259 break;
260 }
261 }
262
263 files = argv + optind;
264 last = argc - optind - 1;
265
266 if (replaying) {
267 while (last >= 0 && !fexists(files[last]))
268 --last;
269 }
270
271 initscr();
272 cbreak();
273 noecho();
274 keypad(stdscr, TRUE);
275 curs_set(0);
276 if (has_colors()) {
277 short pair;
278 short color;
279
280 start_color();
281 /*
282 * Assume pairs is the square of colors, and assign pairs going down
283 * so that there is minimal conflict with the background color (which
284 * counts up). The intent is just to show how color pair values are
285 * saved and restored.
286 */
287 for (pair = 0; pair < COLOR_PAIRS; ++pair) {
288 color = (short) (pair % (COLORS - 1));
289 init_pair(pair, (short) (COLOR_WHITE - color), color);
290 }
291 }
292
293 if (fill_by != 0) {
294 FILE *fp = fopen(fill_by, "r");
295 if (fp != 0) {
296 bool filled = FALSE;
297 move(1, 0);
298 while ((ch = fgetc(fp)) != EOF) {
299 if (addch(UChar(ch)) == ERR) {
300 filled = TRUE;
301 break;
302 }
303 }
304 fclose(fp);
305 if (!filled) {
306 while (addch(' ') != ERR) {
307 ;
308 }
309 }
310 move(0, 0);
311 } else {
312 endwin();
313 fprintf(stderr, "Cannot open \"%s\"\n", fill_by);
314 ExitProgram(EXIT_FAILURE);
315 }
316 }
317
318 if (replaying) {
319
320 /*
321 * Use the last file as the initial/current screen.
322 */
323 if (last < 0) {
324 endwin();
325 printf("No screen-dumps given\n");
326 ExitProgram(EXIT_FAILURE);
327 }
328
329 which = last;
330 if (load_screen(files[which]) == ERR) {
331 endwin();
332 printf("Cannot load screen-dump %s\n", files[which]);
333 ExitProgram(EXIT_FAILURE);
334 }
335 after_load();
336
337 while (!done && (ch = getch()) != ERR) {
338 switch (ch) {
339 case 'n':
340 /*
341 * If we got a "next" here, skip to the final screen before
342 * moving to the next process.
343 */
344 setup_next();
345 which = last;
346 done = TRUE;
347 break;
348 case 'q':
349 cleanup(files);
350 done = TRUE;
351 break;
352 case KEY_BACKSPACE:
353 case '\b':
354 if (--which < 0)
355 which = last;
356 break;
357 case ' ':
358 if (++which > last)
359 which = 0;
360 break;
361 case '?':
362 replay_help();
363 break;
364 default:
365 beep();
366 continue;
367 }
368
369 if (ch == 'q') {
370 ;
371 } else if (scr_restore(files[which]) == ERR) {
372 endwin();
373 printf("Cannot load screen-dump %s\n", files[which]);
374 cleanup(files);
375 ExitProgram(EXIT_FAILURE);
376 } else {
377 wrefresh(curscr);
378 }
379 }
380 endwin();
381 } else {
382 int y = 0;
383 int x = 0;
384 int color = 0;
385 int altchars = 0;
386
387 while (!done) {
388 switch (get_command(which, last)) {
389 case 'n':
390 setup_next();
391 done = TRUE;
392 break;
393 case 'q':
394 cleanup(files);
395 done = TRUE;
396 break;
397 case ' ':
398 if (files[which] != 0) {
399 show_what(which + 1, last);
400 if (scr_dump(files[which]) == ERR) {
401 endwin();
402 printf("Cannot write screen-dump %s\n", files[which]);
403 cleanup(files);
404 done = TRUE;
405 break;
406 }
407 ++which;
408 if (has_colors()) {
409 int cx, cy;
410 short pair = (short) (which % COLOR_PAIRS);
411 /*
412 * Change the background color, to make it more
413 * obvious. But that changes the existing text-color.
414 * Copy the old values from the currently displayed
415 * screen.
416 */
417 bkgd((chtype) COLOR_PAIR(pair));
418 for (cy = 1; cy < LINES; ++cy) {
419 for (cx = 0; cx < COLS; ++cx) {
420 wmove(curscr, cy, cx);
421 wmove(stdscr, cy, cx);
422#if USE_WIDEC_SUPPORT
423 if (win_wch(curscr, &mycc) != ERR) {
424 myxx = wcwidth(mycc.chars[0]);
425 if (myxx > 0) {
426 wadd_wchnstr(stdscr, &mycc, 1);
427 cx += (myxx - 1);
428 }
429 }
430#else
431 waddch(stdscr, winch(curscr));
432#endif
433 }
434 }
435 }
436 } else {
437 beep();
438 }
439 break;
440 case KEY_LEFT:
441 case 'h':
442 if (--x < 0)
443 x = COLS - 1;
444 break;
445 case KEY_DOWN:
446 case 'j':
447 if (++y >= LINES)
448 y = 1;
449 break;
450 case KEY_UP:
451 case 'k':
452 if (--y < 1)
453 y = LINES - 1;
454 break;
455 case KEY_RIGHT:
456 case 'l':
457 if (++x >= COLS)
458 x = 0;
459 break;
460 case 'a':
461 altchars = !altchars;
462 break;
463 case 'c':
464 color = (color + 1) % COLORS;
465 break;
466 case '?':
467 editor_help();
468 break;
469 default:
470 beep();
471 continue;
472 }
473 if (!done) {
474 attr_t attr = (A_REVERSE | COLOR_PAIR(color * COLORS));
475 chtype ch2 = (altchars ? ACS_DIAMOND : '#');
476 move(y, x);
477 addch(ch2 | attr);
478 move(y, x);
479 }
480 }
481 endwin();
482 }
483 ExitProgram(EXIT_SUCCESS);
484}
485
486#else
487int
488main(int argc, char *argv[])
489{
490 printf("This program requires the screen-dump functions\n");
491 ExitProgram(EXIT_FAILURE);
492}
493#endif