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