ncurses 5.6 - patch 20080308
[ncurses.git] / test / rain.c
1 /****************************************************************************
2  * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28 /*
29  * $Id: rain.c,v 1.26 2008/03/09 00:17:09 tom Exp $
30  */
31 #include <test.priv.h>
32
33 /* rain 11/3/1980 EPS/CITHEP */
34
35 #ifdef USE_PTHREADS
36 #include <pthread.h>
37 #endif
38
39 WANT_USE_WINDOW();
40
41 #define MAX_DROP 5
42
43 struct DATA;
44
45 typedef void (*DrawPart) (struct DATA *);
46
47 typedef struct DATA {
48     int y, x;
49 #ifdef USE_PTHREADS
50     pthread_t thread;
51     DrawPart func;
52     int state;
53 #endif
54 } DATA;
55
56 static void
57 onsig(int n GCC_UNUSED)
58 {
59     curs_set(1);
60     endwin();
61     ExitProgram(EXIT_FAILURE);
62 }
63
64 static float
65 ranf(void)
66 {
67     long r = (rand() & 077777);
68     return ((float) r / 32768.);
69 }
70
71 static int
72 random_x(void)
73 {
74     return (((float) (COLS - 4) * ranf()) + 2);
75 }
76
77 static int
78 random_y(void)
79 {
80     return (((float) (LINES - 4) * ranf()) + 2);
81 }
82
83 static int
84 next_j(int j)
85 {
86     if (j == 0)
87         j = MAX_DROP - 1;
88     else
89         --j;
90     if (has_colors()) {
91         int z = (int) (3 * ranf());
92         chtype color = COLOR_PAIR(z);
93         if (z)
94             color |= A_BOLD;
95         attrset(color);
96     }
97     return j;
98 }
99
100 static void
101 part1(DATA * drop)
102 {
103     mvaddch(drop->y, drop->x, '.');
104 }
105
106 static void
107 part2(DATA * drop)
108 {
109     mvaddch(drop->y, drop->x, 'o');
110 }
111
112 static void
113 part3(DATA * drop)
114 {
115     mvaddch(drop->y, drop->x, 'O');
116 }
117
118 static void
119 part4(DATA * drop)
120 {
121     mvaddch(drop->y - 1, drop->x, '-');
122     mvaddstr(drop->y, drop->x - 1, "|.|");
123     mvaddch(drop->y + 1, drop->x, '-');
124 }
125
126 static void
127 part5(DATA * drop)
128 {
129     mvaddch(drop->y - 2, drop->x, '-');
130     mvaddstr(drop->y - 1, drop->x - 1, "/ \\");
131     mvaddstr(drop->y, drop->x - 2, "| O |");
132     mvaddstr(drop->y + 1, drop->x - 1, "\\ /");
133     mvaddch(drop->y + 2, drop->x, '-');
134 }
135
136 static void
137 part6(DATA * drop)
138 {
139     mvaddch(drop->y - 2, drop->x, ' ');
140     mvaddstr(drop->y - 1, drop->x - 1, "   ");
141     mvaddstr(drop->y, drop->x - 2, "     ");
142     mvaddstr(drop->y + 1, drop->x - 1, "   ");
143     mvaddch(drop->y + 2, drop->x, ' ');
144 }
145
146 #ifdef USE_PTHREADS
147 static void
148 napsome(void)
149 {
150     refresh();
151     napms(60);
152 }
153
154 /*
155  * This runs inside the mutex.
156  */
157 static int
158 really_draw(WINDOW *win, void *arg)
159 {
160     DATA *data = (DATA *) arg;
161
162     (void) win;
163     next_j(data->state);
164     data->func(data);
165     return OK;
166 }
167
168 static void
169 draw_part(void (*func) (DATA *), int state, DATA * data)
170 {
171     data->func = func;
172     data->state = state;
173     use_window(stdscr, really_draw, (void *) data);
174     napsome();
175 }
176
177 static void *
178 draw_drop(void *arg)
179 {
180     DATA mydata;
181
182     mydata = *(DATA *) arg;     /* make a copy of caller's data */
183
184     draw_part(part1, 0, &mydata);
185     draw_part(part2, 1, &mydata);
186     draw_part(part3, 2, &mydata);
187     draw_part(part4, 3, &mydata);
188     draw_part(part5, 4, &mydata);
189     draw_part(part6, 0, &mydata);
190
191     return NULL;
192 }
193 #endif
194
195 static int
196 get_input(void)
197 {
198     int ch;
199     ch = USING_WINDOW(stdscr, wgetch);
200     return ch;
201 }
202
203 int
204 main(int argc GCC_UNUSED,
205      char *argv[]GCC_UNUSED)
206 {
207     DATA drop;
208     DATA last[MAX_DROP];
209     int j = 0;
210     bool done = FALSE;
211
212     setlocale(LC_ALL, "");
213
214     CATCHALL(onsig);
215
216     initscr();
217     if (has_colors()) {
218         int bg = COLOR_BLACK;
219         start_color();
220 #if HAVE_USE_DEFAULT_COLORS
221         if (use_default_colors() == OK)
222             bg = -1;
223 #endif
224         init_pair(1, COLOR_BLUE, bg);
225         init_pair(2, COLOR_CYAN, bg);
226     }
227     nl();
228     noecho();
229     curs_set(0);
230     timeout(0);
231
232     for (j = MAX_DROP; --j >= 0;) {
233         last[j].x = random_x();
234         last[j].y = random_y();
235     }
236
237     while (!done) {
238         drop.x = random_x();
239         drop.y = random_y();
240
241 #ifdef USE_PTHREADS
242         if (pthread_create(&(drop.thread), NULL, draw_drop, &drop)) {
243             beep();
244             done = TRUE;
245             continue;
246         }
247 #else
248         /*
249          * The non-threaded code draws parts of each drop on each loop.
250          */
251         part1(&drop);
252
253         part2(&last[j]);
254
255         j = next_j(j);
256         part3(&last[j]);
257
258         j = next_j(j);
259         part4(&last[j]);
260
261         j = next_j(j);
262         part5(&last[j]);
263
264         j = next_j(j);
265         part6(&last[j]);
266
267         last[j] = drop;
268 #endif
269
270         switch (get_input()) {
271         case ('q'):
272         case ('Q'):
273             done = TRUE;
274             break;
275         case 's':
276             nodelay(stdscr, FALSE);
277             break;
278         case ' ':
279             nodelay(stdscr, TRUE);
280             break;
281 #ifdef KEY_RESIZE
282         case (KEY_RESIZE):
283             break;
284 #endif
285         }
286         napms(50);
287     }
288     curs_set(1);
289     endwin();
290     ExitProgram(EXIT_SUCCESS);
291 }