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.31 2008/08/03 20:19:38 tom Exp $
6 */
7
8#include <test.priv.h>
9
10#include <time.h>
11
12/*
13 *  The Australian map
14 */
15static 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
36static NCURSES_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 */
50static RETSIGTYPE
51trap(int sig GCC_UNUSED)
52{
53    endwin();
54    ExitProgram(EXIT_FAILURE);
55}
56
57/*
58 *  Wait for user
59 */
60static int
61WaitForUser(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 = 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
80static void
81set_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(pair, foreground, background);
87	wattrset(win, COLOR_PAIR(pair));
88    }
89}
90
91static chtype
92use_colors(WINDOW *win, int pair, chtype attrs)
93{
94    if (has_colors()) {
95	if (pair > COLOR_PAIRS)
96	    pair = COLOR_PAIRS;
97	attrs |= COLOR_PAIR(pair);
98    }
99    wattrset(win, attrs);
100    return attrs;
101}
102
103/*
104 * Test sub windows
105 */
106static int
107SubWinTest(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    if ((swin1 = subwin(win, sh, sw, by + 3, bx + 5)) == NULL)
117	return 1;
118    if ((swin2 = subwin(win, sh, sw, by + 4, bx + 8)) == NULL)
119	return 1;
120    if ((swin3 = subwin(win, sh, sw, by + 5, bx + 11)) == NULL)
121	return 1;
122
123    set_colors(swin1, 8, COLOR_RED, COLOR_BLUE);
124    werase(swin1);
125    mvwaddstr(swin1, 0, 3, "Sub-window 1");
126    wrefresh(swin1);
127
128    set_colors(swin2, 9, COLOR_CYAN, COLOR_MAGENTA);
129    werase(swin2);
130    mvwaddstr(swin2, 0, 3, "Sub-window 2");
131    wrefresh(swin2);
132
133    set_colors(swin3, 10, COLOR_YELLOW, COLOR_GREEN);
134    werase(swin3);
135    mvwaddstr(swin3, 0, 3, "Sub-window 3");
136    wrefresh(swin3);
137
138    delwin(swin1);
139    delwin(swin2);
140    delwin(swin3);
141    WaitForUser(win);
142    return 0;
143}
144
145static int
146bounce(int n, int *dir, int len)
147{
148    if (*dir > 0)
149	++n;
150    else
151	--n;
152    if (n <= 1 || n >= len - 2)
153	*dir = *dir ? 0 : 1;
154    return n;
155}
156
157/*
158 *  Bouncing balls
159 */
160static int
161BouncingBalls(WINDOW *win)
162{
163    int w, h;
164    int x1, y1, xd1, yd1;
165    int x2, y2, xd2, yd2;
166    int x3, y3, xd3, yd3;
167
168    getmaxyx(win, h, w);
169
170    x1 = 2 + rand() % (w - 4);
171    y1 = 2 + rand() % (h - 4);
172    x2 = 2 + rand() % (w - 4);
173    y2 = 2 + rand() % (h - 4);
174    x3 = 2 + rand() % (w - 4);
175    y3 = 2 + rand() % (h - 4);
176
177    xd1 = 1;
178    yd1 = 1;
179    xd2 = 1;
180    yd2 = 0;
181    xd3 = 0;
182    yd3 = 1;
183
184    nodelay(win, TRUE);
185
186    while (wgetch(win) == ERR) {
187	x1 = bounce(x1, &xd1, w);
188	y1 = bounce(y1, &yd1, h);
189	x2 = bounce(x2, &xd2, w);
190	y2 = bounce(y2, &yd2, h);
191	x3 = bounce(x3, &xd3, w);
192	y3 = bounce(y3, &yd3, h);
193
194	set_colors(win, 11, COLOR_RED, COLOR_BLUE);
195	mvwaddch(win, y1, x1, 'O');
196
197	set_colors(win, 12, COLOR_BLUE, COLOR_RED);
198	mvwaddch(win, y2, x2, '*');
199
200	set_colors(win, 13, COLOR_YELLOW, COLOR_WHITE);
201	mvwaddch(win, y3, x3, '@');
202
203	wmove(win, 0, 0);
204	wrefresh(win);
205	delay_output(100);
206    }
207    return 0;
208}
209
210/*
211 *  Main driver
212 */
213int
214main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
215{
216    WINDOW *win;
217    int w, x, y, i, j, k;
218    char buffer[200];
219    const char *message;
220    int width, height;
221    chtype save[80];
222    chtype c;
223
224    setlocale(LC_ALL, "");
225
226    CATCHALL(trap);
227
228    initscr();
229    if (has_colors())
230	start_color();
231    cbreak();
232    curs_set(0);
233    width = 48;
234    height = 14;		/* Create a drawing window */
235    win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
236    if (win == NULL) {
237	endwin();
238	ExitProgram(EXIT_FAILURE);
239    }
240
241    while (1) {
242	set_colors(win, 1, COLOR_WHITE, COLOR_BLUE);
243	werase(win);
244
245	set_colors(win, 2, COLOR_RED, COLOR_RED);
246	box(win, ACS_VLINE, ACS_HLINE);
247	wrefresh(win);
248	/* Do ramdom output of a character */
249	use_colors(win, 1, A_NORMAL);
250	c = 'a';
251	for (i = 0; i < 5000; ++i) {
252	    x = rand() % (width - 2) + 1;
253	    y = rand() % (height - 2) + 1;
254	    mvwaddch(win, y, x, c);
255	    wrefresh(win);
256	    nodelay(win, TRUE);
257	    if (wgetch(win) != ERR)
258		break;
259	    if (i == 2000) {
260		c = 'b';
261		set_colors(win, 3, COLOR_CYAN, COLOR_YELLOW);
262	    }
263	}
264
265	SubWinTest(win);
266	/* Erase and draw green window */
267	set_colors(win, 4, COLOR_YELLOW, COLOR_GREEN);
268	wbkgd(win, use_colors(win, 4, A_BOLD));
269	werase(win);
270	wrefresh(win);
271	/* Draw RED bounding box */
272	use_colors(win, 2, A_NORMAL);
273	box(win, ' ', ' ');
274	wrefresh(win);
275	/* Display Australia map */
276	use_colors(win, 4, A_BOLD);
277	i = 0;
278	while (*AusMap[i]) {
279	    mvwaddstr(win, i + 1, 8, AusMap[i]);
280	    wrefresh(win);
281	    delay_output(50);
282	    ++i;
283	}
284
285	set_colors(win, 5, COLOR_BLUE, COLOR_WHITE);
286	use_colors(win, 5, A_BLINK);
287	mvwaddstr(win, height - 2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
288	wrefresh(win);
289
290	/* Draw running messages */
291	set_colors(win, 6, COLOR_YELLOW, COLOR_WHITE);
292	message = messages[j = 0];
293	i = 1;
294	w = width - 2;
295	strcpy(buffer, message);
296	while (j < NMESSAGES) {
297	    while ((int) strlen(buffer) < w) {
298		strcat(buffer, " ... ");
299		strcat(buffer, messages[++j % NMESSAGES]);
300	    }
301
302	    if (i < w)
303		mvwaddnstr(win, height / 2, w - i, buffer, i);
304	    else
305		mvwaddnstr(win, height / 2, 1, buffer, w);
306
307	    wrefresh(win);
308	    nodelay(win, TRUE);
309	    if (wgetch(win) != ERR) {
310		flushinp();
311		break;
312	    }
313	    if (i++ >= w) {
314		for (k = 0; (buffer[k] = buffer[k + 1]) != '\0'; k++) ;
315	    }
316	    delay_output(100);
317	}
318
319	j = 0;
320	/*  Draw running As across in RED */
321	set_colors(win, 7, COLOR_RED, COLOR_GREEN);
322	memset(save, ' ', sizeof(save));
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