ncurses 5.7 - patch 20090704
authorThomas E. Dickey <dickey@invisible-island.net>
Sat, 4 Jul 2009 23:55:21 +0000 (23:55 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sat, 4 Jul 2009 23:55:21 +0000 (23:55 +0000)
+ remove wide-character checks from unctrl() (patch by Clemens Ladisch).
+ revise wadd_wch() and wecho_wchar() to eliminate dependency on
  unctrl().
+ continue integrating "sp-funcs" by Juergen Pfeifer (incomplete).

17 files changed:
NEWS
dist.mk
include/curses.h.in
include/nc_panel.h
ncurses/Makefile.in
ncurses/base/MKunctrl.awk
ncurses/base/lib_endwin.c
ncurses/base/lib_getch.c
ncurses/base/lib_mouse.c
ncurses/base/lib_nl.c
ncurses/base/lib_pad.c
ncurses/base/lib_slk.c
ncurses/base/resizeterm.c
ncurses/curses.priv.h
ncurses/tinfo/lib_options.c
ncurses/tty/MKexpanded.sh
ncurses/widechar/lib_add_wch.c

diff --git a/NEWS b/NEWS
index 848a07d777dedeab2c8b415eb8d2f68a7ff43049..8de737131940156ce7b6a5117218b25d3914d1e0 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.1398 2009/06/27 20:59:09 tom Exp $
+-- $Id: NEWS,v 1.1400 2009/07/04 22:12:46 tom Exp $
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
@@ -45,6 +45,12 @@ 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.
 
+20090704
+       + remove wide-character checks from unctrl() (patch by Clemens Ladisch).
+       + revise wadd_wch() and wecho_wchar() to eliminate dependency on
+         unctrl().
+       + continue integrating "sp-funcs" by Juergen Pfeifer (incomplete).
+
 20090627
        + update llib-lncurses[wt] to use sp-funcs.
        + various code-fixes to build/work with --disable-macros configure
diff --git a/dist.mk b/dist.mk
index 4f3110dd717f5216b12da75ced972c7a4db97a65..79f76e234b62bae2086283f4408cd723ca5f1e92 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.706 2009/06/27 22:21:38 tom Exp $
+# $Id: dist.mk,v 1.707 2009/07/04 17:04:26 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 = 7
-NCURSES_PATCH = 20090627
+NCURSES_PATCH = 20090704
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
index 0220752b935f3a90f531efca0ecc12f4d99d1a5c..4342467549b8b43ced67b84f31e5232930c165ac 100644 (file)
@@ -32,7 +32,7 @@
  *     and: Thomas E. Dickey                        1996-on                 *
  ****************************************************************************/
 
-/* $Id: curses.h.in,v 1.202 2009/06/13 21:44:51 tom Exp $ */
+/* $Id: curses.h.in,v 1.203 2009/07/04 20:19:26 tom Exp $ */
 
 #ifndef __NCURSES_H
 #define __NCURSES_H
@@ -844,6 +844,7 @@ extern NCURSES_EXPORT(char *) keybound (int, int);
 extern NCURSES_EXPORT(const char *) curses_version (void);
 extern NCURSES_EXPORT(int) assume_default_colors (int, int);
 extern NCURSES_EXPORT(int) define_key (const char *, int);
+extern NCURSES_EXPORT(int) get_escdelay (void);
 extern NCURSES_EXPORT(int) key_defined (const char *);
 extern NCURSES_EXPORT(int) keyok (int, bool);
 extern NCURSES_EXPORT(int) resize_term (int, int);
index ece9594736835c8f58a2a529b49ce2460e0ab0de..6a9ffea396878f6e2ad38821c86db996fabd28c2 100644 (file)
@@ -31,9 +31,8 @@
  *     and: Thomas E. Dickey                                                *
  ****************************************************************************/
 
-
 /*
- * $Id: nc_panel.h,v 1.6 2009/04/11 21:17:57 tom Exp $
+ * $Id: nc_panel.h,v 1.7 2009/07/04 18:20:02 tom Exp $
  *
  *     nc_panel.h
  *
 #define NC_PANEL_H 1
 
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
 
-struct panel; /* Forward Declaration */
+  struct panel;                        /* Forward Declaration */
 
-struct panelhook {
-  struct panel*   top_panel;
-  struct panel*   bottom_panel;
-  struct panel*   stdscr_pseudo_panel;
+  struct panelhook
+    {
+      struct panel *top_panel;
+      struct panel *bottom_panel;
+      struct panel *stdscr_pseudo_panel;
 #if NO_LEAKS
-  int (*destroy)(struct panel *);
+      int (*destroy) (struct panel *);
 #endif
-};
-
-/* Retrieve the panelhook of the current screen */
-extern NCURSES_EXPORT(struct panelhook*) _nc_panelhook (void);
+    };
 
+  struct screen;               /* Forward declaration */
+/* Retrieve the panelhook of the specified screen */
+  extern NCURSES_EXPORT(struct panelhook *)
+    _nc_panelhook (void);
 #if NCURSES_SP_FUNCS
-extern NCURSES_EXPORT(struct panelhook*) NCURSES_SP_NAME(_nc_panelhook) (SCREEN *);
+  extern NCURSES_EXPORT(struct panelhook *)
+    NCURSES_SP_NAME(_nc_panelhook) (SCREEN *);
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* NC_PANEL_H */
+#endif                         /* NC_PANEL_H */
index 043c80298588f066dd3b5461cc812455c880f81d..0f94e4337650bdff7a4b26938b90700134751c36 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.116 2009/06/27 14:31:36 tom Exp $
+# $Id: Makefile.in,v 1.117 2009/07/04 16:36:11 tom Exp $
 ##############################################################################
 # Copyright (c) 1998-2007,2009 Free Software Foundation, Inc.                #
 #                                                                            #
@@ -165,11 +165,12 @@ TEST_PROGS = \
        hashmap$x \
        lib_mvcur$x
 
-base   = $(srcdir)/base
-serial = $(srcdir)/tty
-tinfo  = $(srcdir)/tinfo
-trace  = $(srcdir)/trace
-wide   = $(srcdir)/widechar
+base    = $(srcdir)/base
+serial  = $(srcdir)/tty
+tinfo   = $(srcdir)/tinfo
+trace   = $(srcdir)/trace
+wide    = $(srcdir)/widechar
+win32con = $(srcdir)/win32con
 
 ################################################################################
 all \
index 2c37d442c9d38e8818bc7066591878ade3d41ac6..2140900e8c3be185b4df4f959f2bc71005c36fe4 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: MKunctrl.awk,v 1.25 2009/04/18 23:43:49 tom Exp $
+# $Id: MKunctrl.awk,v 1.26 2009/07/04 22:05:15 Clemens.Ladisch Exp $
 ##############################################################################
 # Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.                #
 #                                                                            #
@@ -36,12 +36,6 @@ BEGIN        {
                print "#include <curses.priv.h>"
                print "#include <ctype.h>"
                print ""
-               print "#if USE_WIDEC_SUPPORT"
-               print "#if HAVE_WCTYPE_H"
-               print "#include <wctype.h>"
-               print "#endif"
-               print "#endif"
-               print ""
                print "#undef unctrl"
                print ""
        }
@@ -157,16 +151,6 @@ END        {
                print  "\t\t && (check < 160))"
                printf "\t\t\tresult = %s_c1[check - 128];\n", stringname;
                print  "\t\telse"
-               print  "#if USE_WIDEC_SUPPORT"
-               print  "\t\tif ((check >= 160)"
-               print  "\t\t && (check < 256)"
-               print  "\t\t && ((sp != 0)"
-               print  "\t\t  && ((sp->_legacy_coding > 0)"
-               print  "\t\t   || (sp->_legacy_coding == 0"
-               print  "\t\t       && (isprint(check) || iswprint(check))))))"
-               printf "\t\t\tresult = %s_c1[check - 128];\n", stringname;
-               print  "\t\telse"
-               print  "#else"
                print  "\t\tif ((check >= 160)"
                print  "\t\t && (check < 256)"
                print  "\t\t && ((sp != 0)"
@@ -175,7 +159,6 @@ END {
                print  "\t\t       && isprint(check)))))"
                printf "\t\t\tresult = %s_c1[check - 128];\n", stringname;
                print  "\t\telse"
-               print  "#endif /* USE_WIDEC_SUPPORT */"
                print  "#endif /* NCURSES_EXT_FUNCS */"
                printf "\t\t\tresult = %s_table[check];\n", stringname;
                print  "\t} else {"
index 386db4053eddb2d8a9bb6decf34667ae758eeb85..3b552daeff2d0c36c50a496252a2ecefaead3661 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2008,2009 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            *
 */
 
 #include <curses.priv.h>
-#include <term.h>
 
-MODULE_ID("$Id: lib_endwin.c,v 1.20 2009/02/15 00:35:00 tom Exp $")
+MODULE_ID("$Id: lib_endwin.c,v 1.21 2009/07/04 18:35:43 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(endwin) (NCURSES_SP_DCL0)
 {
-    T((T_CALLED("endwin()")));
+    int code = ERR;
+
+    T((T_CALLED("endwin(%p)"), SP_PARM));
 
     if (SP_PARM) {
+#ifdef USE_TERM_DRIVER
+       TERMINAL_CONTROL_BLOCK *TCB = TCBOf(SP_PARM);
+
+       SP_PARM->_endwin = TRUE;
+       if (TCB && TCB->drv && TCB->drv->scexit)
+           TCB->drv->scexit(SP_PARM);
+#else
        SP_PARM->_endwin = TRUE;
        SP_PARM->_mouse_wrap(SP_PARM);
        _nc_screen_wrap();
        _nc_mvcur_wrap();       /* wrap up cursor addressing */
-       returnCode(reset_shell_mode());
+#endif
+       code = NCURSES_SP_NAME(reset_shell_mode) (NCURSES_SP_ARG);
     }
 
-    returnCode(ERR);
+    returnCode(code);
 }
 
 #if NCURSES_SP_FUNCS
index e228355a019ea38a9bd1aaac92a471a0698ff4f9..ccfcc33656df68410e60deb7775c90738ebdadef 100644 (file)
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_getch.c,v 1.103 2009/05/30 15:50:47 tom Exp $")
+MODULE_ID("$Id: lib_getch.c,v 1.104 2009/07/04 20:41:13 tom Exp $")
 
 #include <fifo_defs.h>
 
 #if USE_REENTRANT
-#define GetEscdelay(sp) (sp)->_ESCDELAY
+#define GetEscdelay(sp) *_nc_ptr_Escdelay(sp)
 NCURSES_EXPORT(int *)
 _nc_ptr_Escdelay(SCREEN *sp)
 {
@@ -56,7 +56,7 @@ _nc_ptr_Escdelay(SCREEN *sp)
 NCURSES_EXPORT(int)
 NCURSES_PUBLIC_VAR(ESCDELAY) (void)
 {
-    return *_nc_ptr_Escdelay(CURRENT_SCREEN);
+    return *(_nc_ptr_Escdelay(CURRENT_SCREEN));
 }
 #else
 #define GetEscdelay(sp) ESCDELAY
@@ -71,7 +71,7 @@ NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value)
     int code = OK;
 #if USE_REENTRANT
     if (SP_PARM) {
-       SP_PARM->_ESCDELAY = value;
+       SET_ESCDELAY(value);
     } else {
        code = ERR;
     }
@@ -86,7 +86,33 @@ NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value)
 NCURSES_EXPORT(int)
 set_escdelay(int value)
 {
-    return NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value);
+    int code;
+#if USE_REENTRANT
+    code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value);
+#else
+    ESCDELAY = value;
+    code = OK;
+#endif
+    return code;
+}
+#endif
+#endif /* NCURSES_EXT_FUNCS */
+
+#if NCURSES_EXT_FUNCS
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(get_escdelay) (NCURSES_SP_DCL0)
+{
+#if !USE_REENTRANT
+    (void) SP_PARM;
+#endif
+    return GetEscdelay(SP_PARM);
+}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+get_escdelay (void)
+{
+    return NCURSES_SP_NAME(get_escdelay)(CURRENT_SCREEN);
 }
 #endif
 #endif /* NCURSES_EXT_FUNCS */
@@ -115,10 +141,22 @@ check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl))
 #if USE_SYSMOUSE
     if ((sp->_mouse_type == M_SYSMOUSE)
        && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
-       return 2;
+       return TW_MOUSE;
     }
 #endif
