ncurses 5.9 - patch 20150321
authorThomas E. Dickey <dickey@invisible-island.net>
Sun, 22 Mar 2015 01:12:56 +0000 (01:12 +0000)
committerThomas E. Dickey <dickey@invisible-island.net>
Sun, 22 Mar 2015 01:12:56 +0000 (01:12 +0000)
+ in-progress changes to provide an extended version of putwin and
  getwin which will be capable of reading screen-dumps between the
  wide/normal ncurses configurations.  These are text files, except
  for a magic code at the beginning:
  0       string          \210\210        Screen-dump (ncurses)

14 files changed:
NEWS
VERSION
dist.mk
include/ncurses_defs
man/curs_util.3x
ncurses/base/lib_screen.c
package/debian-mingw/changelog
package/debian-mingw64/changelog
package/debian/changelog
package/mingw-ncurses.nsi
package/mingw-ncurses.spec
package/ncurses.spec
progs/tset.c
test/savescreen.c

diff --git a/NEWS b/NEWS
index 7ede0a206e3b7049f5342053b8df95370770d85c..ab171a1550e2cbf7c2a0d9094076e9acac12a2ae 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,7 +25,7 @@
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
--- $Id: NEWS,v 1.2357 2015/03/07 23:38:25 tom Exp $
+-- $Id: NEWS,v 1.2360 2015/03/21 23:44:50 tom Exp $
 -------------------------------------------------------------------------------
 
 This is a log of changes that ncurses has gone through since Zeyd started
@@ -45,6 +45,13 @@ 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.
 
+20150321
+       + in-progress changes to provide an extended version of putwin and
+         getwin which will be capable of reading screen-dumps between the
+         wide/normal ncurses configurations.  These are text files, except
+         for a magic code at the beginning:
+         0       string          \210\210        Screen-dump (ncurses)
+
 20150307
        + document limitations of getwin in manual page (prompted by discussion
          with John S Urban).
diff --git a/VERSION b/VERSION
index d602f6c308fe57050a2a59a07692f995be2498ec..3dc8c803bf5b48ebff34566fb18c70868bb48e90 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5:0:9  5.9     20150307
+5:0:9  5.9     20150321
diff --git a/dist.mk b/dist.mk
index 04650d0e55c08108c1fd3c7a89b4a1e4ac78ede5..a6574f4052c8c799eead266a03d09d6f21872d12 100644 (file)
--- a/dist.mk
+++ b/dist.mk
@@ -25,7 +25,7 @@
 # use or other dealings in this Software without prior written               #
 # authorization.                                                             #
 ##############################################################################
-# $Id: dist.mk,v 1.1037 2015/03/07 16:12:58 tom Exp $
+# $Id: dist.mk,v 1.1039 2015/03/21 16:25:11 tom Exp $
 # Makefile for creating ncurses distributions.
 #
 # This only needs to be used directly as a makefile by developers, but
@@ -37,7 +37,7 @@ SHELL = /bin/sh
 # These define the major/minor/patch versions of ncurses.
 NCURSES_MAJOR = 5
 NCURSES_MINOR = 9
-NCURSES_PATCH = 20150307
+NCURSES_PATCH = 20150321
 
 # We don't append the patch to the version, since this only applies to releases
 VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR)
index 5a63b256797c27ba49a4e0b1feeba8f54cc1ada9..7381118276eb999df8ed7d94bfc7e970feace533 100644 (file)
@@ -1,6 +1,6 @@
-# $Id: ncurses_defs,v 1.66 2014/09/05 08:46:16 tom Exp $
+# $Id: ncurses_defs,v 1.68 2015/03/21 16:52:07 tom Exp $
 ##############################################################################
-# Copyright (c) 2000-2013,2014 Free Software Foundation, Inc.                #
+# Copyright (c) 2000-2014,2015 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"), #
@@ -189,6 +189,7 @@ NCURSES_CHAR_EQ
 NCURSES_EXPANDED
 NCURSES_EXT_COLORS
 NCURSES_EXT_FUNCS
+NCURSES_EXT_SCREEN_DUMP
 NCURSES_NO_PADDING
 NCURSES_OSPEED_COMPAT
 NCURSES_PATHSEP        ':'
index a0c05fe427e2da0895c7c0b3ffedf294c0a04acb..1b7b9e804b8fa32f99b33d7adb9b5c0f5d5c0b98 100644 (file)
@@ -27,7 +27,7 @@
 .\" authorization.                                                           *
 .\"***************************************************************************
 .\"
