ncurses 5.7 - patch 20110115
[ncurses.git] / test / savescreen.c
1 /****************************************************************************
2  * Copyright (c) 2007-2010,2011 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.15 2011/01/15 18:15:11 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
53 static bool use_init = FALSE;
54
55 static int
56 fexists(const char *name)
57 {
58     struct stat sb;
59     return (stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFREG);
60 }
61
62 static void
63 setup_next(void)
64 {
65     curs_set(1);
66     reset_shell_mode();
67 }
68
69 static void
70 cleanup(char *files[])
71 {
72     int n;
73
74     for (n = 0; files[n] != 0; ++n) {
75         unlink(files[n]);
76     }
77 }
78
79 static int
80 load_screen(char *filename)
81 {
82     int result;
83
84     if (use_init) {
85         if ((result = scr_init(filename)) != ERR)
86             result = scr_restore(filename);
87     } else {
88         result = scr_set(filename);
89     }
90     return result;
91 }
92
93 /*
94  * scr_restore() or scr_set() operates on curscr.  If we read a character using
95  * getch() that will refresh stdscr, wiping out the result.  To avoid that,
96  * copy the data back from curscr to stdscr.
97  */
98 static void
99 after_load(void)
100 {
101     overwrite(curscr, stdscr);
102     doupdate();
103 }
104
105 static void
106 show_what(int which, int last)
107 {
108     int y, x;
109     time_t now = time((time_t *) 0);
110
111     getyx(stdscr, y, x);
112
113     move(0, 0);
114     printw("Saved %d of %d - %s", which, last + 1, ctime(&now));
115
116     move(y, x);
117
118     refresh();
119 }
120
121 static int
122 get_command(int which, int last)
123 {
124     int ch;
125
126     timeout(100);
127
128     do {
129         show_what(which, last);
130         ch = getch();
131     } while (ch == ERR);
132
133     return ch;
134 }
135
136 static void
137 usage(void)
138 {
139     static const char *msg[] =
140     {
141         "Usage: savescreen [-r] files",
142         "",
143         "Options:",
144         " -i  use scr_init/scr_restore rather than scr_set",
145         " -r  replay the screen-dump files"
146     };
147     unsigned n;
148     for (n = 0; n < SIZEOF(msg); ++n) {
149         fprintf(stderr, "%s\n", msg[n]);
150     }
151     ExitProgram(EXIT_FAILURE);
152 }
153
154 int
155 main(int argc, char *argv[])
156 {
157     int ch;
158     int which = 0;
159     int last;
160     bool replaying = FALSE;
161     bool done = FALSE;
162     char **files;
163
164     while ((ch = getopt(argc, argv, "ir")) != -1) {
165         switch (ch) {
166         case 'i':
167             use_init = TRUE;
168             break;
169         case 'r':
170             replaying = TRUE;
171             break;
172         default:
173             usage();
174             break;
175         }
176     }
177
178     files = argv + optind;
179     last = argc - optind - 1;
180
181     if (replaying) {
182         while (last >= 0 && !fexists(files[last]))
183             --last;
184     }
185
186     initscr();
187     cbreak();
188     noecho();
189     keypad(stdscr, TRUE);
190     curs_set(0);
191     if (has_colors()) {
192         start_color();
193         for (ch = 0; ch < COLOR_PAIRS; ++ch) {
194             short pair = (short) (ch % COLOR_PAIRS);
195             init_pair(pair, COLOR_WHITE, (short) (ch % COLORS));
196         }
197     }
198
199     if (replaying) {
200
201         /*
202          * Use the last file as the initial/current screen.
203          */
204         if (last < 0) {
205             endwin();
206             printf("No screen-dumps given\n");
207             ExitProgram(EXIT_FAILURE);
208         }
209
210         which = last;
211         if (load_screen(files[which]) == ERR) {
212             endwin();
213             printf("Cannot load screen-dump %s\n", files[which]);
214             ExitProgram(EXIT_FAILURE);
215         }
216         after_load();
217
218         while (!done && (ch = getch()) != ERR) {
219             switch (ch) {
220             case 'n':
221                 /*
222                  * If we got a "next" here, skip to the final screen before
223                  * moving to the next process.
224                  */
225                 setup_next();
226                 which = last;
227                 done = TRUE;
228                 break;
229             case 'q':
230                 endwin();
231                 cleanup(files);
232                 done = TRUE;
233                 break;
234             case KEY_BACKSPACE:
235             case '\b':
236                 if (--which < 0)
237                     which = last;
238                 break;
239             case ' ':
240                 if (++which > last)
241                     which = 0;
242                 break;
243             default:
244                 beep();
245                 continue;
246             }
247
248             if (ch == 'q') {
249                 ;
250             } else if (scr_restore(files[which]) == ERR) {
251                 endwin();
252                 printf("Cannot load screen-dump %s\n", files[which]);
253                 cleanup(files);
254                 ExitProgram(EXIT_FAILURE);
255             } else {
256                 wrefresh(curscr);
257             }
258         }
259     } else {
260         int y;
261         int x;
262
263         move(2, 0);
264         printw("Use h,j,k,l or arrows to move around the screen\n");
265         printw("Press 'q' to quit, ' ' to dump a screen\n");
266         printw("When the last screen has been dumped, press 'n' to run the\n");
267         printw("screen-loader.  That allows only 'q', backspace and ' ' for\n");
268         printw("stepping through the dumped/restored screens.\n");
269         getyx(stdscr, y, x);
270
271         while (!done) {
272             switch (get_command(which, last)) {
273             case 'n':
274                 setup_next();
275                 done = TRUE;
276                 break;
277             case 'q':
278                 endwin();
279                 cleanup(files);
280                 done = TRUE;
281                 break;
282             case ' ':
283                 if (files[which] != 0) {
284                     show_what(which + 1, last);
285                     if (scr_dump(files[which]) == ERR) {
286                         endwin();
287                         printf("Cannot write screen-dump %s\n", files[which]);
288                         cleanup(files);
289                         done = TRUE;
290                         break;
291                     }
292                     ++which;
293                     if (has_colors()) {
294                         short pair = (short) (which % COLOR_PAIRS);
295                         bkgd((chtype) COLOR_PAIR(pair));
296                     }
297                 } else {
298                     beep();
299                 }
300                 break;
301             case KEY_LEFT:
302             case 'h':
303                 if (--x < 0)
304                     x = COLS - 1;
305                 break;
306             case KEY_DOWN:
307             case 'j':
308                 if (++y >= LINES)
309                     y = 1;
310                 break;
311             case KEY_UP:
312             case 'k':
313                 if (--y < 1)
314                     y = LINES - 1;
315                 break;
316             case KEY_RIGHT:
317             case 'l':
318                 if (++x >= COLS)
319                     x = 0;
320                 break;
321             }
322             if (!done) {
323                 time_t now = time((time_t *) 0);
324
325                 move(0, 0);
326                 addstr(ctime(&now));
327                 move(y, x);
328                 addch('#' | A_REVERSE);
329                 move(y, x);
330             }
331         }
332     }
333     ExitProgram(EXIT_SUCCESS);
334 }
335 #else
336 int
337 main(int argc, char *argv[])
338 {
339     printf("This program requires the screen-dump functions\n");
340     ExitProgram(EXIT_FAILURE);
341 }
342 #endif