# ncurses 5.6 - patch 20080322 - Thomas E. Dickey
#
# ------------------------------------------------------------------------------
#
# Ncurses 5.6 is at
# 	ftp.gnu.org:/pub/gnu
#
# Patches for ncurses 5.6 are in the subdirectory
# 	ftp://invisible-island.net/ncurses/5.6
#
# ------------------------------------------------------------------------------
# patch by Thomas E. Dickey <dickey@invisible-island.net>
# created  Sun Mar 23 01:02:37 UTC 2008
# ------------------------------------------------------------------------------
# NEWS                      |   14 ++++
# dist.mk                   |    4 -
# ncurses/base/lib_addch.c  |    5 +
# ncurses/base/lib_bkgd.c   |    6 +-
# ncurses/trace/lib_trace.c |   16 ++++-
# test/ditto.c              |   44 ++++++++++----
# test/ncurses.c            |  129 ++++++++++++++++++++++++++++++++++---------
# test/rain.c               |  132 +++++++++++++++++++++++++++++++++++++-------
# test/test.priv.h          |   35 ++++++++---
# 9 files changed, 307 insertions(+), 78 deletions(-)
# ------------------------------------------------------------------------------
Index: NEWS
Prereq:  1.1213 
--- ncurses-5.6-20080308+/NEWS	2008-03-09 00:21:51.000000000 +0000
+++ ncurses-5.6-20080322/NEWS	2008-03-23 00:18:40.000000000 +0000
@@ -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 @@
 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
Index: dist.mk
Prereq:  1.633 
--- ncurses-5.6-20080308+/dist.mk	2008-03-02 15:19:41.000000000 +0000
+++ ncurses-5.6-20080322/dist.mk	2008-03-22 16:02:24.000000000 +0000
@@ -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 @@
 # 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: ncurses/base/lib_addch.c
Prereq:  1.108 
--- ncurses-5.6-20080308+/ncurses/base/lib_addch.c	2008-02-03 18:50:27.000000000 +0000
+++ ncurses-5.6-20080322/ncurses/base/lib_addch.c	2008-03-22 23:18:28.000000000 +0000
@@ -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 @@
 		       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 @@
 	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: ncurses/base/lib_bkgd.c
Prereq:  1.35 
--- ncurses-5.6-20080308+/ncurses/base/lib_bkgd.c	2006-05-27 19:20:11.000000000 +0000
+++ ncurses-5.6-20080322/ncurses/base/lib_bkgd.c	2008-03-23 00:09:14.000000000 +0000
@@ -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 @@
 
 	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: ncurses/trace/lib_trace.c
Prereq:  1.65 
--- ncurses-5.6-20080308+/ncurses/trace/lib_trace.c	2007-09-29 21:47:46.000000000 +0000
+++ ncurses-5.6-20080322/ncurses/trace/lib_trace.c	2008-03-22 16:56:48.000000000 +0000
@@ -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 @@
     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: test/ditto.c
Prereq:  1.8 
--- ncurses-5.6-20080308+/test/ditto.c	2007-09-01 21:10:38.000000000 +0000
+++ ncurses-5.6-20080322/test/ditto.c	2008-03-22 20:26:31.000000000 +0000
@@ -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 @@
     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 @@
      * 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: test/ncurses.c
Prereq:  1.309 
--- ncurses-5.6-20080308+/test/ncurses.c	2008-03-08 20:57:09.000000000 +0000
+++ ncurses-5.6-20080322/test/ncurses.c	2008-03-22 23:02:57.000000000 +0000
@@ -40,7 +40,7 @@
    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 @@
 {
     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 @@
 }
 
 #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 @@
 	    case '>':
 		adjust_attr_string(1);
 		break;
-	      case_QUIT:
+	    case case_QUIT:
 		result = FALSE;
 		break;
 	    default:
@@ -1654,7 +1690,7 @@
 	    case '>':
 		wide_adjust_attr_string(1);
 		break;
-	      case_QUIT:
+	    case case_QUIT:
 		result = FALSE;
 		break;
 	    default:
@@ -1783,7 +1819,7 @@
 }
 
 static void
-color_legend(WINDOW *helpwin)
+color_legend(WINDOW *helpwin, bool wide)
 {
     int row = 1;
     int col = 1;
@@ -1796,18 +1832,30 @@
     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 @@
     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 @@
 
 		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 @@
 	}
 
 	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 @@
 	case 'N':
 	    opt_nums = TRUE;
 	    break;
-	  case_QUIT:
+	case case_QUIT:
 	    done = TRUE;
 	    continue;
 	case 'w':
@@ -1961,7 +2018,7 @@
 	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 @@
     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 @@
 	    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 @@
 	    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 @@
 	}
 
 	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 @@
 	case 'N':
 	    opt_nums = TRUE;
 	    break;
-	  case_QUIT:
+	case case_QUIT:
 	    done = TRUE;
 	    continue;
 	case 'w':
@@ -2079,6 +2158,12 @@
 	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 @@
 	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 @@
 	    refresh();
 	    break;
 
-	  case_QUIT:
+	case case_QUIT:
 	    break;
 
 	default:
@@ -2508,7 +2593,7 @@
 	    clrtobot();
 	    break;
 
-	  case_QUIT:
+	case case_QUIT:
 	    goto done;
 
 #if HAVE_SLK_COLOR
@@ -2641,7 +2726,7 @@
 	    clrtobot();
 	    break;
 
-	  case_QUIT:
+	case case_QUIT:
 	    goto done;
 
 	case 'F':
@@ -3644,7 +3729,7 @@
 	case KEY_RIGHT:
 	    j++;
 	    break;
-	  case_QUIT:
+	case case_QUIT:
 	    return ((pair *) 0);
 #ifdef NCURSES_MOUSE_VERSION
 	case KEY_MOUSE:
@@ -4137,16 +4222,6 @@
 
 #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)
 {
     int digit;
@@ -4741,7 +4816,7 @@
 		c = KEY_DC;
 		break;
 	    case ERR:		/* FALLTHRU */
-	      case_QUIT:
+	    case case_QUIT:
 		count = 0;
 		c = KEY_EXIT;
 		break;
Index: test/rain.c
Prereq:  1.26 
--- ncurses-5.6-20080308+/test/rain.c	2008-03-09 00:17:09.000000000 +0000
+++ ncurses-5.6-20080322/test/rain.c	2008-03-22 18:12:01.000000000 +0000
@@ -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 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 @@
 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 @@
     (void) win;
     next_j(data->state);
     data->func(data);
+    refresh();
     return OK;
 }
 
@@ -174,40 +187,116 @@
     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;
 
-    mydata = *(DATA *) arg;	/* make a copy of caller's data */
+    /*
+     * 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;
+    }
 
-    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);
+    do {
+	if (mystats < MAX_THREADS)
+	    drop_threads[mystats].counter++;
+
+	/*
+	 * 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);
+    } 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 @@
     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 @@
     }
     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: test/test.priv.h
Prereq:  1.74 
--- ncurses-5.6-20080308+/test/test.priv.h	2008-02-23 23:02:41.000000000 +0000
+++ ncurses-5.6-20080322/test/test.priv.h	2008-03-22 19:27:11.000000000 +0000
@@ -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 @@
 #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
