ncurses 5.7 - patch 20090912
authorThomas E. Dickey <dickey@invisible-island.net>
Sun, 13 Sep 2009 01:17:05 +0000 (01:17 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sun, 13 Sep 2009 01:17:05 +0000 (01:17 +0000)
+ add some test programs (and make these use the same special keys
  by sharing linedata.h functions):
  test/test_addstr.c
  test/test_addwstr.c
  test/test_addchstr.c
  test/test_add_wchstr.c
+ correct internal _nc_insert_ch() to use _nc_insert_wch() when
  inserting wide characters, since the wins_wch() function that it used
  did not update the cursor position (report by Ciprian Craciun).

16 files changed:
MANIFEST
NEWS
dist.mk
ncurses/base/lib_insch.c
ncurses/curses.priv.h
ncurses/widechar/lib_ins_wch.c
test/README
test/ins_wide.c
test/inserts.c
test/linedata.h [new file with mode: 0644]
test/modules
test/programs
test/test_add_wchstr.c [new file with mode: 0644]
test/test_addchstr.c [new file with mode: 0644]
test/test_addstr.c [new file with mode: 0644]
test/test_addwstr.c [new file with mode: 0644]

index cee2cd0b5fd15d177aec88ada848dcd522706b11..eae005ae367c8000f39b03fc3b649c92e46bf0f6 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
 ./test/key_names.c
 ./test/keynames.c
 ./test/knight.c
 ./test/key_names.c
 ./test/keynames.c
 ./test/knight.c
+./test/linedata.h
 ./test/linux-color.dat
 ./test/listused.sh
 ./test/lrtest.c
 ./test/linux-color.dat
 ./test/listused.sh
 ./test/lrtest.c
 ./test/savescreen.sh
 ./test/tclock.c
 ./test/test.priv.h
 ./test/savescreen.sh
 ./test/tclock.c
 ./test/test.priv.h
+./test/test_add_wchstr.c
+./test/test_addchstr.c
+./test/test_addstr.c
+./test/test_addwstr.c
 ./test/test_arrays.c
 ./test/test_get_wstr.c
 ./test/test_getstr.c
 ./test/test_arrays.c
 ./test/test_get_wstr.c
 ./test/test_getstr.c
diff --git a/NEWS b/NEWS
index bc68b6720fd14904a5ee4fbec4650cbc114886ff..53274b72a474e8109f5c378ce78382f1c245801f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,7 +25,7 @@
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
--- $Id: NEWS,v 1.1430 2009/09/06 16:03:13 tom Exp $
+-- $Id: NEWS,v 1.1434 2009/09/12 23:38:28 tom Exp $
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
@@ -45,6 +45,17 @@ 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.
 
 Changes through 1.9.9e did not credit all contributions;
 it is not possible to add this information.
 
+20090912
+       + add some test programs (and make these use the same special keys
+         by sharing linedata.h functions):
+         test/test_addstr.c
+         test/test_addwstr.c
+         test/test_addchstr.c
+         test/test_add_wchstr.c
+       + correct internal _nc_insert_ch() to use _nc_insert_wch() when
+         inserting wide characters, since the wins_wch() function that it used
+         did not update the cursor position (report by Ciprian Craciun).
+
 20090906
        + fix typo s/is_timeout/is_notimeout/ which made "man is_notimeout" not
          work.
 20090906
        + fix typo s/is_timeout/is_notimeout/ which made "man is_notimeout" not
          work.
diff --git a/dist.mk b/dist.mk
index ee0b9fa4dbf5fd68c434a3acd255bedc61a0263b..e42a63be598502793b9bf94d644c8158e9ec1d1d 100644 (file)
--- a/dist.mk
+++ b/dist.mk
@@ -25,7 +25,7 @@
 # use or other dealings in this Software without prior written               #
 # authorization.                                                             #
 ##############################################################################
 # use or other dealings in this Software without prior written               #
 # authorization.                                                             #
 ##############################################################################
-# $Id: dist.mk,v 1.719 2009/09/06 14:11:10 tom Exp $
+# $Id: dist.mk,v 1.720 2009/09/08 10:31:07 tom Exp $
 # Makefile for creating ncurses distributions.
 #
 # This only needs to be used directly as a makefile by developers, but
 # 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
 # These define the major/minor/patch versions of ncurses.
 NCURSES_MAJOR = 5
 NCURSES_MINOR = 7
-NCURSES_PATCH = 20090906
+NCURSES_PATCH = 20090912
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
index e88b945a741fe178d946694093173bfac4c7daee..583a1990b1d6d414c7906b92bf42d07963cf042a 100644 (file)
@@ -43,7 +43,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_insch.c,v 1.29 2009/05/30 16:45:16 tom Exp $")
+MODULE_ID("$Id: lib_insch.c,v 1.31 2009/09/12 18:11:55 tom Exp $")
 
 /*
  * Insert the given character, updating the current location to simplify
 
 /*
  * Insert the given character, updating the current location to simplify
@@ -56,13 +56,13 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch)
     NCURSES_CH_T wch;
     int count;
     NCURSES_CONST char *s;
     NCURSES_CH_T wch;
     int count;
     NCURSES_CONST char *s;
-    int tabsize =
+    int tabsize = (
 #if USE_REENTRANT
 #if USE_REENTRANT
-    sp->_TABSIZE
+                     sp->_TABSIZE
 #else
 #else
-    TABSIZE
+                     TABSIZE
 #endif
 #endif
-     ;
+    );
 
     switch (ch) {
     case '\t':
 
     switch (ch) {
     case '\t':
@@ -119,7 +119,7 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch)
            wch = _nc_render(win, wch);
            count = _nc_build_wch(win, &wch);
            if (count > 0) {
            wch = _nc_render(win, wch);
            count = _nc_build_wch(win, &wch);
            if (count > 0) {
-               code = wins_wch(win, &wch);
+               code = _nc_insert_wch(win, &wch);
            } else if (count == -1) {
                /* handle EILSEQ */
                if (is8bits(ch)) {
            } else if (count == -1) {
                /* handle EILSEQ */
                if (is8bits(ch)) {
index 444ad558ba244a045f65067bd7366e4e9e271448..272fcc51bbc34167e3dd2da44ce8492d32a53366 100644 (file)
@@ -35,7 +35,7 @@
 
 
 /*
 
 
 /*
- * $Id: curses.priv.h,v 1.436 2009/08/30 18:13:54 tom Exp $
+ * $Id: curses.priv.h,v 1.437 2009/09/12 18:09:17 tom Exp $
  *
  *     curses.priv.h
  *
  *
  *     curses.priv.h
  *
@@ -1812,6 +1812,10 @@ extern NCURSES_EXPORT(int) _nc_waddch_nosync (WINDOW *, const NCURSES_CH_T);
 extern NCURSES_EXPORT(void) _nc_scroll_window (WINDOW *, int const, NCURSES_SIZE_T const, NCURSES_SIZE_T const, NCURSES_CH_T);
 #endif
 
 extern NCURSES_EXPORT(void) _nc_scroll_window (WINDOW *, int const, NCURSES_SIZE_T const, NCURSES_SIZE_T const, NCURSES_CH_T);
 #endif
 
+#if USE_WIDEC_SUPPORT
+extern NCURSES_EXPORT(int) _nc_insert_wch(WINDOW *, const cchar_t *);
+#endif
+
 #if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB)
 extern NCURSES_EXPORT(size_t) _nc_wcrtomb (char *, wchar_t, mbstate_t *);
 #endif
 #if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB)
 extern NCURSES_EXPORT(size_t) _nc_wcrtomb (char *, wchar_t, mbstate_t *);
 #endif
index ef9e1b0a3fd2ef51ee720d91a70337ed79057405..ae3302c4c33527b8f2f787f856a9456276c9ecd0 100644 (file)
 
 #include <curses.priv.h>
 
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_ins_wch.c,v 1.9 2009/05/30 14:52:42 tom Exp $")
+MODULE_ID("$Id: lib_ins_wch.c,v 1.10 2009/09/12 18:07:23 tom Exp $")
 
 /*
  * Insert the given character, updating the current location to simplify
  * inserting a string.
  */
 
 /*
  * Insert the given character, updating the current location to simplify
  * inserting a string.
  */
-static int
+NCURSES_EXPORT(int)
 _nc_insert_wch(WINDOW *win, const cchar_t *wch)
 {
     int cells = wcwidth(CharOf(CHDEREF(wch)));
 _nc_insert_wch(WINDOW *win, const cchar_t *wch)
 {
     int cells = wcwidth(CharOf(CHDEREF(wch)));
index 0b21a49eb558ed5e46689b2caf68c6fec9e7aa13..57b252004564f0828af7c7454021a1e2ad1aaf0a 100644 (file)
@@ -25,7 +25,7 @@
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
--- $Id: README,v 1.40 2009/07/11 19:09:01 tom Exp $
+-- $Id: README,v 1.41 2009/09/12 23:17:29 tom Exp $
 -------------------------------------------------------------------------------
 
 The programs in this directory are designed to test your newest toy :-)
 -------------------------------------------------------------------------------
 
 The programs in this directory are designed to test your newest toy :-)
@@ -211,27 +211,27 @@ libncurses:
 ----------
 BC                             -
 COLORS                         test: echochar ncurses savescreen xmas
 ----------
 BC                             -
 COLORS                         test: echochar ncurses savescreen xmas
-COLOR_PAIR                     test: background blue bs cardfile clip_printw demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock testaddch testcurs view worm xmas
+COLOR_PAIR                     test: background blue bs cardfile clip_printw demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr testaddch testcurs view worm xmas
 COLOR_PAIRS                    test: echochar ncurses newdemo savescreen
 COLOR_PAIRS                    test: echochar ncurses newdemo savescreen
-COLS                           test: cardfile demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto echochar edit_field firework foldkeys hashtest inch_wide inchs ins_wide inserts lrtest movewindow ncurses newdemo rain savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm
+COLS                           test: cardfile demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto echochar edit_field firework foldkeys hashtest inch_wide inchs ins_wide inserts lrtest movewindow ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm
 ESCDELAY                       test: test_opaque
 ESCDELAY                       test: test_opaque
-LINES                          test: cardfile demo_defkey demo_keyok demo_menus demo_panels ditto echochar edit_field firework hanoi hashtest inch_wide inchs ins_wide inserts lrtest movewindow ncurses newdemo rain savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
+LINES                          test: cardfile demo_defkey demo_keyok demo_menus demo_panels ditto echochar edit_field firework hanoi hashtest inch_wide inchs ins_wide inserts lrtest movewindow ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
 PAIR_NUMBER                    test: ncurses
 PC                             lib: ncurses
 SP                             lib: menu
 TABSIZE                                test: test_opaque
 UP                             -
 PAIR_NUMBER                    test: ncurses
 PC                             lib: ncurses
 SP                             lib: menu
 TABSIZE                                test: test_opaque
 UP                             -
-acs_map                                test: gdc ins_wide inserts knight movewindow ncurses newdemo testcurs
-add_wch                                test: demo_panels ncurses
-add_wchnstr                    -
-add_wchstr                     test: view
-addch                          test: blue bs echochar hashtest ncurses savescreen test_opaque testaddch view worm
-addchnstr                      -
-addchstr                       -
-addnstr                                -
-addnwstr                       test: ncurses
-addstr                         test: blue bs cardfile gdc hanoi lrtest ncurses savescreen
-addwstr                                test: ncurses
+acs_map                                test: gdc ins_wide inserts knight movewindow ncurses newdemo test_add_wchstr test_addchstr test_addstr test_addwstr testcurs
+add_wch                                test: demo_panels ncurses test_add_wchstr test_addwstr
+add_wchnstr                    test: test_add_wchstr
+add_wchstr                     test: test_add_wchstr view
+addch                          test: blue bs echochar hashtest ncurses savescreen test_add_wchstr test_addchstr test_addstr test_addwstr test_opaque testaddch view worm
+addchnstr                      test: test_addchstr
+addchstr                       test: test_addchstr
+addnstr                                test: test_addstr
+addnwstr                       test: ncurses test_addwstr
+addstr                         test: blue bs cardfile gdc hanoi lrtest ncurses savescreen test_addstr
+addwstr                                test: ncurses test_addwstr
 assume_default_colors          test: ncurses
 attr_get                       test: ncurses
 attr_off                       test: ncurses
 assume_default_colors          test: ncurses
 attr_get                       test: ncurses
 attr_off                       test: ncurses
@@ -241,20 +241,20 @@ attroff                           test: echochar filter gdc ncurses tclock
 attron                         test: bs echochar filter gdc ncurses
 attrset                                test: bs firework gdc hanoi insdelln ncurses rain tclock testaddch testcurs
 baudrate                       lib: ncurses
 attron                         test: bs echochar filter gdc ncurses
 attrset                                test: bs firework gdc hanoi insdelln ncurses rain tclock testaddch testcurs
 baudrate                       lib: ncurses
-beep                           test: blue bs cardfile chgat clip_printw demo_forms demo_menus demo_panels edit_field hanoi inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view xmas
+beep                           test: blue bs cardfile chgat clip_printw demo_forms demo_menus demo_panels edit_field hanoi inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view xmas
 bkgd                           test: background cardfile demo_forms ncurses savescreen tclock view
 bkgdset                                test: background ncurses testaddch
 bkgrnd                         test: ncurses
 bkgrndset                      test: ncurses
 bkgd                           test: background cardfile demo_forms ncurses savescreen tclock view
 bkgdset                                test: background ncurses testaddch
 bkgrnd                         test: ncurses
 bkgrndset                      test: ncurses
-boolcodes                      test: test_arrays progs: dump_entry
+boolcodes                      test: demo_termcap test_arrays progs: dump_entry
 boolfnames                     test: demo_terminfo test_arrays progs: dump_entry
 boolnames                      test: demo_terminfo test_arrays progs: dump_entry infocmp
 border                         -
 border_set                     -
 boolfnames                     test: demo_terminfo test_arrays progs: dump_entry
 boolnames                      test: demo_terminfo test_arrays progs: dump_entry infocmp
 border                         -
 border_set                     -
-box                            test: cardfile chgat clip_printw demo_forms demo_menus demo_panels ditto edit_field inch_wide inchs ins_wide insdelln inserts lrtest ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
+box                            test: cardfile chgat clip_printw demo_forms demo_menus demo_panels ditto edit_field inch_wide inchs ins_wide insdelln inserts lrtest ncurses newdemo redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 box_set                                test: ncurses
 can_change_color               test: ncurses
 box_set                                test: ncurses
 can_change_color               test: ncurses
-cbreak                         test: background blue bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto filter firework foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses newdemo savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
+cbreak                         test: background blue bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto filter firework foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses newdemo savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
 chgat                          test: chgat
 clear                          test: blue bs gdc ncurses testcurs xmas
 clearok                                test: bs knight
 chgat                          test: chgat
 clear                          test: blue bs gdc ncurses testcurs xmas
 clearok                                test: bs knight
@@ -275,14 +275,14 @@ delay_output                      test: newdemo
 delch                          -
 deleteln                       test: insdelln
 delscreen                      test: ditto dots_mvcur
 delch                          -
 deleteln                       test: insdelln
 delscreen                      test: ditto dots_mvcur
-delwin                         test: cardfile chgat clip_printw demo_forms demo_panels edit_field inch_wide inchs ins_wide insdelln inserts movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
-derwin                         test: cardfile chgat clip_printw demo_forms demo_menus ditto inch_wide inchs ins_wide insdelln inserts movewindow ncurses test_get_wstr test_getstr test_instr test_inwstr test_opaque
-doupdate                       test: cardfile demo_menus demo_panels ditto edit_field ins_wide inserts knight movewindow ncurses redraw savescreen test_get_wstr test_getstr
+delwin                         test: cardfile chgat clip_printw demo_forms demo_panels edit_field inch_wide inchs ins_wide insdelln inserts movewindow ncurses newdemo redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
+derwin                         test: cardfile chgat clip_printw demo_forms demo_menus ditto inch_wide inchs ins_wide insdelln inserts movewindow ncurses test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque
+doupdate                       test: cardfile demo_menus demo_panels ditto edit_field ins_wide inserts knight movewindow ncurses redraw savescreen test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr
 dupwin                         test: edit_field
 echo                           test: bs hanoi ncurses test_get_wstr test_getstr testcurs testscanw
 echo_wchar                     test: ncurses
 echochar                       test: echochar ncurses
 dupwin                         test: edit_field
 echo                           test: bs hanoi ncurses test_get_wstr test_getstr testcurs testscanw
 echo_wchar                     test: ncurses
 echochar                       test: echochar ncurses
-endwin                         test: background blue bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto dots_mvcur echochar filter firework firstlast foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses newdemo rain redraw savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testaddch testcurs testscanw view worm xmas
+endwin                         test: background blue bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto dots_mvcur echochar filter firework firstlast foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses newdemo rain redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testaddch testcurs testscanw view worm xmas
 erase                          test: cardfile demo_menus filter firework firstlast hanoi lrtest ncurses tclock test_opaque testcurs
 erasechar                      lib: ncurses
 erasewchar                     -
 erase                          test: cardfile demo_menus filter firework firstlast hanoi lrtest ncurses tclock test_opaque testcurs
 erasechar                      lib: ncurses
 erasewchar                     -
@@ -299,8 +299,8 @@ getbkgd                             test: ncurses
 getbkgrnd                      test: ncurses
 getcchar                       test: ncurses view
 getch                          test: background blue bs chgat color_set demo_altkeys filter firework firstlast foldkeys hanoi hashtest insdelln lrtest savescreen tclock test_opaque testaddch testcurs view xmas
 getbkgrnd                      test: ncurses
 getcchar                       test: ncurses view
 getch                          test: background blue bs chgat color_set demo_altkeys filter firework firstlast foldkeys hanoi hashtest insdelln lrtest savescreen tclock test_opaque testaddch testcurs view xmas
-getcurx                                test: bs chgat clip_printw demo_altkeys demo_defkey demo_panels foldkeys insdelln movewindow ncurses redraw savescreen test_get_wstr test_getstr test_opaque testcurs
-getcury                                test: bs chgat clip_printw demo_altkeys demo_defkey demo_panels edit_field foldkeys insdelln movewindow ncurses redraw savescreen test_opaque testcurs
+getcurx                                test: bs chgat clip_printw demo_altkeys demo_defkey demo_panels firstlast foldkeys insdelln movewindow ncurses redraw savescreen test_get_wstr test_getstr test_opaque testcurs
+getcury                                test: bs chgat clip_printw demo_altkeys demo_defkey demo_panels edit_field firstlast foldkeys insdelln movewindow ncurses redraw savescreen test_opaque testcurs
 getmaxx                                test: chgat clip_printw demo_panels inch_wide inchs insdelln movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 getmaxy                                test: chgat clip_printw demo_forms demo_panels inch_wide inchs insdelln movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 getmouse                       test: bs knight movewindow ncurses
 getmaxx                                test: chgat clip_printw demo_panels inch_wide inchs insdelln movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 getmaxy                                test: chgat clip_printw demo_forms demo_panels inch_wide inchs insdelln movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 getmouse                       test: bs knight movewindow ncurses
@@ -311,7 +311,7 @@ getpary                             test: movewindow
 getstr                         test: test_getstr
 getwin                         test: ncurses
 halfdelay                      test: view
 getstr                         test: test_getstr
 getwin                         test: ncurses
 halfdelay                      test: view
-has_colors                     test: background bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock testcurs view worm xmas
+has_colors                     test: background bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr testcurs view worm xmas
 has_ic                         test: lrtest
 has_il                         lib: ncurses
 has_key                                lib: ncurses
 has_ic                         test: lrtest
 has_il                         lib: ncurses
 has_key                                lib: ncurses
@@ -328,8 +328,8 @@ inch                                test: inchs
 inchnstr                       test: inchs
 inchstr                                test: inchs
 init_color                     test: ncurses
 inchnstr                       test: inchs
 inchstr                                test: inchs
 init_color                     test: ncurses
-init_pair                      test: background blue bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock testaddch testcurs view worm xmas
-initscr                                test: background blue bs cardfile chgat clip_printw color_set demo_defkey demo_forms demo_keyok demo_menus demo_panels echochar filter firework firstlast gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses newdemo rain redraw savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testaddch testcurs testscanw view worm xmas
+init_pair                      test: background blue bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr testaddch testcurs view worm xmas
+initscr                                test: background blue bs cardfile chgat clip_printw color_set demo_defkey demo_forms demo_keyok demo_menus demo_panels echochar filter firework firstlast gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses newdemo rain redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testaddch testcurs testscanw view worm xmas
 innstr                         test: test_instr
 innwstr                                test: test_inwstr
 ins_nwstr                      test: ins_wide
 innstr                         test: test_instr
 innwstr                                test: test_inwstr
 ins_nwstr                      test: ins_wide
@@ -352,7 +352,9 @@ is_leaveok                  test: test_opaque
 is_linetouched                 lib: form
 is_nodelay                     test: test_opaque
 is_notimeout                   test: test_opaque
 is_linetouched                 lib: form
 is_nodelay                     test: test_opaque
 is_notimeout                   test: test_opaque
+is_pad                         -
 is_scrollok                    test: test_opaque
 is_scrollok                    test: test_opaque
+is_subwin                      -
 is_syncok                      test: test_opaque
 is_term_resized                        -
 is_wintouched                  lib: ncurses
 is_syncok                      test: test_opaque
 is_term_resized                        -
 is_wintouched                  lib: ncurses
@@ -362,7 +364,7 @@ key_name                    test: key_names ncurses
 keybound                       test: demo_altkeys demo_defkey
 keyname                                test: demo_altkeys demo_defkey demo_keyok demo_menus edit_field foldkeys keynames movewindow ncurses redraw testcurs view progs: tic
 keyok                          test: demo_keyok foldkeys
 keybound                       test: demo_altkeys demo_defkey
 keyname                                test: demo_altkeys demo_defkey demo_keyok demo_menus edit_field foldkeys keynames movewindow ncurses redraw testcurs view progs: tic
 keyok                          test: demo_keyok foldkeys
-keypad                         test: bs cardfile chgat clip_printw demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto edit_field filter firework foldkeys hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses redraw savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs testscanw view
+keypad                         test: bs cardfile chgat clip_printw demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto edit_field filter firework foldkeys hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs testscanw view
 killchar                       lib: ncurses
 killwchar                      -
 leaveok                                test: hanoi test_opaque
 killchar                       lib: ncurses
 killwchar                      -
 leaveok                                test: hanoi test_opaque
@@ -372,17 +374,17 @@ meta                              test: key_names keynames ncurses
 mouse_trafo                    -
 mouseinterval                  -
 mousemask                      test: bs demo_forms demo_menus knight movewindow ncurses
 mouse_trafo                    -
 mouseinterval                  -
 mousemask                      test: bs demo_forms demo_menus knight movewindow ncurses
-move                           test: blue bs cardfile chgat demo_altkeys demo_menus echochar foldkeys gdc hanoi hashtest inch_wide inchs ins_wide inserts knight lrtest movewindow ncurses savescreen test_get_wstr test_getstr test_instr test_inwstr test_opaque testscanw view xmas
-mvadd_wch                      test: ncurses
-mvadd_wchnstr                  -
-mvadd_wchstr                   -
-mvaddch                                test: bs gdc hanoi lrtest ncurses rain tclock xmas
-mvaddchnstr                    test: gdc
-mvaddchstr                     -
-mvaddnstr                      -
-mvaddnwstr                     -
-mvaddstr                       test: bs demo_forms gdc hanoi knight ncurses rain tclock testcurs xmas
-mvaddwstr                      -
+move                           test: blue bs cardfile chgat demo_altkeys demo_menus echochar foldkeys gdc hanoi hashtest inch_wide inchs ins_wide inserts knight lrtest movewindow ncurses savescreen test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testscanw view xmas
+mvadd_wch                      test: ncurses test_add_wchstr test_addwstr
+mvadd_wchnstr                  test: test_add_wchstr
+mvadd_wchstr                   test: test_add_wchstr
+mvaddch                                test: bs gdc hanoi lrtest ncurses rain tclock test_add_wchstr test_addchstr test_addstr test_addwstr xmas
+mvaddchnstr                    test: gdc test_addchstr
+mvaddchstr                     test: test_addchstr
+mvaddnstr                      test: test_addstr
+mvaddnwstr                     test: test_addwstr
+mvaddstr                       test: bs demo_forms gdc hanoi knight ncurses rain tclock test_addstr testcurs xmas
+mvaddwstr                      test: test_addwstr
 mvchgat                                test: chgat
 mvcur                          test: dots_mvcur redraw
 mvdelch                                -
 mvchgat                                test: chgat
 mvcur                          test: dots_mvcur redraw
 mvdelch                                -
@@ -415,16 +417,16 @@ mvprintw                  test: bs demo_menus firework hanoi ncurses tclock view
 mvscanw                                -
 mvvline                                test: ncurses
 mvvline_set                    test: ncurses
 mvscanw                                -
 mvvline                                test: ncurses
 mvvline_set                    test: ncurses
-mvwadd_wch                     -
-mvwadd_wchnstr                 lib: form
-mvwadd_wchstr                  test: inch_wide
-mvwaddch                       test: movewindow newdemo testcurs xmas
-mvwaddchnstr                   -
-mvwaddchstr                    test: inchs
-mvwaddnstr                     test: newdemo testcurs
-mvwaddnwstr                    -
-mvwaddstr                      test: ditto firstlast ins_wide inserts knight ncurses newdemo test_instr testcurs xmas
-mvwaddwstr                     test: test_inwstr
+mvwadd_wch                     test: test_add_wchstr test_addwstr
+mvwadd_wchnstr                 test: test_add_wchstr
+mvwadd_wchstr                  test: inch_wide test_add_wchstr
+mvwaddch                       test: movewindow newdemo test_add_wchstr test_addchstr test_addstr test_addwstr testcurs xmas
+mvwaddchnstr                   test: test_addchstr
+mvwaddchstr                    test: inchs test_addchstr
+mvwaddnstr                     test: newdemo test_addstr testcurs
+mvwaddnwstr                    test: test_addwstr
+mvwaddstr                      test: ditto firstlast ins_wide inserts knight ncurses newdemo test_addstr test_addwstr test_instr testcurs xmas
+mvwaddwstr                     test: test_addwstr test_inwstr
 mvwchgat                       test: chgat
 mvwdelch                       test: ncurses
 mvwget_wch                     -
 mvwchgat                       test: chgat
 mvwdelch                       test: ncurses
 mvwget_wch                     -
@@ -454,23 +456,23 @@ mvwinstr                  test: test_instr
 mvwinwstr                      test: test_inwstr
 mvwprintw                      test: chgat clip_printw demo_panels inch_wide inchs insdelln ncurses test_instr test_inwstr testcurs
 mvwscanw                       test: testcurs
 mvwinwstr                      test: test_inwstr
 mvwprintw                      test: chgat clip_printw demo_panels inch_wide inchs insdelln ncurses test_instr test_inwstr testcurs
 mvwscanw                       test: testcurs
-mvwvline                       test: ins_wide inserts movewindow
+mvwvline                       test: ins_wide inserts movewindow test_add_wchstr test_addchstr test_addstr test_addwstr
 mvwvline_set                   -
 napms                          test: demo_panels ditto dots dots_mvcur echochar firework gdc hanoi lrtest ncurses railroad rain tclock test_opaque testcurs view worm xmas progs: tset
 newpad                         test: edit_field ncurses testcurs
 newscr                         lib: ncurses
 newterm                                test: demo_altkeys ditto dots_mvcur filter foldkeys gdc key_names keynames
 mvwvline_set                   -
 napms                          test: demo_panels ditto dots dots_mvcur echochar firework gdc hanoi lrtest ncurses railroad rain tclock test_opaque testcurs view worm xmas progs: tset
 newpad                         test: edit_field ncurses testcurs
 newscr                         lib: ncurses
 newterm                                test: demo_altkeys ditto dots_mvcur filter foldkeys gdc key_names keynames
-newwin                         test: cardfile chgat clip_printw demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto edit_field firstlast inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs xmas
+newwin                         test: cardfile chgat clip_printw demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto edit_field firstlast inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses newdemo redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs xmas
 nl                             test: demo_forms ncurses rain testcurs
 nocbreak                       test: testcurs
 nodelay                                test: ditto firework gdc lrtest ncurses newdemo rain tclock test_opaque view worm xmas
 nl                             test: demo_forms ncurses rain testcurs
 nocbreak                       test: testcurs
 nodelay                                test: ditto firework gdc lrtest ncurses newdemo rain tclock test_opaque view worm xmas
-noecho                         test: background bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto firework firstlast foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses rain redraw savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
+noecho                         test: background bs cardfile chgat clip_printw color_set demo_altkeys demo_defkey demo_forms demo_keyok demo_menus demo_panels ditto firework firstlast foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts knight lrtest movewindow ncurses rain redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs view worm xmas
 nofilter                       -
 nonl                           test: bs demo_forms hashtest movewindow ncurses view worm xmas
 noqiflush                      -
 noraw                          test: demo_forms demo_menus ncurses testcurs
 notimeout                      test: test_opaque
 nofilter                       -
 nonl                           test: bs demo_forms hashtest movewindow ncurses view worm xmas
 noqiflush                      -
 noraw                          test: demo_forms demo_menus ncurses testcurs
 notimeout                      test: test_opaque
-numcodes                       test: test_arrays progs: dump_entry
+numcodes                       test: demo_termcap test_arrays progs: dump_entry
 numfnames                      test: demo_terminfo test_arrays progs: dump_entry
 numnames                       test: demo_terminfo test_arrays progs: dump_entry infocmp
 ospeed                         progs: tset
 numfnames                      test: demo_terminfo test_arrays progs: dump_entry
 numnames                       test: demo_terminfo test_arrays progs: dump_entry infocmp
 ospeed                         progs: tset
@@ -508,9 +510,9 @@ set_curterm                 lib: ncurses
 set_escdelay                   test: test_opaque
 set_tabsize                    test: test_opaque
 set_term                       lib: ncurses
 set_escdelay                   test: test_opaque
 set_tabsize                    test: test_opaque
 set_term                       lib: ncurses
-setcchar                       test: demo_panels ins_wide ncurses view
+setcchar                       test: demo_panels ins_wide ncurses test_add_wchstr test_addwstr view
 setscrreg                      test: view
 setscrreg                      test: view
-setupterm                      test: demo_terminfo dots progs: clear tabs tput tset
+setupterm                      test: demo_termcap demo_terminfo dots progs: clear tabs tput tset
 slk_attr                       -
 slk_attr_off                   -
 slk_attr_on                    -
 slk_attr                       -
 slk_attr_off                   -
 slk_attr_on                    -
@@ -530,9 +532,9 @@ slk_touch                   lib: ncurses
 slk_wset                       test: ncurses
 standend                       test: blue gdc ncurses
 standout                       test: blue ncurses
 slk_wset                       test: ncurses
 standend                       test: blue gdc ncurses
 standout                       test: blue ncurses
-start_color                    test: background blue bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock testaddch testcurs view worm xmas
-stdscr                         test: bs chgat clip_printw demo_altkeys demo_forms demo_menus demo_panels ditto filter firework foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses rain redraw savescreen tclock test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs testscanw view worm xmas
-strcodes                       test: test_arrays progs: dump_entry
+start_color                    test: background blue bs cardfile chgat clip_printw color_set demo_forms demo_menus demo_panels echochar filter firework gdc hanoi ins_wide insdelln inserts knight ncurses newdemo rain savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr testaddch testcurs view worm xmas
+stdscr                         test: bs chgat clip_printw demo_altkeys demo_forms demo_menus demo_panels ditto filter firework foldkeys gdc hanoi hashtest inch_wide inchs ins_wide insdelln inserts key_names keynames knight lrtest movewindow ncurses rain redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs testscanw view worm xmas
+strcodes                       test: demo_termcap test_arrays progs: dump_entry
 strfnames                      test: demo_terminfo test_arrays progs: dump_entry
 strnames                       test: demo_terminfo foldkeys test_arrays progs: dump_entry infocmp tic
 subpad                         test: testcurs
 strfnames                      test: demo_terminfo test_arrays progs: dump_entry
 strnames                       test: demo_terminfo foldkeys test_arrays progs: dump_entry infocmp tic
 subpad                         test: testcurs
@@ -551,7 +553,7 @@ tigetnum                    test: demo_terminfo ncurses progs: tput
 tigetstr                       test: blue demo_defkey demo_terminfo foldkeys testcurs progs: tput
 timeout                                test: rain savescreen
 touchline                      test: chgat clip_printw insdelln
 tigetstr                       test: blue demo_defkey demo_terminfo foldkeys testcurs progs: tput
 timeout                                test: rain savescreen
 touchline                      test: chgat clip_printw insdelln
-touchwin                       test: chgat clip_printw demo_menus edit_field filter firstlast inch_wide inchs ins_wide insdelln inserts movewindow ncurses redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque xmas
+touchwin                       test: chgat clip_printw demo_menus edit_field filter firstlast inch_wide inchs ins_wide insdelln inserts movewindow ncurses redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque xmas
 tparm                          test: dots dots_mvcur progs: tabs tic tput
 tputs                          test: dots dots_mvcur railroad progs: clear tabs tset
 trace                          test: demo_menus hanoi hashtest lrtest ncurses testcurs view worm
 tparm                          test: dots dots_mvcur progs: tabs tic tput
 tputs                          test: dots dots_mvcur railroad progs: clear tabs tset
 trace                          test: demo_menus hanoi hashtest lrtest ncurses testcurs view worm
@@ -578,16 +580,16 @@ vw_printw                 test: clip_printw
 vw_scanw                       -
 vwprintw                       test: movewindow
 vwscanw                                lib: ncurses
 vw_scanw                       -
 vwprintw                       test: movewindow
 vwscanw                                lib: ncurses
-wadd_wch                       test: inch_wide
-wadd_wchnstr                   lib: form
-wadd_wchstr                    -
-waddch                         test: demo_forms demo_panels ditto firstlast inch_wide inchs knight ncurses test_get_wstr test_getstr test_instr test_inwstr test_opaque worm
-waddchnstr                     lib: ncurses
-waddchstr                      -
-waddnstr                       lib: menu
-waddnwstr                      test: ncurses
-waddstr                                test: chgat clip_printw demo_forms demo_panels edit_field firstlast ins_wide insdelln knight ncurses redraw testcurs
-waddwstr                       test: ins_wide test_get_wstr
+wadd_wch                       test: inch_wide test_add_wchstr test_addwstr
+wadd_wchnstr                   test: test_add_wchstr
+wadd_wchstr                    test: test_add_wchstr
+waddch                         test: demo_forms demo_panels ditto firstlast inch_wide inchs knight ncurses test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque worm
+waddchnstr                     test: test_addchstr
+waddchstr                      test: test_addchstr
+waddnstr                       test: test_addstr
+waddnwstr                      test: ncurses test_addwstr
+waddstr                                test: chgat clip_printw demo_forms demo_panels edit_field firstlast ins_wide insdelln knight ncurses redraw test_add_wchstr test_addstr test_addwstr testcurs
+waddwstr                       test: ins_wide test_add_wchstr test_addwstr test_get_wstr
 wattr_get                      -
 wattr_off                      lib: ncurses
 wattr_on                       lib: ncurses
 wattr_get                      -
 wattr_off                      lib: ncurses
 wattr_on                       lib: ncurses
@@ -596,7 +598,7 @@ wattroff                    test: demo_forms ncurses testcurs xmas
 wattron                                test: testcurs xmas
 wattrset                       test: clip_printw demo_forms insdelln ncurses newdemo test_get_wstr test_getstr testcurs xmas
 wbkgd                          test: cardfile demo_forms demo_menus ncurses newdemo testcurs
 wattron                                test: testcurs xmas
 wattrset                       test: clip_printw demo_forms insdelln ncurses newdemo test_get_wstr test_getstr testcurs xmas
 wbkgd                          test: cardfile demo_forms demo_menus ncurses newdemo testcurs
-wbkgdset                       test: demo_panels ins_wide inserts ncurses
+wbkgdset                       test: demo_panels ins_wide inserts ncurses test_add_wchstr test_addchstr test_addstr test_addwstr
 wbkgrnd                                lib: ncurses
 wbkgrndset                     lib: ncurses
 wborder                                test: ncurses
 wbkgrnd                                lib: ncurses
 wbkgrndset                     lib: ncurses
 wborder                                test: ncurses
@@ -604,7 +606,7 @@ wborder_set                 test: ncurses
 wchgat                         test: chgat test_get_wstr test_getstr view
 wclear                         test: ncurses test_opaque testcurs
 wclrtobot                      test: firstlast inch_wide inchs ncurses test_instr test_inwstr testcurs
 wchgat                         test: chgat test_get_wstr test_getstr view
 wclear                         test: ncurses test_opaque testcurs
 wclrtobot                      test: firstlast inch_wide inchs ncurses test_instr test_inwstr testcurs
-wclrtoeol                      test: chgat clip_printw demo_defkey demo_keyok demo_panels firstlast inch_wide inchs ins_wide insdelln inserts knight ncurses test_instr test_inwstr testcurs
+wclrtoeol                      test: chgat clip_printw demo_defkey demo_keyok demo_panels firstlast inch_wide inchs ins_wide insdelln inserts knight ncurses test_add_wchstr test_addchstr test_addstr test_addwstr test_instr test_inwstr testcurs
 wcolor_set                     lib: ncurses
 wcursyncup                     lib: form
 wdelch                         test: ncurses testcurs
 wcolor_set                     lib: ncurses
 wcursyncup                     lib: form
 wdelch                         test: ncurses testcurs
@@ -613,10 +615,10 @@ wecho_wchar                       lib: ncurses
 wechochar                      lib: ncurses
 wenclose                       lib: form
 werase                         test: cardfile demo_forms demo_menus demo_panels edit_field firstlast knight ncurses newdemo test_get_wstr test_getstr test_opaque testcurs xmas
 wechochar                      lib: ncurses
 wenclose                       lib: form
 werase                         test: cardfile demo_forms demo_menus demo_panels edit_field firstlast knight ncurses newdemo test_get_wstr test_getstr test_opaque testcurs xmas
-wget_wch                       test: ins_wide ncurses
+wget_wch                       test: ins_wide ncurses test_add_wchstr test_addwstr
 wget_wstr                      test: test_get_wstr
 wgetbkgrnd                     lib: ncurses
 wget_wstr                      test: test_get_wstr
 wgetbkgrnd                     lib: ncurses
-wgetch                         test: cardfile chgat clip_printw demo_defkey demo_keyok demo_menus demo_panels ditto edit_field gdc insdelln inserts knight movewindow ncurses newdemo rain redraw test_opaque testcurs worm
+wgetch                         test: cardfile chgat clip_printw demo_defkey demo_keyok demo_menus demo_panels ditto edit_field gdc insdelln inserts knight movewindow ncurses newdemo rain redraw test_addchstr test_addstr test_opaque testcurs worm
 wgetn_wstr                     test: ncurses test_get_wstr
 wgetnstr                       test: ncurses test_getstr
 wgetparent                     test: test_opaque
 wgetn_wstr                     test: ncurses test_get_wstr
 wgetnstr                       test: ncurses test_getstr
 wgetparent                     test: test_opaque
@@ -643,11 +645,11 @@ winsstr                           test: inserts
 winstr                         test: test_instr
 winwstr                                test: test_inwstr
 wmouse_trafo                   lib: form
 winstr                         test: test_instr
 winwstr                                test: test_inwstr
 wmouse_trafo                   lib: form
-wmove                          test: chgat clip_printw demo_altkeys demo_defkey demo_keyok demo_menus demo_panels firstlast foldkeys inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses newdemo redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs worm
-wnoutrefresh                   test: demo_menus ditto edit_field inch_wide inchs ins_wide inserts knight movewindow ncurses redraw test_get_wstr test_getstr test_instr test_inwstr test_opaque
-wprintw                                test: chgat clip_printw demo_defkey demo_forms demo_keyok demo_menus demo_panels edit_field inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
+wmove                          test: chgat clip_printw demo_altkeys demo_defkey demo_keyok demo_menus demo_panels firstlast foldkeys inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses newdemo redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs worm
+wnoutrefresh                   test: demo_menus ditto edit_field inch_wide inchs ins_wide inserts knight movewindow ncurses redraw test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque
+wprintw                                test: chgat clip_printw demo_defkey demo_forms demo_keyok demo_menus demo_panels edit_field inch_wide inchs ins_wide insdelln inserts knight movewindow ncurses test_add_wchstr test_addchstr test_addstr test_addwstr test_get_wstr test_getstr test_instr test_inwstr test_opaque testcurs
 wredrawln                      test: redraw
 wredrawln                      test: redraw
-wrefresh                       test: chgat clip_printw demo_forms demo_keyok demo_menus demo_panels edit_field firstlast insdelln knight lrtest movewindow ncurses newdemo redraw savescreen tclock testcurs view worm xmas
+wrefresh                       test: chgat clip_printw demo_forms demo_keyok demo_menus demo_panels edit_field firstlast ins_wide insdelln inserts knight lrtest movewindow ncurses newdemo redraw savescreen tclock test_add_wchstr test_addchstr test_addstr test_addwstr testcurs view worm xmas
 wresize                                test: cardfile ncurses
 wscanw                         test: testcurs
 wscrl                          test: ncurses testcurs
 wresize                                test: cardfile ncurses
 wscanw                         test: testcurs
 wscrl                          test: ncurses testcurs
index 33dafe4fcd05d8117d72e20566a16d3c135a037a..4b95216951ca2fa0435cd7b0930d06fd62577485 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 2002-2006,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 2002-2007,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            *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -26,7 +26,7 @@
  * authorization.                                                           *
  ****************************************************************************/
 /*
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: ins_wide.c,v 1.9 2007/07/21 17:41:55 tom Exp $
+ * $Id: ins_wide.c,v 1.11 2009/09/12 23:02:26 tom Exp $
  *
  * Demonstrate the wins_wstr() and wins_wch functions.
  * Thomas Dickey - 2002/11/23
  *
  * Demonstrate the wins_wstr() and wins_wch functions.
  * Thomas Dickey - 2002/11/23
@@ -45,6 +45,9 @@
 
 #if USE_WIDEC_SUPPORT
 
 
 #if USE_WIDEC_SUPPORT
 
+#define WIDE_LINEDATA
+#include <linedata.h>
+
 /* definitions to make it simpler to compare with inserts.c */
 #define InsNStr    ins_nwstr
 #define InsStr     ins_wstr
 /* definitions to make it simpler to compare with inserts.c */
 #define InsNStr    ins_nwstr
 #define InsStr     ins_wstr
@@ -214,8 +217,7 @@ test_inserts(int level)
 {
     static bool first = TRUE;
 
 {
     static bool first = TRUE;
 
-    wint_t ch;
-    int code;
+    int ch;
     int limit;
     int row = 1;
     int col;
     int limit;
     int row = 1;
     int col;
@@ -282,30 +284,10 @@ test_inserts(int level)
        wbkgdset(work, COLOR_PAIR(1) | ' ');
     }
 
        wbkgdset(work, COLOR_PAIR(1) | ' ');
     }
 
-    while ((code = wget_wch(work, &ch)) != ERR) {
-
-       if (code == KEY_CODE_YES) {
-           switch (ch) {
-           case KEY_DOWN:
-               ch = CTRL('N');
-               break;
-           case KEY_BACKSPACE:
-               ch = '\b';
-               break;
-           default:
-               beep();
-               continue;
-           }
-       } else if (code == ERR) {
-           beep();
-           break;
-       }
-       if (ch == 'q')
-           break;
-
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
        wmove(work, row, margin + 1);
        switch (ch) {
        wmove(work, row, margin + 1);
        switch (ch) {
-       case 'w':
+       case key_RECUR:
            test_inserts(level + 1);
 
            touchwin(look);
            test_inserts(level + 1);
 
            touchwin(look);
@@ -318,7 +300,7 @@ test_inserts(int level)
 
            doupdate();
            break;
 
            doupdate();
            break;
-       case CTRL('N'):
+       case key_NEWLINE:
            if (row < limit) {
                ++row;
                /* put the whole string in, all at once */
            if (row < limit) {
                ++row;
                /* put the whole string in, all at once */
@@ -401,9 +383,6 @@ test_inserts(int level)
                beep();
            }
            break;
                beep();
            }
            break;
-       case KEY_BACKSPACE:
-           ch = '\b';
-           /* FALLTHRU */
        default:
            buffer[length++] = ch;
            buffer[length] = '\0';
        default:
            buffer[length++] = ch;
            buffer[length] = '\0';
@@ -473,6 +452,7 @@ usage(void)
        "Usage: inserts [options]"
        ,""
        ,"Options:"
        "Usage: inserts [options]"
        ,""
        ,"Options:"
+       ,"  -f FILE read data from given file"
        ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
        ,"  -m      perform wmove/move separately from insert-functions"
        ,"  -w      use window-parameter even when stdscr would be implied"
        ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
        ,"  -m      perform wmove/move separately from insert-functions"
        ,"  -w      use window-parameter even when stdscr would be implied"
@@ -490,8 +470,11 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
 
     setlocale(LC_ALL, "");
 
 
     setlocale(LC_ALL, "");
 
-    while ((ch = getopt(argc, argv, "mn:w")) != -1) {
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
        switch (ch) {
        switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
        case 'm':
            m_opt = TRUE;
            break;
        case 'm':
            m_opt = TRUE;
            break;
index 458788a5ff9fc0fe97ca480e64619522490b0346..700c27c1d9b8e267db3f9ad05b6ed1a96db29361 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 2002-2006,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 2002-2007,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            *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -26,7 +26,7 @@
  * authorization.                                                           *
  ****************************************************************************/
 /*
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: inserts.c,v 1.18 2007/07/21 17:41:55 tom Exp $
+ * $Id: inserts.c,v 1.19 2009/09/12 22:50:03 tom Exp $
  *
  * Demonstrate the winsstr() and winsch functions.
  * Thomas Dickey - 2002/10/19
  *
  * Demonstrate the winsstr() and winsch functions.
  * Thomas Dickey - 2002/10/19
@@ -36,6 +36,8 @@
 
 #if HAVE_WINSSTR
 
 
 #if HAVE_WINSSTR
 
+#include <linedata.h>
+
 #define InsNStr    insnstr
 #define InsStr     insstr
 #define MvInsNStr  mvinsnstr
 #define InsNStr    insnstr
 #define InsStr     insstr
 #define MvInsNStr  mvinsnstr
@@ -208,14 +210,10 @@ test_inserts(int level)
        wbkgdset(work, COLOR_PAIR(1) | ' ');
     }
 
        wbkgdset(work, COLOR_PAIR(1) | ' ');
     }
 
-    while ((ch = wgetch(work)) != 'q') {
-       if (ch == ERR) {
-           beep();
-           break;
-       }
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
        wmove(work, row, margin + 1);
        switch (ch) {
        wmove(work, row, margin + 1);
        switch (ch) {
-       case 'w':
+       case key_RECUR:
            test_inserts(level + 1);
 
            touchwin(look);
            test_inserts(level + 1);
 
            touchwin(look);
@@ -228,8 +226,7 @@ test_inserts(int level)
 
            doupdate();
            break;
 
            doupdate();
            break;
-       case CTRL('N'):
-       case KEY_DOWN:
+       case key_NEWLINE:
            if (row < limit) {
                ++row;
                /* put the whole string in, all at once */
            if (row < limit) {
                ++row;
                /* put the whole string in, all at once */
@@ -312,9 +309,6 @@ test_inserts(int level)
                beep();
            }
            break;
                beep();
            }
            break;
-       case KEY_BACKSPACE:
-           ch = '\b';
-           /* FALLTHRU */
        default:
            if (ch <= 0 || ch > 255) {
                beep();
        default:
            if (ch <= 0 || ch > 255) {
                beep();
@@ -388,6 +382,7 @@ usage(void)
        "Usage: inserts [options]"
        ,""
        ,"Options:"
        "Usage: inserts [options]"
        ,""
        ,"Options:"
+       ,"  -f FILE read data from given file"
        ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
        ,"  -m      perform wmove/move separately from insert-functions"
        ,"  -w      use window-parameter even when stdscr would be implied"
        ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
        ,"  -m      perform wmove/move separately from insert-functions"
        ,"  -w      use window-parameter even when stdscr would be implied"
@@ -405,8 +400,11 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
 
     setlocale(LC_ALL, "");
 
 
     setlocale(LC_ALL, "");
 
-    while ((ch = getopt(argc, argv, "mn:w")) != -1) {
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
        switch (ch) {
        switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
        case 'm':
            m_opt = TRUE;
            break;
        case 'm':
            m_opt = TRUE;
            break;
diff --git a/test/linedata.h b/test/linedata.h
new file mode 100644 (file)
index 0000000..b289c44
--- /dev/null
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+#define isQUIT(c)     ((c) == QUIT || (c) == ESCAPE)
+
+#define key_RECUR     CTRL('W')
+#define key_NEWLINE   CTRL('N')
+#define key_BACKSPACE '\b'
+
+static FILE *linedata;
+
+static void
+failed(const char *s)
+{
+    perror(s);
+    ExitProgram(EXIT_FAILURE);
+}
+
+static void
+init_linedata(const char *name)
+{
+    if ((linedata = fopen(name, "r")) == 0) {
+       failed(name);
+    }
+}
+
+static int
+read_linedata(WINDOW *work)
+{
+    int result;
+    if (linedata != 0) {
+       result = fgetc(linedata);
+       if (result == EOF) {
+           fclose(linedata);
+           linedata = 0;
+           result = read_linedata(work);
+       } else {
+           wrefresh(work);
+           if (result == '\n') {
+               result = key_NEWLINE;
+           }
+       }
+    } else {
+#ifdef WIDE_LINEDATA
+       wint_t ch;
+       int code;
+
+       result = ERR;
+       while ((code = wget_wch(work, &ch)) != ERR) {
+
+           if (code == KEY_CODE_YES) {
+               switch (ch) {
+               case KEY_DOWN:
+                   result = key_NEWLINE;
+                   break;
+               case KEY_BACKSPACE:
+                   result = key_BACKSPACE;
+                   break;
+               default:
+                   beep();
+                   continue;
+               }
+           } else if (code != ERR) {
+               result = ch;
+               break;
+           } else {
+               break;
+           }
+       }
+#else
+       result = wgetch(work);
+#endif
+    }
+    return result;
+}
index 08a2f71ff950ef6d6c0765143f29ac9d6f2e186f..1528332e2b8ef06971b996f9e2c55766ef9f113f 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: modules,v 1.38 2009/07/11 12:43:09 tom Exp $
+# $Id: modules,v 1.41 2009/09/12 21:21:06 tom Exp $
 ##############################################################################
 # Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.                #
 #                                                                            #
 ##############################################################################
 # Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.                #
 #                                                                            #
@@ -61,9 +61,9 @@ hanoi         progs           $(srcdir)       $(HEADER_DEPS)
 hashtest       progs           $(srcdir)       $(HEADER_DEPS)
 inch_wide      progs           $(srcdir)       $(HEADER_DEPS)
 inchs          progs           $(srcdir)       $(HEADER_DEPS)
 hashtest       progs           $(srcdir)       $(HEADER_DEPS)
 inch_wide      progs           $(srcdir)       $(HEADER_DEPS)
 inchs          progs           $(srcdir)       $(HEADER_DEPS)
-ins_wide       progs           $(srcdir)       $(HEADER_DEPS)
+ins_wide       progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
 insdelln       progs           $(srcdir)       $(HEADER_DEPS)
 insdelln       progs           $(srcdir)       $(HEADER_DEPS)
-inserts                progs           $(srcdir)       $(HEADER_DEPS)
+inserts                progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
 key_names      progs           $(srcdir)       $(HEADER_DEPS)
 keynames       progs           $(srcdir)       $(HEADER_DEPS)
 knight         progs           $(srcdir)       $(HEADER_DEPS)
 key_names      progs           $(srcdir)       $(HEADER_DEPS)
 keynames       progs           $(srcdir)       $(HEADER_DEPS)
 knight         progs           $(srcdir)       $(HEADER_DEPS)
@@ -76,6 +76,10 @@ rain         progs           $(srcdir)       $(HEADER_DEPS)
 redraw         progs           $(srcdir)       $(HEADER_DEPS)
 savescreen     progs           $(srcdir)       $(HEADER_DEPS)
 tclock         progs           $(srcdir)       $(HEADER_DEPS)
 redraw         progs           $(srcdir)       $(HEADER_DEPS)
 savescreen     progs           $(srcdir)       $(HEADER_DEPS)
 tclock         progs           $(srcdir)       $(HEADER_DEPS)
+test_add_wchstr        progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
+test_addchstr  progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
+test_addstr    progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
+test_addwstr   progs           $(srcdir)       $(HEADER_DEPS)  $(srcdir)/linedata.h
 test_arrays    progs           $(srcdir)       $(HEADER_DEPS)
 test_get_wstr  progs           $(srcdir)       $(HEADER_DEPS)
 test_getstr    progs           $(srcdir)       $(HEADER_DEPS)
 test_arrays    progs           $(srcdir)       $(HEADER_DEPS)
 test_get_wstr  progs           $(srcdir)       $(HEADER_DEPS)
 test_getstr    progs           $(srcdir)       $(HEADER_DEPS)
index 2ebf4ed0028ce69c5537d547cf473b66f1a40ec7..bfcc134eb9ccc9c7a626771acbdc06f6211ccb4f 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: programs,v 1.16 2009/07/11 12:47:15 tom Exp $
+# $Id: programs,v 1.19 2009/09/12 19:44:01 tom Exp $
 ##############################################################################
 # Copyright (c) 2006-2008,2009 Free Software Foundation, Inc.                #
 #                                                                            #
 ##############################################################################
 # Copyright (c) 2006-2008,2009 Free Software Foundation, Inc.                #
 #                                                                            #
@@ -73,6 +73,10 @@ rain         $(LDFLAGS_THREADS)      $(LOCAL_LIBS)   rain
 redraw         $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   redraw
 savescreen     $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   savescreen
 tclock         $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   tclock
 redraw         $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   redraw
 savescreen     $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   savescreen
 tclock         $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   tclock
+test_add_wchstr        $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_add_wchstr
+test_addchstr  $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_addchstr
+test_addstr    $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_addstr
+test_addwstr   $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_addwstr
 test_arrays    $(LDFLAGS_TINFO)        $(LOCAL_LIBS)   test_arrays
 test_get_wstr  $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_get_wstr
 test_getstr    $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_getstr
 test_arrays    $(LDFLAGS_TINFO)        $(LOCAL_LIBS)   test_arrays
 test_get_wstr  $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_get_wstr
 test_getstr    $(LDFLAGS_CURSES)       $(LOCAL_LIBS)   test_getstr
diff --git a/test/test_add_wchstr.c b/test/test_add_wchstr.c
new file mode 100644 (file)
index 0000000..7fa3f14
--- /dev/null
@@ -0,0 +1,547 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+/*
+ * $Id: test_add_wchstr.c,v 1.7 2009/09/13 00:00:28 tom Exp $
+ *
+ * Demonstrate the waddwchstr() and wadd_wch functions.
+ * Thomas Dickey - 2009/9/12
+ *
+ * Note: to provide inputs for *add_wch(), we use setcchar().  A quirk of the
+ * X/Open definition for that function is that the string contains no
+ * characters with negative width.  Any control character (such as tab) falls
+ * into that category.  So it follows that *add_wch() cannot render a tab
+ * character because there is no legal way to construct a cchar_t containing
+ * one.  X/Open does not document this, and it would be logical to assume that
+ * *addwchstr() has the same limitation, but it uses a wchar_t string directly,
+ * and does not document how tabs are handled.
+ */
+
+#include <test.priv.h>
+
+#if USE_WIDEC_SUPPORT
+
+#define WIDE_LINEDATA
+#include <linedata.h>
+
+/* definitions to make it simpler to compare with test_addstr.c */
+#define AddNStr    add_wchnstr
+#define AddStr     add_wchstr
+#define MvAddNStr  mvadd_wchnstr
+#define MvAddStr   mvadd_wchstr
+#define MvWAddNStr mvwadd_wchnstr
+#define MvWAddStr  mvwadd_wchstr
+#define WAddNStr   wadd_wchnstr
+#define WAddStr    wadd_wchstr
+
+#define MY_TABSIZE 8
+
+typedef enum {
+    oDefault = 0,
+    oMove = 1,
+    oWindow = 2,
+    oMoveWindow = 3
+} Options;
+
+static bool m_opt = FALSE;
+static bool w_opt = FALSE;
+static int n_opt = -1;
+
+static cchar_t *temp_buffer;
+static size_t temp_length;
+
+#define TempBuffer(source_len, source_cast) \
+    if (source != 0) { \
+       size_t need = source_len + 1; \
+       wchar_t have[2]; \
+       int n = 0; \
+ \
+       if (need > temp_length) { \
+           temp_length = need * 2; \
+           temp_buffer = typeRealloc(cchar_t, temp_length, temp_buffer); \
+       } \
+       have[0] = 0; \
+       have[1] = 0; \
+       do { \
+           have[0] = source_cast; \
+           setcchar(&temp_buffer[n++], have, A_NORMAL, 0, NULL); \
+       } while (have[0] != 0); \
+    } else if (temp_buffer != 0) { \
+       free(temp_buffer); \
+       temp_buffer = 0; \
+       temp_length = 0; \
+    } \
+    return temp_buffer;
+
+static cchar_t *
+ChStr(const char *source)
+{
+    TempBuffer(strlen(source), UChar(*source++));
+}
+
+static cchar_t *
+ChWStr(const wchar_t *source)
+{
+    TempBuffer(wcslen(source), *source++);
+}
+
+static void
+legend(WINDOW *win, int level, Options state, wchar_t *buffer, int length)
+{
+    NCURSES_CONST char *showstate;
+
+    switch (state) {
+    default:
+    case oDefault:
+       showstate = "";
+       break;
+    case oMove:
+       showstate = " (mvXXX)";
+       break;
+    case oWindow:
+       showstate = " (winXXX)";
+       break;
+    case oMoveWindow:
+       showstate = " (mvwinXXX)";
+       break;
+    }
+
+    wmove(win, 0, 0);
+    wprintw(win,
+           "The Strings/Chars displays should match.  Enter any characters, except:\n");
+    wprintw(win,
+           "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
+    wclrtoeol(win);
+    wprintw(win, "Level %d,%s added %d characters <", level,
+           showstate, length);
+    waddwstr(win, buffer);
+    waddstr(win, ">");
+}
+
+static int
+ColOf(wchar_t *buffer, int length, int margin)
+{
+    int n;
+    int result;
+
+    for (n = 0, result = margin + 1; n < length; ++n) {
+       int ch = buffer[n];
+       switch (ch) {
+       case '\n':
+           /* actually newline should clear the remainder of the line
+            * and move to the next line - but that seems a little awkward
+            * in this example.
+            */
+       case '\r':
+           result = 0;
+           break;
+       case '\b':
+           if (result > 0)
+               --result;
+           break;
+       case '\t':
+           result += (MY_TABSIZE - (result % MY_TABSIZE));
+           break;
+       case '\177':
+           result += 2;
+           break;
+       default:
+           result += wcwidth(ch);
+           if (ch < 32)
+               ++result;
+           break;
+       }
+    }
+    return result;
+}
+
+static int
+ConvertCh(chtype source, cchar_t *target)
+{
+    wchar_t tmp_wchar[2];
+
+    tmp_wchar[0] = source;
+    tmp_wchar[1] = 0;
+    if (setcchar(target, tmp_wchar, A_NORMAL, 0, (void *) 0) == ERR) {
+       beep();
+       return FALSE;
+    }
+    return TRUE;
+}
+
+static int
+MvWAddCh(WINDOW *win, int y, int x, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = mvwadd_wch(win, y, x, &tmp_cchar);
+    } else {
+       code = mvwaddch(win, y, x, ch);
+    }
+    return code;
+}
+
+static int
+MvAddCh(int y, int x, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = mvadd_wch(y, x, &tmp_cchar);
+    } else {
+       code = mvaddch(y, x, ch);
+    }
+    return code;
+}
+
+static int
+WAddCh(WINDOW *win, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = wadd_wch(win, &tmp_cchar);
+    } else {
+       code = waddch(win, ch);
+    }
+    return code;
+}
+
+static int
+AddCh(chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = add_wch(&tmp_cchar);
+    } else {
+       code = addch(ch);
+    }
+    return code;
+}
+
+#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
+static void
+test_add_wchstr(int level)
+{
+    static bool first = TRUE;
+
+    int ch;
+    int limit;
+    int row = 1;
+    int col;
+    int row2, col2;
+    int length;
+    wchar_t buffer[BUFSIZ];
+    WINDOW *look = 0;
+    WINDOW *work = 0;
+    WINDOW *show = 0;
+    int margin = (2 * MY_TABSIZE) - 1;
+    Options option = ((m_opt ? oMove : oDefault)
+                     | ((w_opt || (level > 0)) ? oWindow : oDefault));
+
+    if (first) {
+       static char cmd[80];
+       setlocale(LC_ALL, "");
+
+       putenv(strcpy(cmd, "TABSIZE=8"));
+
+       initscr();
+       (void) cbreak();        /* take input chars one at a time, no wait for \n */
+       (void) noecho();        /* don't echo input */
+       keypad(stdscr, TRUE);
+    }
+
+    limit = LINES - 5;
+    if (level > 0) {
+       look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
+       work = newwin(limit - 2, COLS - (2 * level), 1, level);
+       show = newwin(4, COLS, limit + 1, 0);
+       box(look, 0, 0);
+       wnoutrefresh(look);
+       limit -= 2;
+    } else {
+       work = stdscr;
+       show = derwin(stdscr, 4, COLS, limit + 1, 0);
+    }
+    keypad(work, TRUE);
+
+    for (col = margin + 1; col < COLS; col += MY_TABSIZE)
+       mvwvline(work, row, col, '.', limit - 2);
+
+    mvwvline(work, row, margin, ACS_VLINE, limit - 2);
+    mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
+    limit /= 2;
+
+    mvwadd_wchstr(work, 1, 2, ChStr("String"));
+    mvwadd_wchstr(work, limit + 1, 2, ChStr("Chars"));
+    wnoutrefresh(work);
+
+    buffer[length = 0] = '\0';
+    legend(show, level, option, buffer, length);
+    wnoutrefresh(show);
+
+    doupdate();
+
+    /*
+     * Show the characters added in color, to distinguish from those that
+     * are shifted.
+     */
+    if (has_colors()) {
+       start_color();
+       init_pair(1, COLOR_WHITE, COLOR_BLUE);
+       wbkgdset(work, COLOR_PAIR(1) | ' ');
+    }
+
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
+       wmove(work, row, margin + 1);
+       switch (ch) {
+       case key_RECUR:
+           test_add_wchstr(level + 1);
+
+           touchwin(look);
+           touchwin(work);
+           touchwin(show);
+
+           wnoutrefresh(look);
+           wnoutrefresh(work);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       case key_NEWLINE:
+           if (row < limit) {
+               ++row;
+               /* put the whole string in, all at once */
+               col2 = margin + 1;
+               switch (option) {
+               case oDefault:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (move(row, col2) != ERR) {
+                               AddNStr(ChWStr(buffer + col), LEN(col));
+                           }
+                       }
+                   } else {
+                       if (move(row, col2) != ERR) {
+                           AddStr(ChWStr(buffer));
+                       }
+                   }
+                   break;
+               case oMove:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvAddNStr(row, col2, ChWStr(buffer + col), LEN(col));
+                       }
+                   } else {
+                       MvAddStr(row, col2, ChWStr(buffer));
+                   }
+                   break;
+               case oWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (wmove(work, row, col2) != ERR) {
+                               WAddNStr(work, ChWStr(buffer + col), LEN(col));
+                           }
+                       }
+                   } else {
+                       if (wmove(work, row, col2) != ERR) {
+                           WAddStr(work, ChWStr(buffer));
+                       }
+                   }
+                   break;
+               case oMoveWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvWAddNStr(work, row, col2, ChWStr(buffer +
+                                                              col), LEN(col));
+                       }
+                   } else {
+                       MvWAddStr(work, row, col2, ChWStr(buffer));
+                   }
+                   break;
+               }
+
+               /* do the corresponding single-character add */
+               row2 = limit + row;
+               for (col = 0; col < length; ++col) {
+                   col2 = ColOf(buffer, col, margin);
+                   switch (option) {
+                   case oDefault:
+                       if (move(row2, col2) != ERR) {
+                           AddCh((chtype) buffer[col]);
+                       }
+                       break;
+                   case oMove:
+                       MvAddCh(row2, col2, (chtype) buffer[col]);
+                       break;
+                   case oWindow:
+                       if (wmove(work, row2, col2) != ERR) {
+                           WAddCh(work, (chtype) buffer[col]);
+                       }
+                       break;
+                   case oMoveWindow:
+                       MvWAddCh(work, row2, col2, (chtype) buffer[col]);
+                       break;
+                   }
+               }
+           } else {
+               beep();
+           }
+           break;
+       default:
+           buffer[length++] = ch;
+           buffer[length] = '\0';
+
+           /* put the string in, one character at a time */
+           col = ColOf(buffer, length - 1, margin);
+           switch (option) {
+           case oDefault:
+               if (move(row, col) != ERR) {
+                   AddStr(ChWStr(buffer + length - 1));
+               }
+               break;
+           case oMove:
+               MvAddStr(row, col, ChWStr(buffer + length - 1));
+               break;
+           case oWindow:
+               if (wmove(work, row, col) != ERR) {
+                   WAddStr(work, ChWStr(buffer + length - 1));
+               }
+               break;
+           case oMoveWindow:
+               MvWAddStr(work, row, col, ChWStr(buffer + length - 1));
+               break;
+           }
+
+           /* do the corresponding single-character add */
+           switch (option) {
+           case oDefault:
+               if (move(limit + row, col) != ERR) {
+                   AddCh(ch);
+               }
+               break;
+           case oMove:
+               MvAddCh(limit + row, col, ch);
+               break;
+           case oWindow:
+               if (wmove(work, limit + row, col) != ERR) {
+                   WAddCh(work, ch);
+               }
+               break;
+           case oMoveWindow:
+               MvWAddCh(work, limit + row, col, ch);
+               break;
+           }
+
+           wnoutrefresh(work);
+
+           legend(show, level, option, buffer, length);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       }
+    }
+    if (level > 0) {
+       delwin(show);
+       delwin(work);
+       delwin(look);
+    }
+}
+
+static void
+usage(void)
+{
+    static const char *tbl[] =
+    {
+       "Usage: test_add_wchstr [options]"
+       ,""
+       ,"Options:"
+       ,"  -f FILE read data from given file"
+       ,"  -n NUM  limit string-adds to NUM bytes on ^N replay"
+       ,"  -m      perform wmove/move separately from add-functions"
+       ,"  -w      use window-parameter even when stdscr would be implied"
+    };
+    unsigned n;
+    for (n = 0; n < SIZEOF(tbl); ++n)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
+int
+main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
+{
+    int ch;
+
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
+       switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
+       case 'm':
+           m_opt = TRUE;
+           break;
+       case 'n':
+           n_opt = atoi(optarg);
+           if (n_opt == 0)
+               n_opt = -1;
+           break;
+       case 'w':
+           w_opt = TRUE;
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+    if (optind < argc)
+       usage();
+
+    test_add_wchstr(0);
+    endwin();
+    ExitProgram(EXIT_SUCCESS);
+}
+#else
+int
+main(void)
+{
+    printf("This program requires the wide-ncurses library\n");
+    ExitProgram(EXIT_FAILURE);
+}
+#endif
diff --git a/test/test_addchstr.c b/test/test_addchstr.c
new file mode 100644 (file)
index 0000000..9f8a349
--- /dev/null
@@ -0,0 +1,462 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+/*
+ * $Id: test_addchstr.c,v 1.4 2009/09/13 00:00:58 tom Exp $
+ *
+ * Demonstrate the waddchstr() and waddch functions.
+ * Thomas Dickey - 2009/9/12
+ */
+
+#include <test.priv.h>
+
+#include <linedata.h>
+
+#define AddNStr    addchnstr
+#define AddStr     addchstr
+#define MvAddNStr  mvaddchnstr
+#define MvAddStr   mvaddchstr
+#define MvWAddNStr mvwaddchnstr
+#define MvWAddStr  mvwaddchstr
+#define WAddNStr   waddchnstr
+#define WAddStr    waddchstr
+
+#define AddCh      addch
+#define MvAddCh    mvaddch
+#define MvWAddCh   mvwaddch
+#define WAddCh     waddch
+
+#define MY_TABSIZE 8
+
+typedef enum {
+    oDefault = 0,
+    oMove = 1,
+    oWindow = 2,
+    oMoveWindow = 3
+} Options;
+
+static bool m_opt = FALSE;
+static bool w_opt = FALSE;
+static int n_opt = -1;
+
+static chtype *temp_buffer;
+static size_t temp_length;
+
+#define TempBuffer(source_cast)
+
+static chtype *
+ChStr(const char *source)
+{
+    if (source != 0) {
+       size_t need = strlen(source) + 1;
+       wchar_t have[2];
+       int n = 0;
+
+       if (need > temp_length) {
+           temp_length = need * 2;
+           temp_buffer = typeRealloc(chtype, temp_length, temp_buffer);
+       }
+       have[0] = 0;
+       have[1] = 0;
+       do {
+           temp_buffer[n++] = UChar(*source++);
+       } while (have[0] != 0);
+    } else if (temp_buffer != 0) {
+       free(temp_buffer);
+       temp_buffer = 0;
+       temp_length = 0;
+    }
+    return temp_buffer;
+}
+
+static void
+legend(WINDOW *win, int level, Options state, char *buffer, int length)
+{
+    NCURSES_CONST char *showstate;
+
+    switch (state) {
+    default:
+    case oDefault:
+       showstate = "";
+       break;
+    case oMove:
+       showstate = " (mvXXX)";
+       break;
+    case oWindow:
+       showstate = " (winXXX)";
+       break;
+    case oMoveWindow:
+       showstate = " (mvwinXXX)";
+       break;
+    }
+
+    wmove(win, 0, 0);
+    wprintw(win,
+           "The Strings/Chars displays should match.  Enter any characters, except:\n");
+    wprintw(win,
+           "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
+    wclrtoeol(win);
+    wprintw(win, "Level %d,%s added %d characters <%s>", level,
+           showstate, length, buffer);
+}
+
+static int
+ColOf(char *buffer, int length, int margin)
+{
+    int n;
+    int result;
+
+    for (n = 0, result = margin + 1; n < length; ++n) {
+       int ch = UChar(buffer[n]);
+       switch (ch) {
+       case '\n':
+           /* actually newline should clear the remainder of the line
+            * and move to the next line - but that seems a little awkward
+            * in this example.
+            */
+       case '\r':
+           result = 0;
+           break;
+       case '\b':
+           if (result > 0)
+               --result;
+           break;
+       case '\t':
+           result += (MY_TABSIZE - (result % MY_TABSIZE));
+           break;
+       case '\177':
+           result += 2;
+           break;
+       default:
+           ++result;
+           if (ch < 32)
+               ++result;
+           break;
+       }
+    }
+    return result;
+}
+
+#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
+static void
+test_adds(int level)
+{
+    static bool first = TRUE;
+
+    int ch;
+    int limit;
+    int row = 1;
+    int col;
+    int row2, col2;
+    int length;
+    char buffer[BUFSIZ];
+    WINDOW *look = 0;
+    WINDOW *work = 0;
+    WINDOW *show = 0;
+    int margin = (2 * MY_TABSIZE) - 1;
+    Options option = (Options) ((unsigned) (m_opt
+                                           ? oMove
+                                           : oDefault)
+                               | (unsigned) ((w_opt || (level > 0))
+                                             ? oWindow
+                                             : oDefault));
+
+    if (first) {
+       static char cmd[80];
+       setlocale(LC_ALL, "");
+
+       putenv(strcpy(cmd, "TABSIZE=8"));
+
+       initscr();
+       (void) cbreak();        /* take input chars one at a time, no wait for \n */
+       (void) noecho();        /* don't echo input */
+       keypad(stdscr, TRUE);
+    }
+
+    limit = LINES - 5;
+    if (level > 0) {
+       look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
+       work = newwin(limit - 2, COLS - (2 * level), 1, level);
+       show = newwin(4, COLS, limit + 1, 0);
+       box(look, 0, 0);
+       wnoutrefresh(look);
+       limit -= 2;
+    } else {
+       work = stdscr;
+       show = derwin(stdscr, 4, COLS, limit + 1, 0);
+    }
+    keypad(work, TRUE);
+
+    for (col = margin + 1; col < COLS; col += MY_TABSIZE)
+       mvwvline(work, row, col, '.', limit - 2);
+
+    mvwvline(work, row, margin, ACS_VLINE, limit - 2);
+    mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
+    limit /= 2;
+
+    mvwaddchstr(work, 1, 2, ChStr("String"));
+    mvwaddchstr(work, limit + 1, 2, ChStr("Chars"));
+    wnoutrefresh(work);
+
+    buffer[length = 0] = '\0';
+    legend(show, level, option, buffer, length);
+    wnoutrefresh(show);
+
+    doupdate();
+
+    /*
+     * Show the characters added in color, to distinguish from those that
+     * are shifted.
+     */
+    if (has_colors()) {
+       start_color();
+       init_pair(1, COLOR_WHITE, COLOR_BLUE);
+       wbkgdset(work, COLOR_PAIR(1) | ' ');
+    }
+
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
+       wmove(work, row, margin + 1);
+       switch (ch) {
+       case key_RECUR:
+           test_adds(level + 1);
+
+           touchwin(look);
+           touchwin(work);
+           touchwin(show);
+
+           wnoutrefresh(look);
+           wnoutrefresh(work);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       case key_NEWLINE:
+           if (row < limit) {
+               ++row;
+               /* put the whole string in, all at once */
+               col2 = margin + 1;
+               switch (option) {
+               case oDefault:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (move(row, col2) != ERR) {
+                               AddNStr(ChStr(buffer + col), LEN(col));
+                           }
+                       }
+                   } else {
+                       if (move(row, col2) != ERR) {
+                           AddStr(ChStr(buffer));
+                       }
+                   }
+                   break;
+               case oMove:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvAddNStr(row, col2, ChStr(buffer + col), LEN(col));
+                       }
+                   } else {
+                       MvAddStr(row, col2, ChStr(buffer));
+                   }
+                   break;
+               case oWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (wmove(work, row, col2) != ERR) {
+                               WAddNStr(work, ChStr(buffer + col), LEN(col));
+                           }
+                       }
+                   } else {
+                       if (wmove(work, row, col2) != ERR) {
+                           WAddStr(work, ChStr(buffer));
+                       }
+                   }
+                   break;
+               case oMoveWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvWAddNStr(work, row, col2, ChStr(buffer + col),
+                                      LEN(col));
+                       }
+                   } else {
+                       MvWAddStr(work, row, col2, ChStr(buffer));
+                   }
+                   break;
+               }
+
+               /* do the corresponding single-character add */
+               row2 = limit + row;
+               for (col = 0; col < length; ++col) {
+                   col2 = ColOf(buffer, col, margin);
+                   switch (option) {
+                   case oDefault:
+                       if (move(row2, col2) != ERR) {
+                           AddCh(UChar(buffer[col]));
+                       }
+                       break;
+                   case oMove:
+                       MvAddCh(row2, col2, UChar(buffer[col]));
+                       break;
+                   case oWindow:
+                       if (wmove(work, row2, col2) != ERR) {
+                           WAddCh(work, UChar(buffer[col]));
+                       }
+                       break;
+                   case oMoveWindow:
+                       MvWAddCh(work, row2, col2, UChar(buffer[col]));
+                       break;
+                   }
+               }
+           } else {
+               beep();
+           }
+           break;
+       case KEY_BACKSPACE:
+           ch = '\b';
+           /* FALLTHRU */
+       default:
+           if (ch <= 0 || ch > 255) {
+               beep();
+               break;
+           }
+           buffer[length++] = ch;
+           buffer[length] = '\0';
+
+           /* put the string in, one character at a time */
+           col = ColOf(buffer, length - 1, margin);
+           switch (option) {
+           case oDefault:
+               if (move(row, col) != ERR) {
+                   AddStr(ChStr(buffer + length - 1));
+               }
+               break;
+           case oMove:
+               MvAddStr(row, col, ChStr(buffer + length - 1));
+               break;
+           case oWindow:
+               if (wmove(work, row, col) != ERR) {
+                   WAddStr(work, ChStr(buffer + length - 1));
+               }
+               break;
+           case oMoveWindow:
+               MvWAddStr(work, row, col, ChStr(buffer + length - 1));
+               break;
+           }
+
+           /* do the corresponding single-character add */
+           switch (option) {
+           case oDefault:
+               if (move(limit + row, col) != ERR) {
+                   AddCh(UChar(ch));
+               }
+               break;
+           case oMove:
+               MvAddCh(limit + row, col, UChar(ch));
+               break;
+           case oWindow:
+               if (wmove(work, limit + row, col) != ERR) {
+                   WAddCh(work, UChar(ch));
+               }
+               break;
+           case oMoveWindow:
+               MvWAddCh(work, limit + row, col, UChar(ch));
+               break;
+           }
+
+           wnoutrefresh(work);
+
+           legend(show, level, option, buffer, length);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       }
+    }
+    if (level > 0) {
+       delwin(show);
+       delwin(work);
+       delwin(look);
+    }
+}
+
+static void
+usage(void)
+{
+    static const char *tbl[] =
+    {
+       "Usage: test_addchstr [options]"
+       ,""
+       ,"Options:"
+       ,"  -f FILE read data from given file"
+       ,"  -n NUM  limit string-adds to NUM bytes on ^N replay"
+       ,"  -m      perform wmove/move separately from add-functions"
+       ,"  -w      use window-parameter even when stdscr would be implied"
+    };
+    unsigned n;
+    for (n = 0; n < SIZEOF(tbl); ++n)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
+int
+main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
+{
+    int ch;
+
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
+       switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
+       case 'm':
+           m_opt = TRUE;
+           break;
+       case 'n':
+           n_opt = atoi(optarg);
+           if (n_opt == 0)
+               n_opt = -1;
+           break;
+       case 'w':
+           w_opt = TRUE;
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+    if (optind < argc)
+       usage();
+
+    test_adds(0);
+    endwin();
+    ExitProgram(EXIT_SUCCESS);
+}
diff --git a/test/test_addstr.c b/test/test_addstr.c
new file mode 100644 (file)
index 0000000..a002970
--- /dev/null
@@ -0,0 +1,428 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+/*
+ * $Id: test_addstr.c,v 1.2 2009/09/12 22:52:29 tom Exp $
+ *
+ * Demonstrate the waddstr() and waddch functions.
+ * Thomas Dickey - 2009/9/12
+ */
+
+#include <test.priv.h>
+
+#include <linedata.h>
+
+#define AddNStr    addnstr
+#define AddStr     addstr
+#define MvAddNStr  mvaddnstr
+#define MvAddStr   mvaddstr
+#define MvWAddNStr mvwaddnstr
+#define MvWAddStr  mvwaddstr
+#define WAddNStr   waddnstr
+#define WAddStr    waddstr
+
+#define AddCh      addch
+#define MvAddCh    mvaddch
+#define MvWAddCh   mvwaddch
+#define WAddCh     waddch
+
+#define MY_TABSIZE 8
+
+typedef enum {
+    oDefault = 0,
+    oMove = 1,
+    oWindow = 2,
+    oMoveWindow = 3
+} Options;
+
+static bool m_opt = FALSE;
+static bool w_opt = FALSE;
+static int n_opt = -1;
+
+static void
+legend(WINDOW *win, int level, Options state, char *buffer, int length)
+{
+    NCURSES_CONST char *showstate;
+
+    switch (state) {
+    default:
+    case oDefault:
+       showstate = "";
+       break;
+    case oMove:
+       showstate = " (mvXXX)";
+       break;
+    case oWindow:
+       showstate = " (winXXX)";
+       break;
+    case oMoveWindow:
+       showstate = " (mvwinXXX)";
+       break;
+    }
+
+    wmove(win, 0, 0);
+    wprintw(win,
+           "The Strings/Chars displays should match.  Enter any characters, except:\n");
+    wprintw(win,
+           "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
+    wclrtoeol(win);
+    wprintw(win, "Level %d,%s added %d characters <%s>", level,
+           showstate, length, buffer);
+}
+
+static int
+ColOf(char *buffer, int length, int margin)
+{
+    int n;
+    int result;
+
+    for (n = 0, result = margin + 1; n < length; ++n) {
+       int ch = UChar(buffer[n]);
+       switch (ch) {
+       case '\n':
+           /* actually newline should clear the remainder of the line
+            * and move to the next line - but that seems a little awkward
+            * in this example.
+            */
+       case '\r':
+           result = 0;
+           break;
+       case '\b':
+           if (result > 0)
+               --result;
+           break;
+       case '\t':
+           result += (MY_TABSIZE - (result % MY_TABSIZE));
+           break;
+       case '\177':
+           result += 2;
+           break;
+       default:
+           ++result;
+           if (ch < 32)
+               ++result;
+           break;
+       }
+    }
+    return result;
+}
+
+#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
+static void
+test_adds(int level)
+{
+    static bool first = TRUE;
+
+    int ch;
+    int limit;
+    int row = 1;
+    int col;
+    int row2, col2;
+    int length;
+    char buffer[BUFSIZ];
+    WINDOW *look = 0;
+    WINDOW *work = 0;
+    WINDOW *show = 0;
+    int margin = (2 * MY_TABSIZE) - 1;
+    Options option = (Options) ((unsigned) (m_opt
+                                           ? oMove
+                                           : oDefault)
+                               | (unsigned) ((w_opt || (level > 0))
+                                             ? oWindow
+                                             : oDefault));
+
+    if (first) {
+       static char cmd[80];
+       setlocale(LC_ALL, "");
+
+       putenv(strcpy(cmd, "TABSIZE=8"));
+
+       initscr();
+       (void) cbreak();        /* take input chars one at a time, no wait for \n */
+       (void) noecho();        /* don't echo input */
+       keypad(stdscr, TRUE);
+    }
+
+    limit = LINES - 5;
+    if (level > 0) {
+       look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
+       work = newwin(limit - 2, COLS - (2 * level), 1, level);
+       show = newwin(4, COLS, limit + 1, 0);
+       box(look, 0, 0);
+       wnoutrefresh(look);
+       limit -= 2;
+    } else {
+       work = stdscr;
+       show = derwin(stdscr, 4, COLS, limit + 1, 0);
+    }
+    keypad(work, TRUE);
+
+    for (col = margin + 1; col < COLS; col += MY_TABSIZE)
+       mvwvline(work, row, col, '.', limit - 2);
+
+    mvwvline(work, row, margin, ACS_VLINE, limit - 2);
+    mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
+    limit /= 2;
+
+    mvwaddstr(work, 1, 2, "String");
+    mvwaddstr(work, limit + 1, 2, "Chars");
+    wnoutrefresh(work);
+
+    buffer[length = 0] = '\0';
+    legend(show, level, option, buffer, length);
+    wnoutrefresh(show);
+
+    doupdate();
+
+    /*
+     * Show the characters added in color, to distinguish from those that
+     * are shifted.
+     */
+    if (has_colors()) {
+       start_color();
+       init_pair(1, COLOR_WHITE, COLOR_BLUE);
+       wbkgdset(work, COLOR_PAIR(1) | ' ');
+    }
+
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
+       wmove(work, row, margin + 1);
+       switch (ch) {
+       case key_RECUR:
+           test_adds(level + 1);
+
+           touchwin(look);
+           touchwin(work);
+           touchwin(show);
+
+           wnoutrefresh(look);
+           wnoutrefresh(work);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       case key_NEWLINE:
+           if (row < limit) {
+               ++row;
+               /* put the whole string in, all at once */
+               col2 = margin + 1;
+               switch (option) {
+               case oDefault:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (move(row, col2) != ERR) {
+                               AddNStr(buffer + col, LEN(col));
+                           }
+                       }
+                   } else {
+                       if (move(row, col2) != ERR) {
+                           AddStr(buffer);
+                       }
+                   }
+                   break;
+               case oMove:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvAddNStr(row, col2, buffer + col, LEN(col));
+                       }
+                   } else {
+                       MvAddStr(row, col2, buffer);
+                   }
+                   break;
+               case oWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (wmove(work, row, col2) != ERR) {
+                               WAddNStr(work, buffer + col, LEN(col));
+                           }
+                       }
+                   } else {
+                       if (wmove(work, row, col2) != ERR) {
+                           WAddStr(work, buffer);
+                       }
+                   }
+                   break;
+               case oMoveWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvWAddNStr(work, row, col2, buffer + col, LEN(col));
+                       }
+                   } else {
+                       MvWAddStr(work, row, col2, buffer);
+                   }
+                   break;
+               }
+
+               /* do the corresponding single-character add */
+               row2 = limit + row;
+               for (col = 0; col < length; ++col) {
+                   col2 = ColOf(buffer, col, margin);
+                   switch (option) {
+                   case oDefault:
+                       if (move(row2, col2) != ERR) {
+                           AddCh(UChar(buffer[col]));
+                       }
+                       break;
+                   case oMove:
+                       MvAddCh(row2, col2, UChar(buffer[col]));
+                       break;
+                   case oWindow:
+                       if (wmove(work, row2, col2) != ERR) {
+                           WAddCh(work, UChar(buffer[col]));
+                       }
+                       break;
+                   case oMoveWindow:
+                       MvWAddCh(work, row2, col2, UChar(buffer[col]));
+                       break;
+                   }
+               }
+           } else {
+               beep();
+           }
+           break;
+       default:
+           if (ch <= 0 || ch > 255) {
+               beep();
+               break;
+           }
+           buffer[length++] = ch;
+           buffer[length] = '\0';
+
+           /* put the string in, one character at a time */
+           col = ColOf(buffer, length - 1, margin);
+           switch (option) {
+           case oDefault:
+               if (move(row, col) != ERR) {
+                   AddStr(buffer + length - 1);
+               }
+               break;
+           case oMove:
+               MvAddStr(row, col, buffer + length - 1);
+               break;
+           case oWindow:
+               if (wmove(work, row, col) != ERR) {
+                   WAddStr(work, buffer + length - 1);
+               }
+               break;
+           case oMoveWindow:
+               MvWAddStr(work, row, col, buffer + length - 1);
+               break;
+           }
+
+           /* do the corresponding single-character add */
+           switch (option) {
+           case oDefault:
+               if (move(limit + row, col) != ERR) {
+                   AddCh(UChar(ch));
+               }
+               break;
+           case oMove:
+               MvAddCh(limit + row, col, UChar(ch));
+               break;
+           case oWindow:
+               if (wmove(work, limit + row, col) != ERR) {
+                   WAddCh(work, UChar(ch));
+               }
+               break;
+           case oMoveWindow:
+               MvWAddCh(work, limit + row, col, UChar(ch));
+               break;
+           }
+
+           wnoutrefresh(work);
+
+           legend(show, level, option, buffer, length);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       }
+    }
+    if (level > 0) {
+       delwin(show);
+       delwin(work);
+       delwin(look);
+    }
+}
+
+static void
+usage(void)
+{
+    static const char *tbl[] =
+    {
+       "Usage: test_addstr [options]"
+       ,""
+       ,"Options:"
+       ,"  -f FILE read data from given file"
+       ,"  -n NUM  limit string-adds to NUM bytes on ^N replay"
+       ,"  -m      perform wmove/move separately from add-functions"
+       ,"  -w      use window-parameter even when stdscr would be implied"
+    };
+    unsigned n;
+    for (n = 0; n < SIZEOF(tbl); ++n)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
+int
+main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
+{
+    int ch;
+
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
+       switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
+       case 'm':
+           m_opt = TRUE;
+           break;
+       case 'n':
+           n_opt = atoi(optarg);
+           if (n_opt == 0)
+               n_opt = -1;
+           break;
+       case 'w':
+           w_opt = TRUE;
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+    if (optind < argc)
+       usage();
+
+    test_adds(0);
+    endwin();
+    ExitProgram(EXIT_SUCCESS);
+}
diff --git a/test/test_addwstr.c b/test/test_addwstr.c
new file mode 100644 (file)
index 0000000..a7fe8a2
--- /dev/null
@@ -0,0 +1,511 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+/*
+ * $Id: test_addwstr.c,v 1.2 2009/09/12 22:55:23 tom Exp $
+ *
+ * Demonstrate the waddwstr() and wadd_wch functions.
+ * Thomas Dickey - 2009/9/12
+ *
+ * Note: to provide inputs for *add_wch(), we use setcchar().  A quirk of the
+ * X/Open definition for that function is that the string contains no
+ * characters with negative width.  Any control character (such as tab) falls
+ * into that category.  So it follows that *add_wch() cannot render a tab
+ * character because there is no legal way to construct a cchar_t containing
+ * one.  X/Open does not document this, and it would be logical to assume that
+ * *addwstr() has the same limitation, but it uses a wchar_t string directly,
+ * and does not document how tabs are handled.
+ */
+
+#include <test.priv.h>
+
+#if USE_WIDEC_SUPPORT
+
+#define WIDE_LINEDATA
+#include <linedata.h>
+
+/* definitions to make it simpler to compare with inserts.c */
+#define AddNStr    addnwstr
+#define AddStr     addwstr
+#define MvAddNStr  mvaddnwstr
+#define MvAddStr   mvaddwstr
+#define MvWAddNStr mvwaddnwstr
+#define MvWAddStr  mvwaddwstr
+#define WAddNStr   waddnwstr
+#define WAddStr    waddwstr
+
+#define MY_TABSIZE 8
+
+typedef enum {
+    oDefault = 0,
+    oMove = 1,
+    oWindow = 2,
+    oMoveWindow = 3
+} Options;
+
+static bool m_opt = FALSE;
+static bool w_opt = FALSE;
+static int n_opt = -1;
+
+static void
+legend(WINDOW *win, int level, Options state, wchar_t *buffer, int length)
+{
+    NCURSES_CONST char *showstate;
+
+    switch (state) {
+    default:
+    case oDefault:
+       showstate = "";
+       break;
+    case oMove:
+       showstate = " (mvXXX)";
+       break;
+    case oWindow:
+       showstate = " (winXXX)";
+       break;
+    case oMoveWindow:
+       showstate = " (mvwinXXX)";
+       break;
+    }
+
+    wmove(win, 0, 0);
+    wprintw(win,
+           "The Strings/Chars displays should match.  Enter any characters, except:\n");
+    wprintw(win,
+           "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
+    wclrtoeol(win);
+    wprintw(win, "Level %d,%s inserted %d characters <", level,
+           showstate, length);
+    waddwstr(win, buffer);
+    waddstr(win, ">");
+}
+
+static int
+ColOf(wchar_t *buffer, int length, int margin)
+{
+    int n;
+    int result;
+
+    for (n = 0, result = margin + 1; n < length; ++n) {
+       int ch = buffer[n];
+       switch (ch) {
+       case '\n':
+           /* actually newline should clear the remainder of the line
+            * and move to the next line - but that seems a little awkward
+            * in this example.
+            */
+       case '\r':
+           result = 0;
+           break;
+       case '\b':
+           if (result > 0)
+               --result;
+           break;
+       case '\t':
+           result += (MY_TABSIZE - (result % MY_TABSIZE));
+           break;
+       case '\177':
+           result += 2;
+           break;
+       default:
+           result += wcwidth(ch);
+           if (ch < 32)
+               ++result;
+           break;
+       }
+    }
+    return result;
+}
+
+static int
+ConvertCh(chtype source, cchar_t *target)
+{
+    wchar_t tmp_wchar[2];
+
+    tmp_wchar[0] = source;
+    tmp_wchar[1] = 0;
+    if (setcchar(target, tmp_wchar, A_NORMAL, 0, (void *) 0) == ERR) {
+       beep();
+       return FALSE;
+    }
+    return TRUE;
+}
+
+static int
+MvWAddCh(WINDOW *win, int y, int x, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = mvwadd_wch(win, y, x, &tmp_cchar);
+    } else {
+       code = mvwaddch(win, y, x, ch);
+    }
+    return code;
+}
+
+static int
+MvAddCh(int y, int x, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = mvadd_wch(y, x, &tmp_cchar);
+    } else {
+       code = mvaddch(y, x, ch);
+    }
+    return code;
+}
+
+static int
+WAddCh(WINDOW *win, chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = wadd_wch(win, &tmp_cchar);
+    } else {
+       code = waddch(win, ch);
+    }
+    return code;
+}
+
+static int
+AddCh(chtype ch)
+{
+    int code;
+    cchar_t tmp_cchar;
+
+    if (ConvertCh(ch, &tmp_cchar)) {
+       code = add_wch(&tmp_cchar);
+    } else {
+       code = addch(ch);
+    }
+    return code;
+}
+
+#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
+static void
+test_inserts(int level)
+{
+    static bool first = TRUE;
+
+    int ch;
+    int limit;
+    int row = 1;
+    int col;
+    int row2, col2;
+    int length;
+    wchar_t buffer[BUFSIZ];
+    WINDOW *look = 0;
+    WINDOW *work = 0;
+    WINDOW *show = 0;
+    int margin = (2 * MY_TABSIZE) - 1;
+    Options option = ((m_opt ? oMove : oDefault)
+                     | ((w_opt || (level > 0)) ? oWindow : oDefault));
+
+    if (first) {
+       static char cmd[80];
+       setlocale(LC_ALL, "");
+
+       putenv(strcpy(cmd, "TABSIZE=8"));
+
+       initscr();
+       (void) cbreak();        /* take input chars one at a time, no wait for \n */
+       (void) noecho();        /* don't echo input */
+       keypad(stdscr, TRUE);
+    }
+
+    limit = LINES - 5;
+    if (level > 0) {
+       look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
+       work = newwin(limit - 2, COLS - (2 * level), 1, level);
+       show = newwin(4, COLS, limit + 1, 0);
+       box(look, 0, 0);
+       wnoutrefresh(look);
+       limit -= 2;
+    } else {
+       work = stdscr;
+       show = derwin(stdscr, 4, COLS, limit + 1, 0);
+    }
+    keypad(work, TRUE);
+
+    for (col = margin + 1; col < COLS; col += MY_TABSIZE)
+       mvwvline(work, row, col, '.', limit - 2);
+
+    mvwvline(work, row, margin, ACS_VLINE, limit - 2);
+    mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
+    limit /= 2;
+
+    mvwaddstr(work, 1, 2, "String");
+    mvwaddstr(work, limit + 1, 2, "Chars");
+    wnoutrefresh(work);
+
+    buffer[length = 0] = '\0';
+    legend(show, level, option, buffer, length);
+    wnoutrefresh(show);
+
+    doupdate();
+
+    /*
+     * Show the characters inserted in color, to distinguish from those that
+     * are shifted.
+     */
+    if (has_colors()) {
+       start_color();
+       init_pair(1, COLOR_WHITE, COLOR_BLUE);
+       wbkgdset(work, COLOR_PAIR(1) | ' ');
+    }
+
+    while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
+       wmove(work, row, margin + 1);
+       switch (ch) {
+       case key_RECUR:
+           test_inserts(level + 1);
+
+           touchwin(look);
+           touchwin(work);
+           touchwin(show);
+
+           wnoutrefresh(look);
+           wnoutrefresh(work);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       case key_NEWLINE:
+           if (row < limit) {
+               ++row;
+               /* put the whole string in, all at once */
+               col2 = margin + 1;
+               switch (option) {
+               case oDefault:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (move(row, col2) != ERR) {
+                               AddNStr(buffer + col, LEN(col));
+                           }
+                       }
+                   } else {
+                       if (move(row, col2) != ERR) {
+                           AddStr(buffer);
+                       }
+                   }
+                   break;
+               case oMove:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvAddNStr(row, col2, buffer + col, LEN(col));
+                       }
+                   } else {
+                       MvAddStr(row, col2, buffer);
+                   }
+                   break;
+               case oWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           if (wmove(work, row, col2) != ERR) {
+                               WAddNStr(work, buffer + col, LEN(col));
+                           }
+                       }
+                   } else {
+                       if (wmove(work, row, col2) != ERR) {
+                           WAddStr(work, buffer);
+                       }
+                   }
+                   break;
+               case oMoveWindow:
+                   if (n_opt > 1) {
+                       for (col = 0; col < length; col += n_opt) {
+                           col2 = ColOf(buffer, col, margin);
+                           MvWAddNStr(work, row, col2, buffer + col, LEN(col));
+                       }
+                   } else {
+                       MvWAddStr(work, row, col2, buffer);
+                   }
+                   break;
+               }
+
+               /* do the corresponding single-character insertion */
+               row2 = limit + row;
+               for (col = 0; col < length; ++col) {
+                   col2 = ColOf(buffer, col, margin);
+                   switch (option) {
+                   case oDefault:
+                       if (move(row2, col2) != ERR) {
+                           AddCh((chtype) buffer[col]);
+                       }
+                       break;
+                   case oMove:
+                       MvAddCh(row2, col2, (chtype) buffer[col]);
+                       break;
+                   case oWindow:
+                       if (wmove(work, row2, col2) != ERR) {
+                           WAddCh(work, (chtype) buffer[col]);
+                       }
+                       break;
+                   case oMoveWindow:
+                       MvWAddCh(work, row2, col2, (chtype) buffer[col]);
+                       break;
+                   }
+               }
+           } else {
+               beep();
+           }
+           break;
+       case KEY_BACKSPACE:
+           ch = '\b';
+           /* FALLTHRU */
+       default:
+           buffer[length++] = ch;
+           buffer[length] = '\0';
+
+           /* put the string in, one character at a time */
+           col = ColOf(buffer, length - 1, margin);
+           switch (option) {
+           case oDefault:
+               if (move(row, col) != ERR) {
+                   AddStr(buffer + length - 1);
+               }
+               break;
+           case oMove:
+               MvAddStr(row, col, buffer + length - 1);
+               break;
+           case oWindow:
+               if (wmove(work, row, col) != ERR) {
+                   WAddStr(work, buffer + length - 1);
+               }
+               break;
+           case oMoveWindow:
+               MvWAddStr(work, row, col, buffer + length - 1);
+               break;
+           }
+
+           /* do the corresponding single-character insertion */
+           switch (option) {
+           case oDefault:
+               if (move(limit + row, col) != ERR) {
+                   AddCh(ch);
+               }
+               break;
+           case oMove:
+               MvAddCh(limit + row, col, ch);
+               break;
+           case oWindow:
+               if (wmove(work, limit + row, col) != ERR) {
+                   WAddCh(work, ch);
+               }
+               break;
+           case oMoveWindow:
+               MvWAddCh(work, limit + row, col, ch);
+               break;
+           }
+
+           wnoutrefresh(work);
+
+           legend(show, level, option, buffer, length);
+           wnoutrefresh(show);
+
+           doupdate();
+           break;
+       }
+    }
+    if (level > 0) {
+       delwin(show);
+       delwin(work);
+       delwin(look);
+    }
+}
+
+static void
+usage(void)
+{
+    static const char *tbl[] =
+    {
+       "Usage: inserts [options]"
+       ,""
+       ,"Options:"
+       ,"  -f FILE read data from given file"
+       ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
+       ,"  -m      perform wmove/move separately from insert-functions"
+       ,"  -w      use window-parameter even when stdscr would be implied"
+    };
+    unsigned n;
+    for (n = 0; n < SIZEOF(tbl); ++n)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
+int
+main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
+{
+    int ch;
+
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "f:mn:w")) != -1) {
+       switch (ch) {
+       case 'f':
+           init_linedata(optarg);
+           break;
+       case 'm':
+           m_opt = TRUE;
+           break;
+       case 'n':
+           n_opt = atoi(optarg);
+           if (n_opt == 0)
+               n_opt = -1;
+           break;
+       case 'w':
+           w_opt = TRUE;
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+    if (optind < argc)
+       usage();
+
+    test_inserts(0);
+    endwin();
+    ExitProgram(EXIT_SUCCESS);
+}
+#else
+int
+main(void)
+{
+    printf("This program requires the wide-ncurses library\n");
+    ExitProgram(EXIT_FAILURE);
+}
+#endif