/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1997 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*LINTLIBRARY*/
#include "curses_inc.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
/*
* Initialize the screen image to be the image contained
* in the given file. This is usually used in a child process
* to initialize its idea of the screen image to be that of its
* parent.
*
* filep: pointer to the output stream
* type: 0: <curses> should assume that the physical screen is
* EXACTLY as stored in the file. Therefore, we take
* special care to make sure that /dev/tty and the terminal
* did not change in any way. This information can then
* be used in the update optimization of the new program
* so that the screen does not have to be cleared. Instead,
* curses, by knowing what's on the screen can optimally
* update it with the information of the new program.
*
* 1: Tell <curses> that the stored image should be
* the physical image. Sort of like a huge waddstr onto
* curscr. This can be used when a library wants to save
* a screen image and restore it at a later time.
*
* 2: Tell <curses> that the stored image is the physical
* image and also it is what the new program wants on the
* screen. This can be be thought of as a screen inheritance
* function.
*/
int
scr_reset(FILE *filep, int type)
{
WINDOW *win = NULL, *win1 = NULL;
int *hash, y;
char clearit = FALSE;
short magic;
struct stat statbuf;
time_t ttytime;
if (type != 1 && exit_ca_mode && *exit_ca_mode && non_rev_rmcup) {
if (type == 0)
goto err;
else {
#ifdef DEBUG
if (outf)
fprintf(outf, "clear it because of "
"exit_ca_mode\n");
#endif /* DEBUG */
clearit = TRUE;
}
}
/* check magic number */
if (fread((char *) &magic, sizeof (short), 1, filep) != 1)
goto err;
if (magic != SVR3_DUMP_MAGIC_NUMBER)
goto err;
/* get modification time of image in file */
if (fread((char *) &ttytime, sizeof (time_t), 1, filep) != 1)
goto err;
if ((type != 1) && ((ttyname(cur_term->Filedes) == NULL) ||
(fstat(cur_term->Filedes, &statbuf) < 0) ||
(statbuf.st_mtime != ttytime))) {
if (type == 0)
goto err;
else {
#ifdef DEBUG
if (outf)
fprintf(outf, "Filedes = %hd, "
"statbuf.st_mtime = %d, "
"ttytime = %d\n", cur_term->Filedes,
statbuf.st_mtime, ttytime);
#endif /* DEBUG */
clearit = TRUE;
}
}
/* if get here, everything is ok, read the curscr image */
if (((win = getwin(filep)) == NULL) ||
((type == 2) && ((win1 = dupwin(win)) == NULL)) ||
(win->_maxy != curscr->_maxy) || (win->_maxx != curscr->_maxx) ||
/* soft labels */
(fread((char *) &magic, sizeof (int), 1, filep) != 1))
goto err;
/*
* if soft labels were dumped, we would like either read them
* or advance the file pointer pass them
*/
if (magic) {
short i, labmax, lablen;
SLK_MAP *slk = SP->slk;
/*
* Why doesn't the following line and the two below
* that access those variables work ?
*/
/*
* char **labdis = SP->slk->_ldis, **labval = SP->slk->_lval;
*/
if ((fread((char *) &labmax, sizeof (short), 1, filep) != 1) ||
(fread((char *) &lablen, sizeof (short), 1, filep) != 1)) {
goto err;
}
if (slk != NULL) {
if ((labmax != slk->_num) ||
(lablen != (slk->_len + 1)))
goto err;
for (i = 0; i < labmax; i++) {
/*
* if ((fread(labdis[i], sizeof (char), lablen,
* filep) != lablen) ||
* (fread(labval[i], sizeof (char), lablen,
* filep != lablen))
*/
if ((fread(slk->_ldis[i], sizeof (char),
lablen, filep) != lablen) ||
(fread(slk->_lval[i],
sizeof (char), lablen, filep) != lablen)) {
goto err;
}
}
(*_do_slk_tch)();
} else {
if (fseek(filep, (long) (2 * labmax * lablen *
sizeof (char)), 1) != 0)
goto err;
}
}
/* read the color information(if any) from the file */
if (fread((char *) &magic, sizeof (int), 1, filep) != 1)
goto err;
if (magic) {
int colors, color_pairs;
bool could_change;
int i;
/* if the new terminal doesn't support colors, or it supports */
/* less colors (or color_pairs) than the old terminal, or */
/* start_color() has not been called, simply advance the file */
/* pointer pass the color related info. */
/* Note: must to read the first line of color info, even if the */
/* new terminal doesn't support color, in order to know how to */
/* deal with the rest of the file */
if ((fread((char *) &colors, sizeof (int), 1, filep) != 1) ||
(fread((char *) &color_pairs, sizeof (int), 1,
filep) != 1) || (fread((char *) &could_change,
sizeof (char), 1, filep) != 1))
goto err;
if (max_pairs == -1 || cur_term->_pairs_tbl == NULL ||
colors > max_colors || color_pairs > max_pairs) {
if (fseek(filep, (long) (colors * sizeof (_Color) +
color_pairs * sizeof (_Color_pair)), 1) != 0)
goto err;
} else {
_Color_pair *ptp, *save_ptp;
/* if both old and new terminals could modify colors, read in */
/* color table, and call init_color for each color */
if (could_change) {
if (can_change) {
_Color *ctp, *save_ctp;
if ((save_ctp = (ctp = (_Color *)
malloc(colors *
sizeof (_Color)))) == NULL)
goto err;
if (fread(ctp, sizeof (_Color),
colors, filep) != colors)
goto err;
for (i = 0; i < colors; i++, ctp++) {
/* LINTED */
(void) init_color((short)i,
ctp->r, ctp->g, ctp->b);
}
free(save_ctp);
} else {
/* the old terminal could modify colors, by the new one */
/* cannot skip over color_table info. */
if (fseek(filep, (long) (colors *
sizeof (_Color)), 1) != 0)
goto err;
}
}
/* read color_pairs info. call init_pair for each pair */
if ((save_ptp = (ptp = (_Color_pair *)
malloc(color_pairs * sizeof (_Color_pair)))) ==
NULL)
goto err;
if (fread(ptp, sizeof (_Color_pair), color_pairs,
filep) != color_pairs) {
err:
if (win != NULL)
(void) delwin(win);
if (win1 != NULL)
(void) delwin(win1);
if (type == 0)
curscr->_clear = TRUE;
return (ERR);
}
for (i = 1, ++ptp; i <= color_pairs; i++, ptp++) {
if (ptp->init)
/* LINTED */
(void) init_pair((short)i,
ptp->foreground, ptp->background);
}
free(save_ptp);
}
}
/* substitute read in window for the curscr */
switch (type) {
case 1:
case 2:
(void) delwin(_virtscr);
hash = _VIRTHASH;
if (type == 1) {
SP->virt_scr = _virtscr = win;
_VIRTTOP = 0;
_VIRTBOT = curscr->_maxy - 1;
break;
}
SP->virt_scr = _virtscr = win1;
_VIRTTOP = curscr->_maxy;
_VIRTBOT = -1;
/* clear the hash table */
for (y = curscr->_maxy; y > 0; --y)
*hash++ = _NOHASH;
/* LINTED */ /* Known fall-through on case statement. */
case 0:
{
int saveflag = curscr->_flags & _CANT_BE_IMMED;
(void) delwin(curscr);
SP->cur_scr = curscr = win;
curscr->_sync = TRUE;
curscr->_flags |= saveflag;
hash = _CURHASH;
}
}
/* clear the hash table */
for (y = curscr->_maxy; y > 0; --y)
*hash++ = _NOHASH;
curscr->_clear = clearit;
return (OK);
}