-    rc = _nc_timed_wait(sp, TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl));
+#ifdef USE_TERM_DRIVER
+    rc = TCBOf(sp)->drv->twait(TCBOf(sp),
+                              TWAIT_MASK,
+                              delay,
+                              (int *) 0
+                              EVENTLIST_2nd(evl));
+#else
+    rc = _nc_timed_wait(sp,
+                       TWAIT_MASK,
+                       delay,
+                       (int *) 0
+                       EVENTLIST_2nd(evl));
+#endif
 #if USE_SYSMOUSE
     if ((sp->_mouse_type == M_SYSMOUSE)
        && (sp->_sysmouse_head < sp->_sysmouse_tail)
@@ -220,9 +258,15 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl))
     } else
 #endif
     {                          /* Can block... */
+#ifdef USE_TERM_DRIVER
+       int buf;
+       n = CallDriver_1(sp, read, &buf);
+       ch = buf;
+#else
        unsigned char c2 = 0;
        n = read(sp->_ifd, &c2, 1);
        ch = c2;
+#endif
     }
 
 #ifdef HIDE_EINTR
index f0ad82fc40d5b574c7547c7b0fd4f438f767bcf2..cd760dc0d506adebe193bd9c0fb325f561247981 100644 (file)
@@ -30,6 +30,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                 *
+ *     and: Juergen Pfeifer                         2008                    *
  ****************************************************************************/
 
 /*
 #include <curses.priv.h>
 
 #ifndef CUR
-#define CUR SP_TERMTYPE 
+#define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_mouse.c,v 1.107 2009/05/10 00:48:29 tom Exp $")
+MODULE_ID("$Id: lib_mouse.c,v 1.108 2009/07/04 19:51:08 tom Exp $")
 
 #include <tic.h>
 
@@ -153,7 +154,7 @@ make an error
 #define LIBGPM_SONAME "libgpm.so"
 #endif
 
-#define GET_DLSYM(name) (my_##name = (TYPE_##name) dlsym(SP_PARM->_dlopen_gpm, #name))
+#define GET_DLSYM(name) (my_##name = (TYPE_##name) dlsym(sp->_dlopen_gpm, #name))
 
 #endif                         /* USE_GPM_SUPPORT */
 
