ncurses 6.1 - patch 20191214
[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.47 2019/12/14 23:25:29 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     stop_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
65     nodelay(win, TRUE);
66     t = time((time_t *) 0);
67
68     while (1) {
69         chtype key;
70         if ((int) (key = (chtype) wgetch(win)) != ERR) {
71             if (key == 'q' || key == 'Q')
72                 return 1;
73             else
74                 return 0;
75         }
76         if (time((time_t *) 0) - t > 5)
77             return 0;
78     }
79 }
80
81 static void
82 set_colors(WINDOW *win, int pair, int foreground, int background)
83 {
84     if (has_colors()) {
85         if (pair > COLOR_PAIRS)
86             pair = COLOR_PAIRS;
87         init_pair((short) pair, (short) foreground, (short) background);
88         (void) wattrset(win, AttrArg(COLOR_PAIR(pair), 0));
89     }
90 }
91
92 static chtype
93 use_colors(WINDOW *win, int pair, chtype attrs)
94 {
95     if (has_colors()) {
96         if (pair > COLOR_PAIRS)
97             pair = COLOR_PAIRS;
98         attrs |= (chtype) COLOR_PAIR(pair);
99     }
100     (void) wattrset(win, AttrArg(attrs, 0));
101     return attrs;
102 }
103
104 /*
105  * Test sub windows
106  */
107 static int
108 SubWinTest(WINDOW *win)
109 {
110     int w, h, sw, sh, bx, by;
111     WINDOW *swin1, *swin2, *swin3;
112
113     getmaxyx(win, h, w);
114     getbegyx(win, by, bx);
115     sw = w / 3;
116     sh = h / 3;
117
118     if ((swin1 = subwin(win, sh, sw, by + 3, bx + 5)) == NULL) {
119         return 1;
120     }
121     if ((swin2 = subwin(win, sh, sw, by + 4, bx + 8)) == NULL) {
122         delwin(swin1);
123         return 1;
124     }
125     if ((swin3 = subwin(win, sh, sw, by + 5, bx + 11)) == NULL) {
126         delwin(swin1);
127         delwin(swin2);
128         return 1;
129     }
130
131     set_colors(swin1, 8, COLOR_RED, COLOR_BLUE);
132     werase(swin1);
133     MvWAddStr(swin1, 0, 3, "Sub-window 1");
134     wrefresh(swin1);
135
136     set_colors(swin2, 9, COLOR_CYAN, COLOR_MAGENTA);
137     werase(swin2);
138     MvWAddStr(swin2, 0, 3, "Sub-window 2");
139     wrefresh(swin2);
140
141     set_colors(swin3, 10, COLOR_YELLOW, COLOR_GREEN);
142     werase(swin3);
143     MvWAddStr(swin3, 0, 3, "Sub-window 3");
144     wrefresh(swin3);
145
146     delwin(swin1);
147     delwin(swin2);
148     delwin(swin3);
149     WaitForUser(win);
150     return 0;
151 }
152
153 static int
154 bounce(int n, int *dir, int len)
155 {
156     if (*dir > 0)
157         ++n;
158     else
159         --n;
160     if (n <= 1 || n >= len - 2)
161         *dir = *dir ? 0 : 1;
162     return n;
163 }
164
165 /*
166  *  Bouncing balls
167  */
168 static int
169 BouncingBalls(WINDOW *win)
170 {
171     int w, h;
172     int x1, y1, xd1, yd1;
173     int x2, y2, xd2, yd2;
174     int x3, y3, xd3, yd3;
175
176     getmaxyx(win, h, w);
177
178     x1 = 2 + rand() % (w - 4);
179     y1 = 2 + rand() % (h - 4);
180     x2 = 2 + rand() % (w - 4);
181     y2 = 2 + rand() % (h - 4);
182     x3 = 2 + rand() % (w - 4);
183     y3 = 2 + rand() % (h - 4);
184
185     xd1 = 1;
186     yd1 = 1;
187     xd2 = 1;
188     yd2 = 0;
189     xd3 = 0;
190     yd3 = 1;
191
192     nodelay(win, TRUE);
193
194     while (wgetch(win) == ERR) {
195         x1 = bounce(x1, &xd1, w);
196         y1 = bounce(y1, &yd1, h);
197         x2 = bounce(x2, &xd2, w);
198         y2 = bounce(y2, &yd2, h);
199         x3 = bounce(x3, &xd3, w);
200         y3 = bounce(y3, &yd3, h);
201
202         set_colors(win, 11, COLOR_RED, COLOR_BLUE);
203         MvWAddCh(win, y1, x1, 'O');
204
205         set_colors(win, 12, COLOR_BLUE, COLOR_RED);
206         MvWAddCh(win, y2, x2, '*');
207
208         set_colors(win, 13, COLOR_YELLOW, COLOR_WHITE);
209         MvWAddCh(win, y3, x3, '@');
210
211         wmove(win, 0, 0);
212         wrefresh(win);
213         delay_output(100);
214     }
215     return 0;
216 }
217
218 /*
219  *  Main driver
220  */
221 int
222 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
223 {
224     WINDOW *win;
225     int x, y, i, k;
226     char buffer[SIZEOF(messages) * 80];
227     int width, height;
228     chtype save[80];
229
230     setlocale(LC_ALL, "");
231
232     InitAndCatch(initscr(), trap);
233     if (has_colors())
234         start_color();
235     cbreak();
236     curs_set(0);
237     width = 48;
238     height = 14;                /* Create a drawing window */
239     win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
240     if (win == NULL) {
241         stop_curses();
242         ExitProgram(EXIT_FAILURE);
243     }
244
245     while (1) {
246         int w;
247         int j;
248         chtype c;
249         const char *message;
250
251         set_colors(win, 1, COLOR_WHITE, COLOR_BLUE);
252         werase(win);
253
254         set_colors(win, 2, COLOR_RED, COLOR_RED);
255         box(win, ACS_VLINE, ACS_HLINE);
256         wrefresh(win);
257         /* Do ramdom output of a character */
258         use_colors(win, 1, A_NORMAL);
259         c = 'a';
260         for (i = 0; i < 5000; ++i) {
261             x = rand() % (width - 2) + 1;
262             y = rand() % (height - 2) + 1;
263             MvWAddCh(win, y, x, c);
264             wrefresh(win);
265             nodelay(win, TRUE);
266             if (wgetch(win) != ERR)
267                 break;
268             if (i == 2000) {
269                 c = 'b';
270                 set_colors(win, 3, COLOR_CYAN, COLOR_YELLOW);
271             }
272         }
273
274         SubWinTest(win);
275         /* Erase and draw green window */
276         set_colors(win, 4, COLOR_YELLOW, COLOR_GREEN);
277         wbkgd(win, use_colors(win, 4, A_BOLD));
278         werase(win);
279         wrefresh(win);
280         /* Draw RED bounding box */
281         use_colors(win, 2, A_NORMAL);
282         box(win, ' ', ' ');
283         wrefresh(win);
284         /* Display Australia map */
285         use_colors(win, 4, A_BOLD);
286         i = 0;
287         while (*AusMap[i]) {
288             MvWAddStr(win, i + 1, 8, AusMap[i]);
289             wrefresh(win);
290             delay_output(50);
291             ++i;
292         }
293
294         set_colors(win, 5, COLOR_BLUE, COLOR_WHITE);
295         use_colors(win, 5, A_BLINK);
296         MvWAddStr(win, height - 2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
297         wrefresh(win);
298
299         /* Draw running messages */
300         set_colors(win, 6, COLOR_YELLOW, COLOR_WHITE);
301         message = messages[j = 0];
302         i = 1;
303         w = width - 2;
304         _nc_STRCPY(buffer, message, sizeof(buffer));
305         while (j < NMESSAGES) {
306             while ((int) strlen(buffer) < w) {
307                 _nc_STRCAT(buffer, " ... ", sizeof(buffer));
308                 _nc_STRCAT(buffer, messages[++j % NMESSAGES], sizeof(buffer));
309             }
310
311             if (i < w)
312                 (void) mvwaddnstr(win, height / 2, w - i, buffer, i);
313             else
314                 (void) mvwaddnstr(win, height / 2, 1, buffer, w);
315
316             wrefresh(win);
317             nodelay(win, TRUE);
318             if (wgetch(win) != ERR) {
319                 flushinp();
320                 break;
321             }
322             if (i++ >= w) {
323                 for (k = 0; (buffer[k] = buffer[k + 1]) != '\0'; k++) ;
324             }
325             delay_output(100);
326         }
327
328         j = 0;
329         /*  Draw running As across in RED */
330         set_colors(win, 7, COLOR_RED, COLOR_GREEN);
331         memset(save, ' ', sizeof(save));
332         for (i = 2; i < width - 4; ++i) {
333             k = (int) mvwinch(win, 4, i);
334             if (k == ERR)
335                 break;
336             save[j++] = c = (chtype) k;
337             c &= A_CHARTEXT;
338             MvWAddCh(win, 4, i, c);
339         }
340         wrefresh(win);
341
342         /* Put a message up wait for a key */
343         i = height - 2;
344         use_colors(win, 5, A_NORMAL);
345         MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
346         wrefresh(win);
347
348         if (WaitForUser(win) == 1)
349             break;
350
351         j = 0;                  /* Restore the old line */
352         for (i = 2; i < width - 4; ++i)
353             MvWAddCh(win, 4, i, save[j++]);
354         wrefresh(win);
355
356         BouncingBalls(win);
357         /* Put a message up wait for a key */
358         i = height - 2;
359         use_colors(win, 5, A_NORMAL);
360         MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
361         wrefresh(win);
362         if (WaitForUser(win) == 1)
363             break;
364     }
365     stop_curses();
366     ExitProgram(EXIT_SUCCESS);
367 }