]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/worm.c
ncurses 5.7 - patch 20090803
[ncurses.git] / test / worm.c
index ea407a0c0606827ff629205bfdde8358677ade63..0bcd8d3dddc8e2c86f0cfa406a9972f57bb8dd75 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.
 
   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.59 2008/11/16 00:19:59 juergen Exp $
 */
 
 #include <test.priv.h>
 */
 
 #include <test.priv.h>
@@ -70,6 +70,11 @@ Options:
 #include <pthread.h>
 #endif
 
 #include <pthread.h>
 #endif
 
+WANT_USE_WINDOW();
+
+#define MAX_WORMS      40
+#define MAX_LENGTH     1024
+
 static chtype flavor[] =
 {
     'O', '*', '#', '$', '%', '0', '@',
 static chtype flavor[] =
 {
     'O', '*', '#', '$', '%', '0', '@',
@@ -96,13 +101,15 @@ typedef struct worm {
 static unsigned long sequence = 0;
 static bool quitting = FALSE;
 
 static unsigned long sequence = 0;
 static bool quitting = FALSE;
 
-static WORM worm[40];
+static WORM worm[MAX_WORMS];
 static short **refs;
 static short **refs;
+static int last_x, last_y;
 
 static const char *field;
 static int length = 16, number = 3;
 static chtype trail = ' ';
 
 
 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 */
 #ifdef TRACE
 static int generation, trace_start, trace_end;
 #endif /* TRACE */
@@ -197,8 +204,7 @@ static const struct options {
 static void
 cleanup(void)
 {
 static void
 cleanup(void)
 {
-    standend();
-    refresh();
+    USING_WINDOW(stdscr, wrefresh);
     curs_set(1);
     endwin();
 }
     curs_set(1);
     endwin();
 }
@@ -222,28 +228,27 @@ draw_worm(WINDOW *win, void *data)
 {
     WORM *w = (WORM *) data;
     const struct options *op;
 {
     WORM *w = (WORM *) data;
     const struct options *op;
+    unsigned mask = ~(1 << (w - worm));
+    chtype attrs = w->attrs | ((mask & pending) ? A_REVERSE : 0);
 
     int x;
     int y;
     int h;
 
 
     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) {
     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];
     }
 
        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;
 
     if (++h == length)
        h = 0;
@@ -263,18 +268,18 @@ draw_worm(WINDOW *win, void *data)
     op = &(x == 0
           ? (y == 0
              ? upleft
     op = &(x == 0
           ? (y == 0
              ? upleft
-             : (y == bottom
+             : (y == last_y
                 ? lowleft
                 : left))
                 ? lowleft
                 : left))
-          : (x == last
+          : (x == last_x
              ? (y == 0
                 ? upright
              ? (y == 0
                 ? upright
-                : (y == bottom
+                : (y == last_y
                    ? lowright
                    : right))
              : (y == 0
                 ? upper
                    ? lowright
                    : right))
              : (y == 0
                 ? upper
-                : (y == bottom
+                : (y == last_y
                    ? lower
                    : normal))))[w->orientation];
 
                    ? lower
                    : normal))))[w->orientation];
 
@@ -297,7 +302,7 @@ draw_worm(WINDOW *win, void *data)
 
        if (y < 0)
            y = 0;
 
        if (y < 0)
            y = 0;
-       waddch(win, w->attrs);
+       waddch(win, attrs);
 
        w->ypos[h] = y;
        w->xpos[h] = x;
 
        w->ypos[h] = y;
        w->xpos[h] = x;
@@ -307,19 +312,13 @@ draw_worm(WINDOW *win, void *data)
     return done;
 }
 
     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
 #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 */
     napms(10);                 /* let the other thread(s) have a chance */
+    pending &= ~(1 << bitnum);
     return quitting;
 }
 
     return quitting;
 }
 
@@ -327,12 +326,18 @@ static void *
 start_worm(void *arg)
 {
     unsigned long compare = 0;
 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;
        while (compare < sequence) {
            ++compare;
+#if HAVE_USE_WINDOW
            use_window(stdscr, draw_worm, arg);
            use_window(stdscr, draw_worm, arg);
+#else
+           draw_worm(stdscr, arg);
+#endif
        }
     }
        }
     }
+    Trace(("...start_worm (done)"));
     return NULL;
 }
 #endif
     return NULL;
 }
 #endif
@@ -355,7 +360,13 @@ draw_all_worms(void)
     }
 #else
     for (n = 0, w = &worm[0]; n < number; n++, w++) {
     }
 #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
            done = TRUE;
     }
 #endif
@@ -366,14 +377,40 @@ static int
 get_input(void)
 {
     int ch;
 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;
 }
 
     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(short, 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(short *, LINES, refs);
+       for (y = last_y + 1; y < LINES; y++) {
+           refs[y] = typeMalloc(short, 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
 main(int argc, char *argv[])
 {
@@ -381,7 +418,6 @@ main(int argc, char *argv[])
     int n;
     struct worm *w;
     short *ip;
     int n;
     struct worm *w;
     short *ip;
-    int last, bottom;
     bool done = FALSE;
 
     setlocale(LC_ALL, "");
     bool done = FALSE;
 
     setlocale(LC_ALL, "");
@@ -398,7 +434,7 @@ main(int argc, char *argv[])
        case 'l':
            if (++x == argc)
                goto usage;
        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);
            }
                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;
        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);
            }
                fprintf(stderr, "%s: Invalid number of worms\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
@@ -439,8 +475,8 @@ main(int argc, char *argv[])
 
     curs_set(0);
 
 
     curs_set(0);
 
-    bottom = LINES - 1;
-    last = COLS - 1;
+    last_y = LINES - 1;
+    last_x = COLS - 1;
 
 #ifdef A_COLOR
     if (has_colors()) {
 
 #ifdef A_COLOR
     if (has_colors()) {
@@ -475,7 +511,7 @@ main(int argc, char *argv[])
 
 #ifdef BADCORNER
     /* if addressing the lower right corner doesn't work in your curses */
 
 #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++) {
 #endif /* BADCORNER */
 
     for (n = number, w = &worm[0]; --n >= 0; w++) {
@@ -501,7 +537,7 @@ main(int argc, char *argv[])
     if (field) {
        const char *p;
        p = field;
     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)
            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) {
     nodelay(stdscr, TRUE);
 
     while (!done) {
@@ -530,29 +566,13 @@ main(int argc, char *argv[])
                generation++;
            }
 #endif
                generation++;
            }
 #endif
+
 #ifdef KEY_RESIZE
            if (ch == KEY_RESIZE) {
 #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
            }
 #endif
+
            /*
             * Make it simple to put this into single-step mode, or resume
             * normal operation -T.Dickey
            /*
             * 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);
 
        done = draw_all_worms();
        napms(10);
-       refresh();
+       USING_WINDOW(stdscr, wrefresh);
     }
 
     }
 
+    Trace(("Cleanup"));
     cleanup();
 #ifdef NO_LEAKS
     for (y = 0; y < LINES; y++) {
     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.
      */
     /*
      * 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);
     }
     for (n = 0; n < number; n++) {
        pthread_join(worm[n].thread, NULL);
     }