libpayload: Add PDCurses and ncurses' libform/libmenu
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / demos / worm.c
1 /****************************************************************************
2  * Copyright (c) 2005 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 /*
30
31          @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
32          @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
33          @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
34          @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
35          @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
36          @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
37           @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
38            @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
39             @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
40
41                                  Eric P. Scott
42                           Caltech High Energy Physics
43                                  October, 1980
44
45                            Color by Eric S. Raymond
46                                   July, 1995
47
48 Options:
49         -f                      fill screen with copies of 'WORM' at start.
50         -l <n>                  set worm length
51         -n <n>                  set number of worms
52         -t                      make worms leave droppings
53
54   $Id: worm.c,v 1.16 2008/07/13 16:08:17 wmcbrine Exp $
55 */
56
57 #include <curses.h>
58 #include <stdlib.h>
59 #include <time.h>
60
61 #define FLAVORS 7
62
63 static chtype flavor[FLAVORS] =
64 {
65     'O', '*', '#', '$', '%', '0', '@'
66 };
67
68 static const short xinc[] =
69 {
70     1, 1, 1, 0, -1, -1, -1, 0
71 },
72 yinc[] =
73 {
74     -1, 0, 1, 1, 1, 0, -1, -1
75 };
76
77 static struct worm
78 {
79     int orientation, head;
80     short *xpos, *ypos;
81 } worm[40];
82
83 static const char *field;
84 static int length = 16, number = 3;
85 static chtype trail = ' ';
86
87 static const struct options
88 {
89     int nopts;
90     int opts[3];
91 } normal[8] =
92 {
93     { 3, { 7, 0, 1 } }, { 3, { 0, 1, 2 } }, { 3, { 1, 2, 3 } },
94     { 3, { 2, 3, 4 } }, { 3, { 3, 4, 5 } }, { 3, { 4, 5, 6 } },
95     { 3, { 5, 6, 7 } }, { 3, { 6, 7, 0 } }
96 },
97 upper[8] =
98 {
99     { 1, { 1, 0, 0 } }, { 2, { 1, 2, 0 } }, { 0, { 0, 0, 0 } },
100     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }, { 2, { 4, 5, 0 } },
101     { 1, { 5, 0, 0 } }, { 2, { 1, 5, 0 } }
102 },
103 left[8] =
104 {
105     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
106     { 2, { 2, 3, 0 } }, { 1, { 3, 0, 0 } }, { 2, { 3, 7, 0 } },
107     { 1, { 7, 0, 0 } }, { 2, { 7, 0, 0 } }
108 },
109 right[8] =
110 {
111     { 1, { 7, 0, 0 } }, { 2, { 3, 7, 0 } }, { 1, { 3, 0, 0 } },
112     { 2, { 3, 4, 0 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
113     { 0, { 0, 0, 0 } }, { 2, { 6, 7, 0 } }
114 },
115 lower[8] =
116 {
117     { 0, { 0, 0, 0 } }, { 2, { 0, 1, 0 } }, { 1, { 1, 0, 0 } },
118     { 2, { 1, 5, 0 } }, { 1, { 5, 0, 0 } }, { 2, { 5, 6, 0 } },
119     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }
120 },
121 upleft[8] =
122 {
123     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
124     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }, { 1, { 3, 0, 0 } },
125     { 2, { 1, 3, 0 } }, { 1, { 1, 0, 0 } }
126 },
127 upright[8] =
128 {
129     { 2, { 3, 5, 0 } }, { 1, { 3, 0, 0 } }, { 0, { 0, 0, 0 } },
130     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
131     { 0, { 0, 0, 0 } }, { 1, { 5, 0, 0 } }
132 },
133 lowleft[8] =
134 {
135     { 3, { 7, 0, 1 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
136     { 1, { 1, 0, 0 } }, { 2, { 1, 7, 0 } }, { 1, { 7, 0, 0 } },
137     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }
138 },
139 lowright[8] =
140 {
141     { 0, { 0, 0, 0 } }, { 1, { 7, 0, 0 } }, { 2, { 5, 7, 0 } },
142     { 1, { 5, 0, 0 } }, { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } },
143     { 0, { 0, 0, 0 } }, { 0, { 0, 0, 0 } }
144 };
145
146 static void cleanup(void)
147 {
148     standend();
149     refresh();
150     curs_set(1);
151     endwin();
152 }
153
154 int main(int argc, char *argv[])
155 {
156     const struct options *op;
157     struct worm *w;
158     short **ref, *ip;
159     int x, y, n, h, last, bottom, seed;
160
161     for (x = 1; x < argc; x++)
162     {
163         char *p = argv[x];
164
165         if (*p == '-')
166             p++;
167
168         switch (*p)
169         {
170         case 'f':
171             field = "WORM";
172             break;
173         case 'l':
174             if (++x == argc)
175                 goto usage;
176
177             if ((length = atoi(argv[x])) < 2 || length > 1024)
178             {
179                 fprintf(stderr, "%s: Invalid length\n", *argv);
180                 return EXIT_FAILURE;
181             }
182
183             break;
184         case 'n':
185             if (++x == argc)
186                 goto usage;
187
188             if ((number = atoi(argv[x])) < 1 || number > 40)
189             {
190                 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
191                 return EXIT_FAILURE;
192             }
193
194             break;
195         case 't':
196             trail = '.';
197             break;
198         default:
199               usage:
200             fprintf(stderr, "usage: %s [-field] [-length #] "
201                             "[-number #] [-trail]\n", *argv);
202             return EXIT_FAILURE;
203         }
204     }
205
206 #ifdef XCURSES
207     Xinitscr(argc, argv);
208 #else
209     initscr();
210 #endif
211     seed = time((time_t *)0);
212     srand(seed);
213
214     noecho();
215     cbreak();
216     nonl();
217     keypad(stdscr, TRUE);
218
219     curs_set(0);
220
221     bottom = LINES - 1;
222     last = COLS - 1;
223
224 #ifdef A_COLOR
225     if (has_colors())
226     {
227         int bg = COLOR_BLACK;
228         start_color();
229
230 # if defined(NCURSES_VERSION) || (defined(PDC_BUILD) && PDC_BUILD > 3000)
231         if (use_default_colors() == OK)
232             bg = -1;
233 # endif
234
235 # define SET_COLOR(num, fg) \
236         init_pair(num + 1, fg, bg); \
237         flavor[num] |= COLOR_PAIR(num + 1) | A_BOLD
238
239         SET_COLOR(0, COLOR_GREEN);
240         SET_COLOR(1, COLOR_RED);
241         SET_COLOR(2, COLOR_CYAN);
242         SET_COLOR(3, COLOR_WHITE);
243         SET_COLOR(4, COLOR_MAGENTA);
244         SET_COLOR(5, COLOR_BLUE);
245         SET_COLOR(6, COLOR_YELLOW);
246     }
247 #endif
248
249     ref = malloc(sizeof(short *) * LINES);
250
251     for (y = 0; y < LINES; y++)
252     {
253         ref[y] = malloc(sizeof(short) * COLS);
254
255         for (x = 0; x < COLS; x++)
256             ref[y][x] = 0;
257     }
258
259 #ifdef BADCORNER
260     /* if addressing the lower right corner doesn't work in your curses */
261
262     ref[bottom][last] = 1;
263 #endif
264
265     for (n = number, w = &worm[0]; --n >= 0; w++)
266     {
267         w->orientation = w->head = 0;
268
269         if ((ip = malloc(sizeof(short) * (length + 1))) == NULL)
270         {
271             fprintf(stderr, "%s: out of memory\n", *argv);
272             return EXIT_FAILURE;
273         }
274
275         w->xpos = ip;
276
277         for (x = length; --x >= 0;)
278             *ip++ = -1;
279
280         if ((ip = malloc(sizeof(short) * (length + 1))) == NULL)
281         {
282             fprintf(stderr, "%s: out of memory\n", *argv);
283             return EXIT_FAILURE;
284         }
285
286         w->ypos = ip;
287
288         for (y = length; --y >= 0;)
289             *ip++ = -1;
290     }
291
292     if (field)
293     {
294         const char *p = field;
295
296         for (y = bottom; --y >= 0;)
297             for (x = COLS; --x >= 0;)
298             {
299                 addch((chtype) (*p++));
300
301                 if (!*p)
302                     p = field;
303             }
304     }
305
306     napms(12);
307     refresh();
308     nodelay(stdscr, TRUE);
309
310     for (;;)
311     {
312         int ch;
313
314         if ((ch = getch()) > 0)
315         {
316 #ifdef KEY_RESIZE
317             if (ch == KEY_RESIZE)
318             {
319 # ifdef PDCURSES
320                 resize_term(0, 0);
321                 erase();
322 # endif
323                 if (last != COLS - 1)
324                 {
325                     for (y = 0; y <= bottom; y++)
326                     {
327                         ref[y] = realloc(ref[y], sizeof(short) * COLS);
328
329                         for (x = last + 1; x < COLS; x++)
330                             ref[y][x] = 0;
331                     }
332
333                     last = COLS - 1;
334                 }
335
336                 if (bottom != LINES - 1)
337                 {
338                     for (y = LINES; y <= bottom; y++)
339                         free(ref[y]);
340
341                     ref = realloc(ref, sizeof(short *) * LINES);
342
343                     for (y = bottom + 1; y < LINES; y++)
344                     {
345                         ref[y] = malloc(sizeof(short) * COLS);
346
347                         for (x = 0; x < COLS; x++)
348                             ref[y][x] = 0;
349                     }
350
351                     bottom = LINES - 1;
352                 }
353             }
354
355 #endif /* KEY_RESIZE */
356
357             /* Make it simple to put this into single-step mode,
358                or resume normal operation - T. Dickey */
359
360             if (ch == 'q')
361             {
362                 cleanup();
363                 return EXIT_SUCCESS;
364             }
365             else if (ch == 's')
366                 nodelay(stdscr, FALSE);
367             else if (ch == ' ')
368                 nodelay(stdscr, TRUE);
369         }
370
371         for (n = 0, w = &worm[0]; n < number; n++, w++)
372         {
373             if ((x = w->xpos[h = w->head]) < 0)
374             {
375                 move(y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
376                 addch(flavor[n % FLAVORS]);
377                 ref[y][x]++;
378             }
379             else
380                 y = w->ypos[h];
381
382             if (x > last)
383                 x = last;
384
385             if (y > bottom)
386                 y = bottom;
387
388             if (++h == length)
389                 h = 0;
390
391             if (w->xpos[w->head = h] >= 0)
392             {
393                 int x1 = w->xpos[h];
394                 int y1 = w->ypos[h];
395
396                 if (y1 < LINES && x1 < COLS && --ref[y1][x1] == 0)
397                 {
398                     move(y1, x1);
399                     addch(trail);
400                 }
401             }
402
403             op = &(x == 0 ? (y == 0 ? upleft :
404                   (y == bottom ? lowleft : left)) :
405                   (x == last ? (y == 0 ? upright :
406                   (y == bottom ? lowright : right)) :
407                   (y == 0 ? upper :
408                   (y == bottom ? lower : normal))))
409                   [w->orientation];
410
411             switch (op->nopts)
412             {
413             case 0:
414                 cleanup();
415                 return EXIT_SUCCESS;
416             case 1:
417                 w->orientation = op->opts[0];
418                 break;
419             default:
420                 w->orientation = op->opts[rand() % op->nopts];
421             }
422
423             move(y += yinc[w->orientation], x += xinc[w->orientation]);
424
425             if (y < 0)
426                 y = 0;
427
428             addch(flavor[n % FLAVORS]);
429             ref[w->ypos[h] = y][w->xpos[h] = x]++;
430         }
431         napms(12);
432         refresh();
433     }
434 }