1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*LINTLIBRARY*/
43 
44 #include	<stdlib.h>
45 #include	<string.h>
46 #include	<sys/types.h>
47 #include	"curses_inc.h"
48 
49 /*
50  * Duplicate a window.
51  *
52  * SS:	calling makenew to allocate a new window is wastefull, since
53  *	makenew initializes all the variables, and then we re-initialize
54  *	the desired values to these variables.
55  */
56 
57 WINDOW	*
dupwin(WINDOW * win)58 dupwin(WINDOW *win)
59 {
60 	WINDOW		*new;
61 	int		i, ncolumns = win->_maxx, nlines = win->_maxy;
62 	size_t		line_size = nlines * sizeof (short);
63 	chtype		**wincp, **newcp;
64 	int		ncolsav = ncolumns;
65 
66 	/* allocate storage for new window and do block copy of */
67 	/* old one into new */
68 
69 	if ((new = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
70 		goto out0;
71 
72 	(void) memcpy(new, win, sizeof (WINDOW));
73 
74 	/* allocate storage for "malloced" fields of the new window */
75 
76 	if ((new->_firstch = (short *)malloc((unsigned)2 * line_size)) == NULL)
77 		goto out1;
78 	else
79 		win->_lastch = win->_firstch + nlines;
80 
81 	if ((new->_y = (chtype **) malloc(nlines * sizeof (chtype *))) ==
82 	    NULL) {
83 	/*
84 	 * We put the free's here rather than after the image call, this
85 	 * is because _image free's all the rest of the malloc'ed areas.
86 	 */
87 		free((char *)new->_firstch);
88 out1:
89 		free((char *)new);
90 		goto out0;
91 	}
92 
93 	if (_image(new) == ERR) {
94 out0:
95 		curs_errno = CURS_BAD_MALLOC;
96 #ifdef	DEBUG
97 		strcpy(curs_parm_err, "dupwin");
98 		curserr();
99 #endif	/* DEBUG */
100 		return ((WINDOW *) NULL);
101 	}
102 
103 	/* copy information from "malloced" areas of the old window into new */
104 
105 	wincp = win->_y;
106 	newcp = new->_y;
107 	for (i = 0; i < nlines; ++i, ++wincp, ++newcp) {
108 		chtype		*ws, *we, *ns, *ne, wc;
109 		int		n;
110 
111 		ws = *wincp;
112 		we = ws + ncolsav - 1;
113 		/* skip partial characters */
114 		for (; ws <= we; ++ws)
115 			if (!ISCBIT(*ws))
116 				break;
117 		for (; we >= ws; --we)
118 			if (!ISCBIT(*we))
119 				break;
120 		if (we >= ws) {
121 			wc = *we;
122 			n = _curs_scrwidth[TYPE(wc)];
123 			if ((we + n) <= (*wincp + ncolsav))
124 				we += n;
125 			ns = *newcp + (ws - *wincp);
126 			ne = *newcp + (we - *wincp);
127 			(void) memcpy((char *)ns, (char *)ws,
128 			    (ne-ns)*sizeof (chtype));
129 		} else
130 			ns = ne = *newcp + ncolsav;
131 		/* fill the rest with background chars */
132 		wc = win->_bkgd;
133 		for (ws = *newcp; ws < ns; ++ws)
134 			*ws = wc;
135 		for (ws = *newcp+ncolsav-1; ws >= ne; --ws)
136 			*ws = wc;
137 	}
138 
139 	(void) memcpy((char *)new->_firstch, (char *)win->_firstch,
140 	    2 * line_size);
141 
142 	new->_flags |= _WINCHANGED;
143 	new->_ndescs = 0;
144 	/*
145 	 * Just like we don't create this window as a subwin if the one
146 	 * sent is, we don't create a padwin.  Besides, if the user
147 	 * calls p*refresh a padwin will be created then.
148 	 */
149 	new->_padwin = new->_parent = (WINDOW *) NULL;
150 	new->_pary = new->_parx = -1;
151 
152 	new->_index = win->_index;
153 	new->_nbyte = win->_nbyte;
154 	new->_insmode = win->_insmode;
155 	(void) memcpy((char *)new->_waitc, (char *)win->_waitc,
156 	    _csmax * sizeof (char));
157 
158 	return (new);
159 }
160