]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/worm.c
ncurses 5.9 - patch 20120811
[ncurses.git] / test / worm.c
index ea407a0c0606827ff629205bfdde8358677ade63..98f099cb9cb6e94deb2af7b602705a4e9631dc69 100644 (file)
@@ -61,7 +61,7 @@ Options:
   traces will be dumped.  The program stops and waits for one character of
   input at the beginning and end of the interval.
 
-  $Id: worm.c,v 1.53 2008/01/19 20:56:38 tom Exp $
+  $Id: worm.c,v 1.60 2010/11/13 20:21:21 tom Exp $
 */
 
 #include <test.priv.h>
@@ -70,11 +70,16 @@ Options:
 #include <pthread.h>
 #endif
 
+WANT_USE_WINDOW();
+
+#define MAX_WORMS      40
+#define MAX_LENGTH     1024
+
 static chtype flavor[] =
 {
     'O', '*', '#', '$', '%', '0', '@',
 };
-static const short xinc[] =
+static const int xinc[] =
 {
     1, 1, 1, 0, -1, -1, -1, 0
 }, yinc[] =
@@ -85,8 +90,8 @@ static const short xinc[] =
 typedef struct worm {
     int orientation;
     int head;
-    short *xpos;
-    short *ypos;
+    int *xpos;
+    int *ypos;
     chtype attrs;
 #ifdef USE_PTHREADS
     pthread_t thread;
@@ -96,13 +101,15 @@ typedef struct worm {
 static unsigned long sequence = 0;
 static bool quitting = FALSE;
 
-static WORM worm[40];
-static short **refs;
+static WORM worm[MAX_WORMS];
+static int **refs;
+static int last_x, last_y;
 
 static const char *field;
 static int length = 16, number = 3;
 static chtype trail = ' ';
 
+static unsigned pending;
 #ifdef TRACE
 static int generation, trace_start, trace_end;
 #endif /* TRACE */
@@ -197,8 +204,7 @@ static const struct options {
 static void
 cleanup(void)
 {
-    standend();
-    refresh();
+    USING_WINDOW(stdscr, wrefresh);
     curs_set(1);
     endwin();
 }
@@ -210,11 +216,11 @@ onsig(int sig GCC_UNUSED)
     ExitProgram(EXIT_FAILURE);
 }
 
-static float
+static double
 ranf(void)
 {
     long r = (rand() & 077777);
-    return ((float) r / 32768.);
+    return ((double) r / 32768.);
 }
 
 static int
@@ -222,28 +228,27 @@ draw_worm(WINDOW *win, void *data)
 {
     WORM *w = (WORM *) data;
     const struct options *op;
+    unsigned mask = (unsigned) (~(1 << (w - worm)));
+    chtype attrs = w->attrs | ((mask & pending) ? A_REVERSE : 0);
 
     int x;
     int y;
     int h;
 
-    int bottom = LINES - 1;
-    int last = COLS - 1;
-
     bool done = FALSE;
 
     if ((x = w->xpos[h = w->head]) < 0) {
-       wmove(win, y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
-       waddch(win, w->attrs);
+       wmove(win, y = w->ypos[h] = last_y, x = w->xpos[h] = 0);
+       waddch(win, attrs);
        refs[y][x]++;
     } else {
        y = w->ypos[h];
     }
 
-    if (x > last)
-       x = last;
-    if (y > bottom)
-       y = bottom;
+    if (x > last_x)
+       x = last_x;
+    if (y > last_y)
+       y = last_y;
 
     if (++h == length)
        h = 0;
@@ -263,18 +268,18 @@ draw_worm(WINDOW *win, void *data)
     op = &(x == 0
           ? (y == 0
              ? upleft
-             : (y == bottom
+             : (y == last_y
                 ? lowleft
                 : left))
-          : (x == last
+          : (x == last_x
              ? (y == 0
                 ? upright
-                : (y == bottom
+                : (y == last_y
                    ? lowright
                    : right))
              : (y == 0
                 ? upper
-                : (y == bottom
+                : (y == last_y
                    ? lower
                    : normal))))[w->orientation];
 
@@ -286,7 +291,7 @@ draw_worm(WINDOW *win, void *data)
        w->orientation = op->opts[0];
        break;
     default:
-       w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
+       w->orientation = op->opts[(int) (ranf() * (double) op->nopts)];
        break;
     }
 
@@ -297,7 +302,7 @@ draw_worm(WINDOW *win, void *data)
 
        if (y < 0)
            y = 0;
-       waddch(win, w->attrs);
+       waddch(win, attrs);
 
        w->ypos[h] = y;
        w->xpos[h] = x;
@@ -307,19 +312,13 @@ draw_worm(WINDOW *win, void *data)
     return done;
 }
 
-#if !defined(NCURSES_VERSION_PATCH) || (NCURSES_VERSION_PATCH < 20070915) || !NCURSES_EXT_FUNCS
-static int
-use_window(WINDOW *win, int (*func) (WINDOW *, void *), void *data)
-{
-    return func(win, data);
-}
-#endif
-
 #ifdef USE_PTHREADS
 static bool
-quit_worm(void)
+quit_worm(int bitnum)
 {
+    pending |= (1 << bitnum);
     napms(10);                 /* let the other thread(s) have a chance */
+    pending &= ~(1 << bitnum);
     return quitting;
 }
 
@@ -327,12 +326,18 @@ static void *
 start_worm(void *arg)
 {
     unsigned long compare = 0;
-    while (!quit_worm()) {
+    Trace(("start_worm"));
+    while (!quit_worm(((struct worm *) arg) - worm)) {
        while (compare < sequence) {
            ++compare;
+#if HAVE_USE_WINDOW
            use_window(stdscr, draw_worm, arg);
+#else
+           draw_worm(stdscr, arg);
+#endif
        }
     }
+    Trace(("...start_worm (done)"));
     return NULL;
 }
 #endif
@@ -355,7 +360,13 @@ draw_all_worms(void)
     }
 #else
     for (n = 0, w = &worm[0]; n < number; n++, w++) {
-       if (use_window(stdscr, draw_worm, w))
+       if (
+#if HAVE_USE_WINDOW
+              USING_WINDOW2(stdscr, draw_worm, w)
+#else
+              draw_worm(stdscr, w)
+#endif
+           )
            done = TRUE;
     }
 #endif
@@ -366,22 +377,47 @@ static int
 get_input(void)
 {
     int ch;
-#ifdef USE_PTHREADS
-    ch = use_window(stdscr, (NCURSES_CALLBACK) wgetch, stdscr);
-#else
-    ch = getch();
-#endif
+    ch = USING_WINDOW(stdscr, wgetch);
     return ch;
 }
 
+#ifdef KEY_RESIZE
+static int
+update_refs(WINDOW *win)
+{
+    int x, y;
+
+    (void) win;
+    if (last_x != COLS - 1) {
+       for (y = 0; y <= last_y; y++) {
+           refs[y] = typeRealloc(int, (size_t) COLS, refs[y]);
+           for (x = last_x + 1; x < COLS; x++)
+               refs[y][x] = 0;
+       }
+       last_x = COLS - 1;
+    }
+    if (last_y != LINES - 1) {
+       for (y = LINES; y <= last_y; y++)
+           free(refs[y]);
+       refs = typeRealloc(int *, (size_t) LINES, refs);
+       for (y = last_y + 1; y < LINES; y++) {
+           refs[y] = typeMalloc(int, (size_t) COLS);
+           for (x = 0; x < COLS; x++)
+               refs[y][x] = 0;
+       }
+       last_y = LINES - 1;
+    }
+    return OK;
+}
+#endif
+
 int
 main(int argc, char *argv[])
 {
     int x, y;
     int n;
     struct worm *w;
-    short *ip;
-    int last, bottom;
+    int *ip;
     bool done = FALSE;
 
     setlocale(LC_ALL, "");
@@ -398,7 +434,7 @@ main(int argc, char *argv[])
        case 'l':
            if (++x == argc)
                goto usage;
-           if ((length = atoi(argv[x])) < 2 || length > 1024) {
+           if ((length = atoi(argv[x])) < 2 || length > MAX_LENGTH) {
                fprintf(stderr, "%s: Invalid length\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
@@ -406,7 +442,7 @@ main(int argc, char *argv[])
        case 'n':
            if (++x == argc)
                goto usage;
-           if ((number = atoi(argv[x])) < 1 || number > 40) {
+           if ((number = atoi(argv[x])) < 1 || number > MAX_WORMS) {
                fprintf(stderr, "%s: Invalid number of worms\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
@@ -439,8 +475,8 @@ main(int argc, char *argv[])
 
     curs_set(0);
 
-    bottom = LINES - 1;
-    last = COLS - 1;
+    last_y = LINES - 1;
+    last_x = COLS - 1;
 
 #ifdef A_COLOR
     if (has_colors()) {
@@ -452,7 +488,7 @@ main(int argc, char *argv[])
 #endif
 
 #define SET_COLOR(num, fg) \
-           init_pair(num+1, fg, bg); \
+           init_pair(num+1, (short) fg, (short) bg); \
            flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
 
        SET_COLOR(0, COLOR_GREEN);
@@ -465,9 +501,9 @@ main(int argc, char *argv[])
     }
 #endif /* A_COLOR */
 
-    refs = typeMalloc(short *, LINES);
+    refs = typeMalloc(int *, (size_t) LINES);
     for (y = 0; y < LINES; y++) {
-       refs[y] = typeMalloc(short, COLS);
+       refs[y] = typeMalloc(int, (size_t) COLS);
        for (x = 0; x < COLS; x++) {
            refs[y][x] = 0;
        }
@@ -475,22 +511,22 @@ main(int argc, char *argv[])
 
 #ifdef BADCORNER
     /* if addressing the lower right corner doesn't work in your curses */
-    refs[bottom][last] = 1;
+    refs[last_y][last_x] = 1;
 #endif /* BADCORNER */
 
     for (n = number, w = &worm[0]; --n >= 0; w++) {
-       w->attrs = flavor[n % SIZEOF(flavor)];
+       w->attrs = flavor[(unsigned) n % SIZEOF(flavor)];
        w->orientation = 0;
        w->head = 0;
 
-       if (!(ip = typeMalloc(short, (length + 1)))) {
+       if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
        w->xpos = ip;
        for (x = length; --x >= 0;)
            *ip++ = -1;
-       if (!(ip = typeMalloc(short, (length + 1)))) {
+       if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
@@ -501,7 +537,7 @@ main(int argc, char *argv[])
     if (field) {
        const char *p;
        p = field;
-       for (y = bottom; --y >= 0;) {
+       for (y = last_y; --y >= 0;) {
            for (x = COLS; --x >= 0;) {
                addch((chtype) (*p++));
                if (!*p)
@@ -509,7 +545,7 @@ main(int argc, char *argv[])
            }
        }
     }
-    refresh();
+    USING_WINDOW(stdscr, wrefresh);
     nodelay(stdscr, TRUE);
 
     while (!done) {
@@ -530,29 +566,13 @@ main(int argc, char *argv[])
                generation++;
            }
 #endif
+
 #ifdef KEY_RESIZE
            if (ch == KEY_RESIZE) {
-               if (last != COLS - 1) {
-                   for (y = 0; y <= bottom; y++) {
-                       refs[y] = typeRealloc(short, COLS, refs[y]);
-                       for (x = last + 1; x < COLS; x++)
-                           refs[y][x] = 0;
-                   }
-                   last = COLS - 1;
-               }
-               if (bottom != LINES - 1) {
-                   for (y = LINES; y <= bottom; y++)
-                       free(refs[y]);
-                   refs = typeRealloc(short *, LINES, refs);
-                   for (y = bottom + 1; y < LINES; y++) {
-                       refs[y] = typeMalloc(short, COLS);
-                       for (x = 0; x < COLS; x++)
-                           refs[y][x] = 0;
-                   }
-                   bottom = LINES - 1;
-               }
+               USING_WINDOW(stdscr, update_refs);
            }
 #endif
+
            /*
             * Make it simple to put this into single-step mode, or resume
             * normal operation -T.Dickey
@@ -570,9 +590,10 @@ main(int argc, char *argv[])
 
        done = draw_all_worms();
        napms(10);
-       refresh();
+       USING_WINDOW(stdscr, wrefresh);
     }
 
+    Trace(("Cleanup"));
     cleanup();
 #ifdef NO_LEAKS
     for (y = 0; y < LINES; y++) {
@@ -588,6 +609,7 @@ main(int argc, char *argv[])
     /*
      * Do this just in case one of the threads did not really exit.
      */
+    Trace(("join all threads"));
     for (n = 0; n < number; n++) {
        pthread_join(worm[n].thread, NULL);
     }