-.\" $Id: curs_util.3x,v 1.38 2015/03/07 23:33:38 tom Exp $
+.\" $Id: curs_util.3x,v 1.40 2015/03/15 13:58:59 tom Exp $
 .TH curs_util 3X ""
 .ie \n(.g .ds `` \(lq
 .el       .ds `` ``
@@ -90,7 +90,6 @@ a wide character.
 .PP
 The \fBkeyname\fR routine returns a character string
 corresponding to the key \fIc\fR:
-.RS 3
 .bP
 Printable characters are displayed as themselves,
 e.g., a one-character string containing the key.
@@ -113,7 +112,6 @@ Otherwise (if there is no corresponding name) the function returns null,
 to denote an error.
 X/Open also lists an "UNKNOWN KEY" return value, which some implementations
 return rather than null.
-.RE
 .LP
 The corresponding \fBkey_name\fR returns a character string corresponding
 to the wide-character value \fIw\fR.
@@ -216,6 +214,7 @@ the data written is a copy of the \fBWINDOW\fP structure,
 and its associated character cells.
 The format differs between the wide-character (ncursesw) and
 non-wide (ncurses) libraries.
+You can transfer data between the two, however.
 .bP
 the retrieved window is always created as a top-level window (or pad),
 rather than a subwindow.
@@ -256,11 +255,65 @@ returns an error if the terminal was not initialized.
 returns an error if the associated \fBfwrite\fP calls return an error.
 .RE
 .SH PORTABILITY
+.SS filter
+.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
+erroneously fails to describe the disabling of \fBcuu\fR).
+.SS keyname
+.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 \fB@TIC@\fP.
+This implementation automatically assigns at run-time keycodes to
+user-defined strings which begin with "k".
+The keycodes start at KEY_MAX, but are not guaranteed to be
+the same value for different runs because user-defined codes are
+merged from all terminal descriptions which have been loaded.
+The \fBuse_extended_names\fP function controls whether this data is
+loaded when the terminal description is read by the library.
+.SS nofilter/use_tioctl
+.PP
+The \fBnofilter\fP and \fBuse_tioctl\fP routines are specific to ncurses.
+They were not supported on Version 7, BSD or System V implementations.
+It is recommended that any code depending on ncurses extensions
+be conditioned using NCURSES_VERSION.
+.SS putwin/getwin
+.PP
+The \fBputwin\fP and \fBgetwin\fP functions have several issues with
+portability:
+.bP
+The files written and read by these functions
+use an implementation-specific format.
+Although the format is an obvious target for standardization,
+it has been overlooked.
+.IP
+Interestingly enough, according to the copyright dates in Solaris source,
+the functions (along with \fBscr_init\fP, etc.) originated with
+the University of California, Berkeley (in 1982)
+and were later (in 1988) incorporated into SVr4.
+Oddly, there are no such functions in the 4.3BSD curses sources.
+.bP
+Most implementations simply dump the binary \fBWINDOW\fP structure to the file.
+These include SVr4 curses, NetBSD and PDCurses, as well as older ncurses versions.
+This implementation (as well as the X/Open variant of Solaris curses, dated 1995)
+uses textual dumps.
+.IP
+The implementations which use binary dumps use block-I/O
+(the \fBfwrite\fP and \fBfread\fP functions).
+Those that use textual dumps use buffered-I/O.
+A few applications may happen to write extra data in the file using
+these functions.
+Doing that can run into problems mixing block- and buffered-I/O.
+This implementation reduces the problem on writes by flushing the output.
+However, reading from a file written using mixed schemes may not be succesful.
+.SS unctrl/wunctrl
+.PP
 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 3
 .bP
 the parameter is a 7-bit US\-ASCII code.
 This is the case that X/Open Curses documented.
@@ -279,12 +332,6 @@ and returns the \*(``~@\*('', etc., values in that case.
 .bP
 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
-erroneously fails to describe the disabling of \fBcuu\fR).
 .PP
 The strings returned by \fBunctrl\fR in this implementation are determined
 at compile time,
@@ -309,22 +356,6 @@ 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 \fB@TIC@\fP.
-This implementation automatically assigns at run-time keycodes to
-user-defined strings which begin with "k".
-The keycodes start at KEY_MAX, but are not guaranteed to be
-the same value for different runs because user-defined codes are
-merged from all terminal descriptions which have been loaded.
-The \fBuse_extended_names\fP function controls whether this data is
-loaded when the terminal description is read by the library.
-.PP
-The \fBnofilter\fP and \fBuse_tioctl\fP routines are specific to ncurses.
-They were not supported on Version 7, BSD or System V implementations.
-It is recommended that any code depending on ncurses extensions
-be conditioned using NCURSES_VERSION.
 .SH SEE ALSO
 \fBlegacy_coding\fR(3X),
 \fBcurses\fR(3X),
index 695ed30e7e1000b98011a70b6c0624921ab6ca58..63ef7f5bcf1737ececa1c1f8297a3f69ca0b9e6a 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2011,2015 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 
 #include <curses.priv.h>
 
+#include <ctype.h>
+
 #ifndef CUR
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_screen.c,v 1.41 2011/10/22 15:03:11 tom Exp $")
+MODULE_ID("$Id: lib_screen.c,v 1.64 2015/03/21 23:59:32 tom Exp $")
 
 #define MAX_SIZE 0x3fff                /* 16k is big enough for a window or pad */
 
+#define MARKER '\\'
+#define GUTTER '|'
+#define L_CURL '{'
+#define R_CURL '}'
+
+#define L_MARK "\\{"
+#define R_MARK "}"
+
+/*
+ * Use 0x8888 as the magic number for new-format files, since it cannot be
+ * mistaken for the _cury/_curx pair of 16-bit numbers which start the old
+ * format.  It happens to be unused in the file 5.22 database (2015/03/07).
+ */
+static char my_magic[] =
+{'\210', '\210', '\210', '\210'};
+
+#if NCURSES_EXT_SCREEN_DUMP
+typedef enum {
+    pINT                       /* int */
+    ,pSHORT                    /* short */
+    ,pBOOL                     /* bool */
+    ,pATTR                     /* attr_t */
+    ,pCHAR                     /* chtype */
+    ,pSIZE                     /* NCURSES_SIZE_T */
+#if NCURSES_WIDECHAR
+    ,pCCHAR                    /* cchar_t */
+#endif
+} PARAM_TYPE;
+
+typedef struct {
+    const char *name;
+    attr_t attr;
+} SCR_ATTRS;
+
+typedef struct {
+    const char *name;
+    PARAM_TYPE type;
+    size_t size;
+    size_t offset;
+} SCR_PARAMS;
+
+#define DATA(name) { #name, A_##name }
+static SCR_ATTRS scr_attrs[] =
+{
+    DATA(NORMAL),
+    DATA(STANDOUT),
+    DATA(UNDERLINE),
+    DATA(REVERSE),
+    DATA(BLINK),
+    DATA(DIM),
+    DATA(BOLD),
+    DATA(ALTCHARSET),
+    DATA(INVIS),
+    DATA(PROTECT),
+    DATA(HORIZONTAL),
+    DATA(LEFT),
+    DATA(LOW),
+    DATA(RIGHT),
+    DATA(TOP),
+    DATA(VERTICAL),
+
+#ifdef A_ITALIC
+    DATA(ITALIC),
+#endif
+};
+#undef DATA
+
+#define sizeof2(type,name) sizeof(((type *)0)->name)
+#define DATA(name, type) { #name, type, sizeof2(WINDOW, name), offsetof(WINDOW, name) }
+
+static SCR_PARAMS scr_params[] =
+{
+    DATA(_cury, pSIZE),
+    DATA(_curx, pSIZE),
+    DATA(_maxy, pSIZE),
+    DATA(_maxx, pSIZE),
+    DATA(_begy, pSIZE),
+    DATA(_begx, pSIZE),
+    DATA(_flags, pSHORT),
+    DATA(_attrs, pATTR),
+    DATA(_bkgd, pCHAR),
+    DATA(_notimeout, pBOOL),
+    DATA(_clear, pBOOL),
+    DATA(_leaveok, pBOOL),
+    DATA(_scroll, pBOOL),
+    DATA(_idlok, pBOOL),
+    DATA(_idcok, pBOOL),
+    DATA(_immed, pBOOL),
+    DATA(_sync, pBOOL),
+    DATA(_use_keypad, pBOOL),
+    DATA(_delay, pINT),
+    DATA(_regtop, pSIZE),
+    DATA(_regbottom, pSIZE),
+    DATA(_pad._pad_y, pSIZE),
+    DATA(_pad._pad_x, pSIZE),
+    DATA(_pad._pad_top, pSIZE),
+    DATA(_pad._pad_left, pSIZE),
+    DATA(_pad._pad_bottom, pSIZE),
+    DATA(_pad._pad_right, pSIZE),
+    DATA(_yoffset, pSIZE),
+#if NCURSES_WIDECHAR
+    DATA(_bkgrnd, pCCHAR),
+#if NCURSES_EXT_COLORS
+    DATA(_color, pINT),
+#endif
+#endif
+};
+#undef DATA
+
+static const NCURSES_CH_T blank = NewChar(BLANK_TEXT);
+
+/*
+ * Allocate and read a line of text.  Caller must free it.
+ */
+static char *
+read_txt(FILE *fp)
+{
+    size_t limit = 1024;
+    size_t used = 0;
+    char *result = malloc(limit);
+    char *buffer;
+
+    if (result != 0) {
+       int ch = 0;
+
+       clearerr(fp);
+       result[used] = '\0';
+       do {
+           if (used + 2 >= limit) {
+               limit += 1024;
+               buffer = realloc(result, limit);
+               if (buffer == 0) {
+                   free(result);
+                   result = 0;
+                   break;
+               }
+           }
+           ch = fgetc(fp);
+           if (ch == EOF)
+               break;
+           result[used++] = (char) ch;
+           result[used] = '\0';
+       } while (ch != '\n');
+
+       if (ch == '\n') {
+           result[--used] = '\0';
+           T(("READ:%s", result));
+       } else if (used == 0) {
+           free(result);
+           result = 0;
+       }
+    }
+    return result;
+}
+
+static char *
+decode_attr(char *source, attr_t *target, int *color)
+{
+    bool found = FALSE;
+
+    T(("decode_attr   '%s'", source));
+
+    while (*source) {
+       if (source[0] == MARKER && source[1] == L_CURL) {
+           source += 2;
+           found = TRUE;
+       } else if (source[0] == R_CURL) {
+           source++;
+           found = FALSE;
+       } else if (found) {
+           size_t n;
+           char *next = source;
+
+           if (source[0] == GUTTER) {
+               ++next;
+           } else if (*next == 'C') {
+               int value = 0;
+               next++;
+               while (isdigit(UChar(*next))) {
+                   value = value * 10 + (*next++ - '0');
+               }
+               *target &= ~A_COLOR;
+               if (value > 256) {
+                   *target |= COLOR_PAIR(255);
+               } else {
+                   *target |= COLOR_PAIR(value);
+               }
+               *color = value;
+           } else {
+               while (isalnum(UChar(*next))) {
+                   ++next;
+               }
+               for (n = 0; n < SIZEOF(scr_attrs); ++n) {
+                   if ((size_t) (next - source) == strlen(scr_attrs[n].name)) {
+                       if (scr_attrs[n].attr) {
+                           *target |= scr_attrs[n].attr;
+                       } else {
+                           *target = A_NORMAL;
+                       }
+                       break;
+                   }
+               }
+           }
+           source = next;
+       } else {
+           break;
+       }
+    }
+    return source;
+}
+
+static char *
+decode_char(char *source, int *target)
+{
+    int limit = 0;
+    int base = 16;
+    const char digits[] = "0123456789abcdef";
+
+    T(("decode_char   '%s'", source));
+    *target = ' ';
+    switch (*source) {
+    case '\\':
+       switch (*++source) {
+       case '\\':
+           *target = '\\';
+           ++source;
+           break;
+       case 's':
+           *target = ' ';
+           ++source;
+           break;
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+           base = 8;
+           limit = 3;
+           break;
+       case 'u':
+           limit = 4;
+           ++source;
+           break;
+       case 'U':
+           limit = 8;
+           ++source;
+           break;
+       }
+       if (limit) {
+           *target = 0;
+           while (limit-- > 0) {
+               char *find = strchr(digits, *source++);
+               int ch = (find != 0) ? (int) (find - digits) : -1;
+               *target *= base;
+               if (ch >= 0 && ch < base) {
+                   *target += ch;
+               }
+           }
+       }
+       break;
+    default:
+       *target = *source++;
+       break;
+    }
+    return source;
+}
+
+static char *
+decode_chtype(char *source, chtype fillin, chtype *target)
+{
+    attr_t attr = ChAttrOf(fillin);
+    int color = PAIR_NUMBER(attr);
+    int value;
+
+    T(("decode_chtype '%s'", source));
+    source = decode_attr(source, &attr, &color);
+    source = decode_char(source, &value);
+    *target = ChCharOf(value) | attr | COLOR_PAIR(color);
+    return source;
+}
+
+#if NCURSES_WIDECHAR
+static char *
+decode_cchar(char *source, cchar_t *fillin, cchar_t *target)
+{
+    int color;
+    attr_t attr = fillin->attr;
+    wchar_t chars[CCHARW_MAX];
+
+    T(("decode_cchar  '%s'", source));
+    *target = blank;
+#if NCURSES_EXT_COLORS
+    color = fillin->ext_color;
+#else
+    color = (int) PAIR_NUMBER(attr);
+#endif
+    source = decode_attr(source, &attr, &color);
+    memset(chars, 0, sizeof(chars));
+    source = decode_char(source, &chars[0]);
+    /* FIXME - handle combining characters at this point */
+    setcchar(target, chars, attr, (short) color, NULL);
+    return source;
+}
+#endif
+
+static int
+read_win(WINDOW *win, FILE *fp)
+{
+    int code = ERR;
+    char *txt;
+    char *name;
+    char *value;
+    size_t n;
+    int color;
+#if NCURSES_WIDECHAR
+    NCURSES_CH_T prior;
+#endif
+    chtype prior2;
+
+    memset(win, 0, sizeof(WINDOW));
+    for (;;) {
+       txt = read_txt(fp);
+       if (txt == 0)
+           break;
+       if (!strcmp(txt, "rows:")) {
+           free(txt);
+           code = OK;
+           break;
+       }
+       if ((value = strchr(txt, '=')) == 0) {
+           free(txt);
+           continue;
+       }
+       *value++ = '\0';
+       name = !strcmp(txt, "flag") ? value : txt;
+       for (n = 0; n < SIZEOF(scr_params); ++n) {
+           if (!strcmp(name, scr_params[n].name)) {
+               void *data = (void *) ((char *) win + scr_params[n].offset);
+
+               switch (scr_params[n].type) {
+               case pATTR:
+                   (void) decode_attr(value, data, &color);
+                   break;
+               case pBOOL:
+                   *(bool *) data = TRUE;
+                   break;
+               case pCHAR:
+                   prior2 = ' ';
+                   decode_chtype(value, prior2, data);
+                   break;
+               case pINT:
+                   *(int *) data = atoi(value);
+                   break;
+               case pSHORT:
+                   *(short *) data = (short) atoi(value);
+                   break;
+               case pSIZE:
+                   *(NCURSES_SIZE_T *) data = (NCURSES_SIZE_T) atoi(value);
+                   break;
+#if NCURSES_WIDECHAR
+               case pCCHAR:
+                   prior = blank;
+                   decode_cchar(value, &prior, data);
+                   break;
+#endif
+               }
+               break;
+           }
+       }
+       free(txt);
+    }
+    return code;
+}
+
+static int
+read_row(char *source, NCURSES_CH_T * prior, NCURSES_CH_T * target, int length)
+{
+    while (*source != '\0' && length > 0) {
+#if NCURSES_WIDECHAR
+       source = decode_cchar(source, prior, target);
+#else
+       source = decode_chtype(source, *prior, target);
+#endif
+       *prior = *target;
+       ++target;
+       --length;
+    }
+    while (length-- > 0) {
+       *target++ = blank;
+    }
+    /* FIXME - see what error conditions should apply if I need to return ERR */
+    return 0;
+}
+#endif /* NCURSES_EXT_SCREEN_DUMP */
+
+/*
+ * Originally, getwin/putwin used fread/fwrite, because they used binary data.
+ * The new format uses printable ASCII, which does not have as predictable
+ * sizes.  Consequently, we use buffered I/O, e.g., fgetc/fprintf, which need
+ * special handling if we want to read screen dumps from an older library.
+ */
+static int
+read_block(void *target, size_t length, FILE *fp)
+{
+    int result = 0;
+    char *buffer = target;
+
+    clearerr(fp);
+    while (length-- != 0) {
+       int ch = fgetc(fp);
+       if (ch == EOF) {
+           result = -1;
+           break;
+       }
+       *buffer++ = (char) ch;
+    }
+    return result;
+}
+
 NCURSES_EXPORT(WINDOW *)
 NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep)
 {
     WINDOW tmp, *nwin;
     int n;
+    bool old_format = FALSE;
 
     T((T_CALLED("getwin(%p)"), (void *) filep));
 
     if (filep == 0) {
        returnWin(0);
     }
-    clearerr(filep);
-    if (fread(&tmp, (size_t) 1, sizeof(WINDOW), filep) < sizeof(WINDOW)
-       || ferror(filep)
-       || tmp._maxy == 0
-       || tmp._maxy > MAX_SIZE
-       || tmp._maxx == 0
-       || tmp._maxx > MAX_SIZE) {
+
+    /*
+     * Read the first 4 bytes to determine first if this is an old-format
+     * screen-dump, or new-format.
+     */
+    if (read_block(&tmp, 4, filep) < 0) {
+       returnWin(0);
+    }
+    /*
+     * If this is a new-format file, and we do not support it, give up.
+     */
+    if (!memcmp(&tmp, my_magic, 4)) {
+#if NCURSES_EXT_SCREEN_DUMP
+       if (read_win(&tmp, filep) < 0)
+#endif
+           returnWin(0);
+    } else if (read_block(((char *) &tmp) + 4, sizeof(WINDOW) - 4, filep) < 0) {
+       returnWin(0);
+    } else {
+       old_format = TRUE;
+    }
+
+    /*
+     * Check the window-size:
+     */
+    if (tmp._maxy == 0 ||
+       tmp._maxy > MAX_SIZE ||
+       tmp._maxx == 0 ||
+       tmp._maxx > MAX_SIZE) {
        returnWin(0);
     }
 
@@ -111,14 +554,55 @@ NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep)
        if (tmp._flags & _ISPAD)
            nwin->_pad = tmp._pad;
 
-       for (n = 0; n <= nwin->_maxy; n++) {
-           clearerr(filep);
-           if (fread(nwin->_line[n].text, (size_t) 1, linesize, filep) < linesize
-               || ferror(filep)) {
+       if (old_format) {
+           T(("reading old-format screen dump"));
+           for (n = 0; n <= nwin->_maxy; n++) {
+               if (read_block(nwin->_line[n].text, linesize, filep) < 0) {
+                   delwin(nwin);
+                   returnWin(0);
+               }
+           }
+       }
+#if NCURSES_EXT_SCREEN_DUMP
+       else {
+           char *txt;
+           bool success = TRUE;
+           NCURSES_CH_T prior = blank;
+
+           T(("reading new-format screen dump"));
+           for (n = 0; n <= nwin->_maxy; n++) {
+               long row;
+               char *next;
+
+               if ((txt = read_txt(filep)) == 0) {
+                   T(("...failed to read string for row %d", n + 1));
+                   success = FALSE;
+                   break;
+               }
+               row = strtol(txt, &next, 10);
+               if (row != (n + 1) || *next != ':') {
+                   T(("...failed to read row-number %d", n + 1));
+                   success = FALSE;
+                   break;
+               }
+
+               if (read_row(++next, &prior, nwin->_line[n].text, tmp._maxx
+                            + 1) < 0) {
+                   T(("...failed to read cells for row %d", n + 1));
+                   success = FALSE;
+                   break;
+               }
+               free(txt);
+               txt = 0;
+           }
+
+           if (!success) {
+               free(txt);
                delwin(nwin);
                returnWin(0);
            }
        }
+#endif
        touchwin(nwin);
     }
     returnWin(nwin);
@@ -132,14 +616,212 @@ getwin(FILE *filep)
 }
 #endif
 
+#if NCURSES_EXT_SCREEN_DUMP
+static void
+encode_attr(char *target, attr_t source, attr_t prior)
+{
+    *target = '\0';
+    if (source != prior) {
+       size_t n;
+       bool first = TRUE;
+
+       strcpy(target, L_MARK);
+       target += strlen(target);
+
+       for (n = 0; n < SIZEOF(scr_attrs); ++n) {
+           if ((source & scr_attrs[n].attr) != 0 ||
+               ((source & ALL_BUT_COLOR) == 0 &&
+                (scr_attrs[n].attr == A_NORMAL))) {
+               if (first) {
+                   first = FALSE;
+               } else {
+                   *target++ = '|';
+               }
+               strcpy(target, scr_attrs[n].name);
+               target += strlen(target);
+           }
+       }
+       if ((source & A_COLOR) != (prior & A_COLOR)) {
+           if (!first)
+               *target++ = '|';
+           sprintf(target, "C%d", PAIR_NUMBER(source));
+           target += strlen(target);
+       }
+
+       strcpy(target, R_MARK);
+    }
+}
+
+static void
+encode_cell(char *target, CARG_CH_T source, CARG_CH_T previous)
+{
+#if NCURSES_WIDECHAR
+    size_t n;
+
+    *target = '\0';
+    if (previous->attr != source->attr) {
+       encode_attr(target, source->attr, previous->attr);
+    }
+    target += strlen(target);
+#if NCURSES_EXT_COLORS
+    if (previous->ext_color != source->ext_color) {
+       sprintf(target, "%sC%d%s", L_MARK, source->ext_color, R_MARK);
+    }
+#endif
+    for (n = 0; n < SIZEOF(source->chars); ++n) {
+       if (source->chars[n] == 0)
+           continue;
+       if (source->chars[n] > 0xffff) {
+           sprintf(target, "\\U%08x", source->chars[n]);
+       } else if (source->chars[n] > 0xff) {
+           sprintf(target, "\\u%04x", source->chars[n]);
+       } else if (source->chars[n] < 32 || source->chars[n] >= 127) {
+           sprintf(target, "\\%03o", source->chars[n] & 0xff);
+       } else {
+           switch (source->chars[n]) {
+           case ' ':
+               strcpy(target, "\\s");
+               break;
+           case '\\':
+               strcpy(target, "\\\\");
+               break;
+           default:
+               sprintf(target, "%c", source->chars[n]);
+               break;
+           }
+       }
+       target += strlen(target);
+    }
+#else
+    chtype ch = CharOfD(source);
+
+    *target = '\0';
+    if (AttrOfD(previous) != AttrOfD(source)) {
+       encode_attr(target, AttrOfD(source), AttrOfD(previous));
+    }
+    target += strlen(target);
+    if (ch < 32 || ch >= 127) {
+       sprintf(target, "\\%03o", ch);
+    } else {
+       switch (ch) {
+       case ' ':
+           strcpy(target, "\\s");
+           break;
+       case '\\':
+           strcpy(target, "\\\\");
+           break;
+       default:
+           sprintf(target, "%c", ch);
+           break;
+       }
+    }
+    target += strlen(target);
+#endif
+}
+#endif
+
 NCURSES_EXPORT(int)
 putwin(WINDOW *win, FILE *filep)
 {
     int code = ERR;
-    int n;
+    int y;
 
     T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep));
 
+#if NCURSES_EXT_SCREEN_DUMP
+    if (win != 0) {
+       const char *version = curses_version();
+       char buffer[1024];
+       NCURSES_CH_T last_cell;
+
+       memset(&last_cell, 0, sizeof(last_cell));
+
+       clearerr(filep);
+
+       /*
+        * Our magic number is technically nonprinting, but aside from that,
+        * all of the file is printable ASCII.
+        */
+#define PUTS(s) if (fputs(s, filep) == EOF || ferror(filep)) returnCode(code)
+       PUTS(my_magic);
+       PUTS(version);
+       PUTS("\n");
+       for (y = 0; y < (int) SIZEOF(scr_params); ++y) {
+           const char *name = scr_params[y].name;
+           const char *data = (char *) win + scr_params[y].offset;
+           const void *dp = (const void *) data;
+
+           *buffer = '\0';
+           if (!strncmp(name, "_pad.", 5) && !(win->_flags & _ISPAD)) {
+               continue;
+           }
+           switch (scr_params[y].type) {
+           case pATTR:
+               encode_attr(buffer, (*(const attr_t *) dp) & ~A_CHARTEXT, A_NORMAL);
+               break;
+           case pBOOL:
+               if (!(*(const bool *) data)) {
+                   continue;
+               }
+               strcpy(buffer, name);
+               name = "flag";
+               break;
+           case pCHAR:
+               encode_attr(buffer, *(const attr_t *) dp, A_NORMAL);
+               break;
+           case pINT:
+               if (!(*(const int *) dp))
+                   continue;
+               sprintf(buffer, "%d", *(const int *) dp);
+               break;
+           case pSHORT:
+               if (!(*(const short *) dp))
+                   continue;
+               sprintf(buffer, "%d", *(const short *) dp);
+               break;
+           case pSIZE:
+               if (!(*(const NCURSES_SIZE_T *) dp))
+                   continue;
+               sprintf(buffer, "%d", *(const NCURSES_SIZE_T *) dp);
+               break;
+#if NCURSES_WIDECHAR
+           case pCCHAR:
+               encode_cell(buffer, (CARG_CH_T) dp, CHREF(last_cell));
+               break;
+#endif
+           }
+           /*
+            * Only write non-default data.
+            */
+           if (*buffer != '\0') {
+               if (fprintf(filep, "%s=%s\n", name, buffer) <= 0
+                   || ferror(filep))
+                   returnCode(code);
+           }
+       }
+       /* Write row-data */
+       fprintf(filep, "rows:\n");
+       for (y = 0; y <= win->_maxy; y++) {
+           NCURSES_CH_T *data = win->_line[y].text;
+           int x;
+           if (fprintf(filep, "%d:", y + 1) <= 0
+               || ferror(filep))
+               returnCode(code);
+           for (x = 0; x <= win->_maxx; x++) {
+               encode_cell(buffer, CHREF(data[x]), CHREF(last_cell));
+               last_cell = data[x];
+               PUTS(buffer);
+           }
+           PUTS("\n");
+       }
+    }
+#else
+    /*
+     * This is the original putwin():
+     * A straight binary dump is simple, but its format can depend on whether
+     * ncurses is compiled with wide-character support, and also may depend
+     * on the version of ncurses, e.g., if the WINDOW structure is extended.
+     */
     if (win != 0) {
        size_t len = (size_t) (win->_maxx + 1);
 
@@ -148,8 +830,8 @@ putwin(WINDOW *win, FILE *filep)
            || ferror(filep))
              returnCode(code);
 
-       for (n = 0; n <= win->_maxy; n++) {
-           if (fwrite(win->_line[n].text,
+       for (y = 0; y <= win->_maxy; y++) {
+           if (fwrite(win->_line[y].text,
                       sizeof(NCURSES_CH_T), len, filep) != len
                || ferror(filep)) {
                returnCode(code);
@@ -157,6 +839,7 @@ putwin(WINDOW *win, FILE *filep)
        }
        code = OK;
     }
+#endif
     returnCode(code);
 }
 
@@ -164,21 +847,23 @@ NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file)
 {
     FILE *fp = 0;
+    int code = ERR;
 
     T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
 
-    if (_nc_access(file, R_OK) < 0
-       || (fp = fopen(file, "rb")) == 0) {
-       returnCode(ERR);
-    } else {
+    if (_nc_access(file, R_OK) >= 0
+       && (fp = fopen(file, "rb")) != 0) {
        delwin(NewScreen(SP_PARM));
        NewScreen(SP_PARM) = getwin(fp);
 #if !USE_REENTRANT
        newscr = NewScreen(SP_PARM);
 #endif
        (void) fclose(fp);
-       returnCode(OK);
+       if (NewScreen(SP_PARM) != 0) {
+           code = OK;
+       }
     }
+    returnCode(code);
 }
 
 #if NCURSES_SP_FUNCS
@@ -231,7 +916,9 @@ NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file)
            curscr = CurScreen(SP_PARM);
 #endif
            (void) fclose(fp);
-           code = OK;
+           if (CurScreen(SP_PARM) != 0) {
+               code = OK;
+           }
        }
     }
     returnCode(code);
