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 /*LINTLIBRARY*/
41 
42 #include	<stdlib.h>
43 #include	<string.h>
44 #include	<sys/types.h>
45 #include	"curses_inc.h"
46 
47 /*
48  * Duplicate a window.
49  *
50  * SS:	calling makenew to allocate a new window is wastefull, since
51  *	makenew initializes all the variables, and then we re-initialize
52  *	the desired values to these variables.
53  */
54 
55 WINDOW	*
dupwin(WINDOW * win)56 dupwin(WINDOW *win)
57 {
58 	WINDOW		*new;
59 	int		i, ncolumns = win->_maxx, nlines = win->_maxy;
60 	size_t		line_size = nlines * sizeof (short);
61 	chtype		**wincp, **newcp;
62 	int		ncolsav = ncolumns;
63 
64 	/* allocate storage for new window and do block copy of */
65 	/* old one into new */
66 
67 	if ((new = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
68 		goto out0;
69 
70 	(void) memcpy(new, win, sizeof (WINDOW));
71 
72 	/* allocate storage for "malloced" fields of the new window */
73 
74 	if ((new->_firstch = (short *)malloc((unsigned)2 * line_size)) == NULL)
75 		goto out1;
76 	else
77 		win->_lastch = win->_firstch + nlines;
78 
79 	if ((new->_y = (chtype **) malloc(nlines * sizeof (chtype *))) ==
80 	    NULL) {
81 	/*
82 	 * We put the free's here rather than after the image call, this
83 	 * is because _image free's all the rest of the malloc'ed areas.
84 	 */
85 		free((char *)new->_firstch);
86 out1:
87 		free((char *)new);
88 		goto out0;
89 	}
90 
91 	if (_image(new) == ERR) {
92 out0:
93 		curs_errno = CURS_BAD_MALLOC;
94 #ifdef	DEBUG
95 		strcpy(curs_parm_err, "dupwin");
96 		curserr();
97 #endif	/* DEBUG */
98 		return ((WINDOW *) NULL);
99 	}
100 
101 	/* copy information from "malloced" areas of the old window into new */
102 
103 	wincp = win->_y;
104 	newcp = new->_y;
105 	for (i = 0; i < nlines; ++i, ++wincp, ++newcp) {
106 		chtype		*ws, *we, *ns, *ne, wc;
107 		int		n;
108 
109 		ws = *wincp;
110 		we = ws + ncolsav - 1;
111 		/* skip partial characters */
112 		for (; ws <= we; ++ws)
113 			if (!ISCBIT(*ws))
114 				break;
115 		for (; we >= ws; --we)
116 			if (!ISCBIT(*we))
117 				break;
118 		if (we >= ws) {
119 			wc = *we;
120 			n = _curs_scrwidth[TYPE(wc)];
121 			if ((we + n) <= (*wincp + ncolsav))
122 				we += n;
123 			ns = *newcp + (ws - *wincp);
124 			ne = *newcp + (we - *wincp);
125 			(void) memcpy((char *)ns, (char *)ws,
126 			    (ne-ns)*sizeof (chtype));
127 		} else
128 			ns = ne = *newcp + ncolsav;
129 		/* fill the rest with background chars */
130 		wc = win->_bkgd;
131 		for (ws = *newcp; ws < ns; ++ws)
132 			*ws = wc;
133 		for (ws = *newcp+ncolsav-1; ws >= ne; --ws)
134 			*ws = wc;
135 	}
136 
137 	(void) memcpy((char *)new->_firstch, (char *)win->_firstch,
138 	    2 * line_size);
139 
140 	new->_flags |= _WINCHANGED;
141 	new->_ndescs = 0;
142 	/*
143 	 * Just like we don't create this window as a subwin if the one
144 	 * sent is, we don't create a padwin.  Besides, if the user
145 	 * calls p*refresh a padwin will be created then.
146 	 */
147 	new->_padwin = new->_parent = (WINDOW *) NULL;
148 	new->_pary = new->_parx = -1;
149 
150 	new->_index = win->_index;
151 	new->_nbyte = win->_nbyte;
152 	new->_insmode = win->_insmode;
153 	(void) memcpy((char *)new->_waitc, (char *)win->_waitc,
154 	    _csmax * sizeof (char));
155 
156 	return (new);
157 }
158