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.48 2022/12/10 23:36:05 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
trap(int sig GCC_UNUSED)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
WaitForUser(WINDOW * win)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
set_colors(WINDOW * win,int pair,int foreground,int background)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
use_colors(WINDOW * win,int pair,chtype attrs)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
SubWinTest(WINDOW * win)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
bounce(int n,int * dir,int len)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
BouncingBalls(WINDOW * win)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 static void
usage(int ok)219 usage(int ok)
220 {
221 static const char *msg[] =
222 {
223 "Usage: newdemo [options]"
224 ,""
225 ,USAGE_COMMON
226 };
227 size_t n;
228
229 for (n = 0; n < SIZEOF(msg); n++)
230 fprintf(stderr, "%s\n", msg[n]);
231
232 ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
233 }
234 /* *INDENT-OFF* */
VERSION_COMMON()235 VERSION_COMMON()
236 /* *INDENT-ON* */
237
238 /*
239 * Main driver
240 */
241 int
242 main(int argc, char *argv[])
243 {
244 WINDOW *win;
245 int x, y, i, k;
246 char buffer[SIZEOF(messages) * 80];
247 int width, height;
248 chtype save[80];
249 int ch;
250
251 while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) {
252 switch (ch) {
253 case OPTS_VERSION:
254 show_version(argv);
255 ExitProgram(EXIT_SUCCESS);
256 default:
257 usage(ch == OPTS_USAGE);
258 /* NOTREACHED */
259 }
260 }
261 if (optind < argc)
262 usage(FALSE);
263
264 setlocale(LC_ALL, "");
265
266 InitAndCatch(initscr(), trap);
267 if (has_colors())
268 start_color();
269 cbreak();
270 curs_set(0);
271 width = 48;
272 height = 14; /* Create a drawing window */
273 win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
274 if (win == NULL) {
275 stop_curses();
276 ExitProgram(EXIT_FAILURE);
277 }
278
279 while (1) {
280 int w;
281 int j;
282 chtype c;
283 const char *message;
284
285 set_colors(win, 1, COLOR_WHITE, COLOR_BLUE);
286 werase(win);
287
288 set_colors(win, 2, COLOR_RED, COLOR_RED);
289 box(win, ACS_VLINE, ACS_HLINE);
290 wrefresh(win);
291 /* Do ramdom output of a character */
292 use_colors(win, 1, A_NORMAL);
293 c = 'a';
294 for (i = 0; i < 5000; ++i) {
295 x = rand() % (width - 2) + 1;
296 y = rand() % (height - 2) + 1;
297 MvWAddCh(win, y, x, c);
298 wrefresh(win);
299 nodelay(win, TRUE);
300 if (wgetch(win) != ERR)
301 break;
302 if (i == 2000) {
303 c = 'b';
304 set_colors(win, 3, COLOR_CYAN, COLOR_YELLOW);
305 }
306 }
307
308 SubWinTest(win);
309 /* Erase and draw green window */
310 set_colors(win, 4, COLOR_YELLOW, COLOR_GREEN);
311 wbkgd(win, use_colors(win, 4, A_BOLD));
312 werase(win);
313 wrefresh(win);
314 /* Draw RED bounding box */
315 use_colors(win, 2, A_NORMAL);
316 box(win, ' ', ' ');
317 wrefresh(win);
318 /* Display Australia map */
319 use_colors(win, 4, A_BOLD);
320 i = 0;
321 while (*AusMap[i]) {
322 MvWAddStr(win, i + 1, 8, AusMap[i]);
323 wrefresh(win);
324 delay_output(50);
325 ++i;
326 }
327
328 set_colors(win, 5, COLOR_BLUE, COLOR_WHITE);
329 use_colors(win, 5, A_BLINK);
330 MvWAddStr(win, height - 2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
331 wrefresh(win);
332
333 /* Draw running messages */
334 set_colors(win, 6, COLOR_YELLOW, COLOR_WHITE);
335 message = messages[j = 0];
336 i = 1;
337 w = width - 2;
338 _nc_STRCPY(buffer, message, sizeof(buffer));
339 while (j < NMESSAGES) {
340 while ((int) strlen(buffer) < w) {
341 _nc_STRCAT(buffer, " ... ", sizeof(buffer));
342 _nc_STRCAT(buffer, messages[++j % NMESSAGES], sizeof(buffer));
343 }
344
345 if (i < w)
346 (void) mvwaddnstr(win, height / 2, w - i, buffer, i);
347 else
348 (void) mvwaddnstr(win, height / 2, 1, buffer, w);
349
350 wrefresh(win);
351 nodelay(win, TRUE);
352 if (wgetch(win) != ERR) {
353 flushinp();
354 break;
355 }
356 if (i++ >= w) {
357 for (k = 0; (buffer[k] = buffer[k + 1]) != '\0'; k++) ;
358 }
359 delay_output(100);
360 }
361
362 j = 0;
363 /* Draw running As across in RED */
364 set_colors(win, 7, COLOR_RED, COLOR_GREEN);
365 memset(save, ' ', sizeof(save));
366 for (i = 2; i < width - 4; ++i) {
367 k = (int) mvwinch(win, 4, i);
368 if (k == ERR)
369 break;
370 save[j++] = c = (chtype) k;
371 c &= A_CHARTEXT;
372 MvWAddCh(win, 4, i, c);
373 }
374 wrefresh(win);
375
376 /* Put a message up wait for a key */
377 i = height - 2;
378 use_colors(win, 5, A_NORMAL);
379 MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
380 wrefresh(win);
381
382 if (WaitForUser(win) == 1)
383 break;
384
385 j = 0; /* Restore the old line */
386 for (i = 2; i < width - 4; ++i)
387 MvWAddCh(win, 4, i, save[j++]);
388 wrefresh(win);
389
390 BouncingBalls(win);
391 /* Put a message up wait for a key */
392 i = height - 2;
393 use_colors(win, 5, A_NORMAL);
394 MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
395 wrefresh(win);
396 if (WaitForUser(win) == 1)
397 break;
398 }
399 stop_curses();
400 ExitProgram(EXIT_SUCCESS);
401 }
402