ncurses 5.6 - patch 20080503
authorThomas E. Dickey <dickey@invisible-island.net>
Sun, 4 May 2008 00:48:16 +0000 (00:48 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sun, 4 May 2008 00:48:16 +0000 (00:48 +0000)
+ modify screen.* terminfo entries using new screen+fkeys to fix
  overridden keys in screen.rxvt (Debian #478094) -TD
+ modify internal interfaces to reduce wgetch()'s dependency on the
  global SP.
+ simplify some loops with macros each_screen(), each_window() and
  each_ripoff().
+ continue modifying test/ditto.c toward making it demonstrate
  multithreaded use_screen(), using fifos to pass data between screens.
+ fix typo in form.3x (report by Mike Gran).

25 files changed:
NEWS
dist.mk
man/form.3x
misc/terminfo.src
ncurses/base/lib_delwin.c
ncurses/base/lib_freeall.c
ncurses/base/lib_getch.c
ncurses/base/lib_newwin.c
ncurses/base/lib_restart.c
ncurses/base/lib_set_term.c
ncurses/base/lib_ungetch.c
ncurses/base/resizeterm.c
ncurses/base/use_window.c
ncurses/base/wresize.c
ncurses/curses.priv.h
ncurses/fifo_defs.h
ncurses/tinfo/init_keytry.c
ncurses/tinfo/lib_napms.c
ncurses/tinfo/lib_options.c
ncurses/tinfo/lib_setup.c
ncurses/tinfo/lib_ttyflags.c
ncurses/tty/lib_tstp.c
ncurses/tty/lib_twait.c
ncurses/tty/tty_update.c
test/ditto.c

diff --git a/NEWS b/NEWS
index 0a2f4b81ea03005c8e7c7d4f202134096ce6966c..c5126da03699bd0047554119eadfa91e861d00e4 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.1228 2008/04/19 23:03:52 tom Exp $
+-- $Id: NEWS,v 1.1233 2008/05/03 23:14:39 tom Exp $
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
@@ -45,6 +45,19 @@ 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.
 
+20080503
+       + modify screen.* terminfo entries using new screen+fkeys to fix
+         overridden keys in screen.rxvt (Debian #478094) -TD
+       + modify internal interfaces to reduce wgetch()'s dependency on the
+         global SP.
+       + simplify some loops with macros each_screen(), each_window() and
+         each_ripoff().
+
+20080426
+       + continue modifying test/ditto.c toward making it demonstrate
+         multithreaded use_screen(), using fifos to pass data between screens.
+       + fix typo in form.3x (report by Mike Gran).
+
 20080419
        + add screen.rxvt terminfo entry -TD
        + modify tic -f option to format spaces as \s to prevent them from
diff --git a/dist.mk b/dist.mk
index d2923b7e8bdc0f4af43a3a18ab8e8f2acd6a1d2d..f4becd9bdfc6c78fee07d75abd1ac18ce88e44c8 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.639 2008/04/19 16:27:47 tom Exp $
+# $Id: dist.mk,v 1.641 2008/05/03 12:31:08 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 = 20080419
+NCURSES_PATCH = 20080503
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
index 264662e664ae5367ff759b30c3192af3952fbacc..75fc78aee2d461552b5c07d9845013f4403f1dfc 100644 (file)
@@ -1,6 +1,6 @@
 '\" t
 .\"***************************************************************************
-.\" Copyright (c) 1998-2002,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            *
@@ -27,7 +27,7 @@
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
-.\" $Id: form.3x,v 1.20 2006/11/04 18:50:09 tom Exp $
+.\" $Id: form.3x,v 1.21 2008/04/26 17:11:52 tom Exp $
 .TH form 3X ""
 .SH NAME
 \fBform\fR - curses extension for programming forms
@@ -69,7 +69,7 @@ current_field \fBform_page\fR(3X)
 data_ahead     \fBform_data\fR(3X)
 data_behind    \fBform_data\fR(3X)
 dup_field      \fBform_field_new\fR(3X)
-dynamic_fieldinfo      \fBform_field_info\fR(3X)
+dynamic_field_info     \fBform_field_info\fR(3X)
 field_arg      \fBform_field_validation\fR(3X)
 field_back     \fBform_field_attributes\fR(3X)
 field_buffer   \fBform_field_buffer\fR(3X)
index e86848f29bbe2bf9ffe422daedd801f4e858b493..8627cece61c9d94601899b2ced23010454701146 100644 (file)
@@ -6,8 +6,8 @@
 # Report bugs and new terminal descriptions to
 #      bug-ncurses@gnu.org
 #
-#      $Revision: 1.327 $
-#      $Date: 2008/04/19 22:51:50 $
+#      $Revision: 1.328 $
+#      $Date: 2008/04/29 00:49:41 $
 #
 # The original header is preserved below for reference.  It is noted that there
 # is a "newer" version which differs in some cosmetic details (but actually
@@ -4359,13 +4359,20 @@ screen-256color-bce-s|GNU Screen with 256 colors, BCE, and status line,
 #       if the terminal is wide (132 cols or more)).  If even this
 #       entry cannot be found, "vt100" is used as a substitute.
 #
+# Notwithstanding the manpage, screen uses its own notion of the termcap
+# and some keys from "screen.<term>" are ignored.  Here is an entry which
+# covers those (tested with screen 4.00.02) -TD
+screen+fkeys|function-keys according to screen,
+       kend=\E[4~, kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kfnd@,
+       khome=\E[1~, kslt@,
+#
 # Here are a few customized entries which are useful -TD
 #
 # Notes:
 # (a)  screen does not support invis.
 # (b)  screen's implementation of bw is incorrect according to tack.
 # (c)  screen appears to hardcode the strings for khome/kend, making it
-#      necessary to override the "use=" clause's values.
+#      necessary to override the "use=" clause's values (screen+fkeys).
 # (d)  screen sets $TERMCAP to a termcap-formatted copy of the 'screen' entry,
 #      which is NOT the same as the terminfo screen.<term>.
 # (e)  when screen finds one of these customized entries, it sets $TERM to
@@ -4377,31 +4384,29 @@ screen-256color-bce-s|GNU Screen with 256 colors, BCE, and status line,
 #      translation.  They are suppressed here to show what is tested by tack.
 screen.xterm-xfree86|screen.xterm-new|screen customized for modern xterm,
        bce@, bw,
-       invis@, kIC@, kNXT@, kPRV@, kend=\E[4~, khome=\E[1~, meml@,
-       memu@,
+       invis@, kIC@, kNXT@, kPRV@, meml@, memu@,
        sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m,
-       use=xterm-new,
+       use=screen+fkeys, use=xterm-new,
 # xterm-r6 does not really support khome/kend unless it is propped up by
 # the translations resource.
 screen.xterm-r6|screen customized for X11R6 xterm,
-       bw, use=xterm-r6,
+       bw, use=screen+fkeys, use=xterm-r6,
 # Color applications running in screen and TeraTerm do not play well together
 # on Solaris because Sun's curses implementation gets confused.
 screen.teraterm|disable ncv in teraterm,
        ncv#127,
        acsc=+\020\,\021-\030.^Y0\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
-       use=screen,
+       use=screen+fkeys, use=screen,
 # Other terminals
 screen.rxvt|screen in rxvt,
        bw,
        cvvis@, flash@, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC,
-       kcuu1=\EOA, kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS,
-       use=vt100+enq, use=rxvt+pcfkeys, use=vt220+keypad,
-       use=screen,
+       kcuu1=\EOA, use=screen+fkeys, use=vt100+enq,
+       use=rxvt+pcfkeys, use=vt220+keypad, use=screen,
 # fix the backspace key
 screen.linux|screen in linux console,
        bw,
-       kbs=\177, kcbt@, use=screen,
+       kbs=\177, kcbt@, use=screen+fkeys, use=screen,
 
 screen-w|VT 100/ANSI X3.64 virtual terminal with 132 cols,
        cols#132, use=screen,
@@ -21668,9 +21673,12 @@ v3220|LANPAR Vision II model 3220/3221/3222,
 #      * add xterm+app, xterm+noapp, from xterm #230 -TD
 #      * add/use xterm+pce2 from xterm #230, in xterm+pcfkeys -TD
 #
-# 2007-04-19
+# 2008-04-19
 #      * add screen.rxvt -TD
 #
+# 2008-04-28
+#      * add screen+fkeys (prompted by Debian # 478094) -TD
+#
 # The following sets edit modes for GNU EMACS.
 # Local Variables:
 # fill-prefix:"\t"
index fc68f9d68deeef6f3f7d1065e0151947ceb53a9f..ba5f180d5f3c9e488103b2c8c550a8d63d209d60 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2001,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            *
@@ -40,7 +40,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_delwin.c,v 1.15 2007/12/22 23:34:26 tom Exp $")
+MODULE_ID("$Id: lib_delwin.c,v 1.16 2008/05/03 14:13:51 tom Exp $")
 
 static bool
 cannot_delete(WINDOW *win)
@@ -48,7 +48,7 @@ cannot_delete(WINDOW *win)
     WINDOWLIST *p;
     bool result = TRUE;
 
-    for (p = _nc_windows; p != 0; p = p->next) {
+    for (each_window(p)) {
        if (&(p->win) == win) {
            result = FALSE;
        } else if ((p->win._flags & _SUBWIN) != 0
index dbf0483f24016d8f4532077f8f1396d18449a2f5..4bb7ccc799958ea9e9dcb79b349c7428c88da0aa 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            *
@@ -40,7 +40,7 @@
 extern int malloc_errfd;       /* FIXME */
 #endif
 
-MODULE_ID("$Id: lib_freeall.c,v 1.45 2007/12/22 23:29:37 tom Exp $")
+MODULE_ID("$Id: lib_freeall.c,v 1.46 2008/05/03 14:13:51 tom Exp $")
 
 /*
  * Free all ncurses data.  This is used for testing only (there's no practical
@@ -67,10 +67,10 @@ _nc_freeall(void)
            bool deleted = FALSE;
 
            /* Delete only windows that're not a parent */
-           for (p = _nc_windows; p != 0; p = p->next) {
+           for (each_window(p)) {
                bool found = FALSE;
 
-               for (q = _nc_windows; q != 0; q = q->next) {
+               for (each_window(q)) {
                    if ((p != q)
                        && (q->win._flags & _SUBWIN)
                        && (&(p->win) == q->win._parent)) {
index 11e8052a668c6c8a430ac660162ed3caa8259acb..d9f6b1795c77d83b7579db9a01026b06b40f858f 100644 (file)
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_getch.c,v 1.82 2008/01/19 21:07:30 tom Exp $")
+MODULE_ID("$Id: lib_getch.c,v 1.87 2008/05/03 22:42:10 tom Exp $")
 
 #include <fifo_defs.h>
 
 #if USE_REENTRANT
+#define GetEscdelay(sp) (sp)->_ESCDELAY
 NCURSES_EXPORT(int)
 NCURSES_PUBLIC_VAR(ESCDELAY) (void)
 {
-    return SP ? SP->_ESCDELAY : 1000;
+    return SP ? GetEscdelay(SP) : 1000;
 }
 #else
+#define GetEscdelay(sp) ESCDELAY
 NCURSES_EXPORT_VAR(int)
 ESCDELAY = 1000;               /* max interval betw. chars in funkeys, in millisecs */
 #endif
@@ -84,20 +86,20 @@ set_escdelay(int value)
  * Check for mouse activity, returning nonzero if we find any.
  */
 static int
-check_mouse_activity(int delay EVENTLIST_2nd(_nc_eventlist * evl))
+check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl))
 {
     int rc;
 
 #if USE_SYSMOUSE
-    if ((SP->_mouse_type == M_SYSMOUSE)
-       && (SP->_sysmouse_head < SP->_sysmouse_tail)) {
+    if ((sp->_mouse_type == M_SYSMOUSE)
+       && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
        return 2;
     }
 #endif
-    rc = _nc_timed_wait(TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl));
+    rc = _nc_timed_wait(sp, TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl));
 #if USE_SYSMOUSE
-    if ((SP->_mouse_type == M_SYSMOUSE)
-       && (SP->_sysmouse_head < SP->_sysmouse_tail)
+    if ((sp->_mouse_type == M_SYSMOUSE)
+       && (sp->_sysmouse_head < sp->_sysmouse_tail)
        && (rc == 0)
        && (errno == EINTR)) {
        rc |= 2;
@@ -107,9 +109,9 @@ check_mouse_activity(int delay EVENTLIST_2nd(_nc_eventlist * evl))
 }
 
 static NCURSES_INLINE int
-fifo_peek(void)
+fifo_peek(SCREEN *sp)
 {
-    int ch = SP->_fifo[peek];
+    int ch = sp->_fifo[peek];
     TR(TRACE_IEVENT, ("peeking at %d", peek));
 
     p_inc();
@@ -117,10 +119,10 @@ fifo_peek(void)
 }
 
 static NCURSES_INLINE int
-fifo_pull(void)
+fifo_pull(SCREEN *sp)
 {
     int ch;
-    ch = SP->_fifo[head];
+    ch = sp->_fifo[head];
     TR(TRACE_IEVENT, ("pulling %s from %d", _tracechar(ch), head));
 
     if (peek == head) {
@@ -131,7 +133,7 @@ fifo_pull(void)
 
 #ifdef TRACE
     if (USE_TRACEF(TRACE_IEVENT)) {
-       _nc_fifo_dump();
+       _nc_fifo_dump(sp);
        _nc_unlock_global(tracef);
     }
 #endif
@@ -139,7 +141,7 @@ fifo_pull(void)
 }
 
 static NCURSES_INLINE int
-fifo_push(EVENTLIST_0th(_nc_eventlist * evl))
+fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl))
 {
     int n;
     int ch = 0;
@@ -157,47 +159,47 @@ fifo_push(EVENTLIST_0th(_nc_eventlist * evl))
 #ifdef NCURSES_WGETCH_EVENTS
     if (evl
 #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
-       || (SP->_mouse_fd >= 0)
+       || (sp->_mouse_fd >= 0)
 #endif
        ) {
-       mask = check_mouse_activity(-1 EVENTLIST_2nd(evl));
+       mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl));
     } else
        mask = 0;
 
     if (mask & 4) {
        T(("fifo_push: ungetch KEY_EVENT"));
-       ungetch(KEY_EVENT);
+       _nc_ungetch(sp, KEY_EVENT);
        return KEY_EVENT;
     }
 #elif USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
-    if (SP->_mouse_fd >= 0) {
-       mask = check_mouse_activity(-1 EVENTLIST_2nd(evl));
+    if (sp->_mouse_fd >= 0) {
+       mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl));
     }
 #endif
 
 #if USE_GPM_SUPPORT || USE_EMX_MOUSE
-    if ((SP->_mouse_fd >= 0) && (mask & 2)) {
-       SP->_mouse_event(SP);
+    if ((sp->_mouse_fd >= 0) && (mask & 2)) {
+       sp->_mouse_event(sp);
        ch = KEY_MOUSE;
        n = 1;
     } else
 #endif
 #if USE_SYSMOUSE
-       if ((SP->_mouse_type == M_SYSMOUSE)
-           && (SP->_sysmouse_head < SP->_sysmouse_tail)) {
-       SP->_mouse_event(SP);
+       if ((sp->_mouse_type == M_SYSMOUSE)
+           && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
+       sp->_mouse_event(sp);
        ch = KEY_MOUSE;
        n = 1;
-    } else if ((SP->_mouse_type == M_SYSMOUSE)
+    } else if ((sp->_mouse_type == M_SYSMOUSE)
               && (mask <= 0) && errno == EINTR) {
-       SP->_mouse_event(SP);
+       sp->_mouse_event(sp);
        ch = KEY_MOUSE;
        n = 1;
     } else
 #endif
     {                          /* Can block... */
        unsigned char c2 = 0;
-       n = read(SP->_ifd, &c2, 1);
+       n = read(sp->_ifd, &c2, 1);
        ch = c2;
     }
 
@@ -216,20 +218,20 @@ fifo_push(EVENTLIST_0th(_nc_eventlist * evl))
 #endif
 
     if ((n == -1) || (n == 0)) {
-       TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", SP->_ifd, n, errno));
+       TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno));
        ch = ERR;
     }
     TR(TRACE_IEVENT, ("read %d characters", n));
 
-    SP->_fifo[tail] = ch;
-    SP->_fifohold = 0;
+    sp->_fifo[tail] = ch;
+    sp->_fifohold = 0;
     if (head == -1)
        head = peek = tail;
     t_inc();
     TR(TRACE_IEVENT, ("pushed %s at %d", _tracechar(ch), tail));
 #ifdef TRACE
     if (USE_TRACEF(TRACE_IEVENT)) {
-       _nc_fifo_dump();
+       _nc_fifo_dump(sp);
        _nc_unlock_global(tracef);
     }
 #endif
@@ -237,14 +239,14 @@ fifo_push(EVENTLIST_0th(_nc_eventlist * evl))
 }
 
 static NCURSES_INLINE void
-fifo_clear(void)
+fifo_clear(SCREEN *sp)
 {
-    memset(SP->_fifo, 0, sizeof(SP->_fifo));
+    memset(sp->_fifo, 0, sizeof(sp->_fifo));
     head = -1;
     tail = peek = 0;
 }
 
-static int kgetch(EVENTLIST_0th(_nc_eventlist * evl));
+static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl));
 
 #define wgetch_should_refresh(win) (\
        (is_wintouched(win) || (win->_flags & _HASMOVED)) \
@@ -256,6 +258,7 @@ _nc_wgetch(WINDOW *win,
           int use_meta
           EVENTLIST_2nd(_nc_eventlist * evl))
 {
+    SCREEN *sp = SP;
     int ch;
 #ifdef NCURSES_WGETCH_EVENTS
     long event_delay = -1;
@@ -264,7 +267,7 @@ _nc_wgetch(WINDOW *win,
     T((T_CALLED("_nc_wgetch(%p)"), win));
 
     *result = 0;
-    if (win == 0 || SP == 0) {
+    if (win == 0 || sp == 0) {
        returnCode(ERR);
     }
 
@@ -272,7 +275,7 @@ _nc_wgetch(WINDOW *win,
        if (wgetch_should_refresh(win))
            wrefresh(win);
 
-       *result = fifo_pull();
+       *result = fifo_pull(sp);
        returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
     }
 #ifdef NCURSES_WGETCH_EVENTS
@@ -287,26 +290,26 @@ _nc_wgetch(WINDOW *win,
      * the first character to return it.
      */
     if (head == -1 &&
-       !SP->_notty &&
-       !SP->_raw &&
-       !SP->_cbreak &&
-       !SP->_called_wgetch) {
-       char buf[MAXCOLUMNS], *sp;
+       !sp->_notty &&
+       !sp->_raw &&
+       !sp->_cbreak &&
+       !sp->_called_wgetch) {
+       char buf[MAXCOLUMNS], *bufp;
        int rc;
 
        TR(TRACE_IEVENT, ("filling queue in cooked mode"));
 
-       SP->_called_wgetch = TRUE;
+       sp->_called_wgetch = TRUE;
        rc = wgetnstr(win, buf, MAXCOLUMNS);
-       SP->_called_wgetch = FALSE;
+       sp->_called_wgetch = FALSE;
 
        /* ungetch in reverse order */
 #ifdef NCURSES_WGETCH_EVENTS
        if (rc != KEY_EVENT)
 #endif
-           ungetch('\n');
-       for (sp = buf + strlen(buf); sp > buf; sp--)
-           ungetch(sp[-1]);
+           _nc_ungetch(sp, '\n');
+       for (bufp = buf + strlen(buf); bufp > buf; bufp--)
+           _nc_ungetch(sp, bufp[-1]);
 
 #ifdef NCURSES_WGETCH_EVENTS
        /* Return it first */
@@ -314,24 +317,24 @@ _nc_wgetch(WINDOW *win,
            *result = rc;
        } else
 #endif
-           *result = fifo_pull();
+           *result = fifo_pull(sp);
        returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
     }
 
-    if (win->_use_keypad != SP->_keypad_on)
-       _nc_keypad(win->_use_keypad);
+    if (win->_use_keypad != sp->_keypad_on)
+       _nc_keypad(sp, win->_use_keypad);
 
     if (wgetch_should_refresh(win))
        wrefresh(win);
 
-    if (!win->_notimeout && (win->_delay >= 0 || SP->_cbreak > 1)) {
+    if (!win->_notimeout && (win->_delay >= 0 || sp->_cbreak > 1)) {
        if (head == -1) {       /* fifo is empty */
            int delay;
            int rc;
 
            TR(TRACE_IEVENT, ("timed delay in wgetch()"));
-           if (SP->_cbreak > 1)
-               delay = (SP->_cbreak - 1) * 100;
+           if (sp->_cbreak > 1)
+               delay = (sp->_cbreak - 1) * 100;
            else
                delay = win->_delay;
 
@@ -342,7 +345,7 @@ _nc_wgetch(WINDOW *win,
 
            TR(TRACE_IEVENT, ("delay is %d milliseconds", delay));
 
-           rc = check_mouse_activity(delay EVENTLIST_2nd(evl));
+           rc = check_mouse_activity(sp, delay EVENTLIST_2nd(evl));
 
 #ifdef NCURSES_WGETCH_EVENTS
            if (rc & 4) {
@@ -372,23 +375,23 @@ _nc_wgetch(WINDOW *win,
        int rc;
 
        do {
-           ch = kgetch(EVENTLIST_1st(evl));
+           ch = kgetch(sp EVENTLIST_2nd(evl));
            if (ch == KEY_MOUSE) {
                ++runcount;
-               if (SP->_mouse_inline(SP))
+               if (sp->_mouse_inline(sp))
                    break;
            }
-           if (SP->_maxclick < 0)
+           if (sp->_maxclick < 0)
                break;
        } while
            (ch == KEY_MOUSE
-            && (((rc = check_mouse_activity(SP->_maxclick
+            && (((rc = check_mouse_activity(sp, sp->_maxclick
                                             EVENTLIST_2nd(evl))) != 0
                  && !(rc & 4))
-                || !SP->_mouse_parse(runcount)));
+                || !sp->_mouse_parse(runcount)));
 #ifdef NCURSES_WGETCH_EVENTS
        if ((rc & 4) && !ch == KEY_EVENT) {
-           ungetch(ch);
+           _nc_ungetch(sp, ch);
            ch = KEY_EVENT;
        }
 #endif
@@ -396,28 +399,28 @@ _nc_wgetch(WINDOW *win,
 #ifdef NCURSES_WGETCH_EVENTS
            /* mouse event sequence ended by an event, report event */
            if (ch == KEY_EVENT) {
-               ungetch(KEY_MOUSE);     /* FIXME This interrupts a gesture... */
+               _nc_ungetch(sp, KEY_MOUSE);     /* FIXME This interrupts a gesture... */
            } else
 #endif
            {
                /* mouse event sequence ended by keystroke, store keystroke */
-               ungetch(ch);
+               _nc_ungetch(sp, ch);
                ch = KEY_MOUSE;
            }
        }
     } else {
        if (head == -1)
-           fifo_push(EVENTLIST_1st(evl));
-       ch = fifo_pull();
+           fifo_push(sp EVENTLIST_2nd(evl));
+       ch = fifo_pull(sp);
     }
 
     if (ch == ERR) {
 #if USE_SIZECHANGE
-       if (_nc_handle_sigwinch(FALSE)) {
-           _nc_update_screensize();
+       if (_nc_handle_sigwinch(sp)) {
+           _nc_update_screensize(sp);
            /* resizeterm can push KEY_RESIZE */
            if (cooked_key_in_fifo()) {
-               *result = fifo_pull();
+               *result = fifo_pull(sp);
                returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
            }
        }
@@ -443,7 +446,7 @@ _nc_wgetch(WINDOW *win,
      * However, we provide the same visual result as Solaris, moving the
      * cursor to the left.
      */
-    if (SP->_echo && !(win->_flags & _ISPAD)) {
+    if (sp->_echo && !(win->_flags & _ISPAD)) {
        chtype backup = (ch == KEY_BACKSPACE) ? '\b' : ch;
        if (backup < KEY_MIN)
            wechochar(win, backup);
@@ -452,7 +455,7 @@ _nc_wgetch(WINDOW *win,
     /*
      * Simulate ICRNL mode
      */
-    if ((ch == '\r') && SP->_nl)
+    if ((ch == '\r') && sp->_nl)
        ch = '\n';
 
     /* Strip 8th-bit if so desired.  We do this only for characters that
@@ -474,13 +477,14 @@ _nc_wgetch(WINDOW *win,
 NCURSES_EXPORT(int)
 wgetch_events(WINDOW *win, _nc_eventlist * evl)
 {
+    SCREEN *sp = SP;
     int code;
     unsigned long value;
 
     T((T_CALLED("wgetch_events(%p,%p)"), win, evl));
     code = _nc_wgetch(win,
                      &value,
-                     SP->_use_meta
+                     sp->_use_meta
                      EVENTLIST_2nd(evl));
     if (code != ERR)
        code = value;
@@ -491,13 +495,14 @@ wgetch_events(WINDOW *win, _nc_eventlist * evl)
 NCURSES_EXPORT(int)
 wgetch(WINDOW *win)
 {
+    SCREEN *sp = SP;
     int code;
     unsigned long value;
 
     T((T_CALLED("wgetch(%p)"), win));
     code = _nc_wgetch(win,
                      &value,
-                     (SP ? SP->_use_meta : 0)
+                     (sp ? sp->_use_meta : 0)
                      EVENTLIST_2nd((_nc_eventlist *) 0));
     if (code != ERR)
        code = value;
@@ -520,21 +525,21 @@ wgetch(WINDOW *win)
 */
 
 static int
-kgetch(EVENTLIST_0th(_nc_eventlist * evl))
+kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl))
 {
     TRIES *ptr;
     int ch = 0;
-    int timeleft = ESCDELAY;
+    int timeleft = GetEscdelay(sp);
 
     TR(TRACE_IEVENT, ("kgetch() called"));
 
-    ptr = SP->_keytry;
+    ptr = sp->_keytry;
 
     for (;;) {
-       if (cooked_key_in_fifo() && SP->_fifo[head] >= KEY_MIN) {
+       if (cooked_key_in_fifo() && sp->_fifo[head] >= KEY_MIN) {
            break;
        } else if (!raw_key_in_fifo()) {
-           ch = fifo_push(EVENTLIST_1st(evl));
+           ch = fifo_push(sp EVENTLIST_2nd(evl));
            if (ch == ERR) {
                peek = head;    /* the keys stay uninterpreted */
                return ERR;
@@ -542,12 +547,12 @@ kgetch(EVENTLIST_0th(_nc_eventlist * evl))
 #ifdef NCURSES_WGETCH_EVENTS
            else if (ch == KEY_EVENT) {
                peek = head;    /* the keys stay uninterpreted */
-               return fifo_pull();     /* Remove KEY_EVENT from the queue */
+               return fifo_pull(sp);   /* Remove KEY_EVENT from the queue */
            }
 #endif
        }
 
-       ch = fifo_peek();
+       ch = fifo_peek(sp);
        if (ch >= KEY_MIN) {
            /* If not first in queue, somebody put this key there on purpose in
             * emergency.  Consider it higher priority than the unfinished
@@ -573,7 +578,7 @@ kgetch(EVENTLIST_0th(_nc_eventlist * evl))
        if (ptr->value != 0) {  /* sequence terminated */
            TR(TRACE_IEVENT, ("end of sequence"));
            if (peek == tail)
-               fifo_clear();
+               fifo_clear(sp);
            else
                head = peek;
            return (ptr->value);
@@ -585,7 +590,7 @@ kgetch(EVENTLIST_0th(_nc_eventlist * evl))
            int rc;
 
            TR(TRACE_IEVENT, ("waiting for rest of sequence"));
-           rc = check_mouse_activity(timeleft EVENTLIST_2nd(evl));
+           rc = check_mouse_activity(sp, timeleft EVENTLIST_2nd(evl));
 #ifdef NCURSES_WGETCH_EVENTS
            if (rc & 4) {
                TR(TRACE_IEVENT, ("interrupted by a user event"));
@@ -600,7 +605,7 @@ kgetch(EVENTLIST_0th(_nc_eventlist * evl))
            }
        }
     }
-    ch = fifo_pull();
+    ch = fifo_pull(sp);
     peek = head;
     return ch;
 }
index 84763c93fc27277803d39d67aa63611a2d44cb18..7f7aa3e04f1e8ca01f66e88008ebd9fc2f41ef10 100644 (file)
@@ -42,9 +42,9 @@
 #include <curses.priv.h>
 #include <stddef.h>
 
-MODULE_ID("$Id: lib_newwin.c,v 1.46 2008/04/05 19:16:42 tom Exp $")
+MODULE_ID("$Id: lib_newwin.c,v 1.50 2008/05/03 16:36:39 tom Exp $")
 
-#define window_is(name) (sp->_##name == win)
+#define window_is(name) ((sp)->_##name == win)
 
 #if USE_REENTRANT
 #define remove_window(name) \
@@ -56,27 +56,23 @@ MODULE_ID("$Id: lib_newwin.c,v 1.46 2008/04/05 19:16:42 tom Exp $")
                    name = 0
 #endif
 
-static WINDOW *
+static void
 remove_window_from_screen(WINDOW *win)
 {
-    SCREEN **scan = &_nc_screen_chain;
+    SCREEN *sp;
 
-    while (*scan) {
-       SCREEN *sp = *scan;
+    for (each_screen(sp)) {
        if (window_is(curscr)) {
            remove_window(curscr);
+           break;
        } else if (window_is(stdscr)) {
            remove_window(stdscr);
+           break;
        } else if (window_is(newscr)) {
            remove_window(newscr);
-       } else {
-           scan = &(*scan)->_next_screen;
-           continue;
+           break;
        }
-       break;
     }
-
-    return 0;
 }
 
 NCURSES_EXPORT(int)
@@ -90,7 +86,8 @@ _nc_freewin(WINDOW *win)
 
     if (win != 0) {
        if (_nc_try_global(windowlist) == 0) {
-           for (p = _nc_windows, q = 0; p != 0; q = p, p = p->next) {
+           q = 0;
+           for (each_window(p)) {
                if (&(p->win) == win) {
                    remove_window_from_screen(win);
                    if (q == 0)
@@ -109,6 +106,7 @@ _nc_freewin(WINDOW *win)
                    T(("...deleted win=%p", win));
                    break;
                }
+               q = p;
            }
            _nc_unlock_global(windowlist);
        }
index 858ef65a645d7ef0a3313171aa3198d4fbc7f560..9742ff629fbddc6580c867acc1a7957978cc0dab 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            *
@@ -48,7 +48,7 @@
 
 #include <term.h>              /* lines, columns, cur_term */
 
-MODULE_ID("$Id: lib_restart.c,v 1.8 2007/10/13 19:59:47 tom Exp $")
+MODULE_ID("$Id: lib_restart.c,v 1.9 2008/05/03 22:43:52 tom Exp $")
 
 NCURSES_EXPORT(int)
 restartterm(NCURSES_CONST char *termp, int filenum, int *errret)
@@ -88,7 +88,7 @@ restartterm(NCURSES_CONST char *termp, int filenum, int *errret)
        reset_prog_mode();
 
 #if USE_SIZECHANGE
-       _nc_update_screensize();
+       _nc_update_screensize(SP);
 #endif
 
        result = OK;
index 3f84706016318dd48686599e56c5f9514087e43f..eee1cfc7b2590b463e4695e5483c77a8851f91ed 100644 (file)
@@ -44,7 +44,7 @@
 #include <term.h>              /* cur_term */
 #include <tic.h>
 
-MODULE_ID("$Id: lib_set_term.c,v 1.106 2008/03/29 22:47:24 tom Exp $")
+MODULE_ID("$Id: lib_set_term.c,v 1.108 2008/05/03 22:42:43 tom Exp $")
 
 NCURSES_EXPORT(SCREEN *)
 set_term(SCREEN *screenp)
@@ -94,26 +94,39 @@ _nc_free_keytry(TRIES * kt)
     }
 }
 
+static bool
+delink_screen(SCREEN *sp)
+{
+    SCREEN *last = 0;
+    SCREEN *temp;
+    bool result = FALSE;
+
+    for (each_screen(temp)) {
+       if (temp == sp) {
+           if (last)
+               last = sp->_next_screen;
+           else
+               _nc_screen_chain = sp->_next_screen;
+           result = TRUE;
+           break;
+       }
+       last = temp;
+    }
+    return result;
+}
+
 /*
  * Free the storage associated with the given SCREEN sp.
  */
 NCURSES_EXPORT(void)
 delscreen(SCREEN *sp)
 {
-    SCREEN **scan = &_nc_screen_chain;
     int i;
 
     T((T_CALLED("delscreen(%p)"), sp));
 
-    if (sp != 0) {
-       _nc_lock_global(set_SP);
-       while (*scan) {
-           if (*scan == sp) {
-               *scan = sp->_next_screen;
-               break;
-           }
-           scan = &(*scan)->_next_screen;
-       }
+    _nc_lock_global(set_SP);
+    if (delink_screen(sp)) {
 
        (void) _nc_freewin(sp->_curscr);
        (void) _nc_freewin(sp->_newscr);
@@ -180,8 +193,8 @@ delscreen(SCREEN *sp)
 #endif
            _nc_set_screen(0);
        }
-       _nc_unlock_global(set_SP);
     }
+    _nc_unlock_global(set_SP);
 
     returnVoid;
 }
@@ -267,7 +280,7 @@ _nc_setupscreen(int slines GCC_UNUSED,
     /*
      * We should always check the screensize, just in case.
      */
-    _nc_get_screensize(&slines, &scolumns);
+    _nc_get_screensize(SP, &slines, &scolumns);
     SET_LINES(slines);
     SET_COLS(scolumns);
     T((T_CREATE("screen %s %dx%d"), termname(), LINES, COLS));
index 9570a33edc5eb45e034d2f4dc8b5e20d778b0106..2eda99017bed066b226bd0c51998fee640aacf6f 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2002,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,6 +29,7 @@
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
  ****************************************************************************/
 
 /*
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_ungetch.c,v 1.9 2007/09/29 21:49:56 tom Exp $")
+MODULE_ID("$Id: lib_ungetch.c,v 1.10 2008/05/03 20:20:58 tom Exp $")
 
 #include <fifo_defs.h>
 
 #ifdef TRACE
 NCURSES_EXPORT(void)
-_nc_fifo_dump(void)
+_nc_fifo_dump(SCREEN *sp)
 {
     int i;
     T(("head = %d, tail = %d, peek = %d", head, tail, peek));
     for (i = 0; i < 10; i++)
-       T(("char %d = %s", i, _tracechar(SP->_fifo[i])));
+       T(("char %d = %s", i, _tracechar(sp->_fifo[i])));
 }
 #endif /* TRACE */
 
 NCURSES_EXPORT(int)
-ungetch(int ch)
+_nc_ungetch(SCREEN *sp, int ch)
 {
-    T((T_CALLED("ungetch(%s)"), _tracechar(ch)));
+    int rc = ERR;
 
-    if (tail == -1)
-       returnCode(ERR);
-    if (head == -1) {
-       head = 0;
-       t_inc()
+    if (tail != -1) {
+       if (head == -1) {
+           head = 0;
+           t_inc();
            peek = tail;        /* no raw keys */
-    } else
-       h_dec();
+       } else
+           h_dec();
 
-    SP->_fifo[head] = ch;
-    T(("ungetch %s ok", _tracechar(ch)));
+       sp->_fifo[head] = ch;
+       T(("ungetch %s ok", _tracechar(ch)));
 #ifdef TRACE
-    if (USE_TRACEF(TRACE_IEVENT)) {
-       _nc_fifo_dump();
-       _nc_unlock_global(tracef);
-    }
+       if (USE_TRACEF(TRACE_IEVENT)) {
+           _nc_fifo_dump(sp);
+           _nc_unlock_global(tracef);
+       }
 #endif
-    returnCode(OK);
+       rc = OK;
+    }
+    return rc;
+}
+
+NCURSES_EXPORT(int)
+ungetch(int ch)
+{
+    T((T_CALLED("ungetch(%s)"), _tracechar(ch)));
+    returnCode(_nc_ungetch(SP, ch));
 }
index eb2dd737f94c883b1995e4705eaff3e176c8eeb2..cf2c998e239f405989b9d340e85841c4046a0a26 100644 (file)
@@ -41,7 +41,7 @@
 #include <curses.priv.h>
 #include <term.h>
 
-MODULE_ID("$Id: resizeterm.c,v 1.30 2008/01/12 22:26:56 tom Exp $")
+MODULE_ID("$Id: resizeterm.c,v 1.32 2008/05/03 14:28:55 tom Exp $")
 
 #define stolen_lines (screen_lines - SP->_lines_avail)
 
@@ -69,7 +69,7 @@ show_window_sizes(const char *name)
     _nc_lock_global(windowlist);
     _tracef("%s resizing: %2d x %2d (%2d x %2d)", name, LINES, COLS,
            screen_lines, screen_columns);
-    for (wp = _nc_windows; wp != 0; wp = wp->next) {
+    for (each_window(wp)) {
        _tracef("  window %p is %2ld x %2ld at %2ld,%2ld",
                &(wp->win),
                (long) wp->win._maxy + 1,
@@ -104,7 +104,7 @@ ripped_window(WINDOW *win)
     ripoff_t *rop;
 
     if (win != 0) {
-       for (rop = ripoff_stack; (rop - ripoff_stack) < N_RIPS; rop++) {
+       for (each_ripoff(rop)) {
            if (rop->win == win && rop->line != 0) {
                result = rop;
                break;
@@ -125,7 +125,7 @@ ripped_bottom(WINDOW *win)
     ripoff_t *rop;
 
     if (win != 0) {
-       for (rop = ripoff_stack; (rop - ripoff_stack) < N_RIPS; rop++) {
+       for (each_ripoff(rop)) {
            if (rop->line < 0) {
                result -= rop->line;
                if (rop->win == win) {
@@ -148,7 +148,7 @@ child_depth(WINDOW *cmp)
     if (cmp != 0) {
        WINDOWLIST *wp;
 
-       for (wp = _nc_windows; wp != 0; wp = wp->next) {
+       for (each_window(wp)) {
            WINDOW *tst = &(wp->win);
            if (tst->_parent == cmp) {
                depth = 1 + child_depth(tst);
@@ -251,7 +251,7 @@ decrease_size(int ToLines, int ToCols, int stolen EXTRA_DCLS)
        found = FALSE;
        TR(TRACE_UPDATE, ("decreasing size of windows to %dx%d, depth=%d",
                          ToLines, ToCols, depth));
-       for (wp = _nc_windows; wp != 0; wp = wp->next) {
+       for (each_window(wp)) {
            WINDOW *win = &(wp->win);
 
            if (!(win->_flags & _ISPAD)) {
@@ -285,7 +285,7 @@ increase_size(int ToLines, int ToCols, int stolen EXTRA_DCLS)
        found = FALSE;
        TR(TRACE_UPDATE, ("increasing size of windows to %dx%d, depth=%d",
                          ToLines, ToCols, depth));
-       for (wp = _nc_windows; wp != 0; wp = wp->next) {
+       for (each_window(wp)) {
            WINDOW *win = &(wp->win);
 
            if (!(win->_flags & _ISPAD)) {
@@ -428,7 +428,7 @@ resizeterm(int ToLines, int ToCols)
             * decide which to repaint, since without panels, ncurses does
             * not know which are really on top.
             */
-           for (rop = ripoff_stack; (rop - ripoff_stack) < N_RIPS; rop++) {
+           for (each_ripoff(rop)) {
                if (rop->win != stdscr
                    && rop->win != 0
                    && rop->line < 0) {
index 4d2c1366d0b8c34168141e3224a416052c0503db..4d0fdf6705be6f05836473c658a2a503c7a071e6 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: use_window.c,v 1.6 2008/04/12 17:16:05 tom Exp $")
+MODULE_ID("$Id: use_window.c,v 1.7 2008/05/03 14:09:38 tom Exp $")
 
 #ifdef USE_PTHREADS
 NCURSES_EXPORT(void)
@@ -41,7 +41,7 @@ _nc_lock_window(const WINDOW *win)
     WINDOWLIST *p;
 
     _nc_lock_global(windowlist);
-    for (p = _nc_windows; p != 0; p = p->next) {
+    for (each_window(p)) {
        if (&(p->win) == win) {
            _nc_mutex_lock(&(p->mutex_use_window));
            break;
@@ -54,7 +54,7 @@ _nc_unlock_window(const WINDOW *win)
 {
     WINDOWLIST *p;
 
-    for (p = _nc_windows; p != 0; p = p->next) {
+    for (each_window(p)) {
        if (&(p->win) == win) {
            _nc_mutex_unlock(&(p->mutex_use_window));
            break;
index f756f0f237f777c303655a46c67bf0a4bf914867..ac808c4d2884ca10637b10afcf4f8410d522f0ba 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            *
@@ -32,7 +32,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: wresize.c,v 1.27 2007/12/22 23:20:53 tom Exp $")
+MODULE_ID("$Id: wresize.c,v 1.28 2008/05/03 14:13:51 tom Exp $")
 
 static int
 cleanup_lines(struct ldat *data, int length)
@@ -56,7 +56,7 @@ repair_subwindows(WINDOW *cmp)
 
     _nc_lock_global(windowlist);
 
-    for (wp = _nc_windows; wp != 0; wp = wp->next) {
+    for (each_window(wp)) {
        WINDOW *tst = &(wp->win);
 
        if (tst->_parent == cmp) {
index b43456029226d3997225086077c7e8698853651f..422c74cb2a3f1def5019ad5e6382bb06127a649f 100644 (file)
@@ -34,7 +34,7 @@
 
 
 /*
- * $Id: curses.priv.h,v 1.363 2008/04/12 17:16:26 tom Exp $
+ * $Id: curses.priv.h,v 1.373 2008/05/03 23:30:35 tom Exp $
  *
  *     curses.priv.h
  *
@@ -348,9 +348,6 @@ extern NCURSES_EXPORT(void) _nc_unlock_window(const WINDOW *);
 
 #endif /* USE_PTHREADS */
 
-#define _nc_lock_screen(name)  /* nothing */
-#define _nc_unlock_screen(name)        /* nothing */
-
 #if HAVE_GETTIMEOFDAY
 # define PRECISE_GETTIME 1
 # define TimeType struct timeval
@@ -1167,6 +1164,13 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch;
 # endif
 #endif
 
+/*
+ * Standardize/simplify common loops
+ */
+#define each_screen(p) p = _nc_screen_chain; p != 0; p = (p)->_next_screen
+#define each_window(p) p = _nc_windows; p != 0; p = (p)->next
+#define each_ripoff(p) p = ripoff_stack; (p - ripoff_stack) < N_RIPS; ++p
+
 /*
  * Prefixes for call/return points of library function traces.  We use these to
  * instrument the public functions so that the traces can be easily transformed
@@ -1235,7 +1239,7 @@ extern NCURSES_EXPORT(const char *)     _nc_retrace_cptr (const char *);
 extern NCURSES_EXPORT(int)              _nc_retrace_int (int);
 extern NCURSES_EXPORT(unsigned)         _nc_retrace_unsigned (unsigned);
 extern NCURSES_EXPORT(void *)           _nc_retrace_void_ptr (void *);
-extern NCURSES_EXPORT(void)             _nc_fifo_dump (void);
+extern NCURSES_EXPORT(void)             _nc_fifo_dump (SCREEN *);
 
 #if USE_REENTRANT
 NCURSES_WRAPPED_VAR(long, _nc_outchars);
@@ -1476,15 +1480,18 @@ extern NCURSES_EXPORT(char *) _nc_get_locale(void);
 extern NCURSES_EXPORT(int) _nc_unicode_locale(void);
 extern NCURSES_EXPORT(int) _nc_locale_breaks_acs(void);
 extern NCURSES_EXPORT(int) _nc_setupterm(NCURSES_CONST char *, int, int *, bool);
-extern NCURSES_EXPORT(void) _nc_get_screensize(int *, int *);
+extern NCURSES_EXPORT(void) _nc_get_screensize(SCREEN *, int *, int *);
 
 /* lib_tstp.c */
 #if USE_SIGWINCH
-extern NCURSES_EXPORT(int) _nc_handle_sigwinch(int);
+extern NCURSES_EXPORT(int) _nc_handle_sigwinch(SCREEN *);
 #else
 #define _nc_handle_sigwinch(a) /* nothing */
 #endif
 
+/* lib_ungetch.c */
+extern NCURSES_EXPORT(int) _nc_ungetch (SCREEN *, int);
+
 /* lib_wacs.c */
 #if USE_WIDEC_SUPPORT
 extern NCURSES_EXPORT(void) _nc_init_wacs(void);
@@ -1527,18 +1534,18 @@ extern NCURSES_EXPORT(int) _nc_access (const char *, int);
 extern NCURSES_EXPORT(int) _nc_baudrate (int);
 extern NCURSES_EXPORT(int) _nc_freewin (WINDOW *);
 extern NCURSES_EXPORT(int) _nc_getenv_num (const char *);
-extern NCURSES_EXPORT(int) _nc_keypad (bool);
+extern NCURSES_EXPORT(int) _nc_keypad (SCREEN *, bool);
 extern NCURSES_EXPORT(int) _nc_ospeed (int);
 extern NCURSES_EXPORT(int) _nc_outch (int);
 extern NCURSES_EXPORT(int) _nc_read_termcap_entry (const char *const, TERMTYPE *const);
 extern NCURSES_EXPORT(int) _nc_setupscreen (int, int, FILE *, bool, int);
-extern NCURSES_EXPORT(int) _nc_timed_wait(int, int, int * EVENTLIST_2nd(_nc_eventlist *));
+extern NCURSES_EXPORT(int) _nc_timed_wait(SCREEN *, int, int, int * EVENTLIST_2nd(_nc_eventlist *));
 extern NCURSES_EXPORT(void) _nc_do_color (short, short, bool, int (*)(int));
 extern NCURSES_EXPORT(void) _nc_flush (void);
 extern NCURSES_EXPORT(void) _nc_free_entry(ENTRY *, TERMTYPE *);
 extern NCURSES_EXPORT(void) _nc_freeall (void);
 extern NCURSES_EXPORT(void) _nc_hash_map (void);
-extern NCURSES_EXPORT(void) _nc_init_keytry (void);
+extern NCURSES_EXPORT(void) _nc_init_keytry (SCREEN *);
 extern NCURSES_EXPORT(void) _nc_keep_tic_dir (const char *);
 extern NCURSES_EXPORT(void) _nc_make_oldhash (int i);
 extern NCURSES_EXPORT(void) _nc_scroll_oldhash (int n, int top, int bot);
@@ -1570,7 +1577,7 @@ extern NCURSES_EXPORT(size_t) _nc_wcrtomb (char *, wchar_t, mbstate_t *);
 #endif
 
 #if USE_SIZECHANGE
-extern NCURSES_EXPORT(void) _nc_update_screensize (void);
+extern NCURSES_EXPORT(void) _nc_update_screensize (SCREEN *);
 #endif
 
 #if HAVE_RESIZETERM
index 67799577aeadabfe268a7ce373dfca867b882a97..9655b417d6e73ccc20eb77fe5f6fbf4a141492e4 100644 (file)
 /*
  * Common macros for lib_getch.c, lib_ungetch.c
  *
- * $Id: fifo_defs.h,v 1.4 2002/03/16 20:47:50 tom Exp $
+ * $Id: fifo_defs.h,v 1.5 2008/05/03 20:08:16 tom Exp $
  */
 
 #ifndef FIFO_DEFS_H
 #define FIFO_DEFS_H 1
 
-#define head   SP->_fifohead
-#define tail   SP->_fifotail
+#define head   sp->_fifohead
+#define tail   sp->_fifotail
 /* peek points to next uninterpreted character */
-#define peek   SP->_fifopeek
+#define peek   sp->_fifopeek
 
 #define h_inc() { head == FIFO_SIZE-1 ? head = 0 : head++; if (head == tail) head = -1, tail = 0;}
 #define h_dec() { head == 0 ? head = FIFO_SIZE-1 : head--; if (head == tail) tail = -1;}
 #define t_inc() { tail == FIFO_SIZE-1 ? tail = 0 : tail++; if (tail == head) tail = -1;}
-#define t_dec() { tail == 0 ? tail = FIFO_SIZE-1 : tail--; if (head == tail) fifo_clear();}
+#define t_dec() { tail == 0 ? tail = FIFO_SIZE-1 : tail--; if (head == tail) fifo_clear(sp);}
 #define p_inc() { peek == FIFO_SIZE-1 ? peek = 0 : peek++;}
 
 #define cooked_key_in_fifo()   ((head != -1) && (peek != head))
index d203210615541ed6a496b26a2f84e6aaee496cf5..d30d3ed16a876d3de2bcb0913fb4fedd42141da6 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1999-2005,2006 Free Software Foundation, Inc.              *
+ * Copyright (c) 1999-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 <term_entry.h>
 
-MODULE_ID("$Id: init_keytry.c,v 1.10 2007/04/29 22:57:50 tom Exp $")
+MODULE_ID("$Id: init_keytry.c,v 1.11 2008/05/03 23:09:15 tom Exp $")
 
 /*
 **      _nc_init_keytry()
@@ -64,19 +64,19 @@ _nc_tinfo_fkeysf(void)
 #endif
 
 NCURSES_EXPORT(void)
-_nc_init_keytry(void)
+_nc_init_keytry(SCREEN *sp)
 {
     size_t n;
 
-    /* The SP->_keytry value is initialized in newterm(), where the SP
+    /* The sp->_keytry value is initialized in newterm(), where the sp
      * structure is created, because we can not tell where keypad() or
      * mouse_activate() (which will call keyok()) are first called.
      */
 
-    if (SP != 0) {
+    if (sp != 0) {
        for (n = 0; _nc_tinfo_fkeys[n].code; n++) {
            if (_nc_tinfo_fkeys[n].offset < STRCOUNT) {
-               (void) _nc_add_to_try(&(SP->_keytry),
+               (void) _nc_add_to_try(&(sp->_keytry),
                                      CUR Strings[_nc_tinfo_fkeys[n].offset],
                                      _nc_tinfo_fkeys[n].code);
            }
@@ -88,7 +88,7 @@ _nc_init_keytry(void)
         * names.
         */
        {
-           TERMTYPE *tp = &(SP->_term->type);
+           TERMTYPE *tp = &(sp->_term->type);
            for (n = STRCOUNT; n < NUM_STRINGS(tp); ++n) {
                const char *name = ExtStrname(tp, n, strnames);
                char *value = tp->Strings[n];
@@ -96,7 +96,7 @@ _nc_init_keytry(void)
                    && *name == 'k'
                    && value != 0
                    && key_defined(value) == 0) {
-                   (void) _nc_add_to_try(&(SP->_keytry),
+                   (void) _nc_add_to_try(&(sp->_keytry),
                                          value,
                                          n - STRCOUNT + KEY_MAX);
                }
@@ -104,7 +104,7 @@ _nc_init_keytry(void)
        }
 #endif
 #ifdef TRACE
-       _nc_trace_tries(SP->_keytry);
+       _nc_trace_tries(sp->_keytry);
 #endif
     }
 }
index 926afa836db4d3a7fd289c255ed0e5fc9bd8a9c8..417b3b4b4dbca84432a25320256ada585f0e9517 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2005,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            *
@@ -49,7 +49,7 @@
 #endif
 #endif
 
-MODULE_ID("$Id: lib_napms.c,v 1.15 2005/04/03 13:58:14 tom Exp $")
+MODULE_ID("$Id: lib_napms.c,v 1.17 2008/05/03 21:34:13 tom Exp $")
 
 NCURSES_EXPORT(int)
 napms(int ms)
@@ -67,7 +67,7 @@ napms(int ms)
        }
     }
 #else
-    _nc_timed_wait(0, ms, (int *) 0 EVENTLIST_2nd(0));
+    _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
 #endif
 
     returnCode(OK);
index 5cdd1d468077887f9d7130dc3f610f9dac091bb2..98aae24baacbfc1aca8a6fa8c4f536a56a76b36c 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            *
@@ -43,7 +43,7 @@
 
 #include <term.h>
 
-MODULE_ID("$Id: lib_options.c,v 1.50 2006/12/30 16:03:27 tom Exp $")
+MODULE_ID("$Id: lib_options.c,v 1.52 2008/05/03 23:09:20 tom Exp $")
 
 NCURSES_EXPORT(int)
 idlok(WINDOW *win, bool flag)
@@ -126,7 +126,7 @@ keypad(WINDOW *win, bool flag)
 
     if (win) {
        win->_use_keypad = flag;
-       returnCode(_nc_keypad(flag));
+       returnCode(_nc_keypad(SP, flag));
     } else
        returnCode(ERR);
 }
@@ -220,7 +220,7 @@ typeahead(int fd)
 
 #if NCURSES_EXT_FUNCS
 static int
-has_key_internal(int keycode, TRIES *tp)
+has_key_internal(int keycode, TRIES * tp)
 {
     if (tp == 0)
        return (FALSE);
@@ -247,7 +247,7 @@ has_key(int keycode)
  * the terminal state _before_ switching modes.
  */
 NCURSES_EXPORT(int)
-_nc_keypad(bool flag)
+_nc_keypad(SCREEN *sp, bool flag)
 {
     if (flag && keypad_xmit) {
        TPUTS_TRACE("keypad_xmit");
@@ -259,12 +259,12 @@ _nc_keypad(bool flag)
        _nc_flush();
     }
 
-    if (SP != 0) {
-       if (flag && !SP->_tried) {
-           _nc_init_keytry();
-           SP->_tried = TRUE;
+    if (sp != 0) {
+       if (flag && !sp->_tried) {
+           _nc_init_keytry(sp);
+           sp->_tried = TRUE;
        }
-       SP->_keypad_on = flag;
+       sp->_keypad_on = flag;
     }
     return (OK);
 }
index a376fc60275b8627fd97c7f94e6c7fe47dc0adde..08cb783c5942acc5fb0f14ca82791a325621089d 100644 (file)
@@ -53,7 +53,7 @@
 
 #include <term.h>              /* lines, columns, cur_term */
 
-MODULE_ID("$Id: lib_setup.c,v 1.102 2008/01/19 21:07:45 tom Exp $")
+MODULE_ID("$Id: lib_setup.c,v 1.105 2008/05/03 22:41:42 tom Exp $")
 
 /****************************************************************************
  *
@@ -154,23 +154,19 @@ set_tabsize(int value)
  * If we have a pending SIGWINCH, set the flag in each screen.
  */
 NCURSES_EXPORT(int)
-_nc_handle_sigwinch(int update)
+_nc_handle_sigwinch(SCREEN *sp)
 {
     SCREEN *scan;
 
-    (void) update;             /* no longer used */
-
     if (_nc_globals.have_sigwinch) {
        _nc_globals.have_sigwinch = 0;
 
-       scan = _nc_screen_chain;
-       while (scan) {
+       for (each_screen(scan)) {
            scan->_sig_winch = TRUE;
-           scan = scan->_next_screen;
        }
     }
 
-    return (SP ? SP->_sig_winch : 0);
+    return (sp ? sp->_sig_winch : 0);
 }
 
 #endif
@@ -184,7 +180,7 @@ use_env(bool f)
 }
 
 NCURSES_EXPORT(void)
-_nc_get_screensize(int *linep, int *colp)
+_nc_get_screensize(SCREEN *sp, int *linep, int *colp)
 /* Obtain lines/columns values from the environment and/or terminfo entry */
 {
     int my_tabsize;
@@ -238,7 +234,7 @@ _nc_get_screensize(int *linep, int *colp)
                 * environment variable.
                 */
                if (*linep <= 0)
-                   *linep = (SP != 0 && SP->_filtered) ? 1 : WINSIZE_ROWS(size);
+                   *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size);
                if (*colp <= 0)
                    *colp = WINSIZE_COLS(size);
            }
@@ -279,8 +275,8 @@ _nc_get_screensize(int *linep, int *colp)
        my_tabsize = 8;
 
 #if USE_REENTRANT
-    if (SP != 0)
-       SP->_TABSIZE = my_tabsize;
+    if (sp != 0)
+       sp->_TABSIZE = my_tabsize;
 #else
     TABSIZE = my_tabsize;
 #endif
@@ -289,25 +285,25 @@ _nc_get_screensize(int *linep, int *colp)
 
 #if USE_SIZECHANGE
 NCURSES_EXPORT(void)
-_nc_update_screensize(void)
+_nc_update_screensize(SCREEN *sp)
 {
     int old_lines = lines;
     int new_lines;
     int old_cols = columns;
     int new_cols;
 
-    _nc_get_screensize(&new_lines, &new_cols);
+    _nc_get_screensize(sp, &new_lines, &new_cols);
 
     /*
      * See is_term_resized() and resizeterm().
      * We're doing it this way because those functions belong to the upper
      * ncurses library, while this resides in the lower terminfo library.
      */
-    if (SP != 0
-       && SP->_resize != 0) {
+    if (sp != 0
+       && sp->_resize != 0) {
        if ((new_lines != old_lines) || (new_cols != old_cols))
-           SP->_resize(new_lines, new_cols);
-       SP->_sig_winch = FALSE;
+           sp->_resize(new_lines, new_cols);
+       sp->_sig_winch = FALSE;
     }
 }
 #endif
@@ -590,10 +586,11 @@ _nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse)
      * We should always check the screensize, just in case.
      */
 #if USE_REENTRANT
-    _nc_get_screensize(SP ? &(SP->_LINES) : &(_nc_prescreen._LINES),
+    _nc_get_screensize(SP,
+                      SP ? &(SP->_LINES) : &(_nc_prescreen._LINES),
                       SP ? &(SP->_COLS) : &(_nc_prescreen._COLS));
 #else
-    _nc_get_screensize(&LINES, &COLS);
+    _nc_get_screensize(SP, &LINES, &COLS);
 #endif
 
     if (errret)
index 4cbbf504a0c7e1c085d5de1783954bf0c338e393..2cb9fd67b4dd2ed9f4835fefc0e8bfb3dd8dc7b3 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            *
@@ -38,7 +38,7 @@
 #include <curses.priv.h>
 #include <term.h>              /* cur_term */
 
-MODULE_ID("$Id: lib_ttyflags.c,v 1.15 2007/05/26 18:54:25 tom Exp $")
+MODULE_ID("$Id: lib_ttyflags.c,v 1.16 2008/05/03 22:39:03 tom Exp $")
 
 NCURSES_EXPORT(int)
 _nc_get_tty_mode(TTY * buf)
@@ -147,7 +147,7 @@ reset_prog_mode(void)
        if (_nc_set_tty_mode(&cur_term->Nttyb) == OK) {
            if (SP) {
                if (SP->_keypad_on)
-                   _nc_keypad(TRUE);
+                   _nc_keypad(SP, TRUE);
                NC_BUFFERED(TRUE);
            }
            returnCode(OK);
@@ -163,7 +163,7 @@ reset_shell_mode(void)
 
     if (cur_term != 0) {
        if (SP) {
-           _nc_keypad(FALSE);
+           _nc_keypad(SP, FALSE);
            _nc_flush();
            NC_BUFFERED(FALSE);
        }
index 2a341fa6ba29c3252c36848d8f0286c056beeef7..06c8411caa4d2a2891b63c3febc79b6d0d5e6ba9 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 @@
 #define _POSIX_SOURCE
 #endif
 
-MODULE_ID("$Id: lib_tstp.c,v 1.36 2007/04/21 19:51:29 tom Exp $")
+MODULE_ID("$Id: lib_tstp.c,v 1.37 2008/05/03 16:24:56 tom Exp $")
 
 #if defined(SIGTSTP) && (HAVE_SIGACTION || HAVE_SIGVEC)
 #define USE_SIGTSTP 1
@@ -252,19 +252,17 @@ cleanup(int sig)
        if (signal(sig, SIG_IGN) != SIG_ERR)
 #endif
        {
-           SCREEN *scan = _nc_screen_chain;
-           while (scan) {
-               if (SP != 0
-                   && SP->_ofp != 0
-                   && isatty(fileno(SP->_ofp))) {
-                   SP->_cleanup = TRUE;
-                   SP->_outch = _nc_outch;
+           SCREEN *scan;
+           for (each_screen(scan)) {
+               if (scan->_ofp != 0
+                   && isatty(fileno(scan->_ofp))) {
+                   scan->_cleanup = TRUE;
+                   scan->_outch = _nc_outch;
                }
                set_term(scan);
                endwin();
                if (SP)
                    SP->_endwin = FALSE;        /* in case we have an atexit! */
-               scan = scan->_next_screen;
            }
        }
     }
index ec9daae80390e8d272711dc49bd1befffa959676..6d46081862fdc13eb9fdd253c22c136c94a2e0cb 100644 (file)
@@ -62,7 +62,7 @@
 # endif
 #endif
 
-MODULE_ID("$Id: lib_twait.c,v 1.55 2008/03/01 22:08:31 tom Exp $")
+MODULE_ID("$Id: lib_twait.c,v 1.57 2008/05/03 21:35:57 tom Exp $")
 
 static long
 _nc_gettime(TimeType * t0, bool first)
@@ -137,7 +137,8 @@ _nc_eventlist_timeout(_nc_eventlist * evl)
  * descriptors.
  */
 NCURSES_EXPORT(int)
-_nc_timed_wait(int mode,
+_nc_timed_wait(SCREEN *sp,
+              int mode,
               int milliseconds,
               int *timeleft
               EVENTLIST_2nd(_nc_eventlist * evl))
@@ -199,12 +200,12 @@ _nc_timed_wait(int mode,
 #endif
 
     if (mode & 1) {
-       fds[count].fd = SP->_ifd;
+       fds[count].fd = sp->_ifd;
        fds[count].events = POLLIN;
        count++;
     }
     if ((mode & 2)
-       && (fd = SP->_mouse_fd) >= 0) {
+       && (fd = sp->_mouse_fd) >= 0) {
        fds[count].fd = fd;
        fds[count].events = POLLIN;
        count++;
@@ -307,11 +308,11 @@ _nc_timed_wait(int mode,
     FD_ZERO(&set);
 
     if (mode & 1) {
-       FD_SET(SP->_ifd, &set);
-       count = SP->_ifd + 1;
+       FD_SET(sp->_ifd, &set);
+       count = sp->_ifd + 1;
     }
     if ((mode & 2)
-       && (fd = SP->_mouse_fd) >= 0) {
+       && (fd = sp->_mouse_fd) >= 0) {
        FD_SET(fd, &set);
        count = max(fd, count) + 1;
     }
@@ -424,11 +425,11 @@ _nc_timed_wait(int mode,
            result = 1;         /* redundant, but simple */
 #elif HAVE_SELECT
            if ((mode & 2)
-               && (fd = SP->_mouse_fd) >= 0
+               && (fd = sp->_mouse_fd) >= 0
                && FD_ISSET(fd, &set))
                result |= 2;
            if ((mode & 1)
-               && FD_ISSET(SP->_ifd, &set))
+               && FD_ISSET(sp->_ifd, &set))
                result |= 1;
 #endif
        } else
index 866681369a108ab989a3b45ce3e4dea84ddb7bbd..16fc17d27236ae04960e4fef13bcf5de7f69a549 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            *
@@ -74,7 +74,7 @@
 #include <ctype.h>
 #include <term.h>
 
-MODULE_ID("$Id: tty_update.c,v 1.243 2007/10/13 20:03:32 tom Exp $")
+MODULE_ID("$Id: tty_update.c,v 1.245 2008/05/03 22:43:04 tom Exp $")
 
 /*
  * This define controls the line-breakout optimization.  Every once in a
@@ -645,7 +645,7 @@ doupdate(void)
        SP->_fifohold--;
 
 #if USE_SIZECHANGE
-    if (SP->_endwin || _nc_handle_sigwinch(FALSE)) {
+    if (SP->_endwin || _nc_handle_sigwinch(SP)) {
        /*
         * This is a transparent extension:  XSI does not address it,
         * and applications need not know that ncurses can do it.
@@ -654,7 +654,7 @@ doupdate(void)
         * (this can happen in an xterm, for example), and resize the
         * ncurses data structures accordingly.
         */
-       _nc_update_screensize();
+       _nc_update_screensize(SP);
     }
 #endif
 
index 17a883dd75751dab4e952d015ae0cf130ec41cc6..4873d0d99ad932ddf2e101c46180723f50257f03 100644 (file)
  ****************************************************************************/
 
 /*
- * Author: Thomas E. Dickey <dickey@clark.net> 1998
+ * Author: Thomas E. Dickey (1998-on)
  *
- * $Id: ditto.c,v 1.21 2008/04/19 20:08:45 tom Exp $
+ * $Id: ditto.c,v 1.26 2008/04/26 23:42:39 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
- * machine by specifying its device, e.g.,
+ * program.
+ *
+ * If openpty() is supported, the command line parameters are titles for
+ * the windows showing each screen's data.
+ *
+ * If openpty() is not supported, you must invoke the program by specifying
+ * another terminal on the same machine by specifying its device, e.g.,
  *     ditto /dev/ttyp1
  */
 #include <test.priv.h>
 #include USE_OPENPTY_HEADER
 #endif
 
+#define MAX_FIFO 256
+
+#define THIS_FIFO(n) ((n) % MAX_FIFO)
+#define NEXT_FIFO(n) THIS_FIFO((n) + 1)
+
+typedef struct {
+    unsigned long sequence;
+    int head;
+    int tail;
+    int data[MAX_FIFO];
+} FIFO;
+
+typedef struct {
+    unsigned long sequence;
+} PEEK;
+
+/*
+ * Data "owned" for a single screen.  Each screen is divided into windows that
+ * show the text read from each terminal.  Input from a given screen will also
+ * be read into one window per screen.
+ */
 typedef struct {
     FILE *input;
     FILE *output;
-    SCREEN *screen;
-    WINDOW **windows;
+    SCREEN *screen;            /* this screen - curses internal data */
+    int length;                        /* length of windows[] and peeks[] */
+    char **titles;             /* per-window titles */
+    WINDOW **windows;          /* display data from each screen */
+    PEEK *peeks;               /* indices for each screen's fifo */
+    FIFO fifo;                 /* fifo for this screen */
 } DITTO;
 
+/*
+ * Structure used to pass multiple parameters via the use_screen()
+ * single-parameter interface.
+ */
 typedef struct {
-    int value;                 /* the actual data */
-    int source;                        /* which screen did data come from */
-    int target;                        /* which screen is data going to */
-    DITTO *ditto;
+    int source;                        /* which screen did character come from */
+    int target;                        /* which screen is character going to */
+    DITTO *ditto;              /* data for all screens */
 } DDATA;
 
 static void
@@ -72,6 +105,36 @@ usage(void)
     ExitProgram(EXIT_FAILURE);
 }
 
+/* Add to the head of the fifo, checking for overflow. */
+static void
+put_fifo(FIFO * fifo, int value)
+{
+    int next = NEXT_FIFO(fifo->head);
+    if (next == fifo->tail)
+       fifo->tail = NEXT_FIFO(fifo->tail);
+    fifo->data[next] = value;
+    fifo->head = next;
+    fifo->sequence += 1;
+}
+
+/* Get data from the tail (oldest part) of the fifo, returning -1 if no data.
+ * Since each screen can peek into the fifo, we do not update the tail index,
+ * but modify the peek-index.
+ *
+ * FIXME - test/workaround for case where fifo gets more than a buffer
+ * ahead of peek.
+ */
+static int
+peek_fifo(FIFO * fifo, PEEK * peek)
+{
+    int result = -1;
+    if (peek->sequence < fifo->sequence) {
+       peek->sequence += 1;
+       result = fifo->data[THIS_FIFO(peek->sequence)];
+    }
+    return result;
+}
+
 static FILE *
 open_tty(char *path)
 {
@@ -112,6 +175,64 @@ open_tty(char *path)
     return fp;
 }
 
+static void
+init_screen(SCREEN *sp GCC_UNUSED, void *arg)
+{
+    DITTO *target = (DITTO *) arg;
+    int high, wide;
+    int k;
+
+    cbreak();
+    noecho();
+    scrollok(stdscr, TRUE);
+    nodelay(stdscr, TRUE);
+    box(stdscr, 0, 0);
+
+    target->windows = typeCalloc(WINDOW *, target->length);
+    target->peeks = typeCalloc(PEEK, target->length);
+
+    high = (LINES - 2) / target->length;
+    wide = (COLS - 2);
+    for (k = 0; k < target->length; ++k) {
+       WINDOW *outer = newwin(high, wide, 1 + (high * k), 1);
+       WINDOW *inner = derwin(outer, high - 2, wide - 2, 1, 1);
+
+       box(outer, 0, 0);
+       mvwaddstr(outer, 0, 2, target->titles[k]);
+       wnoutrefresh(outer);
+
+       scrollok(inner, TRUE);
+       nodelay(inner, TRUE);
+       keypad(inner, TRUE);
+
+       target->windows[k] = inner;
+    }
+    doupdate();
+}
+
+static void
+open_screen(DITTO * target, char **source, int length, int which)
+{
+    if (which != 0) {
+       target->input =
+           target->output = open_tty(source[which]);
+    } else {
+       target->input = stdin;
+       target->output = stdout;
+    }
+
+    target->titles = source;
+    target->length = length;
+    target->screen = newterm((char *) 0,       /* assume $TERM is the same */
+                            target->output,
+                            target->input);
+
+    if (target->screen == 0)
+       failed("newterm");
+
+    (void) USING_SCREEN(target->screen, init_screen, target);
+}
+
 static int
 close_screen(SCREEN *sp GCC_UNUSED, void *arg GCC_UNUSED)
 {
@@ -120,24 +241,52 @@ close_screen(SCREEN *sp GCC_UNUSED, void *arg GCC_UNUSED)
     return endwin();
 }
 
+/*
+ * Read data from the 'source' screen.
+ */
 static int
 read_screen(SCREEN *sp GCC_UNUSED, void *arg)
 {
     DDATA *data = (DDATA *) arg;
-    WINDOW *win = data->ditto[data->source].windows[data->source];
+    DITTO *ditto = &(data->ditto[data->source]);
+    WINDOW *win = ditto->windows[data->source];
+    int ch = wgetch(win);
 
-    return wgetch(win);
+    if (ch > 0 && ch < 256)
+       put_fifo(&(ditto->fifo), ch);
+    else
+       ch = ERR;
+
+    return ch;
 }
 
+/*
+ * Write all of the data that's in fifos for the 'target' screen.
+ */
 static int
 write_screen(SCREEN *sp GCC_UNUSED, void *arg GCC_UNUSED)
 {
     DDATA *data = (DDATA *) arg;
-    WINDOW *win = data->ditto[data->target].windows[data->source];
+    DITTO *ditto = &(data->ditto[data->target]);
+    bool changed = FALSE;
+    int which;
+
+    for (which = 0; which < ditto->length; ++which) {
+       WINDOW *win = ditto->windows[which];
+       FIFO *fifo = &(data->ditto[which].fifo);
+       PEEK *peek = &(ditto->peeks[which]);
+       int ch;
 
-    waddch(win, data->value);
-    wnoutrefresh(win);
-    doupdate();
+       while ((ch = peek_fifo(fifo, peek)) > 0) {
+           changed = TRUE;
+
+           waddch(win, ch);
+           wnoutrefresh(win);
+       }
+    }
+
+    if (changed)
+       doupdate();
     return OK;
 }
 
@@ -156,7 +305,7 @@ int
 main(int argc GCC_UNUSED,
      char *argv[]GCC_UNUSED)
 {
-    int j, k;
+    int j;
     int count;
     DITTO *data;
 
@@ -166,50 +315,8 @@ main(int argc GCC_UNUSED,
     if ((data = typeCalloc(DITTO, argc)) == 0)
        failed("calloc data");
 
-    data[0].input = stdin;
-    data[0].output = stdout;
-    for (j = 1; j < argc; j++) {
-       data[j].input =
-           data[j].output = open_tty(argv[j]);
-    }
-
-    /*
-     * If we got this far, we have open connection(s) to the terminal(s).
-     * Set up the screens.
-     */
     for (j = 0; j < argc; j++) {
-       int high, wide;
-
-       data[j].screen = newterm((char *) 0,    /* assume $TERM is the same */
-                                data[j].output,
-                                data[j].input);
-
-       if (data[j].screen == 0)
-           failed("newterm");
-       cbreak();
-       noecho();
-       scrollok(stdscr, TRUE);
-       nodelay(stdscr, TRUE);
-       box(stdscr, 0, 0);
-
-       data[j].windows = typeCalloc(WINDOW *, argc);
-
-       high = (LINES - 2) / argc;
-       wide = (COLS - 2);
-       for (k = 0; k < argc; ++k) {
-           WINDOW *outer = newwin(high, wide, 1 + (high * k), 1);
-           WINDOW *inner = derwin(outer, high - 2, wide - 2, 1, 1);
-
-           box(outer, 0, 0);
-           mvwaddstr(outer, 0, 2, argv[k]);
-           wnoutrefresh(outer);
-
-           scrollok(inner, TRUE);
-           nodelay(inner, TRUE);
-
-           data[j].windows[k] = inner;
-       }
-       doupdate();
+       open_screen(&data[j], argv, argc, j);
     }
 
     /*
@@ -227,14 +334,11 @@ main(int argc GCC_UNUSED,
        ddata.ditto = data;
 
        ch = USING_SCREEN(data[which].screen, read_screen, &ddata);
-       if (ch == ERR) {
-           continue;
-       }
-       if (ch == CTRL('D'))
+       if (ch == CTRL('D')) {
            break;
-
-       ddata.value = ch;
-       show_ditto(data, argc, &ddata);
+       } else if (ch != ERR) {
+           show_ditto(data, argc, &ddata);
+       }
     }
 
     /*