ncurses 5.6 - patch 20070526
authorThomas E. Dickey <dickey@invisible-island.net>
Sat, 26 May 2007 23:44:27 +0000 (23:44 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sat, 26 May 2007 23:44:27 +0000 (23:44 +0000)
+ modify keyname() to use "^X" form only if meta() has been called, or
  if keyname() is called without initializing curses, e.g., via
  initscr() or newterm() (prompted by LinuxBase #1604).
+ document some portability issues in man/curs_util.3x
+ add a shadow copy of TTY buffer to _nc_prescreen to fix applications
  broken by moving that data into SCREEN (cf: 20061230).

NEWS
dist.mk
man/curs_terminfo.3x
man/curs_util.3x
ncurses/base/MKkeyname.awk
ncurses/curses.priv.h
ncurses/tinfo/lib_data.c
ncurses/tinfo/lib_ttyflags.c
test/demo_panels.c

diff --git a/NEWS b/NEWS
index 91ba1efbced5e90f392b9b38e4e3785cb3dbc77b..52c219bc70cc56b71feb7f0b731fd1b7c84d79a0 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.1127 2007/05/12 22:31:49 tom Exp $
+-- $Id: NEWS,v 1.1128 2007/05/26 21:46:41 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,14 @@ 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.
 
+20070526
+       + modify keyname() to use "^X" form only if meta() has been called, or
+         if keyname() is called without initializing curses, e.g., via
+         initscr() or newterm() (prompted by LinuxBase #1604).
+       + document some portability issues in man/curs_util.3x
+       + add a shadow copy of TTY buffer to _nc_prescreen to fix applications
+         broken by moving that data into SCREEN (cf: 20061230).
+
 20070512
        + add 'O' (wide-character panel test) in ncurses.c to demonstrate a
          problem reported by Sadrul H Chowdhury with repainting parts of
 20070512
        + add 'O' (wide-character panel test) in ncurses.c to demonstrate a
          problem reported by Sadrul H Chowdhury with repainting parts of
diff --git a/dist.mk b/dist.mk
index c141803ed2cb1bf5cfe9126347ca7cc010bb54f4..27a30590597349635167bb0a8a1a16e48f926925 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.593 2007/05/12 15:09:42 tom Exp $
+# $Id: dist.mk,v 1.594 2007/05/26 17:49:30 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 = 6
 # These define the major/minor/patch versions of ncurses.
 NCURSES_MAJOR = 5
 NCURSES_MINOR = 6
-NCURSES_PATCH = 20070512
+NCURSES_PATCH = 20070526
 
 # 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 fc2020b5463ab019ef2b6989891c579cf67cf3fc..5af0b8fbe27c6bfdfe8808cf28ff13b0a2dfebf4 100644 (file)
@@ -26,7 +26,7 @@
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
-.\" $Id: curs_terminfo.3x,v 1.27 2007/03/11 00:15:07 tom Exp $
+.\" $Id: curs_terminfo.3x,v 1.28 2007/05/26 20:09:06 tom Exp $
 .TH curs_terminfo 3X ""
 .ds n 5
 .na
 .TH curs_terminfo 3X ""
 .ds n 5
 .na
@@ -319,7 +319,7 @@ the SCREEN data allocated in either \fBinitscr\fR or \fBnewterm\fR.
 So though it is documented as a terminfo function,
 \fBmvcur\fR is really a curses function which is not well specified.
 .PP
 So though it is documented as a terminfo function,
 \fBmvcur\fR is really a curses function which is not well specified.
 .PP
-XSI states that the old location must be given.
+XSI states that the old location must be given for \fBmvcur\fP.
 This implementation allows the caller to use -1's for the old ordinates.
 In that case, the old location is unknown.
 .PP
 This implementation allows the caller to use -1's for the old ordinates.
 In that case, the old location is unknown.
 .PP
index 73b599ec4dd377e6c7c7e59ed512ecb5c50a882a..4c8929abfce752bed172900ab494d051912a007a 100644 (file)
@@ -26,7 +26,7 @@
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
-.\" $Id: curs_util.3x,v 1.23 2007/02/24 15:59:07 tom Exp $
+.\" $Id: curs_util.3x,v 1.25 2007/05/26 21:44:42 tom Exp $
 .TH curs_util 3X ""
 .na
 .hy 0
 .TH curs_util 3X ""
 .na
 .hy 0
@@ -146,6 +146,29 @@ returns an error if the associated \fBfwrite\fP calls return an error.
 The XSI Curses standard, Issue 4 describes these functions.
 It states that \fBunctrl\fR and \fBwunctrl\fR will return a null pointer if
 unsuccessful, but does not define any error conditions.
 The XSI Curses standard, Issue 4 describes these functions.
 It states that \fBunctrl\fR and \fBwunctrl\fR will return a null pointer if
 unsuccessful, but does not define any error conditions.
+This implementation checks for three cases:
+.RS
+.TP 5
+-
+the parameter is a 7-bit US-ASCII code.
+This is the case that X/Open Curses documented.
+.TP 5
+-
+the parameter is in the range 128-159, i.e., a C1 control code.
+If \fBuse_legacy_coding\fP has been called with a \fB2\fP parameter,
+\fBunctrl\fP returns the parameter, i.e., a one-character string with
+the parameter as the first character.
+Otherwise, it returns ``~@'', ``~A'', etc., analogous to ``^@'', ``^A'', C0 controls.
+.IP
+X/Open Curses does not document whether \fBunctrl\fP can be called before
+initializing curses.
+This implementation permits that,
+and returns the ``~@'', etc., values in that case.
+.TP 5
+-
+parameter values outside the 0 to 255 range.
+\fBunctrl\fP returns a null pointer.
+.RE
 .PP
 The SVr4 documentation describes the action of \fBfilter\fR only in the vaguest
 terms.  The description here is adapted from the XSI Curses standard (which
 .PP
 The SVr4 documentation describes the action of \fBfilter\fR only in the vaguest
 terms.  The description here is adapted from the XSI Curses standard (which
@@ -157,13 +180,24 @@ showing C1 controls from the upper-128 codes with a `~' prefix rather than `^'.
 Other implementations have different conventions.
 For example, they may show both sets of control characters with `^',
 and strip the parameter to 7 bits.
 Other implementations have different conventions.
 For example, they may show both sets of control characters with `^',
 and strip the parameter to 7 bits.
-Or they may ignore C1 controls and treat all of the upper-1280 codes as
+Or they may ignore C1 controls and treat all of the upper-128 codes as
 printable.
 This implementation uses 8 bits but does not modify the string to reflect
 locale.
 The \fBuse_legacy_coding\fP function allows the caller to
 change the output of \fBunctrl\fP.
 .PP
 printable.
 This implementation uses 8 bits but does not modify the string to reflect
 locale.
 The \fBuse_legacy_coding\fP function allows the caller to
 change the output of \fBunctrl\fP.
 .PP
+Likewise, the \fBmeta\fP function allows the caller to change the
+output of \fBkeyname\fP, i.e.,
+it determines whether to use the `M-' prefix
+for ``meta'' keys (codes in the range 128 to 255).
+Both \fBuse_legacy_coding\fP and \fBmeta\fP succeed only after
+curses is initialized. 
+X/Open Curses does not document the treatment of codes 128 to 159.
+When treating them as ``meta'' keys
+(or if \fBkeyname\fP is called before initializing curses),
+this implementation returns strings ``M-^@'', ``M-^A'', etc.
+.PP
 The \fBkeyname\fP function may return the names of user-defined
 string capabilities which are defined in the terminfo entry via the \fB-x\fP
 option of \fBtic\fP.
 The \fBkeyname\fP function may return the names of user-defined
 string capabilities which are defined in the terminfo entry via the \fB-x\fP
 option of \fBtic\fP.
@@ -182,7 +216,8 @@ be conditioned using NCURSES_VERSION.
 \fBcurses\fR(3X),
 \fBcurs_initscr\fR(3X),
 \fBcurs_kernel\fR(3X),
 \fBcurses\fR(3X),
 \fBcurs_initscr\fR(3X),
 \fBcurs_kernel\fR(3X),
-\fBcurs_scr_dump\fR(3X).
+\fBcurs_scr_dump\fR(3X),
+\fBlegacy_coding\fR(3X).
 .\"#
 .\"# The following sets edit modes for GNU EMACS
 .\"# Local Variables:
 .\"#
 .\"# The following sets edit modes for GNU EMACS
 .\"# Local Variables:
index b27eb75ab8b6ddbf0f954b375cde2ba62b3bfb7b..68903e434a4a4e8f78527ea821d4e34c21205411 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: MKkeyname.awk,v 1.32 2007/04/21 23:01:49 tom Exp $
+# $Id: MKkeyname.awk,v 1.33 2007/05/26 20:58:24 tom Exp $
 ##############################################################################
 # Copyright (c) 1999-2006,2007 Free Software Foundation, Inc.                #
 #                                                                            #
 ##############################################################################
 # Copyright (c) 1999-2006,2007 Free Software Foundation, Inc.                #
 #                                                                            #
@@ -74,7 +74,7 @@ END {
        print "                         if (MyTable[c] == 0) {"
        print "                                 int cc = c;"
        print "                                 p = name;"
        print "                         if (MyTable[c] == 0) {"
        print "                                 int cc = c;"
        print "                                 p = name;"
-       print "                                 if (cc >= 128) {"
+       print "                                 if (cc >= 128 && (SP == 0 || SP->_use_meta)) {"
        print "                                         strcpy(p, \"M-\");"
        print "                                         p += 2;"
        print "                                         cc -= 128;"
        print "                                         strcpy(p, \"M-\");"
        print "                                         p += 2;"
        print "                                         cc -= 128;"
index 44e4528d2da74e6e0177ee016552ca582d519736..931b0fa51a0ee023ab0f400eba6378df35fd931a 100644 (file)
@@ -34,7 +34,7 @@
 
 
 /*
 
 
 /*
- * $Id: curses.priv.h,v 1.331 2007/05/12 18:10:46 tom Exp $
+ * $Id: curses.priv.h,v 1.332 2007/05/26 18:47:51 tom Exp $
  *
  *     curses.priv.h
  *
  *
  *     curses.priv.h
  *
@@ -551,6 +551,7 @@ typedef struct {
        ripoff_t        rippedoff[N_RIPS];
        ripoff_t        *rsp;
        TPARM_STATE     tparm_state;
        ripoff_t        rippedoff[N_RIPS];
        ripoff_t        *rsp;
        TPARM_STATE     tparm_state;
+       TTY             *saved_tty;     /* savetty/resetty information      */
 #if BROKEN_LINKER || USE_REENTRANT
        chtype          *real_acs_map;
 #endif
 #if BROKEN_LINKER || USE_REENTRANT
        chtype          *real_acs_map;
 #endif
index aee05075eaac88b8ca8b5adc9848c8a12db769c0..63b8f644cdb89a4a6c5979872949cc75a6f661c0 100644 (file)
@@ -41,7 +41,7 @@
 
 #include <curses.priv.h>
 
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_data.c,v 1.25 2007/05/12 18:12:12 tom Exp $")
+MODULE_ID("$Id: lib_data.c,v 1.26 2007/05/26 18:48:07 tom Exp $")
 
 /*
  * OS/2's native linker complains if we don't initialize public data when
 
 /*
  * OS/2's native linker complains if we don't initialize public data when
@@ -210,6 +210,7 @@ NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = {
        NUM_VARS_0s,            /* dynamic_var */
        NUM_VARS_0s,            /* static_vars */
     },
        NUM_VARS_0s,            /* dynamic_var */
        NUM_VARS_0s,            /* static_vars */
     },
+    NULL,                      /* saved_tty */
 #if BROKEN_LINKER || USE_REENTRANT
     NULL,                      /* real_acs_map */
 #endif
 #if BROKEN_LINKER || USE_REENTRANT
     NULL,                      /* real_acs_map */
 #endif
index 66f08ec9fc1897772c522ffa8568d0727ceab7b0..4cbbf504a0c7e1c085d5de1783954bf0c338e393 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2006,2007 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            *
 #include <curses.priv.h>
 #include <term.h>              /* cur_term */
 
 #include <curses.priv.h>
 #include <term.h>              /* cur_term */
 
-MODULE_ID("$Id: lib_ttyflags.c,v 1.14 2006/12/30 21:37:20 tom Exp $")
+MODULE_ID("$Id: lib_ttyflags.c,v 1.15 2007/05/26 18:54:25 tom Exp $")
 
 NCURSES_EXPORT(int)
 _nc_get_tty_mode(TTY * buf)
 {
     int result = OK;
 
 
 NCURSES_EXPORT(int)
 _nc_get_tty_mode(TTY * buf)
 {
     int result = OK;
 
-    if (cur_term == 0) {
+    if (buf == 0) {
        result = ERR;
     } else {
        result = ERR;
     } else {
-       for (;;) {
-           if (GET_TTY(cur_term->Filedes, buf) != 0) {
-               if (errno == EINTR)
-                   continue;
-               result = ERR;
+       if (cur_term == 0) {
+           result = ERR;
+       } else {
+           for (;;) {
+               if (GET_TTY(cur_term->Filedes, buf) != 0) {
+                   if (errno == EINTR)
+                       continue;
+                   result = ERR;
+               }
+               break;
            }
            }
-           break;
        }
        }
-    }
 
 
-    if (result == ERR)
-       memset(buf, 0, sizeof(*buf));
+       if (result == ERR)
+           memset(buf, 0, sizeof(*buf));
 
 
-    TR(TRACE_BITS, ("_nc_get_tty_mode(%d): %s",
-                   cur_term->Filedes, _nc_trace_ttymode(buf)));
+       TR(TRACE_BITS, ("_nc_get_tty_mode(%d): %s",
+                       cur_term->Filedes, _nc_trace_ttymode(buf)));
+    }
     return (result);
 }
 
     return (result);
 }
 
@@ -71,22 +75,26 @@ _nc_set_tty_mode(TTY * buf)
 {
     int result = OK;
 
 {
     int result = OK;
 
-    if (cur_term == 0) {
+    if (buf == 0) {
        result = ERR;
     } else {
        result = ERR;
     } else {
-       for (;;) {
-           if (SET_TTY(cur_term->Filedes, buf) != 0) {
-               if (errno == EINTR)
-                   continue;
-               if ((errno == ENOTTY) && (SP != 0))
-                   SP->_notty = TRUE;
-               result = ERR;
+       if (cur_term == 0) {
+           result = ERR;
+       } else {
+           for (;;) {
+               if (SET_TTY(cur_term->Filedes, buf) != 0) {
+                   if (errno == EINTR)
+                       continue;
+                   if ((errno == ENOTTY) && (SP != 0))
+                       SP->_notty = TRUE;
+                   result = ERR;
+               }
+               break;
            }
            }
-           break;
        }
        }
+       TR(TRACE_BITS, ("_nc_set_tty_mode(%d): %s",
+                       cur_term->Filedes, _nc_trace_ttymode(buf)));
     }
     }
-    TR(TRACE_BITS, ("_nc_set_tty_mode(%d): %s",
-                   cur_term->Filedes, _nc_trace_ttymode(buf)));
     return (result);
 }
 
     return (result);
 }
 
@@ -164,6 +172,22 @@ reset_shell_mode(void)
     returnCode(ERR);
 }
 
     returnCode(ERR);
 }
 
+static TTY *
+saved_tty(void)
+{
+    TTY *result = 0;
+
+    if (SP != 0) {
+       result = &(SP->_saved_tty);
+    } else {
+       if (_nc_prescreen.saved_tty == 0) {
+           _nc_prescreen.saved_tty = typeCalloc(TTY, 1);
+       }
+       result = _nc_prescreen.saved_tty;
+    }
+    return result;
+}
+
 /*
 **     savetty()  and  resetty()
 **
 /*
 **     savetty()  and  resetty()
 **
@@ -174,7 +198,7 @@ savetty(void)
 {
     T((T_CALLED("savetty()")));
 
 {
     T((T_CALLED("savetty()")));
 
-    returnCode(_nc_get_tty_mode(&(SP->_saved_tty)));
+    returnCode(_nc_get_tty_mode(saved_tty()));
 }
 
 NCURSES_EXPORT(int)
 }
 
 NCURSES_EXPORT(int)
@@ -182,5 +206,5 @@ resetty(void)
 {
     T((T_CALLED("resetty()")));
 
 {
     T((T_CALLED("resetty()")));
 
-    returnCode(_nc_set_tty_mode(&(SP->_saved_tty)));
+    returnCode(_nc_set_tty_mode(saved_tty()));
 }
 }
index fa6ab48d208abc47be0c39b2aba9c3a8135efec9..5723263cc572c8c8118292254560b18e1a916323 100755 (executable)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 2003,2006 Free Software Foundation, Inc.                   *
+ * Copyright (c) 2007 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: demo_panels.c,v 1.2 2006/04/01 19:08:03 tom Exp $
+ * $Id: demo_panels.c,v 1.5 2007/05/26 22:35:46 tom Exp $
  *
  * Demonstrate a variety of functions from the panel library.
  * Thomas Dickey - 2003/4/26
  *
  * Demonstrate a variety of functions from the panel library.
  * Thomas Dickey - 2003/4/26
@@ -44,10 +44,376 @@ replace_panel                      -
 
 #include <panel.h>
 
 
 #include <panel.h>
 
+typedef void (*InitPanel) (void);
+typedef void (*FillPanel) (PANEL *);
+
+static bool use_colors;
+
+static NCURSES_CONST char *mod[] =
+{
+    "test ",
+    "TEST ",
+    "(**) ",
+    "*()* ",
+    "<--> ",
+    "LAST "
+};
+
+/*+-------------------------------------------------------------------------
+       saywhat(text)
+--------------------------------------------------------------------------*/
+static void
+saywhat(NCURSES_CONST char *text)
+{
+    wmove(stdscr, LINES - 1, 0);
+    wclrtoeol(stdscr);
+    if (text != 0 && *text != '\0') {
+       waddstr(stdscr, text);
+       waddstr(stdscr, "; ");
+    }
+    waddstr(stdscr, "press any key to continue");
+}                              /* end of saywhat */
+
+static PANEL *
+mkpanel(short color, int rows, int cols, int tly, int tlx)
+{
+    WINDOW *win;
+    PANEL *pan = 0;
+    char *userdata = malloc(3);
+
+    if ((win = newwin(rows, cols, tly, tlx)) != 0) {
+       if ((pan = new_panel(win)) == 0) {
+           delwin(win);
+       } else if (use_colors) {
+           short fg = (color == COLOR_BLUE) ? COLOR_WHITE : COLOR_BLACK;
+           short bg = color;
+
+           init_pair(color, fg, bg);
+           wbkgdset(win, (chtype) (COLOR_PAIR(color) | ' '));
+       } else {
+           wbkgdset(win, A_BOLD | ' ');
+       }
+    }
+    sprintf(userdata, "p%d", color % 8);
+    set_panel_userptr(pan, (NCURSES_CONST void *) userdata);
+    return pan;
+}
+
+/*+-------------------------------------------------------------------------
+       rmpanel(pan)
+--------------------------------------------------------------------------*/
+static void
+rmpanel(PANEL * pan)
+{
+    WINDOW *win = panel_window(pan);
+    del_panel(pan);
+    delwin(win);
+}                              /* end of rmpanel */
+
+/*+-------------------------------------------------------------------------
+       pflush()
+--------------------------------------------------------------------------*/
+static void
+pflush(void)
+{
+    update_panels();
+    doupdate();
+}                              /* end of pflush */
+
+/*+-------------------------------------------------------------------------
+       fill_panel(win)
+--------------------------------------------------------------------------*/
+static void
+init_panel(void)
+{
+    register int y, x;
+
+    for (y = 0; y < LINES - 1; y++) {
+       for (x = 0; x < COLS; x++)
+           wprintw(stdscr, "%d", (y + x) % 10);
+    }
+}
+
+static void
+fill_panel(PANEL * pan)
+{
+    WINDOW *win = panel_window(pan);
+    int num = ((const char *) panel_userptr(pan))[1];
+    int y, x;
+
+    wmove(win, 1, 1);
+    wprintw(win, "-pan%c-", num);
+    wclrtoeol(win);
+    box(win, 0, 0);
+    for (y = 2; y < getmaxy(win) - 1; y++) {
+       for (x = 1; x < getmaxx(win) - 1; x++) {
+           wmove(win, y, x);
+           waddch(win, UChar(num));
+       }
+    }
+}
+
+#if USE_WIDEC_SUPPORT
+static void
+make_fullwidth_digit(cchar_t *target, int digit)
+{
+    wchar_t source[2];
+
+    source[0] = digit + 0xff10;
+    source[1] = 0;
+    setcchar(target, source, A_NORMAL, 0, 0);
+}
+
+static void
+init_wide_panel(void)
+{
+    int digit;
+    cchar_t temp[10];
+
+    for (digit = 0; digit < 10; ++digit)
+       make_fullwidth_digit(&temp[digit], digit);
+
+    do {
+       int y, x;
+       getyx(stdscr, y, x);
+       digit = (y + x / 2) % 10;
+    } while (add_wch(&temp[digit]) != ERR);
+}
+
+static void
+fill_wide_panel(PANEL * pan)
+{
+    WINDOW *win = panel_window(pan);
+    int num = ((const char *) panel_userptr(pan))[1];
+    int y, x;
+
+    wmove(win, 1, 1);
+    wprintw(win, "-pan%c-", num);
+    wclrtoeol(win);
+    box(win, 0, 0);
+    for (y = 2; y < getmaxy(win) - 1; y++) {
+       for (x = 1; x < getmaxx(win) - 1; x++) {
+           wmove(win, y, x);
+           waddch(win, UChar(num));
+       }
+    }
+}
+#endif
+
+#define MAX_PANELS 5
+
+static void
+canned_panel(PANEL * px[MAX_PANELS + 1], NCURSES_CONST char *cmd)
+{
+    int which = cmd[1] - '0';
+
+    saywhat(cmd);
+    switch (*cmd) {
+    case 'h':
+       hide_panel(px[which]);
+       break;
+    case 's':
+       show_panel(px[which]);
+       break;
+    case 't':
+       top_panel(px[which]);
+       break;
+    case 'b':
+       bottom_panel(px[which]);
+       break;
+    case 'd':
+       rmpanel(px[which]);
+       break;
+    }
+    pflush();
+    wgetch(stdscr);
+}
+
+static void
+demo_panels(void (*myInit) (void), void (*myFill) (PANEL *))
+{
+    int itmp;
+    PANEL *px[MAX_PANELS + 1];
+
+    scrollok(stdscr, FALSE);   /* we don't want stdscr to scroll! */
+    refresh();
+
+    myInit();
+    for (itmp = 1; itmp <= MAX_PANELS; ++itmp)
+       px[itmp] = 0;
+
+    px[1] = mkpanel(COLOR_RED,
+                   LINES / 2 - 2,
+                   COLS / 8 + 1,
+                   0,
+                   0);
+
+    px[2] = mkpanel(COLOR_GREEN,
+                   LINES / 2 + 1,
+                   COLS / 7,
+                   LINES / 4,
+                   COLS / 10);
+
+    px[3] = mkpanel(COLOR_YELLOW,
+                   LINES / 4,
+                   COLS / 10,
+                   LINES / 2,
+                   COLS / 9);
+
+    px[4] = mkpanel(COLOR_BLUE,
+                   LINES / 2 - 2,
+                   COLS / 8,
+                   LINES / 2 - 2,
+                   COLS / 3);
+
+    px[5] = mkpanel(COLOR_MAGENTA,
+                   LINES / 2 - 2,
+                   COLS / 8,
+                   LINES / 2,
+                   COLS / 2 - 2);
+
+    myFill(px[1]);
+    myFill(px[2]);
+    myFill(px[3]);
+    myFill(px[4]);
+    myFill(px[5]);
+
+    hide_panel(px[4]);
+    hide_panel(px[5]);
+    pflush();
+    saywhat("");
+    wgetch(stdscr);
+
+    saywhat("h3 s1 s2 s4 s5");
+    move_panel(px[1], 0, 0);
+    hide_panel(px[3]);
+    show_panel(px[1]);
+    show_panel(px[2]);
+    show_panel(px[4]);
+    show_panel(px[5]);
+    pflush();
+    wgetch(stdscr);
+
+    canned_panel(px, "s1");
+    canned_panel(px, "s2");
+
+    saywhat("m2");
+    move_panel(px[2], LINES / 3 + 1, COLS / 8);
+    pflush();
+    wgetch(stdscr);
+
+    canned_panel(px, "s3");
+
+    saywhat("m3");
+    move_panel(px[3], LINES / 4 + 1, COLS / 15);
+    pflush();
+    wgetch(stdscr);
+
+    canned_panel(px, "b3");
+    canned_panel(px, "s4");
+    canned_panel(px, "s5");
+    canned_panel(px, "t3");
+    canned_panel(px, "t1");
+    canned_panel(px, "t2");
+    canned_panel(px, "t3");
+    canned_panel(px, "t4");
+
+    for (itmp = 0; itmp < 6; itmp++) {
+       WINDOW *w4 = panel_window(px[4]);
+       WINDOW *w5 = panel_window(px[5]);
+
+       saywhat("m4");
+       wmove(w4, LINES / 8, 1);
+       waddstr(w4, mod[itmp]);
+       move_panel(px[4], LINES / 6, itmp * (COLS / 8));
+       wmove(w5, LINES / 6, 1);
+       waddstr(w5, mod[itmp]);
+       pflush();
+       wgetch(stdscr);
+
+       saywhat("m5");
+       wmove(w4, LINES / 6, 1);
+       waddstr(w4, mod[itmp]);
+       move_panel(px[5], LINES / 3 - 1, (itmp * 10) + 6);
+       wmove(w5, LINES / 8, 1);
+       waddstr(w5, mod[itmp]);
+       pflush();
+       wgetch(stdscr);
+    }
+
+    saywhat("m4");
+    move_panel(px[4], LINES / 6, itmp * (COLS / 8));
+    pflush();
+    wgetch(stdscr);
+
+    canned_panel(px, "t5");
+    canned_panel(px, "t2");
+    canned_panel(px, "t1");
+    canned_panel(px, "d2");
+    canned_panel(px, "h3");
+    canned_panel(px, "d1");
+    canned_panel(px, "d4");
+    canned_panel(px, "d5");
+    canned_panel(px, "d3");
+
+    wgetch(stdscr);
+
+    erase();
+    endwin();
+}
+
+static void
+usage(void)
+{
+    static const char *const tbl[] =
+    {
+       "Usage: demo_panels [options]"
+       ,""
+       ,"Options:"
+       ,"  -m       do not use colors"
+#if USE_WIDEC_SUPPORT
+       ,"  -w       use wide-characters in panels and background"
+#endif
+    };
+    size_t n;
+    for (n = 0; n < SIZEOF(tbl); n++)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
 int
 int
-main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
+main(int argc, char *argv[])
 {
 {
-    printf("Not implemented - demo for panel library\n");
+    int c;
+    bool monochrome = FALSE;
+    InitPanel myInit = init_panel;
+    FillPanel myFill = fill_panel;
+
+    while ((c = getopt(argc, argv, "mw")) != EOF) {
+       switch (c) {
+       case 'm':
+           monochrome = TRUE;
+           break;
+#if USE_WIDEC_SUPPORT
+       case 'w':
+           myInit = init_wide_panel;
+           myFill = fill_wide_panel;
+           break;
+#endif
+       default:
+           usage();
+       }
+    }
+
+    initscr();
+
+    use_colors = monochrome ? FALSE : has_colors();
+    if (use_colors)
+       start_color();
+
+    demo_panels(myInit, myFill);
+    endwin();
+
     return EXIT_SUCCESS;
 }
 #else
     return EXIT_SUCCESS;
 }
 #else