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