@@ -347,6 +348,9 @@ handle_sysmouse(int sig GCC_UNUSED)
 }
 #endif /* USE_SYSMOUSE */
 
+#ifndef USE_TERM_DRIVER
+#define xterm_kmous "\033[M"
+
 static void
 init_xterm_mouse(SCREEN *sp)
 {
@@ -355,6 +359,7 @@ init_xterm_mouse(SCREEN *sp)
     if (!VALID_STRING(sp->_mouse_xtermcap))
        sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;";
 }
+#endif
 
 static void
 enable_xterm_mouse(SCREEN *sp, int enable)
@@ -483,8 +488,6 @@ enable_gpm_mouse(SCREEN *sp, bool enable)
 }
 #endif /* USE_GPM_SUPPORT */
 
-#define xterm_kmous "\033[M"
-
 static void
 initialize_mousetype(SCREEN *sp)
 {
@@ -519,7 +522,7 @@ initialize_mousetype(SCREEN *sp)
     /* OS/2 VIO */
 #if USE_EMX_MOUSE
     if (!sp->_emxmouse_thread
-       && strstr(cur_term->type.term_names, "xterm") == 0
+       && strstr(TerminalOf(sp)->type.term_names, "xterm") == 0
        && key_mouse) {
        int handles[2];
 
@@ -626,16 +629,21 @@ initialize_mousetype(SCREEN *sp)
     }
 #endif /* USE_SYSMOUSE */
 
+#ifdef USE_TERM_DRIVER
+    CallDriver(sp, initmouse);
+#else
     /* we know how to recognize mouse events under "xterm" */
     if (key_mouse != 0) {
        if (!strcmp(key_mouse, xterm_kmous)
-           || strstr(cur_term->type.term_names, "xterm") != 0) {
+           || strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
            init_xterm_mouse(sp);
        }
-    } else if (strstr(cur_term->type.term_names, "xterm") != 0) {
+    } else if (strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
        if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK)
            init_xterm_mouse(sp);
     }
+#endif
+
     returnVoid;
 }
 
index 9a05ab8bc73583f025c0ef9c3c25921adb1f0bb3..28c1848cb6bf1d8be35718f1646edab5ac2c8141 100644 (file)
@@ -44,7 +44,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_nl.c,v 1.10 2009/02/21 20:58:21 tom Exp $")
+MODULE_ID("$Id: lib_nl.c,v 1.11 2009/07/04 00:25:53 tom Exp $")
 
 #ifdef __EMX__
 #include <io.h>
@@ -59,7 +59,7 @@ NCURSES_SP_NAME(nl) (NCURSES_SP_DCL0)
     SP_PARM->_nl = TRUE;
 #ifdef __EMX__
     _nc_flush();
-    _fsetmode(NC_OUTPUT, "t");
+    _fsetmode(NC_OUTPUT(SP_PARM), "t");
 #endif
     returnCode(OK);
 }
@@ -81,7 +81,7 @@ NCURSES_SP_NAME(nonl) (NCURSES_SP_DCL0)
     SP_PARM->_nl = FALSE;
 #ifdef __EMX__
     _nc_flush();
-    _fsetmode(NC_OUTPUT, "b");
+    _fsetmode(NC_OUTPUT(SP_PARM), "b");
 #endif
     returnCode(OK);
 }
index 43d9ed7e33691e8fedf48b90cf1b6748cc04e09e..ccd3ad7efd89eaf2a403fd5191e569360db35fd7 100644 (file)
@@ -42,7 +42,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_pad.c,v 1.43 2009/04/18 18:25:37 tom Exp $")
+MODULE_ID("$Id: lib_pad.c,v 1.44 2009/07/04 19:45:20 tom Exp $")
 
 NCURSES_EXPORT(WINDOW *)
 NCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c)
@@ -51,12 +51,13 @@ NCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c)
     NCURSES_CH_T *ptr;
     int i;
 
-    T((T_CALLED("newpad(%d, %d)"), l, c));
+    T((T_CALLED("newpad(%p,%d, %d)"), SP_PARM, l, c));
 
     if (l <= 0 || c <= 0)
        returnWin(0);
 
-    if ((win = _nc_makenew(l, c, 0, 0, _ISPAD)) == NULL)
+    win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx l, c, 0, 0, _ISPAD);
+    if (win == NULL)
        returnWin(0);
 
     for (i = 0; i < l; i++) {
@@ -104,10 +105,14 @@ prefresh(WINDOW *win,
         int smaxrow,
         int smaxcol)
 {
+#if NCURSES_SP_FUNCS
+    SCREEN *sp = _nc_screen_of(win);
+#endif
+
     T((T_CALLED("prefresh()")));
     if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow,
                     smaxcol) != ERR
-       && doupdate() != ERR) {
+       && NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG) != ERR) {
        returnCode(OK);
     }
     returnCode(ERR);
