1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2019,2020 Thomas E. Dickey                                     *
3*32bb5217SDaniel Fojt  * Copyright 1998-2017,2018 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
33fdd4e1e0SJan Lentfer  *     and: Thomas E. Dickey                        1996 on                 *
3400d8f3c4SJohn Marino  *     and: Juergen Pfeifer                         2009                    *
35fdd4e1e0SJan Lentfer  ****************************************************************************/
36fdd4e1e0SJan Lentfer 
37fdd4e1e0SJan Lentfer #include <curses.priv.h>
38fdd4e1e0SJan Lentfer 
393468e90cSJohn Marino #include <ctype.h>
403468e90cSJohn Marino 
4100d8f3c4SJohn Marino #ifndef CUR
4200d8f3c4SJohn Marino #define CUR SP_TERMTYPE
4300d8f3c4SJohn Marino #endif
4400d8f3c4SJohn Marino 
45*32bb5217SDaniel Fojt MODULE_ID("$Id: lib_screen.c,v 1.97 2020/02/02 23:34:34 tom Exp $")
461d102085SJan Lentfer 
471d102085SJan Lentfer #define MAX_SIZE 0x3fff		/* 16k is big enough for a window or pad */
48fdd4e1e0SJan Lentfer 
493468e90cSJohn Marino #define MARKER '\\'
503468e90cSJohn Marino #define APPEND '+'
513468e90cSJohn Marino #define GUTTER '|'
523468e90cSJohn Marino #define L_CURL '{'
533468e90cSJohn Marino #define R_CURL '}'
543468e90cSJohn Marino 
55*32bb5217SDaniel Fojt #if USE_STRING_HACKS && HAVE_SNPRINTF
56*32bb5217SDaniel Fojt #define ARG_SLIMIT(name) size_t name,
57*32bb5217SDaniel Fojt #else
58*32bb5217SDaniel Fojt #define ARG_SLIMIT(name)	/* nothing */
59*32bb5217SDaniel Fojt #endif
60*32bb5217SDaniel Fojt 
61*32bb5217SDaniel Fojt #define CUR_SLIMIT _nc_SLIMIT(limit - (target - base))
62*32bb5217SDaniel Fojt #define TOP_SLIMIT _nc_SLIMIT(sizeof(buffer))
63*32bb5217SDaniel Fojt 
643468e90cSJohn Marino /*
65*32bb5217SDaniel Fojt  * Use 0x888888 as the magic number for new-format files, since it cannot be
663468e90cSJohn Marino  * mistaken for the _cury/_curx pair of 16-bit numbers which start the old
673468e90cSJohn Marino  * format.  It happens to be unused in the file 5.22 database (2015/03/07).
683468e90cSJohn Marino  */
693468e90cSJohn Marino static const char my_magic[] =
703468e90cSJohn Marino {'\210', '\210', '\210', '\210'};
713468e90cSJohn Marino 
723468e90cSJohn Marino #if NCURSES_EXT_PUTWIN
733468e90cSJohn Marino typedef enum {
743468e90cSJohn Marino     pINT			/* int */
753468e90cSJohn Marino     ,pSHORT			/* short */
763468e90cSJohn Marino     ,pBOOL			/* bool */
773468e90cSJohn Marino     ,pATTR			/* attr_t */
783468e90cSJohn Marino     ,pCHAR			/* chtype */
793468e90cSJohn Marino     ,pSIZE			/* NCURSES_SIZE_T */
803468e90cSJohn Marino #if NCURSES_WIDECHAR
813468e90cSJohn Marino     ,pCCHAR			/* cchar_t */
823468e90cSJohn Marino #endif
833468e90cSJohn Marino } PARAM_TYPE;
843468e90cSJohn Marino 
853468e90cSJohn Marino typedef struct {
863468e90cSJohn Marino     const char name[11];
873468e90cSJohn Marino     attr_t attr;
883468e90cSJohn Marino } SCR_ATTRS;
893468e90cSJohn Marino 
903468e90cSJohn Marino typedef struct {
913468e90cSJohn Marino     const char name[17];
923468e90cSJohn Marino     PARAM_TYPE type;
933468e90cSJohn Marino     size_t size;
943468e90cSJohn Marino     size_t offset;
953468e90cSJohn Marino } SCR_PARAMS;
963468e90cSJohn Marino 
973468e90cSJohn Marino #define DATA(name) { { #name }, A_##name }
983468e90cSJohn Marino static const SCR_ATTRS scr_attrs[] =
993468e90cSJohn Marino {
1003468e90cSJohn Marino     DATA(NORMAL),
1013468e90cSJohn Marino     DATA(STANDOUT),
1023468e90cSJohn Marino     DATA(UNDERLINE),
1033468e90cSJohn Marino     DATA(REVERSE),
1043468e90cSJohn Marino     DATA(BLINK),
1053468e90cSJohn Marino     DATA(DIM),
1063468e90cSJohn Marino     DATA(BOLD),
1073468e90cSJohn Marino     DATA(ALTCHARSET),
1083468e90cSJohn Marino     DATA(INVIS),
1093468e90cSJohn Marino     DATA(PROTECT),
1103468e90cSJohn Marino     DATA(HORIZONTAL),
1113468e90cSJohn Marino     DATA(LEFT),
1123468e90cSJohn Marino     DATA(LOW),
1133468e90cSJohn Marino     DATA(RIGHT),
1143468e90cSJohn Marino     DATA(TOP),
1153468e90cSJohn Marino     DATA(VERTICAL),
1163468e90cSJohn Marino 
1173468e90cSJohn Marino #ifdef A_ITALIC
1183468e90cSJohn Marino     DATA(ITALIC),
1193468e90cSJohn Marino #endif
1203468e90cSJohn Marino };
1213468e90cSJohn Marino #undef DATA
1223468e90cSJohn Marino 
1233468e90cSJohn Marino #define sizeof2(type,name) sizeof(((type *)0)->name)
1243468e90cSJohn Marino #define DATA(name, type) { { #name }, type, sizeof2(WINDOW, name), offsetof(WINDOW, name) }
1253468e90cSJohn Marino 
1263468e90cSJohn Marino static const SCR_PARAMS scr_params[] =
1273468e90cSJohn Marino {
1283468e90cSJohn Marino     DATA(_cury, pSIZE),
1293468e90cSJohn Marino     DATA(_curx, pSIZE),
1303468e90cSJohn Marino     DATA(_maxy, pSIZE),
1313468e90cSJohn Marino     DATA(_maxx, pSIZE),
1323468e90cSJohn Marino     DATA(_begy, pSIZE),
1333468e90cSJohn Marino     DATA(_begx, pSIZE),
1343468e90cSJohn Marino     DATA(_flags, pSHORT),
1353468e90cSJohn Marino     DATA(_attrs, pATTR),
1363468e90cSJohn Marino     DATA(_bkgd, pCHAR),
1373468e90cSJohn Marino     DATA(_notimeout, pBOOL),
1383468e90cSJohn Marino     DATA(_clear, pBOOL),
1393468e90cSJohn Marino     DATA(_leaveok, pBOOL),
1403468e90cSJohn Marino     DATA(_scroll, pBOOL),
1413468e90cSJohn Marino     DATA(_idlok, pBOOL),
1423468e90cSJohn Marino     DATA(_idcok, pBOOL),
1433468e90cSJohn Marino     DATA(_immed, pBOOL),
1443468e90cSJohn Marino     DATA(_sync, pBOOL),
1453468e90cSJohn Marino     DATA(_use_keypad, pBOOL),
1463468e90cSJohn Marino     DATA(_delay, pINT),
1473468e90cSJohn Marino     DATA(_regtop, pSIZE),
1483468e90cSJohn Marino     DATA(_regbottom, pSIZE),
1493468e90cSJohn Marino     DATA(_pad._pad_y, pSIZE),
1503468e90cSJohn Marino     DATA(_pad._pad_x, pSIZE),
1513468e90cSJohn Marino     DATA(_pad._pad_top, pSIZE),
1523468e90cSJohn Marino     DATA(_pad._pad_left, pSIZE),
1533468e90cSJohn Marino     DATA(_pad._pad_bottom, pSIZE),
1543468e90cSJohn Marino     DATA(_pad._pad_right, pSIZE),
1553468e90cSJohn Marino     DATA(_yoffset, pSIZE),
1563468e90cSJohn Marino #if NCURSES_WIDECHAR
1573468e90cSJohn Marino     DATA(_bkgrnd, pCCHAR),
1583468e90cSJohn Marino #if NCURSES_EXT_COLORS
1593468e90cSJohn Marino     DATA(_color, pINT),
1603468e90cSJohn Marino #endif
1613468e90cSJohn Marino #endif
1623468e90cSJohn Marino };
1633468e90cSJohn Marino #undef DATA
1643468e90cSJohn Marino 
1653468e90cSJohn Marino static const NCURSES_CH_T blank = NewChar(BLANK_TEXT);
1663468e90cSJohn Marino 
1673468e90cSJohn Marino /*
1683468e90cSJohn Marino  * Allocate and read a line of text.  Caller must free it.
1693468e90cSJohn Marino  */
1703468e90cSJohn Marino static char *
read_txt(FILE * fp)1713468e90cSJohn Marino read_txt(FILE *fp)
1723468e90cSJohn Marino {
1733468e90cSJohn Marino     size_t limit = 1024;
1743468e90cSJohn Marino     char *result = malloc(limit);
1753468e90cSJohn Marino     char *buffer;
1763468e90cSJohn Marino 
1773468e90cSJohn Marino     if (result != 0) {
1783468e90cSJohn Marino 	int ch = 0;
179*32bb5217SDaniel Fojt 	size_t used = 0;
1803468e90cSJohn Marino 
1813468e90cSJohn Marino 	clearerr(fp);
1823468e90cSJohn Marino 	result[used] = '\0';
1833468e90cSJohn Marino 	do {
1843468e90cSJohn Marino 	    if (used + 2 >= limit) {
1853468e90cSJohn Marino 		limit += 1024;
1863468e90cSJohn Marino 		buffer = realloc(result, limit);
1873468e90cSJohn Marino 		if (buffer == 0) {
1883468e90cSJohn Marino 		    free(result);
1893468e90cSJohn Marino 		    result = 0;
1903468e90cSJohn Marino 		    break;
1913468e90cSJohn Marino 		}
1923468e90cSJohn Marino 		result = buffer;
1933468e90cSJohn Marino 	    }
1943468e90cSJohn Marino 	    ch = fgetc(fp);
1953468e90cSJohn Marino 	    if (ch == EOF)
1963468e90cSJohn Marino 		break;
1973468e90cSJohn Marino 	    result[used++] = (char) ch;
1983468e90cSJohn Marino 	    result[used] = '\0';
1993468e90cSJohn Marino 	} while (ch != '\n');
2003468e90cSJohn Marino 
2013468e90cSJohn Marino 	if (ch == '\n') {
2023468e90cSJohn Marino 	    result[--used] = '\0';
2033468e90cSJohn Marino 	    T(("READ:%s", result));
2043468e90cSJohn Marino 	} else if (used == 0) {
2053468e90cSJohn Marino 	    free(result);
2063468e90cSJohn Marino 	    result = 0;
2073468e90cSJohn Marino 	}
2083468e90cSJohn Marino     }
2093468e90cSJohn Marino     return result;
2103468e90cSJohn Marino }
2113468e90cSJohn Marino 
2123468e90cSJohn Marino static char *
decode_attr(char * source,attr_t * target,int * color)2133468e90cSJohn Marino decode_attr(char *source, attr_t *target, int *color)
2143468e90cSJohn Marino {
2153468e90cSJohn Marino     bool found = FALSE;
2163468e90cSJohn Marino 
2173468e90cSJohn Marino     T(("decode_attr   '%s'", source));
2183468e90cSJohn Marino 
2193468e90cSJohn Marino     while (*source) {
2203468e90cSJohn Marino 	if (source[0] == MARKER && source[1] == L_CURL) {
2213468e90cSJohn Marino 	    source += 2;
2223468e90cSJohn Marino 	    found = TRUE;
2233468e90cSJohn Marino 	} else if (source[0] == R_CURL) {
2243468e90cSJohn Marino 	    source++;
2253468e90cSJohn Marino 	    found = FALSE;
2263468e90cSJohn Marino 	} else if (found) {
2273468e90cSJohn Marino 	    size_t n;
2283468e90cSJohn Marino 	    char *next = source;
2293468e90cSJohn Marino 
2303468e90cSJohn Marino 	    if (source[0] == GUTTER) {
2313468e90cSJohn Marino 		++next;
2323468e90cSJohn Marino 	    } else if (*next == 'C') {
2333468e90cSJohn Marino 		int value = 0;
2343468e90cSJohn Marino 		unsigned pair;
2353468e90cSJohn Marino 		next++;
2363468e90cSJohn Marino 		while (isdigit(UChar(*next))) {
2373468e90cSJohn Marino 		    value = value * 10 + (*next++ - '0');
2383468e90cSJohn Marino 		}
2393468e90cSJohn Marino 		*target &= ~A_COLOR;
2403468e90cSJohn Marino 		pair = (unsigned) ((value > 256)
2413468e90cSJohn Marino 				   ? COLOR_PAIR(255)
2423468e90cSJohn Marino 				   : COLOR_PAIR(value));
2433468e90cSJohn Marino 		*target |= pair;
2443468e90cSJohn Marino 		*color = value;
2453468e90cSJohn Marino 	    } else {
2463468e90cSJohn Marino 		while (isalnum(UChar(*next))) {
2473468e90cSJohn Marino 		    ++next;
2483468e90cSJohn Marino 		}
2493468e90cSJohn Marino 		for (n = 0; n < SIZEOF(scr_attrs); ++n) {
2503468e90cSJohn Marino 		    if ((size_t) (next - source) == strlen(scr_attrs[n].name)) {
2513468e90cSJohn Marino 			if (scr_attrs[n].attr) {
2523468e90cSJohn Marino 			    *target |= scr_attrs[n].attr;
2533468e90cSJohn Marino 			} else {
2543468e90cSJohn Marino 			    *target = A_NORMAL;
2553468e90cSJohn Marino 			}
2563468e90cSJohn Marino 			break;
2573468e90cSJohn Marino 		    }
2583468e90cSJohn Marino 		}
2593468e90cSJohn Marino 	    }
2603468e90cSJohn Marino 	    source = next;
2613468e90cSJohn Marino 	} else {
2623468e90cSJohn Marino 	    break;
2633468e90cSJohn Marino 	}
2643468e90cSJohn Marino     }
2653468e90cSJohn Marino     return source;
2663468e90cSJohn Marino }
2673468e90cSJohn Marino 
2683468e90cSJohn Marino static char *
decode_char(char * source,int * target)2693468e90cSJohn Marino decode_char(char *source, int *target)
2703468e90cSJohn Marino {
2713468e90cSJohn Marino     int limit = 0;
2723468e90cSJohn Marino     int base = 16;
2733468e90cSJohn Marino     const char digits[] = "0123456789abcdef";
2743468e90cSJohn Marino 
2753468e90cSJohn Marino     T(("decode_char   '%s'", source));
2763468e90cSJohn Marino     *target = ' ';
2773468e90cSJohn Marino     switch (*source) {
2783468e90cSJohn Marino     case MARKER:
2793468e90cSJohn Marino 	switch (*++source) {
2803468e90cSJohn Marino 	case APPEND:
2813468e90cSJohn Marino 	    break;
2823468e90cSJohn Marino 	case MARKER:
2833468e90cSJohn Marino 	    *target = MARKER;
2843468e90cSJohn Marino 	    ++source;
2853468e90cSJohn Marino 	    break;
2863468e90cSJohn Marino 	case 's':
2873468e90cSJohn Marino 	    *target = ' ';
2883468e90cSJohn Marino 	    ++source;
2893468e90cSJohn Marino 	    break;
2903468e90cSJohn Marino 	case '0':
2913468e90cSJohn Marino 	case '1':
2923468e90cSJohn Marino 	case '2':
2933468e90cSJohn Marino 	case '3':
2943468e90cSJohn Marino 	    base = 8;
2953468e90cSJohn Marino 	    limit = 3;
2963468e90cSJohn Marino 	    break;
2973468e90cSJohn Marino 	case 'u':
2983468e90cSJohn Marino 	    limit = 4;
2993468e90cSJohn Marino 	    ++source;
3003468e90cSJohn Marino 	    break;
3013468e90cSJohn Marino 	case 'U':
3023468e90cSJohn Marino 	    limit = 8;
3033468e90cSJohn Marino 	    ++source;
3043468e90cSJohn Marino 	    break;
3053468e90cSJohn Marino 	}
3063468e90cSJohn Marino 	if (limit) {
3073468e90cSJohn Marino 	    *target = 0;
3083468e90cSJohn Marino 	    while (limit-- > 0) {
3093468e90cSJohn Marino 		char *find = strchr(digits, *source++);
3103468e90cSJohn Marino 		int ch = (find != 0) ? (int) (find - digits) : -1;
3113468e90cSJohn Marino 		*target *= base;
3123468e90cSJohn Marino 		if (ch >= 0 && ch < base) {
3133468e90cSJohn Marino 		    *target += ch;
3143468e90cSJohn Marino 		}
3153468e90cSJohn Marino 	    }
3163468e90cSJohn Marino 	}
3173468e90cSJohn Marino 	break;
3183468e90cSJohn Marino     default:
3193468e90cSJohn Marino 	*target = *source++;
3203468e90cSJohn Marino 	break;
3213468e90cSJohn Marino     }
3223468e90cSJohn Marino     return source;
3233468e90cSJohn Marino }
3243468e90cSJohn Marino 
3253468e90cSJohn Marino static char *
decode_chtype(char * source,chtype fillin,chtype * target)3263468e90cSJohn Marino decode_chtype(char *source, chtype fillin, chtype *target)
3273468e90cSJohn Marino {
3283468e90cSJohn Marino     attr_t attr = ChAttrOf(fillin);
3293468e90cSJohn Marino     int color = PAIR_NUMBER((int) attr);
3303468e90cSJohn Marino     int value;
3313468e90cSJohn Marino 
3323468e90cSJohn Marino     T(("decode_chtype '%s'", source));
3333468e90cSJohn Marino     source = decode_attr(source, &attr, &color);
3343468e90cSJohn Marino     source = decode_char(source, &value);
3353468e90cSJohn Marino     *target = (ChCharOf(value) | attr | (chtype) COLOR_PAIR(color));
3363468e90cSJohn Marino     /* FIXME - ignore combining characters */
3373468e90cSJohn Marino     return source;
3383468e90cSJohn Marino }
3393468e90cSJohn Marino 
3403468e90cSJohn Marino #if NCURSES_WIDECHAR
3413468e90cSJohn Marino static char *
decode_cchar(char * source,cchar_t * fillin,cchar_t * target)3423468e90cSJohn Marino decode_cchar(char *source, cchar_t *fillin, cchar_t *target)
3433468e90cSJohn Marino {
3443468e90cSJohn Marino     int color;
3453468e90cSJohn Marino     attr_t attr = fillin->attr;
3463468e90cSJohn Marino     wchar_t chars[CCHARW_MAX];
3473468e90cSJohn Marino     int append = 0;
3483468e90cSJohn Marino     int value = 0;
3493468e90cSJohn Marino 
3503468e90cSJohn Marino     T(("decode_cchar  '%s'", source));
3513468e90cSJohn Marino     *target = blank;
3523468e90cSJohn Marino #if NCURSES_EXT_COLORS
3533468e90cSJohn Marino     color = fillin->ext_color;
3543468e90cSJohn Marino #else
3553468e90cSJohn Marino     color = (int) PAIR_NUMBER(attr);
3563468e90cSJohn Marino #endif
3573468e90cSJohn Marino     source = decode_attr(source, &attr, &color);
3583468e90cSJohn Marino     memset(chars, 0, sizeof(chars));
3593468e90cSJohn Marino     source = decode_char(source, &value);
3603468e90cSJohn Marino     chars[0] = (wchar_t) value;
3613468e90cSJohn Marino     /* handle combining characters */
3623468e90cSJohn Marino     while (source[0] == MARKER && source[1] == APPEND) {
3633468e90cSJohn Marino 	source += 2;
3643468e90cSJohn Marino 	source = decode_char(source, &value);
3653468e90cSJohn Marino 	if (++append < CCHARW_MAX) {
3663468e90cSJohn Marino 	    chars[append] = (wchar_t) value;
3673468e90cSJohn Marino 	}
3683468e90cSJohn Marino     }
369*32bb5217SDaniel Fojt     setcchar(target, chars, attr, (short) color, &color);
3703468e90cSJohn Marino     return source;
3713468e90cSJohn Marino }
3723468e90cSJohn Marino #endif
3733468e90cSJohn Marino 
3743468e90cSJohn Marino static int
read_win(WINDOW * win,FILE * fp)3753468e90cSJohn Marino read_win(WINDOW *win, FILE *fp)
3763468e90cSJohn Marino {
3773468e90cSJohn Marino     int code = ERR;
3783468e90cSJohn Marino     size_t n;
3793468e90cSJohn Marino     int color;
3803468e90cSJohn Marino #if NCURSES_WIDECHAR
3813468e90cSJohn Marino     NCURSES_CH_T prior;
3823468e90cSJohn Marino #endif
3833468e90cSJohn Marino     chtype prior2;
3843468e90cSJohn Marino 
3853468e90cSJohn Marino     memset(win, 0, sizeof(WINDOW));
3863468e90cSJohn Marino     for (;;) {
387*32bb5217SDaniel Fojt 	char *name;
388*32bb5217SDaniel Fojt 	char *value;
389*32bb5217SDaniel Fojt 	char *txt = read_txt(fp);
390*32bb5217SDaniel Fojt 
3913468e90cSJohn Marino 	if (txt == 0)
3923468e90cSJohn Marino 	    break;
3933468e90cSJohn Marino 	if (!strcmp(txt, "rows:")) {
3943468e90cSJohn Marino 	    free(txt);
3953468e90cSJohn Marino 	    code = OK;
3963468e90cSJohn Marino 	    break;
3973468e90cSJohn Marino 	}
3983468e90cSJohn Marino 	if ((value = strchr(txt, '=')) == 0) {
3993468e90cSJohn Marino 	    free(txt);
4003468e90cSJohn Marino 	    continue;
4013468e90cSJohn Marino 	}
4023468e90cSJohn Marino 	*value++ = '\0';
4033468e90cSJohn Marino 	name = !strcmp(txt, "flag") ? value : txt;
4043468e90cSJohn Marino 	for (n = 0; n < SIZEOF(scr_params); ++n) {
4053468e90cSJohn Marino 	    if (!strcmp(name, scr_params[n].name)) {
4063468e90cSJohn Marino 		void *data = (void *) ((char *) win + scr_params[n].offset);
4073468e90cSJohn Marino 
4083468e90cSJohn Marino 		switch (scr_params[n].type) {
4093468e90cSJohn Marino 		case pATTR:
4103468e90cSJohn Marino 		    (void) decode_attr(value, data, &color);
4113468e90cSJohn Marino 		    break;
4123468e90cSJohn Marino 		case pBOOL:
4133468e90cSJohn Marino 		    *(bool *) data = TRUE;
4143468e90cSJohn Marino 		    break;
4153468e90cSJohn Marino 		case pCHAR:
4163468e90cSJohn Marino 		    prior2 = ' ';
4173468e90cSJohn Marino 		    decode_chtype(value, prior2, data);
4183468e90cSJohn Marino 		    break;
4193468e90cSJohn Marino 		case pINT:
4203468e90cSJohn Marino 		    *(int *) data = atoi(value);
4213468e90cSJohn Marino 		    break;
4223468e90cSJohn Marino 		case pSHORT:
4233468e90cSJohn Marino 		    *(short *) data = (short) atoi(value);
4243468e90cSJohn Marino 		    break;
4253468e90cSJohn Marino 		case pSIZE:
4263468e90cSJohn Marino 		    *(NCURSES_SIZE_T *) data = (NCURSES_SIZE_T) atoi(value);
4273468e90cSJohn Marino 		    break;
4283468e90cSJohn Marino #if NCURSES_WIDECHAR
4293468e90cSJohn Marino 		case pCCHAR:
4303468e90cSJohn Marino 		    prior = blank;
4313468e90cSJohn Marino 		    decode_cchar(value, &prior, data);
4323468e90cSJohn Marino 		    break;
4333468e90cSJohn Marino #endif
4343468e90cSJohn Marino 		}
4353468e90cSJohn Marino 		break;
4363468e90cSJohn Marino 	    }
4373468e90cSJohn Marino 	}
4383468e90cSJohn Marino 	free(txt);
4393468e90cSJohn Marino     }
4403468e90cSJohn Marino     return code;
4413468e90cSJohn Marino }
4423468e90cSJohn Marino 
4433468e90cSJohn Marino static int
read_row(char * source,NCURSES_CH_T * prior,NCURSES_CH_T * target,int length)4443468e90cSJohn Marino read_row(char *source, NCURSES_CH_T * prior, NCURSES_CH_T * target, int length)
4453468e90cSJohn Marino {
4463468e90cSJohn Marino     while (*source != '\0' && length > 0) {
4473468e90cSJohn Marino #if NCURSES_WIDECHAR
448*32bb5217SDaniel Fojt 	int len;
449*32bb5217SDaniel Fojt 
4503468e90cSJohn Marino 	source = decode_cchar(source, prior, target);
451*32bb5217SDaniel Fojt 	len = _nc_wacs_width(target->chars[0]);
4523468e90cSJohn Marino 	if (len > 1) {
453*32bb5217SDaniel Fojt 	    int n;
454*32bb5217SDaniel Fojt 
4553468e90cSJohn Marino 	    SetWidecExt(CHDEREF(target), 0);
4563468e90cSJohn Marino 	    for (n = 1; n < len; ++n) {
4573468e90cSJohn Marino 		target[n] = target[0];
4583468e90cSJohn Marino 		SetWidecExt(CHDEREF(target), n);
4593468e90cSJohn Marino 	    }
4603468e90cSJohn Marino 	    target += (len - 1);
4613468e90cSJohn Marino 	    length -= (len - 1);
4623468e90cSJohn Marino 	}
4633468e90cSJohn Marino #else
4643468e90cSJohn Marino 	source = decode_chtype(source, *prior, target);
4653468e90cSJohn Marino #endif
4663468e90cSJohn Marino 	*prior = *target;
4673468e90cSJohn Marino 	++target;
4683468e90cSJohn Marino 	--length;
4693468e90cSJohn Marino     }
4703468e90cSJohn Marino     while (length-- > 0) {
4713468e90cSJohn Marino 	*target++ = blank;
4723468e90cSJohn Marino     }
4733468e90cSJohn Marino     /* FIXME - see what error conditions should apply if I need to return ERR */
4743468e90cSJohn Marino     return 0;
4753468e90cSJohn Marino }
4763468e90cSJohn Marino #endif /* NCURSES_EXT_PUTWIN */
4773468e90cSJohn Marino 
4783468e90cSJohn Marino /*
4793468e90cSJohn Marino  * Originally, getwin/putwin used fread/fwrite, because they used binary data.
4803468e90cSJohn Marino  * The new format uses printable ASCII, which does not have as predictable
4813468e90cSJohn Marino  * sizes.  Consequently, we use buffered I/O, e.g., fgetc/fprintf, which need
4823468e90cSJohn Marino  * special handling if we want to read screen dumps from an older library.
4833468e90cSJohn Marino  */
4843468e90cSJohn Marino static int
read_block(void * target,size_t length,FILE * fp)4853468e90cSJohn Marino read_block(void *target, size_t length, FILE *fp)
4863468e90cSJohn Marino {
4873468e90cSJohn Marino     int result = 0;
4883468e90cSJohn Marino     char *buffer = target;
4893468e90cSJohn Marino 
4903468e90cSJohn Marino     clearerr(fp);
4913468e90cSJohn Marino     while (length-- != 0) {
4923468e90cSJohn Marino 	int ch = fgetc(fp);
4933468e90cSJohn Marino 	if (ch == EOF) {
4943468e90cSJohn Marino 	    result = -1;
4953468e90cSJohn Marino 	    break;
4963468e90cSJohn Marino 	}
4973468e90cSJohn Marino 	*buffer++ = (char) ch;
4983468e90cSJohn Marino     }
4993468e90cSJohn Marino     return result;
5003468e90cSJohn Marino }
5013468e90cSJohn Marino 
502fdd4e1e0SJan Lentfer NCURSES_EXPORT(WINDOW *)
NCURSES_SP_NAME(getwin)50300d8f3c4SJohn Marino NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep)
504fdd4e1e0SJan Lentfer {
505fdd4e1e0SJan Lentfer     WINDOW tmp, *nwin;
5063468e90cSJohn Marino     bool old_format = FALSE;
507fdd4e1e0SJan Lentfer 
50800d8f3c4SJohn Marino     T((T_CALLED("getwin(%p)"), (void *) filep));
509fdd4e1e0SJan Lentfer 
5103468e90cSJohn Marino     if (filep == 0) {
5113468e90cSJohn Marino 	returnWin(0);
5123468e90cSJohn Marino     }
5133468e90cSJohn Marino 
5143468e90cSJohn Marino     /*
5153468e90cSJohn Marino      * Read the first 4 bytes to determine first if this is an old-format
5163468e90cSJohn Marino      * screen-dump, or new-format.
5173468e90cSJohn Marino      */
518*32bb5217SDaniel Fojt     if (read_block(&tmp, (size_t) 4, filep) < 0) {
5193468e90cSJohn Marino 	returnWin(0);
5203468e90cSJohn Marino     }
5213468e90cSJohn Marino     /*
5223468e90cSJohn Marino      * If this is a new-format file, and we do not support it, give up.
5233468e90cSJohn Marino      */
524*32bb5217SDaniel Fojt     if (!memcmp(&tmp, my_magic, (size_t) 4)) {
5253468e90cSJohn Marino #if NCURSES_EXT_PUTWIN
5263468e90cSJohn Marino 	if (read_win(&tmp, filep) < 0)
5273468e90cSJohn Marino #endif
5283468e90cSJohn Marino 	    returnWin(0);
5293468e90cSJohn Marino     } else if (read_block(((char *) &tmp) + 4, sizeof(WINDOW) - 4, filep) < 0) {
5303468e90cSJohn Marino 	returnWin(0);
5313468e90cSJohn Marino     } else {
5323468e90cSJohn Marino 	old_format = TRUE;
5333468e90cSJohn Marino     }
5343468e90cSJohn Marino 
5353468e90cSJohn Marino     /*
5363468e90cSJohn Marino      * Check the window-size:
5373468e90cSJohn Marino      */
5383468e90cSJohn Marino     if (tmp._maxy == 0 ||
5393468e90cSJohn Marino 	tmp._maxy > MAX_SIZE ||
5403468e90cSJohn Marino 	tmp._maxx == 0 ||
5413468e90cSJohn Marino 	tmp._maxx > MAX_SIZE) {
542fdd4e1e0SJan Lentfer 	returnWin(0);
54300d8f3c4SJohn Marino     }
544fdd4e1e0SJan Lentfer 
545fdd4e1e0SJan Lentfer     if (tmp._flags & _ISPAD) {
54600d8f3c4SJohn Marino 	nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx
54700d8f3c4SJohn Marino 					tmp._maxy + 1,
54800d8f3c4SJohn Marino 					tmp._maxx + 1);
549fdd4e1e0SJan Lentfer     } else {
55000d8f3c4SJohn Marino 	nwin = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
55100d8f3c4SJohn Marino 					tmp._maxy + 1,
55200d8f3c4SJohn Marino 					tmp._maxx + 1, 0, 0);
553fdd4e1e0SJan Lentfer     }
554fdd4e1e0SJan Lentfer 
555fdd4e1e0SJan Lentfer     /*
556fdd4e1e0SJan Lentfer      * We deliberately do not restore the _parx, _pary, or _parent
557fdd4e1e0SJan Lentfer      * fields, because the window hierarchy within which they
558fdd4e1e0SJan Lentfer      * made sense is probably gone.
559fdd4e1e0SJan Lentfer      */
560fdd4e1e0SJan Lentfer     if (nwin != 0) {
561*32bb5217SDaniel Fojt 	int n;
56200d8f3c4SJohn Marino 	size_t linesize = sizeof(NCURSES_CH_T) * (size_t) (tmp._maxx + 1);
56300d8f3c4SJohn Marino 
564fdd4e1e0SJan Lentfer 	nwin->_curx = tmp._curx;
565fdd4e1e0SJan Lentfer 	nwin->_cury = tmp._cury;
566fdd4e1e0SJan Lentfer 	nwin->_maxy = tmp._maxy;
567fdd4e1e0SJan Lentfer 	nwin->_maxx = tmp._maxx;
568fdd4e1e0SJan Lentfer 	nwin->_begy = tmp._begy;
569fdd4e1e0SJan Lentfer 	nwin->_begx = tmp._begx;
570fdd4e1e0SJan Lentfer 	nwin->_yoffset = tmp._yoffset;
571fdd4e1e0SJan Lentfer 	nwin->_flags = tmp._flags & ~(_SUBWIN);
572fdd4e1e0SJan Lentfer 
5731d102085SJan Lentfer 	WINDOW_ATTRS(nwin) = WINDOW_ATTRS(&tmp);
574fdd4e1e0SJan Lentfer 	nwin->_nc_bkgd = tmp._nc_bkgd;
575fdd4e1e0SJan Lentfer 
576fdd4e1e0SJan Lentfer 	nwin->_notimeout = tmp._notimeout;
577fdd4e1e0SJan Lentfer 	nwin->_clear = tmp._clear;
578fdd4e1e0SJan Lentfer 	nwin->_leaveok = tmp._leaveok;
579fdd4e1e0SJan Lentfer 	nwin->_idlok = tmp._idlok;
580fdd4e1e0SJan Lentfer 	nwin->_idcok = tmp._idcok;
581fdd4e1e0SJan Lentfer 	nwin->_immed = tmp._immed;
582fdd4e1e0SJan Lentfer 	nwin->_scroll = tmp._scroll;
583fdd4e1e0SJan Lentfer 	nwin->_sync = tmp._sync;
584fdd4e1e0SJan Lentfer 	nwin->_use_keypad = tmp._use_keypad;
585fdd4e1e0SJan Lentfer 	nwin->_delay = tmp._delay;
586fdd4e1e0SJan Lentfer 
587fdd4e1e0SJan Lentfer 	nwin->_regtop = tmp._regtop;
588fdd4e1e0SJan Lentfer 	nwin->_regbottom = tmp._regbottom;
589fdd4e1e0SJan Lentfer 
590fdd4e1e0SJan Lentfer 	if (tmp._flags & _ISPAD)
591fdd4e1e0SJan Lentfer 	    nwin->_pad = tmp._pad;
592fdd4e1e0SJan Lentfer 
5933468e90cSJohn Marino 	if (old_format) {
5943468e90cSJohn Marino 	    T(("reading old-format screen dump"));
595fdd4e1e0SJan Lentfer 	    for (n = 0; n <= nwin->_maxy; n++) {
5963468e90cSJohn Marino 		if (read_block(nwin->_line[n].text, linesize, filep) < 0) {
597fdd4e1e0SJan Lentfer 		    delwin(nwin);
598fdd4e1e0SJan Lentfer 		    returnWin(0);
599fdd4e1e0SJan Lentfer 		}
600fdd4e1e0SJan Lentfer 	    }
6013468e90cSJohn Marino 	}
6023468e90cSJohn Marino #if NCURSES_EXT_PUTWIN
6033468e90cSJohn Marino 	else {
6043468e90cSJohn Marino 	    char *txt = 0;
6053468e90cSJohn Marino 	    bool success = TRUE;
6063468e90cSJohn Marino 	    NCURSES_CH_T prior = blank;
6073468e90cSJohn Marino 
6083468e90cSJohn Marino 	    T(("reading new-format screen dump"));
6093468e90cSJohn Marino 	    for (n = 0; n <= nwin->_maxy; n++) {
6103468e90cSJohn Marino 		long row;
6113468e90cSJohn Marino 		char *next;
6123468e90cSJohn Marino 
6133468e90cSJohn Marino 		if ((txt = read_txt(filep)) == 0) {
6143468e90cSJohn Marino 		    T(("...failed to read string for row %d", n + 1));
6153468e90cSJohn Marino 		    success = FALSE;
6163468e90cSJohn Marino 		    break;
6173468e90cSJohn Marino 		}
6183468e90cSJohn Marino 		row = strtol(txt, &next, 10);
6193468e90cSJohn Marino 		if (row != (n + 1) || *next != ':') {
6203468e90cSJohn Marino 		    T(("...failed to read row-number %d", n + 1));
6213468e90cSJohn Marino 		    success = FALSE;
6223468e90cSJohn Marino 		    break;
6233468e90cSJohn Marino 		}
6243468e90cSJohn Marino 
6253468e90cSJohn Marino 		if (read_row(++next, &prior, nwin->_line[n].text, tmp._maxx
6263468e90cSJohn Marino 			     + 1) < 0) {
6273468e90cSJohn Marino 		    T(("...failed to read cells for row %d", n + 1));
6283468e90cSJohn Marino 		    success = FALSE;
6293468e90cSJohn Marino 		    break;
6303468e90cSJohn Marino 		}
6313468e90cSJohn Marino 		free(txt);
6323468e90cSJohn Marino 		txt = 0;
6333468e90cSJohn Marino 	    }
6343468e90cSJohn Marino 
6353468e90cSJohn Marino 	    if (!success) {
6363468e90cSJohn Marino 		free(txt);
6373468e90cSJohn Marino 		delwin(nwin);
6383468e90cSJohn Marino 		returnWin(0);
6393468e90cSJohn Marino 	    }
6403468e90cSJohn Marino 	}
6413468e90cSJohn Marino #endif
642fdd4e1e0SJan Lentfer 	touchwin(nwin);
643fdd4e1e0SJan Lentfer     }
644fdd4e1e0SJan Lentfer     returnWin(nwin);
645fdd4e1e0SJan Lentfer }
646fdd4e1e0SJan Lentfer 
64700d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
64800d8f3c4SJohn Marino NCURSES_EXPORT(WINDOW *)
getwin(FILE * filep)64900d8f3c4SJohn Marino getwin(FILE *filep)
65000d8f3c4SJohn Marino {
65100d8f3c4SJohn Marino     return NCURSES_SP_NAME(getwin) (CURRENT_SCREEN, filep);
65200d8f3c4SJohn Marino }
65300d8f3c4SJohn Marino #endif
65400d8f3c4SJohn Marino 
6553468e90cSJohn Marino #if NCURSES_EXT_PUTWIN
6563468e90cSJohn Marino static void
encode_attr(char * target,ARG_SLIMIT (limit)attr_t source,attr_t prior,int source_color,int prior_color)657*32bb5217SDaniel Fojt encode_attr(char *target, ARG_SLIMIT(limit)
658*32bb5217SDaniel Fojt 	    attr_t source,
659*32bb5217SDaniel Fojt 	    attr_t prior,
660*32bb5217SDaniel Fojt 	    int source_color,
661*32bb5217SDaniel Fojt 	    int prior_color)
6623468e90cSJohn Marino {
663*32bb5217SDaniel Fojt #if USE_STRING_HACKS && HAVE_SNPRINTF
664*32bb5217SDaniel Fojt     char *base = target;
665*32bb5217SDaniel Fojt #endif
6663468e90cSJohn Marino     source &= ~A_CHARTEXT;
6673468e90cSJohn Marino     prior &= ~A_CHARTEXT;
6683468e90cSJohn Marino 
6693468e90cSJohn Marino     *target = '\0';
670*32bb5217SDaniel Fojt     if ((source != prior) || (source_color != prior_color)) {
6713468e90cSJohn Marino 	size_t n;
6723468e90cSJohn Marino 	bool first = TRUE;
6733468e90cSJohn Marino 
6743468e90cSJohn Marino 	*target++ = MARKER;
6753468e90cSJohn Marino 	*target++ = L_CURL;
6763468e90cSJohn Marino 
6773468e90cSJohn Marino 	for (n = 0; n < SIZEOF(scr_attrs); ++n) {
6783468e90cSJohn Marino 	    if ((source & scr_attrs[n].attr) != 0 ||
6793468e90cSJohn Marino 		((source & ALL_BUT_COLOR) == 0 &&
6803468e90cSJohn Marino 		 (scr_attrs[n].attr == A_NORMAL))) {
6813468e90cSJohn Marino 		if (first) {
6823468e90cSJohn Marino 		    first = FALSE;
6833468e90cSJohn Marino 		} else {
6843468e90cSJohn Marino 		    *target++ = '|';
6853468e90cSJohn Marino 		}
686*32bb5217SDaniel Fojt 		_nc_STRCPY(target, scr_attrs[n].name, limit);
6873468e90cSJohn Marino 		target += strlen(target);
6883468e90cSJohn Marino 	    }
6893468e90cSJohn Marino 	}
690*32bb5217SDaniel Fojt 	if (source_color != prior_color) {
6913468e90cSJohn Marino 	    if (!first)
6923468e90cSJohn Marino 		*target++ = '|';
693*32bb5217SDaniel Fojt 	    _nc_SPRINTF(target, CUR_SLIMIT "C%d", source_color);
6943468e90cSJohn Marino 	    target += strlen(target);
6953468e90cSJohn Marino 	}
6963468e90cSJohn Marino 
6973468e90cSJohn Marino 	*target++ = R_CURL;
6983468e90cSJohn Marino 	*target = '\0';
6993468e90cSJohn Marino     }
7003468e90cSJohn Marino }
7013468e90cSJohn Marino 
7023468e90cSJohn Marino static void
encode_cell(char * target,ARG_SLIMIT (limit)CARG_CH_T source,CARG_CH_T previous)703*32bb5217SDaniel Fojt encode_cell(char *target, ARG_SLIMIT(limit) CARG_CH_T source, CARG_CH_T previous)
7043468e90cSJohn Marino {
705*32bb5217SDaniel Fojt #if USE_STRING_HACKS && HAVE_SNPRINTF
706*32bb5217SDaniel Fojt     char *base = target;
707*32bb5217SDaniel Fojt #endif
7083468e90cSJohn Marino #if NCURSES_WIDECHAR
7093468e90cSJohn Marino     size_t n;
710*32bb5217SDaniel Fojt     int source_pair = GetPair(*source);
711*32bb5217SDaniel Fojt     int previous_pair = GetPair(*previous);
7123468e90cSJohn Marino 
7133468e90cSJohn Marino     *target = '\0';
714*32bb5217SDaniel Fojt     if ((previous->attr != source->attr) || (previous_pair != source_pair)) {
715*32bb5217SDaniel Fojt 	encode_attr(target, CUR_SLIMIT
716*32bb5217SDaniel Fojt 		    source->attr,
717*32bb5217SDaniel Fojt 		    previous->attr,
718*32bb5217SDaniel Fojt 		    source_pair,
719*32bb5217SDaniel Fojt 		    previous_pair);
7203468e90cSJohn Marino     }
7213468e90cSJohn Marino     target += strlen(target);
7223468e90cSJohn Marino #if NCURSES_EXT_COLORS
7233468e90cSJohn Marino     if (previous->ext_color != source->ext_color) {
724*32bb5217SDaniel Fojt 	_nc_SPRINTF(target, CUR_SLIMIT
725*32bb5217SDaniel Fojt 		    "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL);
7263468e90cSJohn Marino     }
7273468e90cSJohn Marino #endif
7283468e90cSJohn Marino     for (n = 0; n < SIZEOF(source->chars); ++n) {
7293468e90cSJohn Marino 	unsigned uch = (unsigned) source->chars[n];
7303468e90cSJohn Marino 	if (uch == 0)
7313468e90cSJohn Marino 	    continue;
7323468e90cSJohn Marino 	if (n) {
7333468e90cSJohn Marino 	    *target++ = MARKER;
7343468e90cSJohn Marino 	    *target++ = APPEND;
7353468e90cSJohn Marino 	}
7363468e90cSJohn Marino 	*target++ = MARKER;
7373468e90cSJohn Marino 	if (uch > 0xffff) {
738*32bb5217SDaniel Fojt 	    _nc_SPRINTF(target, CUR_SLIMIT "U%08x", uch);
7393468e90cSJohn Marino 	} else if (uch > 0xff) {
740*32bb5217SDaniel Fojt 	    _nc_SPRINTF(target, CUR_SLIMIT "u%04x", uch);
7413468e90cSJohn Marino 	} else if (uch < 32 || uch >= 127) {
742*32bb5217SDaniel Fojt 	    _nc_SPRINTF(target, CUR_SLIMIT "%03o", uch & 0xff);
7433468e90cSJohn Marino 	} else {
7443468e90cSJohn Marino 	    switch (uch) {
7453468e90cSJohn Marino 	    case ' ':
746*32bb5217SDaniel Fojt 		_nc_STRCPY(target, "s", limit);
7473468e90cSJohn Marino 		break;
7483468e90cSJohn Marino 	    case MARKER:
7493468e90cSJohn Marino 		*target++ = MARKER;
7503468e90cSJohn Marino 		*target = '\0';
7513468e90cSJohn Marino 		break;
7523468e90cSJohn Marino 	    default:
753*32bb5217SDaniel Fojt 		--target;
754*32bb5217SDaniel Fojt 		_nc_SPRINTF(target, CUR_SLIMIT "%c", uch);
7553468e90cSJohn Marino 		break;
7563468e90cSJohn Marino 	    }
7573468e90cSJohn Marino 	}
7583468e90cSJohn Marino 	target += strlen(target);
7593468e90cSJohn Marino     }
7603468e90cSJohn Marino #else
7613468e90cSJohn Marino     chtype ch = CharOfD(source);
7623468e90cSJohn Marino 
7633468e90cSJohn Marino     *target = '\0';
7643468e90cSJohn Marino     if (AttrOfD(previous) != AttrOfD(source)) {
765*32bb5217SDaniel Fojt 	encode_attr(target, CUR_SLIMIT
766*32bb5217SDaniel Fojt 		    AttrOfD(source),
767*32bb5217SDaniel Fojt 		    AttrOfD(previous),
768*32bb5217SDaniel Fojt 		    GetPair(source),
769*32bb5217SDaniel Fojt 		    GetPair(previous));
7703468e90cSJohn Marino     }
7713468e90cSJohn Marino     target += strlen(target);
7723468e90cSJohn Marino     *target++ = MARKER;
7733468e90cSJohn Marino     if (ch < 32 || ch >= 127) {
774*32bb5217SDaniel Fojt 	_nc_SPRINTF(target, CUR_SLIMIT "%03o", UChar(ch));
7753468e90cSJohn Marino     } else {
7763468e90cSJohn Marino 	switch (ch) {
7773468e90cSJohn Marino 	case ' ':
778*32bb5217SDaniel Fojt 	    _nc_STRCPY(target, "s", limit);
7793468e90cSJohn Marino 	    break;
7803468e90cSJohn Marino 	case MARKER:
7813468e90cSJohn Marino 	    *target++ = MARKER;
7823468e90cSJohn Marino 	    *target = '\0';
7833468e90cSJohn Marino 	    break;
7843468e90cSJohn Marino 	default:
785*32bb5217SDaniel Fojt 	    --target;
786*32bb5217SDaniel Fojt 	    _nc_SPRINTF(target, CUR_SLIMIT "%c", UChar(ch));
7873468e90cSJohn Marino 	    break;
7883468e90cSJohn Marino 	}
7893468e90cSJohn Marino     }
7903468e90cSJohn Marino #endif
7913468e90cSJohn Marino }
7923468e90cSJohn Marino #endif
7933468e90cSJohn Marino 
794fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
putwin(WINDOW * win,FILE * filep)795fdd4e1e0SJan Lentfer putwin(WINDOW *win, FILE *filep)
796fdd4e1e0SJan Lentfer {
797fdd4e1e0SJan Lentfer     int code = ERR;
798fdd4e1e0SJan Lentfer 
79900d8f3c4SJohn Marino     T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep));
800fdd4e1e0SJan Lentfer 
8013468e90cSJohn Marino #if NCURSES_EXT_PUTWIN
8023468e90cSJohn Marino     if (win != 0) {
8033468e90cSJohn Marino 	const char *version = curses_version();
8043468e90cSJohn Marino 	char buffer[1024];
8053468e90cSJohn Marino 	NCURSES_CH_T last_cell;
806*32bb5217SDaniel Fojt 	int y;
8073468e90cSJohn Marino 
8083468e90cSJohn Marino 	memset(&last_cell, 0, sizeof(last_cell));
8093468e90cSJohn Marino 
8103468e90cSJohn Marino 	clearerr(filep);
8113468e90cSJohn Marino 
8123468e90cSJohn Marino 	/*
8133468e90cSJohn Marino 	 * Our magic number is technically nonprinting, but aside from that,
8143468e90cSJohn Marino 	 * all of the file is printable ASCII.
8153468e90cSJohn Marino 	 */
8163468e90cSJohn Marino #define PUTS(s) if (fputs(s, filep) == EOF || ferror(filep)) returnCode(code)
8173468e90cSJohn Marino 	PUTS(my_magic);
8183468e90cSJohn Marino 	PUTS(version);
8193468e90cSJohn Marino 	PUTS("\n");
8203468e90cSJohn Marino 	for (y = 0; y < (int) SIZEOF(scr_params); ++y) {
8213468e90cSJohn Marino 	    const char *name = scr_params[y].name;
8223468e90cSJohn Marino 	    const char *data = (char *) win + scr_params[y].offset;
8233468e90cSJohn Marino 	    const void *dp = (const void *) data;
824*32bb5217SDaniel Fojt 	    attr_t attr;
8253468e90cSJohn Marino 
8263468e90cSJohn Marino 	    *buffer = '\0';
827*32bb5217SDaniel Fojt 	    if (!strncmp(name, "_pad.", (size_t) 5) && !(win->_flags & _ISPAD)) {
8283468e90cSJohn Marino 		continue;
8293468e90cSJohn Marino 	    }
8303468e90cSJohn Marino 	    switch (scr_params[y].type) {
8313468e90cSJohn Marino 	    case pATTR:
832*32bb5217SDaniel Fojt 		attr = (*(const attr_t *) dp) & ~A_CHARTEXT;
833*32bb5217SDaniel Fojt 		encode_attr(buffer, TOP_SLIMIT
834*32bb5217SDaniel Fojt 			    (*(const attr_t *) dp) & ~A_CHARTEXT,
835*32bb5217SDaniel Fojt 			    A_NORMAL,
836*32bb5217SDaniel Fojt 			    COLOR_PAIR((int) attr),
837*32bb5217SDaniel Fojt 			    0);
8383468e90cSJohn Marino 		break;
8393468e90cSJohn Marino 	    case pBOOL:
8403468e90cSJohn Marino 		if (!(*(const bool *) data)) {
8413468e90cSJohn Marino 		    continue;
8423468e90cSJohn Marino 		}
843*32bb5217SDaniel Fojt 		_nc_STRCPY(buffer, name, sizeof(buffer));
8443468e90cSJohn Marino 		name = "flag";
8453468e90cSJohn Marino 		break;
8463468e90cSJohn Marino 	    case pCHAR:
847*32bb5217SDaniel Fojt 		attr = (*(const attr_t *) dp);
848*32bb5217SDaniel Fojt 		encode_attr(buffer, TOP_SLIMIT
849*32bb5217SDaniel Fojt 			    * (const attr_t *) dp,
850*32bb5217SDaniel Fojt 			    A_NORMAL,
851*32bb5217SDaniel Fojt 			    COLOR_PAIR((int) attr),
852*32bb5217SDaniel Fojt 			    0);
8533468e90cSJohn Marino 		break;
8543468e90cSJohn Marino 	    case pINT:
8553468e90cSJohn Marino 		if (!(*(const int *) dp))
8563468e90cSJohn Marino 		    continue;
857*32bb5217SDaniel Fojt 		_nc_SPRINTF(buffer, TOP_SLIMIT
858*32bb5217SDaniel Fojt 			    "%d", *(const int *) dp);
8593468e90cSJohn Marino 		break;
8603468e90cSJohn Marino 	    case pSHORT:
8613468e90cSJohn Marino 		if (!(*(const short *) dp))
8623468e90cSJohn Marino 		    continue;
863*32bb5217SDaniel Fojt 		_nc_SPRINTF(buffer, TOP_SLIMIT
864*32bb5217SDaniel Fojt 			    "%d", *(const short *) dp);
8653468e90cSJohn Marino 		break;
8663468e90cSJohn Marino 	    case pSIZE:
8673468e90cSJohn Marino 		if (!(*(const NCURSES_SIZE_T *) dp))
8683468e90cSJohn Marino 		    continue;
869*32bb5217SDaniel Fojt 		_nc_SPRINTF(buffer, TOP_SLIMIT
870*32bb5217SDaniel Fojt 			    "%d", *(const NCURSES_SIZE_T *) dp);
8713468e90cSJohn Marino 		break;
8723468e90cSJohn Marino #if NCURSES_WIDECHAR
8733468e90cSJohn Marino 	    case pCCHAR:
874*32bb5217SDaniel Fojt 		encode_cell(buffer, TOP_SLIMIT
875*32bb5217SDaniel Fojt 			    (CARG_CH_T) dp, CHREF(last_cell));
8763468e90cSJohn Marino 		break;
8773468e90cSJohn Marino #endif
8783468e90cSJohn Marino 	    }
8793468e90cSJohn Marino 	    /*
8803468e90cSJohn Marino 	     * Only write non-default data.
8813468e90cSJohn Marino 	     */
8823468e90cSJohn Marino 	    if (*buffer != '\0') {
8833468e90cSJohn Marino 		if (fprintf(filep, "%s=%s\n", name, buffer) <= 0
8843468e90cSJohn Marino 		    || ferror(filep))
8853468e90cSJohn Marino 		    returnCode(code);
8863468e90cSJohn Marino 	    }
8873468e90cSJohn Marino 	}
8883468e90cSJohn Marino 	/* Write row-data */
8893468e90cSJohn Marino 	fprintf(filep, "rows:\n");
8903468e90cSJohn Marino 	for (y = 0; y <= win->_maxy; y++) {
8913468e90cSJohn Marino 	    NCURSES_CH_T *data = win->_line[y].text;
8923468e90cSJohn Marino 	    int x;
8933468e90cSJohn Marino 	    if (fprintf(filep, "%d:", y + 1) <= 0
8943468e90cSJohn Marino 		|| ferror(filep))
8953468e90cSJohn Marino 		returnCode(code);
8963468e90cSJohn Marino 	    for (x = 0; x <= win->_maxx; x++) {
8973468e90cSJohn Marino #if NCURSES_WIDECHAR
898*32bb5217SDaniel Fojt 		int len = _nc_wacs_width(data[x].chars[0]);
899*32bb5217SDaniel Fojt 		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
9003468e90cSJohn Marino 		last_cell = data[x];
9013468e90cSJohn Marino 		PUTS(buffer);
9023468e90cSJohn Marino 		if (len > 1)
9033468e90cSJohn Marino 		    x += (len - 1);
9043468e90cSJohn Marino #else
905*32bb5217SDaniel Fojt 		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
9063468e90cSJohn Marino 		last_cell = data[x];
9073468e90cSJohn Marino 		PUTS(buffer);
9083468e90cSJohn Marino #endif
9093468e90cSJohn Marino 	    }
9103468e90cSJohn Marino 	    PUTS("\n");
9113468e90cSJohn Marino 	}
912*32bb5217SDaniel Fojt 	code = OK;
9133468e90cSJohn Marino     }
9143468e90cSJohn Marino #else
9153468e90cSJohn Marino     /*
9163468e90cSJohn Marino      * This is the original putwin():
9173468e90cSJohn Marino      * A straight binary dump is simple, but its format can depend on whether
9183468e90cSJohn Marino      * ncurses is compiled with wide-character support, and also may depend
9193468e90cSJohn Marino      * on the version of ncurses, e.g., if the WINDOW structure is extended.
9203468e90cSJohn Marino      */
921fdd4e1e0SJan Lentfer     if (win != 0) {
9221d102085SJan Lentfer 	size_t len = (size_t) (win->_maxx + 1);
923*32bb5217SDaniel Fojt 	int y;
924fdd4e1e0SJan Lentfer 
925fdd4e1e0SJan Lentfer 	clearerr(filep);
9263468e90cSJohn Marino 	if (fwrite(win, sizeof(WINDOW), (size_t) 1, filep) != 1
927fdd4e1e0SJan Lentfer 	    || ferror(filep))
928fdd4e1e0SJan Lentfer 	      returnCode(code);
929fdd4e1e0SJan Lentfer 
9303468e90cSJohn Marino 	for (y = 0; y <= win->_maxy; y++) {
9313468e90cSJohn Marino 	    if (fwrite(win->_line[y].text,
932fdd4e1e0SJan Lentfer 		       sizeof(NCURSES_CH_T), len, filep) != len
933fdd4e1e0SJan Lentfer 		|| ferror(filep)) {
934fdd4e1e0SJan Lentfer 		returnCode(code);
935fdd4e1e0SJan Lentfer 	    }
936fdd4e1e0SJan Lentfer 	}
937fdd4e1e0SJan Lentfer 	code = OK;
938fdd4e1e0SJan Lentfer     }
9393468e90cSJohn Marino #endif
940fdd4e1e0SJan Lentfer     returnCode(code);
941fdd4e1e0SJan Lentfer }
942fdd4e1e0SJan Lentfer 
943fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
NCURSES_SP_NAME(scr_restore)94400d8f3c4SJohn Marino NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file)
945fdd4e1e0SJan Lentfer {
946fdd4e1e0SJan Lentfer     FILE *fp = 0;
9473468e90cSJohn Marino     int code = ERR;
948fdd4e1e0SJan Lentfer 
94900d8f3c4SJohn Marino     T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
950fdd4e1e0SJan Lentfer 
9513468e90cSJohn Marino     if (_nc_access(file, R_OK) >= 0
952*32bb5217SDaniel Fojt 	&& (fp = fopen(file, BIN_R)) != 0) {
95300d8f3c4SJohn Marino 	delwin(NewScreen(SP_PARM));
95400d8f3c4SJohn Marino 	NewScreen(SP_PARM) = getwin(fp);
9551d102085SJan Lentfer #if !USE_REENTRANT
95600d8f3c4SJohn Marino 	newscr = NewScreen(SP_PARM);
9571d102085SJan Lentfer #endif
958fdd4e1e0SJan Lentfer 	(void) fclose(fp);
9593468e90cSJohn Marino 	if (NewScreen(SP_PARM) != 0) {
9603468e90cSJohn Marino 	    code = OK;
961fdd4e1e0SJan Lentfer 	}
962fdd4e1e0SJan Lentfer     }
9633468e90cSJohn Marino     returnCode(code);
9643468e90cSJohn Marino }
965fdd4e1e0SJan Lentfer 
96600d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
96700d8f3c4SJohn Marino NCURSES_EXPORT(int)
scr_restore(const char * file)96800d8f3c4SJohn Marino scr_restore(const char *file)
96900d8f3c4SJohn Marino {
97000d8f3c4SJohn Marino     return NCURSES_SP_NAME(scr_restore) (CURRENT_SCREEN, file);
97100d8f3c4SJohn Marino }
97200d8f3c4SJohn Marino #endif
97300d8f3c4SJohn Marino 
974fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
scr_dump(const char * file)975fdd4e1e0SJan Lentfer scr_dump(const char *file)
976fdd4e1e0SJan Lentfer {
9773468e90cSJohn Marino     int result;
978fdd4e1e0SJan Lentfer     FILE *fp = 0;
979fdd4e1e0SJan Lentfer 
980fdd4e1e0SJan Lentfer     T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file)));
981fdd4e1e0SJan Lentfer 
982fdd4e1e0SJan Lentfer     if (_nc_access(file, W_OK) < 0
983*32bb5217SDaniel Fojt 	|| (fp = fopen(file, BIN_W)) == 0) {
9843468e90cSJohn Marino 	result = ERR;
985fdd4e1e0SJan Lentfer     } else {
986fdd4e1e0SJan Lentfer 	(void) putwin(newscr, fp);
987fdd4e1e0SJan Lentfer 	(void) fclose(fp);
9883468e90cSJohn Marino 	result = OK;
989fdd4e1e0SJan Lentfer     }
9903468e90cSJohn Marino     returnCode(result);
991fdd4e1e0SJan Lentfer }
992fdd4e1e0SJan Lentfer 
993fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
NCURSES_SP_NAME(scr_init)99400d8f3c4SJohn Marino NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file)
995fdd4e1e0SJan Lentfer {
99600d8f3c4SJohn Marino     int code = ERR;
997fdd4e1e0SJan Lentfer 
99800d8f3c4SJohn Marino     T((T_CALLED("scr_init(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
999fdd4e1e0SJan Lentfer 
100000d8f3c4SJohn Marino     if (SP_PARM != 0 &&
100100d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
100200d8f3c4SJohn Marino 	InfoOf(SP_PARM).caninit
100300d8f3c4SJohn Marino #else
100400d8f3c4SJohn Marino 	!(exit_ca_mode && non_rev_rmcup)
100500d8f3c4SJohn Marino #endif
100600d8f3c4SJohn Marino 	) {
1007*32bb5217SDaniel Fojt 	FILE *fp = 0;
1008*32bb5217SDaniel Fojt 
100900d8f3c4SJohn Marino 	if (_nc_access(file, R_OK) >= 0
1010*32bb5217SDaniel Fojt 	    && (fp = fopen(file, BIN_R)) != 0) {
101100d8f3c4SJohn Marino 	    delwin(CurScreen(SP_PARM));
101200d8f3c4SJohn Marino 	    CurScreen(SP_PARM) = getwin(fp);
10131d102085SJan Lentfer #if !USE_REENTRANT
101400d8f3c4SJohn Marino 	    curscr = CurScreen(SP_PARM);
10151d102085SJan Lentfer #endif
1016fdd4e1e0SJan Lentfer 	    (void) fclose(fp);
10173468e90cSJohn Marino 	    if (CurScreen(SP_PARM) != 0) {
101800d8f3c4SJohn Marino 		code = OK;
101900d8f3c4SJohn Marino 	    }
102000d8f3c4SJohn Marino 	}
10213468e90cSJohn Marino     }
102200d8f3c4SJohn Marino     returnCode(code);
102300d8f3c4SJohn Marino }
102400d8f3c4SJohn Marino 
102500d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
102600d8f3c4SJohn Marino NCURSES_EXPORT(int)
scr_init(const char * file)102700d8f3c4SJohn Marino scr_init(const char *file)
102800d8f3c4SJohn Marino {
102900d8f3c4SJohn Marino     return NCURSES_SP_NAME(scr_init) (CURRENT_SCREEN, file);
103000d8f3c4SJohn Marino }
103100d8f3c4SJohn Marino #endif
103200d8f3c4SJohn Marino 
103300d8f3c4SJohn Marino NCURSES_EXPORT(int)
NCURSES_SP_NAME(scr_set)103400d8f3c4SJohn Marino NCURSES_SP_NAME(scr_set) (NCURSES_SP_DCLx const char *file)
103500d8f3c4SJohn Marino {
10363468e90cSJohn Marino     int code = ERR;
10373468e90cSJohn Marino 
103800d8f3c4SJohn Marino     T((T_CALLED("scr_set(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
103900d8f3c4SJohn Marino 
10403468e90cSJohn Marino     if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == OK) {
104100d8f3c4SJohn Marino 	delwin(NewScreen(SP_PARM));
104200d8f3c4SJohn Marino 	NewScreen(SP_PARM) = dupwin(curscr);
104300d8f3c4SJohn Marino #if !USE_REENTRANT
104400d8f3c4SJohn Marino 	newscr = NewScreen(SP_PARM);
104500d8f3c4SJohn Marino #endif
10463468e90cSJohn Marino 	if (NewScreen(SP_PARM) != 0) {
10473468e90cSJohn Marino 	    code = OK;
1048fdd4e1e0SJan Lentfer 	}
1049fdd4e1e0SJan Lentfer     }
10503468e90cSJohn Marino     returnCode(code);
10513468e90cSJohn Marino }
1052fdd4e1e0SJan Lentfer 
105300d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
1054fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
scr_set(const char * file)1055fdd4e1e0SJan Lentfer scr_set(const char *file)
1056fdd4e1e0SJan Lentfer {
105700d8f3c4SJohn Marino     return NCURSES_SP_NAME(scr_set) (CURRENT_SCREEN, file);
105800d8f3c4SJohn Marino }
10591d102085SJan Lentfer #endif
1060