ncurses 6.1 - patch 20190330
[ncurses.git] / test / newdemo.c
1 /*
2  *  newdemo.c   -       A demo program using PDCurses. The program illustrate
3  *                      the use of colours for text output.
4  *
5  * $Id: newdemo.c,v 1.45 2017/09/30 15:43:08 tom Exp $
6  */
7
8 #include <test.priv.h>
9
10 #include <time.h>
11
12 /*
13  *  The Australian map
14  */
15 static CONST_MENUS char *AusMap[16] =
16 {
17     "           A           A ",
18     "    N.T. AAAAA       AAAA ",
19     "     AAAAAAAAAAA  AAAAAAAA ",
20     "   AAAAAAAAAAAAAAAAAAAAAAAAA Qld.",
21     "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
22     "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
23     " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
24     "   AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.",
25     "W.A. AAAAAAAAA      AAAAAA Vic.",
26     "       AAA   S.A.     AA",
27     "                       A  Tas.",
28     ""
29 };
30
31 /*
32  *  Funny messages
33  */
34 #define NMESSAGES   6
35
36 static const char *messages[] =
37 {
38     "Hello from the Land Down Under",
39     "The Land of crocs. and a big Red Rock",
40     "Where the sunflower runs along the highways",
41     "the dusty red roads lead one to loneliness",
42     "Blue sky in the morning and",
43     "freezing nights and twinkling stars",
44     ""
45 };
46
47 /*
48  *  Trap interrupt
49  */
50 static void
51 trap(int sig GCC_UNUSED)
52 {
53     exit_curses();
54     ExitProgram(EXIT_FAILURE);
55 }
56
57 /*
58  *  Wait for user
59  */
60 static int
61 WaitForUser(WINDOW *win)
62 {
63     time_t t;
64     chtype key;
65
66     nodelay(win, TRUE);
67     t = time((time_t *) 0);
68     while (1) {
69         if ((int) (key = (chtype) wgetch(win)) != ERR) {
70             if (key == 'q' || key == 'Q')
71                 return 1;
72             else
73                 return 0;
74         }
75         if (time((time_t *) 0) - t > 5)
76             return 0;
77     }
78 }
79
80 static void
81 set_colors(WINDOW *win, int pair, int foreground, int background)
82 {
83     if (has_colors()) {
84         if (pair > COLOR_PAIRS)
85             pair = COLOR_PAIRS;
86         init_pair((short) pair, (short) foreground, (short) background);
87         (void) wattrset(win, AttrArg(COLOR_PAIR(pair), 0));
88     }
89 }
90
91 static chtype
92 use_colors(WINDOW *win, int pair, chtype attrs)
93 {
94     if (has_colors()) {
95         if (pair > COLOR_PAIRS)
96             pair = COLOR_PAIRS;
97         attrs |= (chtype) COLOR_PAIR(pair);
98     }
99     (void) wattrset(win, AttrArg(attrs, 0));
100     return attrs;
101 }
102
103 /*
104  * Test sub windows
105  */
106 static int
107 SubWinTest(WINDOW *win)
108 {
109     int w, h, sw, sh, bx, by;
110     WINDOW *swin1, *swin2, *swin3;
111
112     getmaxyx(win, h, w);
113     getbegyx(win, by, bx);
114     sw = w / 3;
115     sh = h / 3;
116
117     if ((swin1 = subwin(win, sh, sw, by + 3, bx + 5)) == NULL) {
118         return 1;
119     }
120     if ((swin2 = subwin(win, sh, sw, by + 4, bx + 8)) == NULL) {
121         delwin(swin1);
122         return 1;
123     }
124     if ((swin3 = subwin(win, sh, sw, by + 5, bx + 11)) == NULL) {
125         delwin(swin1);
126         delwin(swin2);
127         return 1;
128     }
129
130     set_colors(swin1, 8, COLOR_RED, COLOR_BLUE);
131     werase(swin1);
132     MvWAddStr(swin1, 0, 3, "Sub-window 1");
133     wrefresh(swin1);
134
135     set_colors(swin2, 9, COLOR_CYAN, COLOR_MAGENTA);
136     werase(swin2);
137     MvWAddStr(swin2, 0, 3, "Sub-window 2");
138     wrefresh(swin2);
139
140     set_colors(swin3, 10, COLOR_YELLOW, COLOR_GREEN);
141     werase(swin3);
142     MvWAddStr(swin3, 0, 3, "Sub-window 3");
143     wrefresh(swin3);
144
145     delwin(swin1);
146     delwin(swin2);
147     delwin(swin3);
148     WaitForUser(win);
149     return 0;
150 }
151
152 static int
153 bounce(int n, int *dir, int len)
154 {
155     if (*dir > 0)
156         ++n;
157     else
158         --n;
159     if (n <= 1 || n >= len - 2)
160         *dir = *dir ? 0 : 1;
161     return n;
162 }
163
164 /*
165  *  Bouncing balls
166  */
167 static int
168 BouncingBalls(WINDOW *win)
169 {
170     int w, h;
171     int x1, y1, xd1, yd1;
172     int x2, y2, xd2, yd2;
173     int x3, y3, xd3, yd3;
174
175     getmaxyx(win, h, w);
176
177     x1 = 2 + rand() % (w - 4);
178     y1 = 2 + rand() % (h - 4);
179     x2 = 2 + rand() % (w - 4);
180     y2 = 2 + rand() % (h - 4);
181     x3 = 2 + rand() % (w - 4);
182     y3 = 2 + rand() % (h - 4);
183
184     xd1 = 1;
185     yd1 = 1;
186     xd2 = 1;
187     yd2 = 0;
188     xd3 = 0;
189     yd3 = 1;
190
191     nodelay(win, TRUE);
192
193     while (wgetch(win) == ERR) {
194         x1 = bounce(x1, &xd1, w);
195         y1 = bounce(y1, &yd1, h);
196         x2 = bounce(x2, &xd2, w);
197         y2 = bounce(y2, &yd2, h);
198         x3 = bounce(x3, &xd3, w);
199         y3 = bounce(y3, &yd3, h);
200
201         set_colors(win, 11, COLOR_RED, COLOR_BLUE);
202         MvWAddCh(win, y1, x1, 'O');
203
204         set_colors(win, 12, COLOR_BLUE, COLOR_RED);
205         MvWAddCh(win, y2, x2, '*');
206
207         set_colors(win, 13, COLOR_YELLOW, COLOR_WHITE);
208         MvWAddCh(win, y3, x3, '@');
209
210         wmove(win, 0, 0);
211         wrefresh(win);
212         delay_output(100);
213     }
214     return 0;
215 }
216
217 /*
218  *  Main driver
219  */
220 int
221 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
222 {
223     WINDOW *win;
224     int w, x, y, i, j, k;
225     char buffer[SIZEOF(messages) * 80];
226     const char *message;
227     int width, height;
228     chtype save[80];
229     chtype c;
230
231     setlocale(LC_ALL, "");
232
233     InitAndCatch(initscr(), trap);
234     if (has_colors())
235         start_color();
236     cbreak();
237     curs_set(0);
238     width = 48;
239     height = 14;                /* Create a drawing window */
240     win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
241     if (win == NULL) {
242         exit_curses();
243         ExitProgram(EXIT_FAILURE);
244     }
245
246     while (1) {
247         set_colors(win, 1, COLOR_WHITE, COLOR_BLUE);
248         werase(win);
249
250         set_colors(win, 2, COLOR_RED, COLOR_RED);
251         box(win, ACS_VLINE, ACS_HLINE);
252         wrefresh(win);
253         /* Do ramdom output of a character */
254         use_colors(win, 1, A_NORMAL);
255         c = 'a';
256         for (i = 0; i < 5000; ++i) {
257             x = rand() % (width - 2) + 1;
258             y = rand() % (height - 2) + 1;
259             MvWAddCh(win, y, x, c);
260             wrefresh(win);
261             nodelay(win, TRUE);
262             if (wgetch(win) != ERR)
263                 break;
264             if (i == 2000) {
265                 c = 'b';
266                 set_colors(win, 3, COLOR_CYAN, COLOR_YELLOW);
267             }
268         }
269
270         SubWinTest(win);
271         /* Erase and draw green window */
272         set_colors(win, 4, COLOR_YELLOW, COLOR_GREEN);
273         wbkgd(win, use_colors(win, 4, A_BOLD));
274         werase(win);
275         wrefresh(win);
276         /* Draw RED bounding box */
277         use_colors(win, 2, A_NORMAL);
278         box(win, ' ', ' ');
279         wrefresh(win);
280         /* Display Australia map */
281         use_colors(win, 4, A_BOLD);
282         i = 0;
283         while (*AusMap[i]) {
284             MvWAddStr(win, i + 1, 8, AusMap[i]);
285             wrefresh(win);
286             delay_output(50);
287             ++i;
288         }
289
290         set_colors(win, 5, COLOR_BLUE, COLOR_WHITE);
291         use_colors(win, 5, A_BLINK);
292         MvWAddStr(win, height - 2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
293         wrefresh(win);
294
295         /* Draw running messages */
296         set_colors(win, 6, COLOR_YELLOW, COLOR_WHITE);
297         message = messages[j = 0];
298         i = 1;
299         w = width - 2;
300         _nc_STRCPY(buffer, message, sizeof(buffer));
301         while (j < NMESSAGES) {
302             while ((int) strlen(buffer) < w) {
303                 _nc_STRCAT(buffer, " ... ", sizeof(buffer));
304                 _nc_STRCAT(buffer, messages[++j % NMESSAGES], sizeof(buffer));
305             }
306
307             if (i < w)
308                 (void) mvwaddnstr(win, height / 2, w - i, buffer, i);
309             else
310                 (void) mvwaddnstr(win, height / 2, 1, buffer, w);
311
312             wrefresh(win);
313             nodelay(win, TRUE);
314             if (wgetch(win) != ERR) {
315                 flushinp();
316                 break;
317             }
318             if (i++ >= w) {
319                 for (k = 0; (buffer[k] = buffer[k + 1]) != '\0'; k++) ;
320             }
321             delay_output(100);
322         }
323
324         j = 0;
325         /*  Draw running As across in RED */
326         set_colors(win, 7, COLOR_RED, COLOR_GREEN);
327         memset(save, ' ', sizeof(save));
328         for (i = 2; i < width - 4; ++i) {
329             k = (int) mvwinch(win, 4, i);
330             if (k == ERR)
331                 break;
332             save[j++] = c = (chtype) k;
333             c &= A_CHARTEXT;
334             MvWAddCh(win, 4, i, c);
335         }
336         wrefresh(win);
337
338         /* Put a message up wait for a key */
339         i = height - 2;
340         use_colors(win, 5, A_NORMAL);
341         MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
342         wrefresh(win);
343
344         if (WaitForUser(win) == 1)
345             break;
346
347         j = 0;                  /* Restore the old line */
348         for (i = 2; i < width - 4; ++i)
349             MvWAddCh(win, 4, i, save[j++]);
350         wrefresh(win);
351
352         BouncingBalls(win);
353         /* Put a message up wait for a key */
354         i = height - 2;
355         use_colors(win, 5, A_NORMAL);
356         MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
357         wrefresh(win);
358         if (WaitForUser(win) == 1)
359             break;
360     }
361     exit_curses();
362     ExitProgram(EXIT_SUCCESS);
363 }