@@ -126,6 +131,7 @@ pnoutrefresh(WINDOW *win,
     NCURSES_SIZE_T m, n;
     NCURSES_SIZE_T pmaxrow;
     NCURSES_SIZE_T pmaxcol;
+    SCREEN *sp;
 
 #if USE_SCROLL_HINTS
     const int my_len = 2;      /* parameterize the threshold for hardscroll */
@@ -142,6 +148,8 @@ pnoutrefresh(WINDOW *win,
     if (!(win->_flags & _ISPAD))
        returnCode(ERR);
 
+    sp = _nc_screen_of(win);
+
     /* negative values are interpreted as zero */
     if (pminrow < 0)
        pminrow = 0;
@@ -172,8 +180,8 @@ pnoutrefresh(WINDOW *win,
        pmaxcol = pmincol + smaxcol - smincol;
     }
 
-    if (smaxrow >= screen_lines(CURRENT_SCREEN)
-       || smaxcol >= screen_columns(CURRENT_SCREEN)
+    if (smaxrow >= screen_lines(sp)
+       || smaxcol >= screen_columns(sp)
        || sminrow > smaxrow
        || smincol > smaxcol)
        returnCode(ERR);
@@ -204,13 +212,13 @@ pnoutrefresh(WINDOW *win,
      * merely change the costs of various update cases.
      */
 #if USE_SCROLL_HINTS
-    wide = (smincol < my_len && smaxcol > (newscr->_maxx - my_len));
+    wide = (smincol < my_len && smaxcol > (NewScreen(sp)->_maxx - my_len));
 #endif
 
     for (i = pminrow, m = sminrow + win->_yoffset;
-        i <= pmaxrow && m <= newscr->_maxy;
+        i <= pmaxrow && m <= NewScreen(sp)->_maxy;
         i++, m++) {
-       register struct ldat *nline = &newscr->_line[m];
+       register struct ldat *nline = &NewScreen(sp)->_line[m];
        register struct ldat *oline = &win->_line[i];
        for (j = pmincol, n = smincol; j <= pmaxcol; j++, n++) {
            NCURSES_CH_T ch = oline->text[j];
@@ -239,9 +247,9 @@ pnoutrefresh(WINDOW *win,
                || nind > smaxrow) {
                nind = _NEWINDEX;
            } else if (displaced) {
-               register struct ldat *pline = &curscr->_line[nind];
+               register struct ldat *pline = &CurScreen(sp)->_line[nind];
                for (j = 0; j <= my_len; j++) {
-                   int k = newscr->_maxx - j;
+                   int k = NewScreen(sp)->_maxx - j;
                    if (pline->text[j] != nline->text[j]
                        || pline->text[k] != nline->text[k]) {
                        nind = _NEWINDEX;
@@ -276,7 +284,7 @@ pnoutrefresh(WINDOW *win,
 
     if (win->_clear) {
        win->_clear = FALSE;
-       newscr->_clear = TRUE;
+       NewScreen(sp)->_clear = TRUE;
     }
 
     /*
@@ -288,10 +296,10 @@ pnoutrefresh(WINDOW *win,
        && win->_curx >= pmincol
        && win->_cury <= pmaxrow
        && win->_curx <= pmaxcol) {
-       newscr->_cury = win->_cury - pminrow + win->_begy + win->_yoffset;
-       newscr->_curx = win->_curx - pmincol + win->_begx;
+       NewScreen(sp)->_cury = win->_cury - pminrow + win->_begy + win->_yoffset;
+       NewScreen(sp)->_curx = win->_curx - pmincol + win->_begx;
     }
-    newscr->_leaveok = win->_leaveok;
+    NewScreen(sp)->_leaveok = win->_leaveok;
     win->_flags &= ~_HASMOVED;
 
     /*
index 2f1a92118382e9811f094d2e3f04cdef8b294f05..127c2990560dd7f2789672c28ce1ba0ccd6a832f 100644 (file)
  */
 
 #include <curses.priv.h>
-
 #include <ctype.h>
-#include <term.h>              /* num_labels, label_*, plab_norm */
 
 #ifndef CUR
-#define CUR SP_TERMTYPE 
+#define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_slk.c,v 1.38 2009/05/10 00:48:29 tom Exp $")
+MODULE_ID("$Id: lib_slk.c,v 1.39 2009/07/04 18:37:57 tom Exp $")
 
 /*
  * Free any memory related to soft labels, return an error.
  */
 static int
-slk_failed(void)
+slk_failed(NCURSES_SP_DCL0)
 {
-    if (SP->_slk) {
-       FreeIfNeeded(SP->_slk->ent);
-       free(SP->_slk);
-       SP->_slk = (SLK *) 0;
+    if ((0 != SP_PARM) && SP_PARM->_slk) {
+       FreeIfNeeded(SP_PARM->_slk->ent);
+       free(SP_PARM->_slk);
+       SP_PARM->_slk = (SLK *) 0;
     }
     return ERR;
 }
 
+NCURSES_EXPORT(int)
+_nc_format_slks(NCURSES_SP_DCLx int cols)
+{
+    int gap, i, x;
+    unsigned max_length = SP_PARM->_slk->maxlen;
+
+    if (!SP_PARM)
+       return ERR;
+
+    if (SP_PARM->slk_format >= 3) {    /* PC style */
+       gap = (cols - 3 * (3 + 4 * max_length)) / 2;
+
+       if (gap < 1)
+           gap = 1;
+
+       for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) {
+           SP_PARM->_slk->ent[i].ent_x = x;
+           x += max_length;
+           x += (i == 3 || i == 7) ? gap : 1;
+       }
+    } else {
+       if (SP_PARM->slk_format == 2) {         /* 4-4 */
+           gap = cols - (SP_PARM->_slk->maxlab * max_length) - 6;
+
+           if (gap < 1)
+               gap = 1;
+           for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) {
+               SP_PARM->_slk->ent[i].ent_x = x;
+               x += max_length;
+               x += (i == 3) ? gap : 1;
+           }
+       } else {
+           if (SP_PARM->slk_format == 1) {     /* 1 -> 3-2-3 */
+               gap = (cols - (SP_PARM->_slk->maxlab * max_length) - 5)
+                   / 2;
+
+               if (gap < 1)
+                   gap = 1;
+               for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) {
+                   SP_PARM->_slk->ent[i].ent_x = x;
+                   x += max_length;
+                   x += (i == 2 || i == 4) ? gap : 1;
+               }
+           } else
+               returnCode(slk_failed(NCURSES_SP_ARG));
+       }
+    }
+    SP_PARM->_slk->dirty = TRUE;
+
+    return OK;
+}
+
 /*
  * Initialize soft labels.
  * Called from newterm()
@@ -72,111 +122,91 @@ slk_failed(void)
 NCURSES_EXPORT(int)
 _nc_slk_initialize(WINDOW *stwin, int cols)
 {
-#if NCURSES_SP_FUNCS
-    SCREEN *sp = CURRENT_SCREEN;
-#endif
-    int i, x;
+    int i;
     int res = OK;
     unsigned max_length;
+    SCREEN *sp;
+    TERMINAL *term;
+    int numlab;
 
     T((T_CALLED("_nc_slk_initialize()")));
 
-    if (SP->_slk) {            /* we did this already, so simply return */
+    assert(stwin);
+
+    sp = _nc_screen_of(stwin);
+    if (0 == sp)
+       returnCode(ERR);
+
+    term = TerminalOf(SP_PARM);
+    assert(term);
+
+    numlab = InfoOf(SP_PARM).numlabels;
+
+    if (SP_PARM->_slk) {       /* we did this already, so simply return */
        returnCode(OK);
-    } else if ((SP->_slk = typeCalloc(SLK, 1)) == 0)
+    } else if ((SP_PARM->_slk = typeCalloc(SLK, 1)) == 0)
        returnCode(ERR);
 
-    SP->_slk->ent = NULL;
+    SP_PARM->_slk->hidden = TRUE;
+    SP_PARM->_slk->ent = NULL;
+    if (!SP_PARM->slk_format)
+       SP_PARM->slk_format = _nc_globals.slk_format;
 
     /*
      * If we use colors, vidputs() will suppress video attributes that conflict
      * with colors.  In that case, we're still guaranteed that "reverse" would
      * work.
      */
-    if ((no_color_video & 1) == 0)
-       SetAttr(SP->_slk->attr, A_STANDOUT);
+    if ((InfoOf(SP_PARM).nocolorvideo & 1) == 0)
+       SetAttr(SP_PARM->_slk->attr, A_STANDOUT);
     else
-       SetAttr(SP->_slk->attr, A_REVERSE);
-
-    SP->_slk->maxlab = ((num_labels > 0)
-                       ? num_labels
-                       : MAX_SKEY(_nc_globals.slk_format));
-    SP->_slk->maxlen = ((num_labels > 0)
-                       ? label_width * label_height
-                       : MAX_SKEY_LEN(_nc_globals.slk_format));
-    SP->_slk->labcnt = ((SP->_slk->maxlab < MAX_SKEY(_nc_globals.slk_format))
-                       ? MAX_SKEY(_nc_globals.slk_format)
-                       : SP->_slk->maxlab);
-
-    if (SP->_slk->maxlen <= 0
-       || SP->_slk->labcnt <= 0
-       || (SP->_slk->ent = typeCalloc(slk_ent,
-                                      (unsigned) SP->_slk->labcnt)) == NULL)
-       returnCode(slk_failed());
-
-    max_length = SP->_slk->maxlen;
-    for (i = 0; i < SP->_slk->labcnt; i++) {
+       SetAttr(SP_PARM->_slk->attr, A_REVERSE);
+
+    SP_PARM->_slk->maxlab = ((numlab > 0)
+                            ? numlab
+                            : MAX_SKEY(SP_PARM->slk_format));
+    SP_PARM->_slk->maxlen = ((numlab > 0)
+                            ? InfoOf(SP_PARM).labelwidth * InfoOf(SP_PARM).labelheight
+                            : MAX_SKEY_LEN(SP_PARM->slk_format));
+    SP_PARM->_slk->labcnt = ((SP_PARM->_slk->maxlab < MAX_SKEY(SP_PARM->slk_format))
+                            ? MAX_SKEY(SP_PARM->slk_format)
+                            : SP_PARM->_slk->maxlab);
+
+    if (SP_PARM->_slk->maxlen <= 0
+       || SP_PARM->_slk->labcnt <= 0
+       || (SP_PARM->_slk->ent = typeCalloc(slk_ent,
+                                           (unsigned) SP_PARM->_slk->labcnt))
+       == NULL)
+       returnCode(slk_failed(NCURSES_SP_ARG));
+
+    max_length = SP_PARM->_slk->maxlen;
+    for (i = 0; i < SP_PARM->_slk->labcnt; i++) {
        size_t used = max_length + 1;
 
-       if ((SP->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used)) == 0)
-           returnCode(slk_failed());
-       memset(SP->_slk->ent[i].ent_text, 0, used);
+       SP_PARM->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used);
+       if (SP_PARM->_slk->ent[i].ent_text == 0)
+           returnCode(slk_failed(NCURSES_SP_ARG));
+       memset(SP_PARM->_slk->ent[i].ent_text, 0, used);
 
-       if ((SP->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used)) == 0)
-           returnCode(slk_failed());
-       memset(SP->_slk->ent[i].form_text, 0, used);
+       SP_PARM->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used);
+       if (SP_PARM->_slk->ent[i].form_text == 0)
+           returnCode(slk_failed(NCURSES_SP_ARG));
+       memset(SP_PARM->_slk->ent[i].form_text, 0, used);
 
-       memset(SP->_slk->ent[i].form_text, ' ', max_length);
-       SP->_slk->ent[i].visible = (char) (i < SP->_slk->maxlab);
+       memset(SP_PARM->_slk->ent[i].form_text, ' ', max_length);
+       SP_PARM->_slk->ent[i].visible = (char) (i < SP_PARM->_slk->maxlab);
     }
-    if (_nc_globals.slk_format >= 3) { /* PC style */
-       int gap = (cols - 3 * (3 + 4 * max_length)) / 2;
-
-       if (gap < 1)
-           gap = 1;
-
-       for (i = x = 0; i < SP->_slk->maxlab; i++) {
-           SP->_slk->ent[i].ent_x = x;
-           x += max_length;
-           x += (i == 3 || i == 7) ? gap : 1;
-       }
-    } else {
-       if (_nc_globals.slk_format == 2) {      /* 4-4 */
-           int gap = cols - (SP->_slk->maxlab * max_length) - 6;
 
-           if (gap < 1)
-               gap = 1;
-           for (i = x = 0; i < SP->_slk->maxlab; i++) {
-               SP->_slk->ent[i].ent_x = x;
-               x += max_length;
-               x += (i == 3) ? gap : 1;
-           }
-       } else {
-           if (_nc_globals.slk_format == 1) {  /* 1 -> 3-2-3 */
-               int gap = (cols - (SP->_slk->maxlab * max_length) - 5)
-               / 2;
+    res = _nc_format_slks(NCURSES_SP_ARGx cols);
 
-               if (gap < 1)
-                   gap = 1;
-               for (i = x = 0; i < SP->_slk->maxlab; i++) {
-                   SP->_slk->ent[i].ent_x = x;
-                   x += max_length;
-                   x += (i == 2 || i == 4) ? gap : 1;
-               }
-           } else
-               returnCode(slk_failed());
-       }
-    }
-    SP->_slk->dirty = TRUE;
-    if ((SP->_slk->win = stwin) == NULL) {
-       returnCode(slk_failed());
+    if ((SP_PARM->_slk->win = stwin) == NULL) {
+       returnCode(slk_failed(NCURSES_SP_ARG));
     }
 
     /* We now reset the format so that the next newterm has again
      * per default no SLK keys and may call slk_init again to
      * define a new layout. (juergen 03-Mar-1999)
      */
-    SP->slk_format = _nc_globals.slk_format;
     _nc_globals.slk_format = 0;
     returnCode(res);
 }
@@ -187,14 +217,16 @@ _nc_slk_initialize(WINDOW *stwin, int cols)
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_restore) (NCURSES_SP_DCL0)
 {
-    T((T_CALLED("slk_restore()")));
+    T((T_CALLED("slk_restore(%p)"), SP_PARM));
 
+    if (0 == SP_PARM)
+       returnCode(ERR);
     if (SP_PARM->_slk == NULL)
-       return (ERR);
+       returnCode(ERR);
     SP_PARM->_slk->hidden = FALSE;
     SP_PARM->_slk->dirty = TRUE;
 
-    returnCode(slk_refresh());
+    returnCode(NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_ARG));
 }
 
 #if NCURSES_SP_FUNCS
index cf99ad0d3b2fbb4d199a8cac59a2b131e740753e..494f429dfb665c972be86fab5edb5e733f0d5134 100644 (file)
@@ -28,6 +28,7 @@
 
 /****************************************************************************
  *  Author: Thomas E. Dickey                                                *
+ *     and: Juergen Pfeifer                                                 *
  ****************************************************************************/
 
 /*
  */
 
 #include <curses.priv.h>
-#include <term.h>
 
 #ifndef CUR
-#define CUR SP_TERMTYPE 
+#define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: resizeterm.c,v 1.39 2009/05/10 00:48:29 tom Exp $")
-
-#define stolen_lines (screen_lines - SP->_lines_avail)
+MODULE_ID("$Id: resizeterm.c,v 1.40 2009/07/04 18:38:49 tom Exp $")
 
 /*
  * If we're trying to be reentrant, do not want any local statics.
@@ -121,7 +119,7 @@ ripped_window(WINDOW *win)
     ripoff_t *rop;
 
     if (win != 0) {
-#if NCURSES_SP_FUNCS
+#ifdef USE_SP_RIPOFF
        SCREEN *sp = _nc_screen_of(win);
 #endif
        for (each_ripoff(rop)) {
@@ -145,7 +143,7 @@ ripped_bottom(WINDOW *win)
     ripoff_t *rop;
 
     if (win != 0) {
-#if NCURSES_SP_FUNCS
+#ifdef USE_SP_RIPOFF
        SCREEN *sp = _nc_screen_of(win);
 #endif
        for (each_ripoff(rop)) {
@@ -169,7 +167,7 @@ child_depth(WINDOW *cmp)
     int depth = 0;
 
     if (cmp != 0) {
-#if NCURSES_SP_FUNCS
+#ifdef USE_SP_WINDOWLIST
        SCREEN *sp = _nc_screen_of(cmp);
 #endif
        WINDOWLIST *wp;
@@ -229,6 +227,12 @@ adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS)
         * move it to the same relative position.
         */
        win->_begy = ToLines - ripped_bottom(win) - 0 - win->_yoffset;
+       if (rop->hook == _nc_slk_initialize)
+           _nc_format_slks(
+#if NCURSES_SP_FUNCS
+               _nc_screen_of(win),
+#endif
+               ToCols);
     } else if (win->_begy >= bottom) {
        /*
         * If it is below the bottom of the new screen, move up by the same
@@ -379,10 +383,17 @@ NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols)
            decrease_size(NCURSES_SP_ARGx ToLines, ToCols, was_stolen EXTRA_ARGS);
        }
 
-       screen_lines(SP_PARM) = lines = ToLines;
-       screen_columns(SP_PARM) = columns = ToCols;
+       screen_lines(SP_PARM) = ToLines;
+       screen_columns(SP_PARM) = ToCols;
+
+#ifdef USE_TERM_DRIVER
+       CallDriver_2(SP_PARM, setsize, ToLines, ToCols);
+#else
+       lines = ToLines;
+       columns = ToCols;
+#endif
 
-       SP_PARM->_lines_avail = lines - was_stolen;
+       SP_PARM->_lines_avail = ToLines - was_stolen;
 
        if (SP_PARM->oldhash) {
            FreeAndNull(SP_PARM->oldhash);
index 5f6b6b74345090967237bba7a52a164d78029982..caf71161f2dc395d26e6bea145a97e3499077562 100644 (file)
@@ -35,7 +35,7 @@
 
 
 /*
- * $Id: curses.priv.h,v 1.427 2009/06/27 20:31:54 tom Exp $
+ * $Id: curses.priv.h,v 1.430 2009/07/04 20:40:42 tom Exp $
  *
  *     curses.priv.h
  *
@@ -395,6 +395,9 @@ NCURSES_EXPORT(int *)        _nc_ptr_Escdelay (SCREEN *);
 
 #define ptrLines(sp)         &LINES
 #define ptrCols(sp)          &COLS
+#define ptrTabsize(sp)       &TABSIZE
+#define ptrEscdelay(sp)      &ESCDELAY
+
 #define SET_LINES(value)     LINES = value
 #define SET_COLS(value)      COLS = value
 #define SET_TABSIZE(value)   TABSIZE = value
@@ -934,8 +937,8 @@ struct screen {
        bool            _nc_sp_idlok;
        bool            _nc_sp_idcok;
 
-#define _nc_idlok SP->_nc_sp_idlok
-#define _nc_idcok SP->_nc_sp_idcok
+#define _nc_idlok SP_PARM->_nc_sp_idlok
+#define _nc_idcok SP_PARM->_nc_sp_idcok
 
        /*
         * These are the data that support the mouse interface.
@@ -1848,7 +1851,7 @@ extern NCURSES_EXPORT_VAR(SCREEN *) SP;
 #define screen_columns(sp)      (sp)->_columns
 
 extern NCURSES_EXPORT(int) _nc_slk_initialize (WINDOW *, int);
-extern NCURSES_EXPORT(int) _nc_format_slks (SCREEN *, int);
+extern NCURSES_EXPORT(int) _nc_format_slks (NCURSES_SP_DCLx int _c);
 
 /*
  * Some constants related to SLK's
index f22d6c5c2fc617adc7a1511b5347a71040fe8591..908ee1b07a98bae4d2f07aacfb01c73923a9474a 100644 (file)
@@ -48,7 +48,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_options.c,v 1.64 2009/05/23 23:58:07 tom Exp $")
+MODULE_ID("$Id: lib_options.c,v 1.65 2009/07/04 18:14:31 tom Exp $")
 
 static int _nc_meta(SCREEN *, bool);
 
@@ -70,6 +70,9 @@ idlok(WINDOW *win, bool flag)
 NCURSES_EXPORT(void)
 idcok(WINDOW *win, bool flag)
 {
+#if NCURSES_SP_FUNCS
+    SCREEN *sp = CURRENT_SCREEN;
+#endif
     T((T_CALLED("idcok(%p,%d)"), win, flag));
 
     if (win)
index e13996ed914a8d9a942a4d3cb212291b622e45d9..c7741ae7ce210335b18f275674c7873a9a7cb16b 100755 (executable)
@@ -29,7 +29,7 @@
 #
 # Author: Thomas E. Dickey, 1997-on
 #
-# $Id: MKexpanded.sh,v 1.15 2009/06/27 20:37:50 tom Exp $
+# $Id: MKexpanded.sh,v 1.16 2009/07/04 16:45:03 tom Exp $
 #
 # Script to generate 'expanded.c', a dummy source that contains functions
 # corresponding to complex macros used in this library.  By making functions,
@@ -55,6 +55,11 @@ cat <<EOF
 #define NEED_NCURSES_CH_T 1
 #include <curses.priv.h>
 #include <term.h>
+
+#ifndef CUR
+#define CUR SP_TERMTYPE
+#endif
+
 #if NCURSES_EXPANDED
 EOF
 
index 93b41bb4930cdd38bf8f0339ee683716c7791e33..c1c565c13436b757fca7ea344365ad0f35087ac6 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 2004,2006 Free Software Foundation, Inc.                   *
+ * Copyright (c) 2004-2006,2009 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            *
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_add_wch.c,v 1.6 2006/12/02 21:19:17 tom Exp $")
+#if HAVE_WCTYPE_H
+#include <wctype.h>
+#endif
 
-NCURSES_EXPORT(int)
-wadd_wch(WINDOW *win, const cchar_t *wch)
+MODULE_ID("$Id: lib_add_wch.c,v 1.7 2009/07/04 21:59:25 tom Exp $")
+
+/* clone/adapt lib_addch.c */
+static const cchar_t blankchar = NewChar(BLANK_TEXT);
+
+/*
+ * Ugly microtweaking alert.  Everything from here to end of module is
+ * likely to be speed-critical -- profiling data sure says it is!
+ * Most of the important screen-painting functions are shells around
+ * wadd_wch().  So we make every effort to reduce function-call overhead
+ * by inlining stuff, even at the cost of making wrapped copies for
+ * export.  Also we supply some internal versions that don't call the
+ * window sync hook, for use by string-put functions.
+ */
+
+/* Return bit mask for clearing color pair number if given ch has color */
+#define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0))
+
+static NCURSES_INLINE cchar_t
+render_char(WINDOW *win, cchar_t ch)
+/* compute a rendition of the given char correct for the current context */
 {
-    PUTC_DATA;
-    int n;
-    int code = ERR;
+    attr_t a = WINDOW_ATTRS(win);
+    int pair = GetPair(ch);
 
-    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win,
-                                     _tracech_t(wch)));
-
-    if (win != 0) {
-       PUTC_INIT;
-       for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
-           attr_t attrs = (wch->attr & A_ATTRIBUTES);
-
-           if ((PUTC_ch = wch->chars[PUTC_i]) == L'\0')
-               break;
-           if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) {
-               code = ERR;
-               if (is8bits(PUTC_ch))
-                   code = waddch(win, UChar(PUTC_ch) | attrs);
-               break;
+    if (ISBLANK(ch)
+       && AttrOf(ch) == A_NORMAL
+       && pair == 0) {
+       /* color/pair in attrs has precedence over bkgrnd */
+       ch = win->_nc_bkgd;
+       SetAttr(ch, a | AttrOf(win->_nc_bkgd));
+       if ((pair = GET_WINDOW_PAIR(win)) == 0)
+           pair = GetPair(win->_nc_bkgd);
+       SetPair(ch, pair);
+    } else {
+       /* color in attrs has precedence over bkgrnd */
+       a |= AttrOf(win->_nc_bkgd) & COLOR_MASK(a);
+       /* color in ch has precedence */
+       if (pair == 0) {
+           if ((pair = GET_WINDOW_PAIR(win)) == 0)
+               pair = GetPair(win->_nc_bkgd);
+       }
+#if 0
+       if (pair > 255) {
+           cchar_t fixme = ch;
+           SetPair(fixme, pair);
+       }
+#endif
+       AddAttr(ch, (a & COLOR_MASK(AttrOf(ch))));
+       SetPair(ch, pair);
+    }
+
+    TR(TRACE_VIRTPUT,
+       ("render_char bkg %s (%d), attrs %s (%d) -> ch %s (%d)",
+       _tracech_t2(1, CHREF(win->_nc_bkgd)),
+       GetPair(win->_nc_bkgd),
+       _traceattr(WINDOW_ATTRS(win)),
+       GET_WINDOW_PAIR(win),
+       _tracech_t2(3, CHREF(ch)),
+       GetPair(ch)));
+
+    return (ch);
+}
+
+/* check if position is legal; if not, return error */
+#ifndef NDEBUG                 /* treat this like an assertion */
+#define CHECK_POSITION(win, x, y) \
+       if (y > win->_maxy \
+        || x > win->_maxx \
+        || y < 0 \
+        || x < 0) { \
+               TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \
+                                  "(_maxx = %d, _maxy = %d)", win, x, y, \
+                                  win->_maxx, win->_maxy)); \
+               return(ERR); \
+       }
+#else
+#define CHECK_POSITION(win, x, y)      /* nothing */
+#endif
+
+static bool
+newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos)
+{
+    bool result = FALSE;
+
+    if (*ypos >= win->_regtop && *ypos == win->_regbottom) {
+       *ypos = win->_regbottom;
+       result = TRUE;
+    } else {
+       *ypos += 1;
+    }
+    return result;
+}
+
+/*
+ * The _WRAPPED flag is useful only for telling an application that we've just
+ * wrapped the cursor.  We don't do anything with this flag except set it when
+ * wrapping, and clear it whenever we move the cursor.  If we try to wrap at
+ * the lower-right corner of a window, we cannot move the cursor (since that
+ * wouldn't be legal).  So we return an error (which is what SVr4 does). 
+ * Unlike SVr4, we can successfully add a character to the lower-right corner
+ * (Solaris 2.6 does this also, however).
+ */
+static int
+wrap_to_next_line(WINDOW *win)
+{
+    win->_flags |= _WRAPPED;
+    if (newline_forces_scroll(win, &(win->_cury))) {
+       win->_curx = win->_maxx;
+       if (!win->_scroll)
+           return (ERR);
+       scroll(win);
+    }
+    win->_curx = 0;
+    return (OK);
+}
+
+static int wadd_wch_literal(WINDOW *, cchar_t);
+/*
+ * Fill the given number of cells with blanks using the current background
+ * rendition.  This saves/restores the current x-position.
+ */
+static void
+fill_cells(WINDOW *win, int count)
+{
+    cchar_t blank = blankchar;
+    int save_x = win->_curx;
+    int save_y = win->_cury;
+
+    while (count-- > 0) {
+       if (wadd_wch_literal(win, blank) == ERR)
+           break;
+    }
+    win->_curx = save_x;
+    win->_cury = save_y;
+}
+
+static int
+wadd_wch_literal(WINDOW *win, cchar_t ch)
+{
+    int x;
+    int y;
+    struct ldat *line;
+
+    x = win->_curx;
+    y = win->_cury;
+
+    CHECK_POSITION(win, x, y);
+
+    ch = render_char(win, ch);
+
+    line = win->_line + y;
+
+    CHANGED_CELL(line, x);
+
+    /*
+     * Non-spacing characters are added to the current cell.
+     *
+     * Spacing characters that are wider than one column require some display
+     * adjustments.
+     */
+    {
+       int len = wcwidth(CharOf(ch));
+       int i;
+       int j;
+       wchar_t *chars;
+
+       if (len == 0) {         /* non-spacing */
+           if ((x > 0 && y >= 0)
+               || (win->_maxx >= 0 && win->_cury >= 1)) {
+               if (x > 0 && y >= 0)
+                   chars = (win->_line[y].text[x - 1].chars);
+               else
+                   chars = (win->_line[y - 1].text[win->_maxx].chars);
+               for (i = 0; i < CCHARW_MAX; ++i) {
+                   if (chars[i] == 0) {
+                       TR(TRACE_VIRTPUT,
+                          ("added non-spacing %d: %x",
+                           x, (int) CharOf(ch)));
+                       chars[i] = CharOf(ch);
+                       break;
+                   }
+               }
            }
-           for (n = 0; n < PUTC_n; n++) {
-               if ((code = waddch(win, UChar(PUTC_buf[n]) | attrs)) == ERR) {
+           goto testwrapping;
+       } else if (len > 1) {   /* multi-column characters */
+           /*
+            * Check if the character will fit on the current line.  If it does
+            * not fit, fill in the remainder of the line with blanks.  and
+            * move to the next line.
+            */
+           if (len > win->_maxx + 1) {
+               TR(TRACE_VIRTPUT, ("character will not fit"));
+               return ERR;
+           } else if (x + len > win->_maxx + 1) {
+               int count = win->_maxx + 1 - x;
+               TR(TRACE_VIRTPUT, ("fill %d remaining cells", count));
+               fill_cells(win, count);
+               if (wrap_to_next_line(win) == ERR)
+                   return ERR;
+               x = win->_curx;
+               y = win->_cury;
+               line = win->_line + y;
+           }
+           /*
+            * Check for cells which are orphaned by adding this character, set
+            * those to blanks.
+            *
+            * FIXME: this actually could fill j-i cells, more complicated to
+            * setup though.
+            */
+           for (i = 0; i < len; ++i) {
+               if (isWidecBase(win->_line[y].text[x + i])) {
+                   break;
+               } else if (isWidecExt(win->_line[y].text[x + i])) {
+                   for (j = i; x + j <= win->_maxx; ++j) {
+                       if (!isWidecExt(win->_line[y].text[x + j])) {
+                           TR(TRACE_VIRTPUT, ("fill %d orphan cells", j));
+                           fill_cells(win, j);
+                           break;
+                       }
+                   }
                    break;
                }
            }
-           if (code == ERR)
-               break;
+           /*
+            * Finally, add the cells for this character.
+            */
+           for (i = 0; i < len; ++i) {
+               cchar_t value = ch;
+               SetWidecExt(value, i);
+               TR(TRACE_VIRTPUT, ("multicolumn %d:%d (%d,%d)",
+                                  i + 1, len,
+                                  win->_begy + y, win->_begx + x));
+               line->text[x] = value;
+               CHANGED_CELL(line, x);
+               ++x;
+           }
+           goto testwrapping;
        }
     }
 
-    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
-    return (code);
+    /*
+     * Single-column characters.
+     */
+    line->text[x++] = ch;
+    /*
+     * This label is used only for wide-characters.
+     */
+  testwrapping:
+
+    TR(TRACE_VIRTPUT, ("cell (%ld, %ld..%d) = %s",
+                      (long) win->_cury, (long) win->_curx, x - 1,
+                      _tracech_t(CHREF(ch))));
+
+    if (x > win->_maxx) {
+       return wrap_to_next_line(win);
+    }
+    win->_curx = x;
+    return OK;
 }
 
-NCURSES_EXPORT(int)
-wecho_wchar(WINDOW *win, const cchar_t *wch)
+static NCURSES_INLINE int
+wadd_wch_nosync(WINDOW *win, cchar_t ch)
+/* the workhorse function -- add a character to the given window */
 {
-    PUTC_DATA;
-    int n;
-    int code = ERR;
+    NCURSES_SIZE_T x, y;
+    wchar_t *s;
+    int tabsize = 8;
 
-    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wecho_wchar(%p, %s)"), win,
-                                     _tracech_t(wch)));
-
-    if (win != 0) {
-       PUTC_INIT;
-       for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
-           attr_t attrs = (wch->attr & A_ATTRIBUTES);
-
-           if ((PUTC_ch = wch->chars[PUTC_i]) == L'\0')
-               break;
-           if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) {
-               code = ERR;
-               if (is8bits(PUTC_ch))
-                   code = waddch(win, UChar(PUTC_ch) | attrs);
-               break;
+    /*
+     * If we are using the alternate character set, forget about locale.
+     * Otherwise, if the locale * claims the code is printable, treat it that
+     * way.
+     */
+    if ((AttrOf(ch) & A_ALTCHARSET)
+       || iswprint(CharOf(ch)))
+       return wadd_wch_literal(win, ch);
+
+    /*
+     * Handle carriage control and other codes that are not printable, or are
+     * known to expand to more than one character according to unctrl().
+     */
+    x = win->_curx;
+    y = win->_cury;
+
+    switch (CharOf(ch)) {
+    case '\t':
+#if USE_REENTRANT
+       tabsize = sp->_TABSIZE;
+#else
+       tabsize = TABSIZE;
+#endif
+       x += (tabsize - (x % tabsize));
+       /*
+        * Space-fill the tab on the bottom line so that we'll get the
+        * "correct" cursor position.
+        */
+       if ((!win->_scroll && (y == win->_regbottom))
+           || (x <= win->_maxx)) {
+           cchar_t blank = blankchar;
+           AddAttr(blank, AttrOf(ch));
+           while (win->_curx < x) {
+               if (wadd_wch_literal(win, blank) == ERR)
+                   return (ERR);
            }
-           for (n = 0; n < PUTC_n; n++) {
-               if ((code = waddch(win, UChar(PUTC_buf[n]) | attrs)) == ERR) {
-                   break;
+           break;
+       } else {
+           wclrtoeol(win);
+           win->_flags |= _WRAPPED;
+           if (newline_forces_scroll(win, &y)) {
+               x = win->_maxx;
+               if (win->_scroll) {
+                   scroll(win);
+                   x = 0;
                }
+           } else {
+               x = 0;
+           }
+       }
+       break;
+    case '\n':
+       wclrtoeol(win);
+       if (newline_forces_scroll(win, &y)) {
+           if (win->_scroll)
+               scroll(win);
+           else
+               return (ERR);
+       }
+       /* FALLTHRU */
+    case '\r':
+       x = 0;
+       win->_flags &= ~_WRAPPED;
+       break;
+    case '\b':
+       if (x == 0)
+           return (OK);
+       x--;
+       win->_flags &= ~_WRAPPED;
+       break;
+    default:
+       if ((s = wunctrl(&ch)) != 0) {
+           while (*s) {
+               cchar_t sch;
+               SetChar(sch, *s++, AttrOf(ch));
+               if_EXT_COLORS(SetPair(sch, GetPair(ch)));
+               if (wadd_wch_literal(win, sch) == ERR)
+                   return ERR;
            }
-           if (code == ERR)
-               break;
+           return OK;
        }
-       wrefresh(win);
+       return ERR;
     }
 
+    win->_curx = x;
+    win->_cury = y;
+
+    return OK;
+}
+
+/*
+ * The versions below call _nc_synchook().  We wanted to avoid this in the
+ * version exported for string puts; they'll call _nc_synchook once at end
+ * of run.
+ */
+
+/* These are actual entry points */
+
+NCURSES_EXPORT(int)
+wadd_wch(WINDOW *win, const cchar_t *wch)
+{
+    int code = ERR;
+
+    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win,
+                                     _tracecchar_t(wch)));
+
+    if (win && (wadd_wch_nosync(win, *wch) != ERR)) {
+       _nc_synchook(win);
+       code = OK;
+    }
+
+    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
+    return (code);
+}
+
+NCURSES_EXPORT(int)
+wecho_wchar(WINDOW *win, const cchar_t *wch)
+{
+    int code = ERR;
+
+    TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win,
+                                     _tracecchar_t(wch)));
+
+    if (win && (wadd_wch_nosync(win, *wch) != ERR)) {
+       bool save_immed = win->_immed;
+       win->_immed = TRUE;
+       _nc_synchook(win);
+       win->_immed = save_immed;
+       code = OK;
+    }
     TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
     return (code);
 }