root/usr/src/lib/libcurses/screen/dupwin.c
/*
 * 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.
 */

/*LINTLIBRARY*/

#include        <stdlib.h>
#include        <string.h>
#include        <sys/types.h>
#include        "curses_inc.h"

/*
 * Duplicate a window.
 *
 * SS:  calling makenew to allocate a new window is wastefull, since
 *      makenew initializes all the variables, and then we re-initialize
 *      the desired values to these variables.
 */

WINDOW  *
dupwin(WINDOW *win)
{
        WINDOW          *new;
        int             i, ncolumns = win->_maxx, nlines = win->_maxy;
        size_t          line_size = nlines * sizeof (short);
        chtype          **wincp, **newcp;
        int             ncolsav = ncolumns;

        /* allocate storage for new window and do block copy of */
        /* old one into new */

        if ((new = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
                goto out0;

        (void) memcpy(new, win, sizeof (WINDOW));

        /* allocate storage for "malloced" fields of the new window */

        if ((new->_firstch = (short *)malloc((unsigned)2 * line_size)) == NULL)
                goto out1;
        else
                win->_lastch = win->_firstch + nlines;

        if ((new->_y = (chtype **) malloc(nlines * sizeof (chtype *))) ==
            NULL) {
        /*
         * We put the free's here rather than after the image call, this
         * is because _image free's all the rest of the malloc'ed areas.
         */
                free((char *)new->_firstch);
out1:
                free((char *)new);
                goto out0;
        }

        if (_image(new) == ERR) {
out0:
                curs_errno = CURS_BAD_MALLOC;
#ifdef  DEBUG
                strcpy(curs_parm_err, "dupwin");
                curserr();
#endif  /* DEBUG */
                return ((WINDOW *) NULL);
        }

        /* copy information from "malloced" areas of the old window into new */

        wincp = win->_y;
        newcp = new->_y;
        for (i = 0; i < nlines; ++i, ++wincp, ++newcp) {
                chtype          *ws, *we, *ns, *ne, wc;
                int             n;

                ws = *wincp;
                we = ws + ncolsav - 1;
                /* skip partial characters */
                for (; ws <= we; ++ws)
                        if (!ISCBIT(*ws))
                                break;
                for (; we >= ws; --we)
                        if (!ISCBIT(*we))
                                break;
                if (we >= ws) {
                        wc = *we;
                        n = _curs_scrwidth[TYPE(wc)];
                        if ((we + n) <= (*wincp + ncolsav))
                                we += n;
                        ns = *newcp + (ws - *wincp);
                        ne = *newcp + (we - *wincp);
                        (void) memcpy((char *)ns, (char *)ws,
                            (ne-ns)*sizeof (chtype));
                } else
                        ns = ne = *newcp + ncolsav;
                /* fill the rest with background chars */
                wc = win->_bkgd;
                for (ws = *newcp; ws < ns; ++ws)
                        *ws = wc;
                for (ws = *newcp+ncolsav-1; ws >= ne; --ws)
                        *ws = wc;
        }

        (void) memcpy((char *)new->_firstch, (char *)win->_firstch,
            2 * line_size);

        new->_flags |= _WINCHANGED;
        new->_ndescs = 0;
        /*
         * Just like we don't create this window as a subwin if the one
         * sent is, we don't create a padwin.  Besides, if the user
         * calls p*refresh a padwin will be created then.
         */
        new->_padwin = new->_parent = (WINDOW *) NULL;
        new->_pary = new->_parx = -1;

        new->_index = win->_index;
        new->_nbyte = win->_nbyte;
        new->_insmode = win->_insmode;
        (void) memcpy((char *)new->_waitc, (char *)win->_waitc,
            _csmax * sizeof (char));

        return (new);
}