@@ -248,18 +935,21 @@ scr_init(const char *file)
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_set) (NCURSES_SP_DCLx const char *file)
 {
+    int code = ERR;
+
     T((T_CALLED("scr_set(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
 
-    if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == ERR) {
-       returnCode(ERR);
-    } else {
+    if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == OK) {
        delwin(NewScreen(SP_PARM));
        NewScreen(SP_PARM) = dupwin(curscr);
 #if !USE_REENTRANT
        newscr = NewScreen(SP_PARM);
 #endif
-       returnCode(OK);
+       if (NewScreen(SP_PARM) != 0) {
+           code = OK;
+       }
     }
+    returnCode(code);
 }
 
 #if NCURSES_SP_FUNCS
index 1856c656d2e2ce33a133349a6606d9154b903da9..c35d9db2d9aedab2407bb821cfcd26266567faf9 100644 (file)
@@ -1,8 +1,8 @@
-ncurses6 (5.9+20150307) unstable; urgency=low
+ncurses6 (5.9+20150321) unstable; urgency=low
 
   * latest weekly patch
 
- -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 07 Mar 2015 11:12:58 -0500
+ -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 21 Mar 2015 12:25:03 -0400
 
 ncurses6 (5.9-20131005) unstable; urgency=low
 
index 1856c656d2e2ce33a133349a6606d9154b903da9..c35d9db2d9aedab2407bb821cfcd26266567faf9 100644 (file)
@@ -1,8 +1,8 @@
-ncurses6 (5.9+20150307) unstable; urgency=low
+ncurses6 (5.9+20150321) unstable; urgency=low
 
   * latest weekly patch
 
- -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 07 Mar 2015 11:12:58 -0500
+ -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 21 Mar 2015 12:25:03 -0400
 
 ncurses6 (5.9-20131005) unstable; urgency=low
 
index 96cfae7301d757f58a2f4d9cdd8a4d60294ebf75..4de0db5035357ce7bcd8ba2bedf18a4a81edfa03 100644 (file)
@@ -1,8 +1,8 @@
-ncurses6 (5.9+20150307) unstable; urgency=low
+ncurses6 (5.9+20150321) unstable; urgency=low
 
   * latest weekly patch
 
- -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 07 Mar 2015 11:12:58 -0500
+ -- Thomas E. Dickey <dickey@invisible-island.net>  Sat, 21 Mar 2015 12:25:03 -0400
 
 ncurses6 (5.9-20120608) unstable; urgency=low
 
index 5225992930b183f692194599aeeb32d2c3a94be3..2c3dc8bb2f5a3971d9f0a067cd3fc74b46e0ac80 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: mingw-ncurses.nsi,v 1.90 2015/03/07 16:12:58 tom Exp $\r
+; $Id: mingw-ncurses.nsi,v 1.92 2015/03/21 16:25:11 tom Exp $\r
 \r
 ; TODO add examples\r
 ; TODO bump ABI to 6\r
@@ -10,7 +10,7 @@
 !define VERSION_MAJOR "5"\r
 !define VERSION_MINOR "9"\r
 !define VERSION_YYYY  "2015"\r
-!define VERSION_MMDD  "0307"\r
+!define VERSION_MMDD  "0321"\r
 !define VERSION_PATCH ${VERSION_YYYY}${VERSION_MMDD}\r
 \r
 !define MY_ABI   "5"\r
index a02b15ea04f05221cbf1872f994f5ccdcee11700..89896ca8a9f91892ef84c4db94824f39951b9b5b 100644 (file)
@@ -3,7 +3,7 @@
 Summary: shared libraries for terminal handling
 Name: mingw32-ncurses6
 Version: 5.9
-Release: 20150307
+Release: 20150321
 License: X11
 Group: Development/Libraries
 Source: ncurses-%{version}-%{release}.tgz
index 00e1edd9c75785e942795e366a8e08ffa63a16ae..f724253f2e331a3e28be2efcb8b324bc5c9cf960 100644 (file)
@@ -1,7 +1,7 @@
 Summary: shared libraries for terminal handling
 Name: ncurses6
 Version: 5.9
-Release: 20150307
+Release: 20150321
 License: X11
 Group: Development/Libraries
 Source: ncurses-%{version}-%{release}.tgz
index f01acd72109170b94ed9cfa0210e10cbf56e09e2..475b3e6391d140d156a93903d21ca74dfc348ee7 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2013,2015 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            *
@@ -119,7 +119,7 @@ char *ttyname(int fd);
 #include <dump_entry.h>
 #include <transform.h>
 
-MODULE_ID("$Id: tset.c,v 1.93 2013/12/15 01:05:56 tom Exp $")
+MODULE_ID("$Id: tset.c,v 1.94 2015/03/21 16:34:59 tom Exp $")
 
 /*
  * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
@@ -745,7 +745,7 @@ get_termcap_entry(char *userarg)
 #define DISABLED(val)   ((int)(val) <= 0)
 #endif
 
-#define CHK(val, dft)   (DISABLED(val) ? dft : val)
+#define CHK(val, dft)   (unsigned char) (DISABLED(val) ? dft : val)
 
 static bool set_tabs(void);
 
@@ -1305,8 +1305,8 @@ main(int argc, char **argv)
            if (WINSIZE_ROWS(win) == 0 &&
                WINSIZE_COLS(win) == 0 &&
                tlines > 0 && tcolumns > 0) {
-               WINSIZE_ROWS(win) = tlines;
-               WINSIZE_COLS(win) = tcolumns;
+               WINSIZE_ROWS(win) = (unsigned short) tlines;
+               WINSIZE_COLS(win) = (unsigned short) tcolumns;
                (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
            }
        }
index 44d7d1ca1a6b4223b0f1b8faeb8c3ef27210f070..3bdf87108567fca3f617b9115fc960dad1464a6d 100644 (file)
@@ -26,7 +26,7 @@
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: savescreen.c,v 1.21 2015/03/07 21:55:35 tom Exp $
+ * $Id: savescreen.c,v 1.23 2015/03/21 21:35:00 tom Exp $
  *
  * Demonstrate save/restore functions from the curses library.
  * Thomas Dickey - 2007/7/14
@@ -51,6 +51,7 @@
 #endif
 
 static bool use_init = FALSE;
+static bool keep_dumps = FALSE;
 
 static int
 fexists(const char *name)
@@ -71,8 +72,10 @@ cleanup(char *files[])
 {
     int n;
 
-    for (n = 0; files[n] != 0; ++n) {
-       unlink(files[n]);
+    if (!keep_dumps) {
+       for (n = 0; files[n] != 0; ++n) {
+           unlink(files[n]);
+       }
     }
 }
 
@@ -209,6 +212,7 @@ usage(void)
        "",
        "Options:",
        " -i  use scr_init/scr_restore rather than scr_set",
+       " -k  keep the restored dump-files rather than removing them",
        " -r  replay the screen-dump files"
     };
     unsigned n;
@@ -228,11 +232,16 @@ main(int argc, char *argv[])
     bool done = FALSE;
     char **files;
 
-    while ((ch = getopt(argc, argv, "ir")) != -1) {
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "ikr")) != -1) {
        switch (ch) {
        case 'i':
            use_init = TRUE;
            break;
+       case 'k':
+           keep_dumps = TRUE;
+           break;
        case 'r':
            replaying = TRUE;
            break;
@@ -268,7 +277,7 @@ main(int argc, char *argv[])
         */
        for (pair = 0; pair < COLOR_PAIRS; ++pair) {
            color = (short) (pair % (COLORS - 1));
-           init_pair(pair, COLOR_WHITE - color, color);
+           init_pair(pair, (short) (COLOR_WHITE - color), color);
        }
     }