ncurses 5.6 - patch 20080322
authorThomas E. Dickey <dickey@invisible-island.net>
Sun, 23 Mar 2008 01:02:37 +0000 (01:02 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sun, 23 Mar 2008 01:02:37 +0000 (01:02 +0000)
+ fill in extended-color pair two more places in wbkgrndset() and
  waddch_nosync() (prompted by Sedeno's patch).
+ fill in extended-color pair in _nc_build_wch() to make colors work
  for wide-characters using extended-colors (patch by Alejandro R
  Sedeno).
+ add x/X toggles to ncurses.c C color test to test/demo
  wide-characters with extended-colors.
+ add a/A toggles to ncurses.c c/C color tests.
+ modify test/ditto.c to use use_screen().
+ finish modifying test/rain.c to demonstrate threads.

NEWS
dist.mk
ncurses/base/lib_addch.c
ncurses/base/lib_bkgd.c
ncurses/trace/lib_trace.c
test/ditto.c
test/ncurses.c
test/rain.c
test/test.priv.h

diff --git a/NEWS b/NEWS
index 6f9efb113fed8bc85c133c25f8c89686964dc18e..9c96eb98b9ba665af5bff62097c883b07bf41930 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,7 +25,7 @@
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
--- $Id: NEWS,v 1.1213 2008/03/09 00:21:51 tom Exp $
+-- $Id: NEWS,v 1.1216 2008/03/23 00:18:40 tom Exp $
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
@@ -45,6 +45,18 @@ See the AUTHORS file for the corresponding full names.
 Changes through 1.9.9e did not credit all contributions;
 it is not possible to add this information.
 
+20080322
+       + fill in extended-color pair two more places in wbkgrndset() and
+         waddch_nosync() (prompted by Sedeno's patch).
+       + fill in extended-color pair in _nc_build_wch() to make colors work
+         for wide-characters using extended-colors (patch by Alejandro R
+         Sedeno).
+       + add x/X toggles to ncurses.c C color test to test/demo
+         wide-characters with extended-colors.
+       + add a/A toggles to ncurses.c c/C color tests.
+       + modify test/ditto.c to use use_screen().
+       + finish modifying test/rain.c to demonstrate threads.
+
 20080308
        + start modifying test/rain.c for threading demo.
        + modify test/ncurses.c to make 'f' test accept the f/F/b/F/</> toggles
diff --git a/dist.mk b/dist.mk
index 851936cf2e984efe9326aee93d803d4a0f6299c5..2ec32b3ba2e464ad8db643c383eb34d57f5a882b 100644 (file)
--- a/dist.mk
+++ b/dist.mk
@@ -25,7 +25,7 @@
 # use or other dealings in this Software without prior written               #
 # authorization.                                                             #
 ##############################################################################
-# $Id: dist.mk,v 1.633 2008/03/02 15:19:41 tom Exp $
+# $Id: dist.mk,v 1.635 2008/03/22 16:02:24 tom Exp $
 # Makefile for creating ncurses distributions.
 #
 # This only needs to be used directly as a makefile by developers, but
@@ -37,7 +37,7 @@ SHELL = /bin/sh
 # These define the major/minor/patch versions of ncurses.
 NCURSES_MAJOR = 5
 NCURSES_MINOR = 6
-NCURSES_PATCH = 20080308
+NCURSES_PATCH = 20080322
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
index 1ef6cc5803d3f3dca39cd370d1faad2c57e00fcb..489dd23e887d3582be7ac40742460419a21a8090 100644 (file)
@@ -36,7 +36,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_addch.c,v 1.108 2008/02/03 18:50:27 tom Exp $")
+MODULE_ID("$Id: lib_addch.c,v 1.110 2008/03/22 23:18:28 tom Exp $")
 
 static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT);
 
@@ -217,7 +217,9 @@ _nc_build_wch(WINDOW *win, ARG_CH_T ch)
                       buffer,
                       WINDOW_EXT(win, addch_used), &state)) > 0) {
        attr_t attrs = AttrOf(CHDEREF(ch));
+       int pair = GetPair(CHDEREF(ch));
        SetChar(CHDEREF(ch), result, attrs);
+       if_EXT_COLORS(SetPair(CHDEREF(ch), pair));
        WINDOW_EXT(win, addch_used) = 0;
     } else if (len == -1) {
        /*
@@ -474,6 +476,7 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch)
        while (*s) {
            NCURSES_CH_T sch;
            SetChar(sch, *s++, AttrOf(ch));
+           if_EXT_COLORS(SetPair(sch, GetPair(ch)));
            if (waddch_literal(win, sch) == ERR)
                return ERR;
        }
index e6a0cb000b15902e7bafa1c35f0b04c904ab667c..c99e0c5fc3a886c3763d7e9a4a4117db488af7cd 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -36,7 +36,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_bkgd.c,v 1.35 2006/05/27 19:20:11 tom Exp $")
+MODULE_ID("$Id: lib_bkgd.c,v 1.36 2008/03/23 00:09:14 tom Exp $")
 
 /*
  * Set the window's background information.
@@ -70,7 +70,7 @@ wbkgrndset(WINDOW *win, const ARG_CH_T ch)
 
        if (CharOf(CHDEREF(ch)) == L('\0')) {
            SetChar(win->_nc_bkgd, BLANK_TEXT, AttrOf(CHDEREF(ch)));
-           SetPair(win->_nc_bkgd, GetPair(CHDEREF(ch)));
+           if_EXT_COLORS(SetPair(win->_nc_bkgd, GetPair(CHDEREF(ch))));
        } else {
            win->_nc_bkgd = CHDEREF(ch);
        }
index d634438a97ac6330ee6ead8066d9adc9b4fd4cbe..03acb16cba91a5339ef0b8f817f2d8275db2f70d 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -46,7 +46,7 @@
 
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_trace.c,v 1.65 2007/09/29 21:47:46 tom Exp $")
+MODULE_ID("$Id: lib_trace.c,v 1.66 2008/03/22 16:56:48 tom Exp $")
 
 NCURSES_EXPORT_VAR(unsigned) _nc_tracing = 0; /* always define this */
 
@@ -167,6 +167,18 @@ _nc_va_tracef(const char *fmt, va_list ap)
     if (doit != 0) {
        if (TraceFP == 0)
            TraceFP = stderr;
+#ifdef USE_PTHREADS
+       /*
+        * TRACE_ICALLS is "really" needed to show normal use with threaded
+        * applications, since anything can be running during a napms(),
+        * making it appear in the hierarchical trace as it other functions
+        * are being called.
+        *
+        * Rather than add the complication of a per-thread stack, just
+        * show the thread-id in each line of the trace.
+        */
+       fprintf(TraceFP, "%#lx:", (long) pthread_self());
+#endif
        if (before || after) {
            int n;
            for (n = 1; n < TraceLevel; n++)
index 96677b99a8519434661158ea7c4c50fbbeda2085..86e116e049363dbde728405b09cf7eac31e8584f 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -29,7 +29,7 @@
 /*
  * Author: Thomas E. Dickey <dickey@clark.net> 1998
  *
- * $Id: ditto.c,v 1.8 2007/09/01 21:10:38 tom Exp $
+ * $Id: ditto.c,v 1.11 2008/03/22 20:26:31 tom Exp $
  *
  * The program illustrates how to set up multiple screens from a single
  * program.  Invoke the program by specifying another terminal on the same
@@ -79,17 +79,37 @@ open_tty(char *path)
     return fp;
 }
 
+static int
+close_screen(void *arg)
+{
+    (void) arg;
+    return endwin();
+}
+
+static int
+read_screen(void *arg)
+{
+    (void) arg;
+    return getch();
+}
+
+static int
+write_screen(WINDOW *win, void *arg)
+{
+    (void) win;
+    addstr((char *) arg);
+    refresh();
+    return OK;
+}
+
 static void
-show_ditto(DITTO * data, int count, int which, int ch)
+show_ditto(DITTO * data, int count, char *msg)
 {
     int n;
 
     for (n = 0; n < count; n++) {
-       set_term(data[n].screen);
-       addch(UChar(ch));
-       refresh();
+       USING_SCREEN(data[n].screen, write_screen, (void *) msg);
     }
-    set_term(data[which].screen);
 }
 
 int
@@ -134,27 +154,27 @@ main(int argc GCC_UNUSED,
      * of the screens.
      */
     for (count = 0;; ++count) {
+       char message[80];
        int ch;
        int which = (count % argc);
 
-       set_term(data[which].screen);
        napms(20);
-       ch = getch();
+       ch = USING_SCREEN(data[which].screen, read_screen, 0);
        if (ch == ERR) {
            /* echochar('.'); */
            continue;
        }
        if (ch == CTRL('D'))
            break;
-       show_ditto(data, argc, which, ch);
+       sprintf(message, "from[%d:%d] '%c' (%#x)\n", count, which, ch, ch);
+       show_ditto(data, argc, message);
     }
 
     /*
      * Cleanup and exit
      */
     for (j = argc - 1; j >= 0; j--) {
-       set_term(data[j].screen);
-       endwin();
+       USING_SCREEN(data[j].screen, close_screen, 0);
     }
     ExitProgram(EXIT_SUCCESS);
 }
index 7933e719232f5524955c7e1f4447ee3a4dcbc011..752fe87dc7558c8f96be71d5c6aa5b340f670970 100644 (file)
@@ -40,7 +40,7 @@ AUTHOR
    Author: Eric S. Raymond <esr@snark.thyrsus.com> 1993
            Thomas E. Dickey (beginning revision 1.27 in 1996).
 
-$Id: ncurses.c,v 1.309 2008/03/08 20:57:09 tom Exp $
+$Id: ncurses.c,v 1.312 2008/03/22 23:02:57 tom Exp $
 
 ***************************************************************************/
 
@@ -172,7 +172,7 @@ isQuit(int c)
 {
     return ((c) == QUIT || (c) == ESCAPE);
 }
-#define case_QUIT      case QUIT: case ESCAPE
+#define case_QUIT      QUIT: case ESCAPE
 
 /* Common function to allow ^T to toggle trace-mode in the middle of a test
  * so that trace-files can be made smaller.
@@ -270,6 +270,42 @@ wGetstring(WINDOW *win, char *buffer, int limit)
 }
 
 #if USE_WIDEC_SUPPORT
+static wchar_t
+fullwidth_of(int ch)
+{
+    return (ch + 0xff10 - '0');
+}
+
+static void
+make_fullwidth_text(wchar_t *target, const char *source)
+{
+    int ch;
+    while ((ch = *source++) != 0) {
+       *target++ = fullwidth_of(ch);
+    }
+    *target = 0;
+}
+
+static void
+make_narrow_text(wchar_t *target, const char *source)
+{
+    int ch;
+    while ((ch = *source++) != 0) {
+       *target++ = ch;
+    }
+    *target = 0;
+}
+
+static void
+make_fullwidth_digit(cchar_t *target, int digit)
+{
+    wchar_t source[2];
+
+    source[0] = fullwidth_of(digit + '0');
+    source[1] = 0;
+    setcchar(target, source, A_NORMAL, 0, 0);
+}
+
 static int
 wGet_wchar(WINDOW *win, wint_t *result)
 {
@@ -1378,7 +1414,7 @@ attr_getc(int *skip, short *fg, short *bg, short *tx, int *ac, unsigned *kc)
            case '>':
                adjust_attr_string(1);
                break;
-             case_QUIT:
+           case case_QUIT:
                result = FALSE;
                break;
            default:
@@ -1654,7 +1690,7 @@ wide_attr_getc(int *skip, short *fg, short *bg, short *tx, int *ac, unsigned *kc
            case '>':
                wide_adjust_attr_string(1);
                break;
-             case_QUIT:
+           case case_QUIT:
                result = FALSE;
                break;
            default:
@@ -1783,7 +1819,7 @@ show_color_name(int y, int x, int color, bool wide)
 }
 
 static void
-color_legend(WINDOW *helpwin)
+color_legend(WINDOW *helpwin, bool wide)
 {
     int row = 1;
     int col = 1;
@@ -1796,18 +1832,30 @@ color_legend(WINDOW *helpwin)
     mvwprintw(helpwin, row++, col,
              "longer than one screen. Control/N and Control/P can be used");
     mvwprintw(helpwin, row++, col,
-             "in place up up/down arrow.  Use pageup/pagedown to scroll a");
+             "in place of up/down arrow.  Use pageup/pagedown to scroll a");
     mvwprintw(helpwin, row++, col,
              "full screen; control/B and control/F can be used here.");
     ++row;
     mvwprintw(helpwin, row++, col,
              "Toggles:");
+    mvwprintw(helpwin, row++, col,
+             "  a/A     toggle altcharset off/on");
     mvwprintw(helpwin, row++, col,
              "  b/B     toggle bold off/on");
     mvwprintw(helpwin, row++, col,
              "  n/N     toggle text/number on/off");
     mvwprintw(helpwin, row++, col,
              "  w/W     toggle width between 8/16 colors");
+#if USE_WIDEC_SUPPORT
+    if (wide) {
+       mvwprintw(helpwin, row++, col,
+                 "Wide characters:");
+       mvwprintw(helpwin, row++, col,
+                 "  x/X     toggle text between ASCII and wide-character");
+    }
+#else
+    (void) wide;
+#endif
 }
 
 #define set_color_test(name, value) if (name != value) { name = value; base_row = 0; }
@@ -1827,6 +1875,7 @@ color_test(void)
     char numbered[80];
     const char *hello;
     bool done = FALSE;
+    bool opt_acsc = FALSE;
     bool opt_bold = FALSE;
     bool opt_wide = FALSE;
     bool opt_nums = FALSE;
@@ -1878,6 +1927,8 @@ color_test(void)
 
                init_pair(pair, fg, bg);
                attron((attr_t) COLOR_PAIR(pair));
+               if (opt_acsc)
+                   attron((attr_t) A_ALTCHARSET);
                if (opt_bold)
                    attron((attr_t) A_BOLD);
 
@@ -1898,6 +1949,12 @@ color_test(void)
        }
 
        switch (wGetchar(stdscr)) {
+       case 'a':
+           opt_acsc = FALSE;
+           break;
+       case 'A':
+           opt_acsc = TRUE;
+           break;
        case 'b':
            opt_bold = FALSE;
            break;
@@ -1910,7 +1967,7 @@ color_test(void)
        case 'N':
            opt_nums = TRUE;
            break;
-         case_QUIT:
+       case case_QUIT:
            done = TRUE;
            continue;
        case 'w':
@@ -1961,7 +2018,7 @@ color_test(void)
        case '?':
            if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                box(helpwin, 0, 0);
-               color_legend(helpwin);
+               color_legend(helpwin, FALSE);
                wGetchar(helpwin);
                delwin(helpwin);
            }
@@ -1993,9 +2050,12 @@ wide_color_test(void)
     char numbered[80];
     const char *hello;
     bool done = FALSE;
+    bool opt_acsc = FALSE;
     bool opt_bold = FALSE;
     bool opt_wide = FALSE;
     bool opt_nums = FALSE;
+    bool opt_xchr = FALSE;
+    wchar_t buffer[10];
     WINDOW *helpwin;
 
     while (!done) {
@@ -2011,6 +2071,13 @@ wide_color_test(void)
            hello = "Hello";
            per_row = 8;
        }
+       if (opt_xchr) {
+           make_fullwidth_text(buffer, hello);
+           width *= 2;
+           per_row /= 2;
+       } else {
+           make_narrow_text(buffer, hello);
+       }
 
        row_limit = (pairs_max + per_row - 1) / per_row;
 
@@ -2038,14 +2105,20 @@ wide_color_test(void)
            if (row >= 0 && move(row, col) != ERR) {
                init_pair(pair, i % COLORS, i / COLORS);
                color_set(pair, NULL);
+               if (opt_acsc)
+                   attr_on((attr_t) A_ALTCHARSET, NULL);
                if (opt_bold)
                    attr_on((attr_t) A_BOLD, NULL);
 
                if (opt_nums) {
                    sprintf(numbered, "{%02X}", i);
-                   hello = numbered;
+                   if (opt_xchr) {
+                       make_fullwidth_text(buffer, numbered);
+                   } else {
+                       make_narrow_text(buffer, numbered);
+                   }
                }
-               printw("%-*.*s", width, width, hello);
+               addnwstr(buffer, width);
                attr_set(A_NORMAL, 0, NULL);
 
                if ((i % per_row) == 0 && (i % COLORS) == 0) {
@@ -2058,6 +2131,12 @@ wide_color_test(void)
        }
 
        switch (c = wGetchar(stdscr)) {
+       case 'a':
+           opt_acsc = FALSE;
+           break;
+       case 'A':
+           opt_acsc = TRUE;
+           break;
        case 'b':
            opt_bold = FALSE;
            break;
@@ -2070,7 +2149,7 @@ wide_color_test(void)
        case 'N':
            opt_nums = TRUE;
            break;
-         case_QUIT:
+       case case_QUIT:
            done = TRUE;
            continue;
        case 'w':
@@ -2079,6 +2158,12 @@ wide_color_test(void)
        case 'W':
            set_color_test(opt_wide, TRUE);
            break;
+       case 'x':
+           opt_xchr = FALSE;
+           break;
+       case 'X':
+           opt_xchr = TRUE;
+           break;
        case CTRL('p'):
        case KEY_UP:
            if (base_row <= 0) {
@@ -2121,7 +2206,7 @@ wide_color_test(void)
        case '?':
            if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                box(helpwin, 0, 0);
-               color_legend(helpwin);
+               color_legend(helpwin, TRUE);
                wGetchar(helpwin);
                delwin(helpwin);
            }
@@ -2338,7 +2423,7 @@ color_edit(void)
            refresh();
            break;
 
-         case_QUIT:
+       case case_QUIT:
            break;
 
        default:
@@ -2508,7 +2593,7 @@ slk_test(void)
            clrtobot();
            break;
 
-         case_QUIT:
+       case case_QUIT:
            goto done;
 
 #if HAVE_SLK_COLOR
@@ -2641,7 +2726,7 @@ wide_slk_test(void)
            clrtobot();
            break;
 
-         case_QUIT:
+       case case_QUIT:
            goto done;
 
        case 'F':
@@ -3644,7 +3729,7 @@ selectcell(int uli, int ulj, int lri, int lrj)
        case KEY_RIGHT:
            j++;
            break;
-         case_QUIT:
+       case case_QUIT:
            return ((pair *) 0);
 #ifdef NCURSES_MOUSE_VERSION
        case KEY_MOUSE:
@@ -4136,16 +4221,6 @@ fill_panel(PANEL * pan)
 }
 
 #if USE_WIDEC_SUPPORT
-static void
-make_fullwidth_digit(cchar_t *target, int digit)
-{
-    wchar_t source[2];
-
-    source[0] = digit + 0xff10;
-    source[1] = 0;
-    setcchar(target, source, A_NORMAL, 0, 0);
-}
-
 static void
 init_wide_panel(void)
 {
@@ -4741,7 +4816,7 @@ padgetch(WINDOW *win)
                c = KEY_DC;
                break;
            case ERR:           /* FALLTHRU */
-             case_QUIT:
+           case case_QUIT:
                count = 0;
                c = KEY_EXIT;
                break;
index 3f6c39fc8f19a066e52b4e5f871c4e62b7949203..411306a71f9dbcdf55690b415cf1621be44ca6e3 100644 (file)
@@ -26,7 +26,7 @@
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: rain.c,v 1.26 2008/03/09 00:17:09 tom Exp $
+ * $Id: rain.c,v 1.33 2008/03/22 18:12:01 tom Exp $
  */
 #include <test.priv.h>
 
@@ -38,7 +38,8 @@
 
 WANT_USE_WINDOW();
 
-#define MAX_DROP 5
+#define MAX_THREADS    10
+#define MAX_DROP       5
 
 struct DATA;
 
@@ -47,12 +48,24 @@ typedef void (*DrawPart) (struct DATA *);
 typedef struct DATA {
     int y, x;
 #ifdef USE_PTHREADS
-    pthread_t thread;
     DrawPart func;
     int state;
 #endif
 } DATA;
 
+#ifdef USE_PTHREADS
+pthread_cond_t cond_next_drop;
+pthread_mutex_t mutex_next_drop;
+static int used_threads;
+
+typedef struct {
+    pthread_t myself;
+    long counter;
+} STATS;
+
+static STATS drop_threads[MAX_THREADS];
+#endif
+
 static void
 onsig(int n GCC_UNUSED)
 {
@@ -147,12 +160,11 @@ part6(DATA * drop)
 static void
 napsome(void)
 {
-    refresh();
     napms(60);
 }
 
 /*
- * This runs inside the mutex.
+ * This runs inside the use_window() mutex.
  */
 static int
 really_draw(WINDOW *win, void *arg)
@@ -162,6 +174,7 @@ really_draw(WINDOW *win, void *arg)
     (void) win;
     next_j(data->state);
     data->func(data);
+    refresh();
     return OK;
 }
 
@@ -174,40 +187,116 @@ draw_part(void (*func) (DATA *), int state, DATA * data)
     napsome();
 }
 
+/*
+ * Tell the threads that one of them can start work on a new raindrop.
+ * They may all be busy if we're sending requests too rapidly.
+ */
+static int
+put_next_drop(void)
+{
+    pthread_cond_signal(&cond_next_drop);
+    pthread_mutex_unlock(&mutex_next_drop);
+
+    return 0;
+}
+
+/*
+ * Wait until we're assigned the task of drawing a new raindrop.
+ */
+static int
+get_next_drop(void)
+{
+    pthread_mutex_lock(&mutex_next_drop);
+    pthread_cond_wait(&cond_next_drop, &mutex_next_drop);
+
+    return TRUE;
+}
+
 static void *
 draw_drop(void *arg)
 {
     DATA mydata;
+    int mystats;
+
+    /*
+     * Find myself in the list of threads so we can count the number of loops.
+     */
+    for (mystats = 0; mystats < MAX_THREADS; ++mystats) {
+       if (drop_threads[mystats].myself == pthread_self())
+           break;
+    }
+
+    do {
+       if (mystats < MAX_THREADS)
+           drop_threads[mystats].counter++;
 
-    mydata = *(DATA *) arg;    /* make a copy of caller's data */
+       /*
+        * Make a copy of caller's data.  We're cheating for the cases after
+        * the first loop since we still have a pointer into the main thread
+        * to the data which it uses for setting up this thread (but it has
+        * been modified to use different coordinates).
+        */
+       mydata = *(DATA *) arg;
 
-    draw_part(part1, 0, &mydata);
-    draw_part(part2, 1, &mydata);
-    draw_part(part3, 2, &mydata);
-    draw_part(part4, 3, &mydata);
-    draw_part(part5, 4, &mydata);
-    draw_part(part6, 0, &mydata);
+       draw_part(part1, 0, &mydata);
+       draw_part(part2, 1, &mydata);
+       draw_part(part3, 2, &mydata);
+       draw_part(part4, 3, &mydata);
+       draw_part(part5, 4, &mydata);
+       draw_part(part6, 0, &mydata);
+    } while (get_next_drop());
 
     return NULL;
 }
+
+/*
+ * The description of pthread_create() is misleading, since it implies that
+ * threads will exit cleanly after their function returns.
+ * 
+ * Since they do not (and the number of threads is limited by system
+ * resources), make a limited number of threads, and signal any that are
+ * waiting when we want a thread past that limit.
+ */
+static int
+start_drop(DATA * data)
+{
+    int rc;
+
+    if (!used_threads) {
+       /* mutex and condition for signalling thread */
+       pthread_mutex_init(&mutex_next_drop, NULL);
+       pthread_cond_init(&cond_next_drop, NULL);
+    }
+
+    if (used_threads < MAX_THREADS) {
+       rc = pthread_create(&(drop_threads[used_threads].myself),
+                           NULL,
+                           draw_drop,
+                           data);
+       ++used_threads;
+    } else {
+       rc = put_next_drop();
+    }
+    return rc;
+}
 #endif
 
 static int
 get_input(void)
 {
-    int ch;
-    ch = USING_WINDOW(stdscr, wgetch);
-    return ch;
+    return USING_WINDOW(stdscr, wgetch);
 }
 
 int
 main(int argc GCC_UNUSED,
      char *argv[]GCC_UNUSED)
 {
+    bool done = FALSE;
     DATA drop;
+#ifndef USE_PTHREADS
     DATA last[MAX_DROP];
+#endif
     int j = 0;
-    bool done = FALSE;
 
     setlocale(LC_ALL, "");
 
@@ -229,20 +318,20 @@ main(int argc GCC_UNUSED,
     curs_set(0);
     timeout(0);
 
+#ifndef USE_PTHREADS
     for (j = MAX_DROP; --j >= 0;) {
        last[j].x = random_x();
        last[j].y = random_y();
     }
+#endif
 
     while (!done) {
        drop.x = random_x();
        drop.y = random_y();
 
 #ifdef USE_PTHREADS
-       if (pthread_create(&(drop.thread), NULL, draw_drop, &drop)) {
+       if (start_drop(&drop) != 0) {
            beep();
-           done = TRUE;
-           continue;
        }
 #else
        /*
@@ -287,5 +376,10 @@ main(int argc GCC_UNUSED,
     }
     curs_set(1);
     endwin();
+#ifdef USE_PTHREADS
+    printf("Counts per thread:\n");
+    for (j = 0; j < MAX_THREADS; ++j)
+       printf("  %d:%ld\n", j, drop_threads[j].counter);
+#endif
     ExitProgram(EXIT_SUCCESS);
 }
index 0eabbcc754779e68714c518d705cb5f470703e5f..d5a8b9a5d00de326eeb78f65c819b068119c3d1e 100644 (file)
@@ -29,7 +29,7 @@
 /****************************************************************************
  *  Author: Thomas E. Dickey                    1996-on                     *
  ****************************************************************************/
-/* $Id: test.priv.h,v 1.74 2008/02/23 23:02:41 tom Exp $ */
+/* $Id: test.priv.h,v 1.75 2008/03/22 19:27:11 tom Exp $ */
 
 #ifndef __TEST_PRIV_H
 #define __TEST_PRIV_H 1
@@ -528,23 +528,36 @@ extern char *tgoto(char *, int, int);     /* available, but not prototyped */
 #define CONST_MENUS /* nothing */
 #endif
 
+#ifndef HAVE_USE_WINDOW
+#if !defined(NCURSES_VERSION_PATCH) || (NCURSES_VERSION_PATCH < 20070915) || !NCURSES_EXT_FUNCS
+#define HAVE_USE_WINDOW 0
+#else
+#define HAVE_USE_WINDOW 1
+#endif
+#endif
+
 /*
  * Simplify setting up demo of threading with these macros.
  */
-#if !defined(NCURSES_VERSION_PATCH) || (NCURSES_VERSION_PATCH < 20070915) || !NCURSES_EXT_FUNCS
+
+#if !HAVE_USE_WINDOW
 typedef int (*NCURSES_CALLBACK)(WINDOW *, void *);
-#define WANT_USE_WINDOW() \
-static int \
-use_window(WINDOW *win, int (*func) (WINDOW *, void *), void *data) \
-{ \
-    return func(win, data); \
-} \
-       extern void _nc_want_use_window(void)
+#endif
+
+#if HAVE_USE_WINDOW
 #define USING_WINDOW(w,func) use_window(w, (NCURSES_CALLBACK) func, w)
+#define WANT_USE_WINDOW() extern void _nc_want_use_window(void)
 #else
-#define WANT_USE_WINDOW() /* nothing */ \
-       extern void _nc_want_use_window(void)
 #define USING_WINDOW(w,func) func(w)
+#define WANT_USE_WINDOW() extern void _nc_want_use_window(void)
+#endif
+
+#if HAVE_USE_WINDOW
+#define USING_SCREEN(s,func,data) use_screen(s, (NCURSES_CALLBACK) func, data)
+#define WANT_USE_SCREEN() extern void _nc_want_use_screen(void)
+#else
+#define USING_SCREEN(s,func,data) func(data)
+#define WANT_USE_SCREEN() extern void _nc_want_use_screen(void)
 #endif
 
 #ifdef TRACE