You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
319 lines
9.6 KiB
C
319 lines
9.6 KiB
C
/* PDCurses */
|
|
|
|
#include <curspriv.h>
|
|
#include <assert.h>
|
|
|
|
/*man-start**************************************************************
|
|
|
|
scr_dump
|
|
--------
|
|
|
|
### Synopsis
|
|
|
|
int putwin(WINDOW *win, FILE *filep);
|
|
WINDOW *getwin(FILE *filep);
|
|
int scr_dump(const char *filename);
|
|
int scr_init(const char *filename);
|
|
int scr_restore(const char *filename);
|
|
int scr_set(const char *filename);
|
|
|
|
### Description
|
|
|
|
getwin() reads window-related data previously stored in a file by
|
|
putwin(). It then creates and initialises a new window using that
|
|
data.
|
|
|
|
putwin() writes all data associated with a window into a file, using
|
|
an unspecified format. This information can be retrieved later using
|
|
getwin().
|
|
|
|
scr_dump() writes the current contents of the virtual screen to the
|
|
file named by filename in an unspecified format.
|
|
|
|
scr_restore() function sets the virtual screen to the contents of the
|
|
file named by filename, which must have been written using
|
|
scr_dump(). The next refresh operation restores the screen to the way
|
|
it looked in the dump file.
|
|
|
|
In PDCurses, scr_init() does nothing, and scr_set() is a synonym for
|
|
scr_restore(). Also, scr_dump() and scr_restore() save and load from
|
|
curscr. This differs from some other implementations, where
|
|
scr_init() works with curscr, and scr_restore() works with newscr;
|
|
but the effect should be the same. (PDCurses has no newscr.)
|
|
|
|
### Return Value
|
|
|
|
On successful completion, getwin() returns a pointer to the window it
|
|
created. Otherwise, it returns a null pointer. Other functions return
|
|
OK or ERR.
|
|
|
|
### Portability
|
|
X/Open ncurses NetBSD
|
|
putwin Y Y Y
|
|
getwin Y Y Y
|
|
scr_dump Y Y -
|
|
scr_init Y Y -
|
|
scr_restore Y Y -
|
|
scr_set Y Y -
|
|
|
|
**man-end****************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define DUMPVER 2 /* Should be updated whenever the WINDOW struct is
|
|
changed */
|
|
|
|
static void _stuff_chtype_into_eight_bytes( char *buff, const chtype c)
|
|
{
|
|
const chtype text = c & A_CHARTEXT;
|
|
const chtype color_pair = PAIR_NUMBER( c);
|
|
const chtype attribs = (c >> PDC_CHARTEXT_BITS) & (((chtype)1 << PDC_ATTRIBUTE_BITS) - 1);
|
|
const uint32_t x = (uint32_t)text | ((uint32_t)attribs << 21);
|
|
const uint32_t y = ((uint32_t)attribs >> 11) | ((uint32_t)color_pair << 1);
|
|
|
|
memcpy( buff, &x, 4);
|
|
memcpy( buff + 4, &y, 4);
|
|
/* Should reverse these eight bytes on big-Endian machines */
|
|
}
|
|
|
|
static chtype _get_chtype_from_eight_bytes( const char *buff)
|
|
{
|
|
uint32_t x, y;
|
|
chtype c, text, color_pair, attribs;
|
|
|
|
/* Should reverse these eight bytes on big-Endian machines */
|
|
memcpy( &x, buff, 4);
|
|
memcpy( &y, buff + 4, 4);
|
|
text = (chtype)x & A_CHARTEXT;
|
|
attribs = (chtype)( ((x >> 21) & 0xfff) | ((y & 1) << 11));
|
|
color_pair = (chtype)(y >> 1) & 0xfffff;
|
|
c = text | (attribs << PDC_CHARTEXT_BITS) | COLOR_PAIR( color_pair);
|
|
return( (chtype)c);
|
|
}
|
|
|
|
/* In PDCursesMod 4.3.3 and earlier, the on-disk representation of a
|
|
window was entirely binary. A WINDOW struct was written out, and the
|
|
window's chtype data was written out. Portability of these files was
|
|
nearly zero. Alignment and structure packing differences, differences
|
|
in the sizes of ints, bools, and pointers, 32-bit vs. 64-bit
|
|
chtypes and endianness would usually ensure that a file written by one
|
|
program couldn't be read by another.
|
|
|
|
Adding grief to this is the fact that the window structure changed in
|
|
4.3.1. Files written with 4.3.0 and earlier could not be read in
|
|
4.3.1 and later.
|
|
|
|
The window structure is now written out in ASCII, which should help
|
|
with cross-compiler and cross-OS compatibility. chtypes are expanded
|
|
to the 64-bit form on writing and compacted back upon reading. You
|
|
will get scrambled colors and/or attributes if you make a file with
|
|
one program that uses attributes or color pairs beyond the reach of
|
|
the program reading the file. Error checks for this may be added. */
|
|
|
|
static const char *_format_nine_ints = "%d %d %d %d %d %d %d %d %d\n";
|
|
static const char *_format_three_ints = "%d %d %d\n";
|
|
|
|
int putwin(WINDOW *win, FILE *filep)
|
|
{
|
|
char buff[16];
|
|
int y, x;
|
|
|
|
PDC_LOG(("putwin() - called\n"));
|
|
|
|
assert( filep);
|
|
/* write the marker and the WINDOW struct */
|
|
|
|
if( !filep || !fprintf( filep, "%s\n", curses_version( )))
|
|
return( ERR);
|
|
|
|
if( !fprintf( filep, _format_nine_ints,
|
|
DUMPVER, (int)sizeof( WINDOW), win->_cury, win->_curx,
|
|
win->_maxy, win->_maxx, win->_begy, win->_begx, win->_flags))
|
|
return( ERR);
|
|
|
|
if( !fprintf( filep, _format_nine_ints,
|
|
win->_clear, win->_leaveit, win->_scroll, win->_nodelay,
|
|
win->_immed, win->_sync, win->_use_keypad, win->_tmarg, win->_bmarg))
|
|
return( ERR);
|
|
|
|
if( !fprintf( filep, _format_three_ints,
|
|
win->_delayms, win->_parx, win->_pary))
|
|
return( ERR);
|
|
|
|
_stuff_chtype_into_eight_bytes( buff, win->_attrs);
|
|
_stuff_chtype_into_eight_bytes( buff + 8, win->_bkgd);
|
|
if( !fwrite(buff, 16, 1, filep))
|
|
return ERR;
|
|
|
|
for( y = 0; y < win->_maxy && win->_y[y]; y++)
|
|
for( x = 0; x < win->_maxx; x++)
|
|
{
|
|
_stuff_chtype_into_eight_bytes( buff, win->_y[y][x]);
|
|
if( !fwrite(buff, 8, 1, filep))
|
|
return ERR;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
void PDC_add_window_to_list( WINDOW *win);
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable: 4701) /* suppress spurious warnings */
|
|
#endif /* about 'uninitialised' variables */
|
|
|
|
WINDOW *getwin(FILE *filep)
|
|
{
|
|
WINDOW *win, temp_win;
|
|
char buff[80];
|
|
int nlines, y;
|
|
int _clear, _leaveit, _scroll, _nodelay, _immed, _sync, _use_keypad;
|
|
int version, window_size;
|
|
bool failure = FALSE;
|
|
|
|
PDC_LOG(("getwin() - called\n"));
|
|
|
|
assert( filep);
|
|
memset( &temp_win, 0, sizeof( WINDOW));
|
|
|
|
if (!filep || !fgets( buff, sizeof( buff), filep)
|
|
|| strncmp( buff, curses_version( ), 14))
|
|
failure = TRUE;
|
|
else if( !fgets( buff, sizeof( buff), filep)
|
|
|| 9 != sscanf( buff, _format_nine_ints, &version, &window_size,
|
|
&temp_win._cury, &temp_win._curx, &temp_win._maxy, &temp_win._maxx,
|
|
&temp_win._begy, &temp_win._begx, &temp_win._flags)
|
|
|| version != DUMPVER)
|
|
failure = TRUE;
|
|
else if( !fgets( buff, sizeof( buff), filep)
|
|
|| 9 != sscanf( buff, _format_nine_ints, &_clear, &_leaveit,
|
|
&_scroll, &_nodelay, &_immed, &_sync, &_use_keypad,
|
|
&temp_win._tmarg, &temp_win._bmarg))
|
|
failure = TRUE;
|
|
else if( !fgets( buff, sizeof( buff), filep)
|
|
|| 3 != sscanf( buff, _format_three_ints, &temp_win._delayms,
|
|
&temp_win._parx, &temp_win._pary))
|
|
failure = TRUE;
|
|
else if( !fread( buff, 16, 1, filep))
|
|
failure = TRUE;
|
|
|
|
if( failure)
|
|
return (WINDOW *)NULL;
|
|
|
|
win = PDC_makenew( temp_win._maxy, temp_win._maxx, temp_win._begy, temp_win._begx);
|
|
if (!win)
|
|
return (WINDOW *)NULL;
|
|
else
|
|
{
|
|
chtype **saved_y = win->_y;
|
|
int *saved_firstch = win->_firstch;
|
|
int *saved_lastch = win->_lastch;
|
|
|
|
memcpy( win, &temp_win, sizeof( WINDOW));
|
|
win->_y = saved_y;
|
|
win->_firstch = saved_firstch;
|
|
win->_lastch = saved_lastch;
|
|
}
|
|
win->_attrs = _get_chtype_from_eight_bytes( buff);
|
|
win->_bkgd = _get_chtype_from_eight_bytes( buff + 8);
|
|
win->_clear = (bool)_clear;
|
|
win->_leaveit = (bool)_leaveit;
|
|
win->_scroll = (bool)_scroll;
|
|
win->_nodelay = (bool)_nodelay;
|
|
win->_immed = (bool)_immed;
|
|
win->_sync = (bool)_sync;
|
|
win->_use_keypad = (bool)_use_keypad;
|
|
|
|
nlines = win->_maxy;
|
|
|
|
/* allocate the lines */
|
|
|
|
win = PDC_makelines(win);
|
|
if (!win)
|
|
return (WINDOW *)NULL;
|
|
|
|
/* read them */
|
|
|
|
for( y = 0; y < nlines && !failure; y++)
|
|
{
|
|
const int ncols = win->_maxx;
|
|
int x;
|
|
|
|
for( x = 0; x < ncols && !failure; x++)
|
|
{
|
|
if (!fread( buff, 8, 1, filep))
|
|
failure = TRUE;
|
|
else
|
|
win->_y[y][x] = _get_chtype_from_eight_bytes( buff);
|
|
}
|
|
}
|
|
|
|
if( failure)
|
|
{
|
|
delwin(win);
|
|
return (WINDOW *)NULL;
|
|
}
|
|
|
|
touchwin(win);
|
|
PDC_add_window_to_list( win);
|
|
|
|
return win;
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( default: 4701)
|
|
#endif
|
|
|
|
int scr_dump(const char *filename)
|
|
{
|
|
FILE *filep;
|
|
|
|
PDC_LOG(("scr_dump() - called: filename %s\n", filename));
|
|
|
|
if (filename && (filep = fopen(filename, "wb")) != NULL)
|
|
{
|
|
int result = putwin(curscr, filep);
|
|
fclose(filep);
|
|
return result;
|
|
}
|
|
|
|
return ERR;
|
|
}
|
|
|
|
int scr_init(const char *filename)
|
|
{
|
|
PDC_LOG(("scr_init() - called: filename %s\n", filename));
|
|
|
|
INTENTIONALLY_UNUSED_PARAMETER( filename);
|
|
return OK;
|
|
}
|
|
|
|
int scr_restore(const char *filename)
|
|
{
|
|
FILE *filep;
|
|
|
|
PDC_LOG(("scr_restore() - called: filename %s\n", filename));
|
|
|
|
if (filename && (filep = fopen(filename, "rb")) != NULL)
|
|
{
|
|
WINDOW *replacement = getwin(filep);
|
|
fclose(filep);
|
|
|
|
if (replacement)
|
|
{
|
|
int result = overwrite(replacement, curscr);
|
|
delwin(replacement);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return ERR;
|
|
}
|
|
|
|
int scr_set(const char *filename)
|
|
{
|
|
PDC_LOG(("scr_set() - called: filename %s\n", filename));
|
|
|
|
return scr_restore(filename);
|
|
}
|