xref: /netbsd-src/lib/libcurses/border.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: border.c,v 1.10 2007/05/28 15:01:54 blymn Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Julian Coleman.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __RCSID("$NetBSD: border.c,v 1.10 2007/05/28 15:01:54 blymn Exp $");
42 #endif				/* not lint */
43 
44 #include <stdlib.h>
45 #include <string.h>
46 
47 #include "curses.h"
48 #include "curses_private.h"
49 
50 #ifndef _CURSES_USE_MACROS
51 
52 /*
53  * border --
54  *	Draw a border around stdscr using the specified
55  *	delimiting characters.
56  */
57 int
58 border(chtype left, chtype right, chtype top, chtype bottom, chtype topleft,
59        chtype topright, chtype botleft, chtype botright)
60 {
61 	return wborder(stdscr, left, right, top, bottom, topleft, topright,
62 	    botleft, botright);
63 }
64 
65 #endif
66 
67 /*
68  * wborder --
69  *	Draw a border around the given window using the specified delimiting
70  *	characters.
71  */
72 int
73 wborder(WINDOW *win, chtype left, chtype right, chtype top, chtype bottom,
74 	chtype topleft, chtype topright, chtype botleft, chtype botright)
75 {
76 	int	 endy, endx, i;
77 	__LDATA	*fp, *lp;
78 
79 	if (!(left & __CHARTEXT))
80 		left |= ACS_VLINE;
81 	if (!(right & __CHARTEXT))
82 		right |= ACS_VLINE;
83 	if (!(top & __CHARTEXT))
84 		top |= ACS_HLINE;
85 	if (!(bottom & __CHARTEXT))
86 		bottom |= ACS_HLINE;
87 	if (!(topleft & __CHARTEXT))
88 		topleft |= ACS_ULCORNER;
89 	if (!(topright & __CHARTEXT))
90 		topright |= ACS_URCORNER;
91 	if (!(botleft & __CHARTEXT))
92 		botleft |= ACS_LLCORNER;
93 	if (!(botright & __CHARTEXT))
94 		botright |= ACS_LRCORNER;
95 
96 #ifdef DEBUG
97 	__CTRACE(__CTRACE_INPUT, "wborder: left = %c, 0x%x\n",
98 	    left & __CHARTEXT, left & __ATTRIBUTES);
99 	__CTRACE(__CTRACE_INPUT, "wborder: right = %c, 0x%x\n",
100 	    right & __CHARTEXT, right & __ATTRIBUTES);
101 	__CTRACE(__CTRACE_INPUT, "wborder: top = %c, 0x%x\n",
102 	    top & __CHARTEXT, top & __ATTRIBUTES);
103 	__CTRACE(__CTRACE_INPUT, "wborder: bottom = %c, 0x%x\n",
104 	    bottom & __CHARTEXT, bottom & __ATTRIBUTES);
105 	__CTRACE(__CTRACE_INPUT, "wborder: topleft = %c, 0x%x\n",
106 	    topleft & __CHARTEXT, topleft & __ATTRIBUTES);
107 	__CTRACE(__CTRACE_INPUT, "wborder: topright = %c, 0x%x\n",
108 	    topright & __CHARTEXT, topright & __ATTRIBUTES);
109 	__CTRACE(__CTRACE_INPUT, "wborder: botleft = %c, 0x%x\n",
110 	    botleft & __CHARTEXT, botleft & __ATTRIBUTES);
111 	__CTRACE(__CTRACE_INPUT, "wborder: botright = %c, 0x%x\n",
112 	    botright & __CHARTEXT, botright & __ATTRIBUTES);
113 #endif
114 
115 	/* Merge window and background attributes */
116 	left |= (left & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
117 	left |= (left & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
118 	right |= (right & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
119 	right |= (right & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
120 	top |= (top & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
121 	top |= (top & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
122 	bottom |= (bottom & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
123 	bottom |= (bottom & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
124 	topleft |= (topleft & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
125 	topleft |= (topleft & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
126 	topright |= (topright & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
127 	topright |= (topright & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
128 	botleft |= (botleft & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
129 	botleft |= (botleft & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
130 	botright |= (botright & __COLOR) ? (win->wattr & ~__COLOR) : win->wattr;
131 	botright |= (botright & __COLOR) ? (win->battr & ~__COLOR) : win->battr;
132 
133 	endx = win->maxx - 1;
134 	endy = win->maxy - 1;
135 	fp = win->lines[0]->line;
136 	lp = win->lines[endy]->line;
137 
138 	/* Sides */
139 	for (i = 1; i < endy; i++) {
140 		win->lines[i]->line[0].ch = (wchar_t) left & __CHARTEXT;
141 		win->lines[i]->line[0].attr = (attr_t) left & __ATTRIBUTES;
142 		win->lines[i]->line[endx].ch = (wchar_t) right & __CHARTEXT;
143 		win->lines[i]->line[endx].attr = (attr_t) right & __ATTRIBUTES;
144 #ifdef HAVE_WCHAR
145 		SET_WCOL(win->lines[i]->line[0], 1);
146 		SET_WCOL(win->lines[i]->line[endx], 1);
147 #endif
148 	}
149 	for (i = 1; i < endx; i++) {
150 		fp[i].ch = (wchar_t) top & __CHARTEXT;
151 		fp[i].attr = (attr_t) top & __ATTRIBUTES;
152 		lp[i].ch = (wchar_t) bottom & __CHARTEXT;
153 		lp[i].attr = (attr_t) bottom & __ATTRIBUTES;
154 #ifdef HAVE_WCHAR
155 		SET_WCOL(fp[i], 1);
156 		SET_WCOL(lp[i], 1);
157 #endif
158 	}
159 
160 	/* Corners */
161 	if (!(win->maxx == LINES && win->maxy == COLS &&
162 	    (win->flags & __SCROLLOK) && (win->flags & __SCROLLWIN))) {
163 		fp[0].ch = (wchar_t) topleft & __CHARTEXT;
164 		fp[0].attr = (attr_t) topleft & __ATTRIBUTES;
165 		fp[endx].ch = (wchar_t) topright & __CHARTEXT;
166 		fp[endx].attr = (attr_t) topright & __ATTRIBUTES;
167 		lp[0].ch = (wchar_t) botleft & __CHARTEXT;
168 		lp[0].attr = (attr_t) botleft & __ATTRIBUTES;
169 		lp[endx].ch = (wchar_t) botright & __CHARTEXT;
170 		lp[endx].attr = (attr_t) botright & __ATTRIBUTES;
171 #ifdef HAVE_WCHAR
172 		SET_WCOL(fp[0], 1);
173 		SET_WCOL(fp[endx], 1);
174 		SET_WCOL(lp[0], 1);
175 		SET_WCOL(lp[endx], 1);
176 #endif
177 	}
178 	__touchwin(win);
179 	return (OK);
180 }
181 
182 int border_set(const cchar_t *ls, const cchar_t *rs, const cchar_t *ts,
183 	   const cchar_t *bs, const cchar_t *tl, const cchar_t *tr,
184 	   const cchar_t *bl, const cchar_t *br)
185 {
186 #ifndef HAVE_WCHAR
187 	return ERR;
188 #else
189 	return wborder_set(stdscr, ls, rs, ts, bs, tl, tr, bl, br);
190 #endif /* HAVE_WCHAR */
191 }
192 
193 int wborder_set(WINDOW *win, const cchar_t *ls, const cchar_t *rs,
194 		const cchar_t *ts, const cchar_t *bs,
195 		const cchar_t *tl, const cchar_t *tr,
196 		const cchar_t *bl, const cchar_t *br)
197 {
198 #ifndef HAVE_WCHAR
199 	return ERR;
200 #else
201 	int	 endy, endx, i, j, k, cw, pcw, tlcw, blcw, trcw, brcw;
202 	cchar_t left, right, bottom, top, topleft, topright, botleft, botright;
203 	nschar_t *np, *tnp;
204 
205 	if ( ls && wcwidth( ls->vals[ 0 ]))
206 		memcpy( &left, ls, sizeof( cchar_t ));
207 	else
208 		setcchar( &left, &WACS_VLINE, win->wattr, 0, NULL );
209 	if ( rs && wcwidth( rs->vals[ 0 ]))
210 		memcpy( &right, rs, sizeof( cchar_t ));
211 	else
212 		setcchar( &right, &WACS_VLINE, win->wattr, 0, NULL );
213 	if ( ts && wcwidth( ts->vals[ 0 ]))
214 		memcpy( &top, ts, sizeof( cchar_t ));
215 	else
216 		setcchar( &top, &WACS_HLINE, win->wattr, 0, NULL );
217 	if ( bs && wcwidth( bs->vals[ 0 ]))
218 		memcpy( &bottom, bs, sizeof( cchar_t ));
219 	else
220 		setcchar( &bottom, &WACS_HLINE, win->wattr, 0, NULL );
221 	if ( tl && wcwidth( tl->vals[ 0 ]))
222 		memcpy( &topleft, tl, sizeof( cchar_t ));
223 	else
224 		setcchar( &topleft, &WACS_ULCORNER, win->wattr, 0, NULL );
225 	if ( tr && wcwidth( tr->vals[ 0 ]))
226 		memcpy( &topright, tr, sizeof( cchar_t ));
227 	else
228 		setcchar( &topright, &WACS_URCORNER, win->wattr, 0, NULL );
229 	if ( bl && wcwidth( bl->vals[ 0 ]))
230 		memcpy( &botleft, bl, sizeof( cchar_t ));
231 	else
232 		setcchar( &botleft, &WACS_LLCORNER, win->wattr, 0, NULL );
233 	if ( br && wcwidth( br->vals[ 0 ]))
234 		memcpy( &botright, br, sizeof( cchar_t ));
235 	else
236 		setcchar( &botright, &WACS_LRCORNER, win->wattr, 0, NULL );
237 
238 #ifdef DEBUG
239 	__CTRACE(__CTRACE_INPUT, "wborder_set: left = %c, 0x%x\n",
240 	    left.vals[0], left.attributes );
241 	__CTRACE(__CTRACE_INPUT, "wborder_set: right = %c, 0x%x\n",
242 	    right.vals[0], right.attributes );
243 	__CTRACE(__CTRACE_INPUT, "wborder_set: top = %c, 0x%x\n",
244 	    top.vals[0], top.attributes );
245 	__CTRACE(__CTRACE_INPUT, "wborder_set: bottom = %c, 0x%x\n",
246 	    bottom.vals[0], bottom.attributes );
247 	__CTRACE(__CTRACE_INPUT, "wborder_set: topleft = %c, 0x%x\n",
248 	    topleft.vals[0], topleft.attributes );
249 	__CTRACE(__CTRACE_INPUT, "wborder_set: topright = %c, 0x%x\n",
250 	    topright.vals[0], topright.attributes );
251 	__CTRACE(__CTRACE_INPUT, "wborder_set: botleft = %c, 0x%x\n",
252 	    botleft.vals[0], botleft.attributes );
253 	__CTRACE(__CTRACE_INPUT, "wborder_set: botright = %c, 0x%x\n",
254 	    botright.vals[0], botright.attributes );
255 #endif
256 
257 	/* Merge window attributes */
258 	left.attributes |= (left.attributes & __COLOR) ?
259 		(win->wattr & ~__COLOR) : win->wattr;
260 	right.attributes |= (right.attributes & __COLOR) ?
261 		(win->wattr & ~__COLOR) : win->wattr;
262 	top.attributes |= (top.attributes & __COLOR) ?
263 		(win->wattr & ~__COLOR) : win->wattr;
264 	bottom.attributes |= (bottom.attributes & __COLOR) ?
265 		(win->wattr & ~__COLOR) : win->wattr;
266 	topleft.attributes |= (topleft.attributes & __COLOR) ?
267 		(win->wattr & ~__COLOR) : win->wattr;
268 	topright.attributes |= (topright.attributes & __COLOR) ?
269 		(win->wattr & ~__COLOR) : win->wattr;
270 	botleft.attributes |= (botleft.attributes & __COLOR) ?
271 		(win->wattr & ~__COLOR) : win->wattr;
272 	botright.attributes |= (botright.attributes & __COLOR) ?
273 		(win->wattr & ~__COLOR) : win->wattr;
274 
275 	endx = win->maxx - 1;
276 	endy = win->maxy - 1;
277 
278 	/* Sides */
279 	for (i = 1; i < endy; i++) {
280 		/* left border */
281 		cw = wcwidth( left.vals[ 0 ]);
282 		for ( j = 0; j < cw; j++ ) {
283 			win->lines[i]->line[j].ch = left.vals[ 0 ];
284 			win->lines[i]->line[j].attr = left.attributes;
285 			np = win->lines[i]->line[j].nsp;
286 			if (np) {
287 				while ( np ) {
288 					tnp = np->next;
289 					free( np );
290 					np = tnp;
291 				}
292 				win->lines[i]->line[j].nsp = NULL;
293 			}
294 			if ( j )
295 				SET_WCOL( win->lines[i]->line[j], -j );
296 			else {
297 				SET_WCOL( win->lines[i]->line[j], cw );
298 				if ( left.elements > 1 ) {
299 					for (k = 1; k < left.elements; k++) {
300 						np = (nschar_t *)malloc(sizeof(nschar_t));
301 						if (!np)
302 							return ERR;
303 						np->ch = left.vals[ k ];
304 						np->next = win->lines[i]->line[j].nsp;
305 						win->lines[i]->line[j].nsp
306 							= np;
307 					}
308 				}
309 			}
310 		}
311 		for ( j = cw; WCOL( win->lines[i]->line[j]) < 0; j++ ) {
312 #ifdef DEBUG
313 			__CTRACE(__CTRACE_INPUT,
314 			    "wborder_set: clean out partial char[%d]", j);
315 #endif /* DEBUG */
316 			win->lines[i]->line[j].ch = ( wchar_t )btowc(win->bch);
317 			if (_cursesi_copy_nsp(win->bnsp,
318 					      &win->lines[i]->line[j]) == ERR)
319 				return ERR;
320 			SET_WCOL( win->lines[i]->line[j], 1 );
321 		}
322 		/* right border */
323 		cw = wcwidth( right.vals[ 0 ]);
324 		pcw = WCOL( win->lines[i]->line[endx - cw]);
325 		for ( j = endx - cw + 1; j <= endx; j++ ) {
326 			win->lines[i]->line[j].ch = right.vals[ 0 ];
327 			win->lines[i]->line[j].attr = right.attributes;
328 			np = win->lines[i]->line[j].nsp;
329 			if (np) {
330 				while ( np ) {
331 					tnp = np->next;
332 					free( np );
333 					np = tnp;
334 				}
335 				win->lines[i]->line[j].nsp = NULL;
336 			}
337 			if ( j == endx - cw + 1 ) {
338 				SET_WCOL( win->lines[i]->line[j], cw );
339 				if ( right.elements > 1 ) {
340 					for (k = 1; k < right.elements; k++) {
341 						np = (nschar_t *)malloc(sizeof(nschar_t));
342 						if (!np)
343 							return ERR;
344 						np->ch = right.vals[ k ];
345 						np->next = win->lines[i]->line[j].nsp;
346 						win->lines[i]->line[j].nsp
347 							= np;
348 					}
349 				}
350 			} else
351 				SET_WCOL( win->lines[i]->line[j],
352 					endx - cw + 1 - j );
353 		}
354 		if ( pcw != 1 ) {
355 #ifdef DEBUG
356 			__CTRACE(__CTRACE_INPUT,
357 			    "wborder_set: clean out partial chars[%d:%d]",
358 			    endx - cw + pcw, endx - cw );
359 #endif /* DEBUG */
360 			k = pcw < 0 ? endx -cw + pcw : endx - cw;
361 			for ( j = endx - cw; j >= k; j-- ) {
362 				win->lines[i]->line[j].ch
363 					= (wchar_t)btowc(win->bch);
364 				if (_cursesi_copy_nsp(win->bnsp,
365 					       &win->lines[i]->line[j]) == ERR)
366 					return ERR;
367 				win->lines[i]->line[j].attr = win->battr;
368 				SET_WCOL( win->lines[i]->line[j], 1 );
369 			}
370 		}
371 	}
372 	tlcw = wcwidth( topleft.vals[ 0 ]);
373 	blcw = wcwidth( botleft.vals[ 0 ]);
374 	trcw = wcwidth( topright.vals[ 0 ]);
375 	brcw = wcwidth( botright.vals[ 0 ]);
376 	/* upper border */
377 	cw = wcwidth( top.vals[ 0 ]);
378 	for (i = tlcw; i <= min( endx - cw, endx - trcw ); i += cw ) {
379 		for ( j = 0; j < cw; j++ ) {
380 			win->lines[ 0 ]->line[i + j].ch = top.vals[ 0 ];
381 			win->lines[ 0 ]->line[i + j].attr = top.attributes;
382 			np = win->lines[ 0 ]->line[i + j].nsp;
383 			if (np) {
384 				while ( np ) {
385 					tnp = np->next;
386 					free( np );
387 					np = tnp;
388 				}
389 				win->lines[ 0 ]->line[i + j].nsp = NULL;
390 			}
391 			if ( j )
392 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], -j );
393 			else {
394 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], cw );
395 				if ( top.elements > 1 ) {
396 					for ( k = 1; k < top.elements; k++ ) {
397 						np = (nschar_t *)malloc(sizeof(nschar_t));
398 						if (!np)
399 							return ERR;
400 						np->ch = top.vals[ k ];
401 						np->next = win->lines[0]->line[i + j].nsp;
402 						win->lines[0]->line[i + j].nsp
403 							= np;
404 					}
405 				}
406 			}
407 		}
408 	}
409 	while ( i <= endx - trcw ) {
410 		win->lines[0]->line[i].ch =
411 			( wchar_t )btowc(( int ) win->bch );
412 		if (_cursesi_copy_nsp(win->bnsp,
413 				      &win->lines[0]->line[i]) == ERR)
414 			return ERR;
415 		win->lines[ 0 ]->line[ i ].attr = win->battr;
416 		SET_WCOL( win->lines[ 0 ]->line[ i ], 1 );
417 		i++;
418 	}
419 	/* lower border */
420 	for (i = blcw; i <= min( endx - cw, endx - brcw ); i += cw ) {
421 		for ( j = 0; j < cw; j++ ) {
422 			win->lines[ endy ]->line[i + j].ch = bottom.vals[ 0 ];
423 			win->lines[endy]->line[i + j].attr = bottom.attributes;
424 			np = win->lines[ endy ]->line[i + j].nsp;
425 			if (np) {
426 				while ( np ) {
427 					tnp = np->next;
428 					free( np );
429 					np = tnp;
430 				}
431 				win->lines[ endy ]->line[i + j].nsp = NULL;
432 			}
433 			if ( j )
434 				SET_WCOL( win->lines[endy]->line[i + j], -j);
435 			else {
436 				SET_WCOL( win->lines[endy]->line[i + j], cw );
437 				if ( bottom.elements > 1 ) {
438 					for ( k = 1; k < bottom.elements;
439 							k++ ) {
440 						if ( !( np = ( nschar_t *)malloc( sizeof( nschar_t ))))
441 							return ERR;
442 						np->ch = bottom.vals[ k ];
443 						np->next = win->lines[endy]->line[i + j].nsp;
444 						win->lines[endy]->line[i + j].nsp = np;
445 					}
446 				}
447 			}
448 		}
449 	}
450 	while ( i <= endx - brcw ) {
451 		win->lines[endy]->line[i].ch =
452 			(wchar_t)btowc((int) win->bch );
453 		if (_cursesi_copy_nsp(win->bnsp,
454 				      &win->lines[endy]->line[i]) == ERR)
455 			return ERR;
456 		win->lines[ endy ]->line[ i ].attr = win->battr;
457 		SET_WCOL( win->lines[ endy ]->line[ i ], 1 );
458 		i++;
459 	}
460 
461 	/* Corners */
462 	if (!(win->maxx == LINES && win->maxy == COLS &&
463 		(win->flags & __SCROLLOK) && (win->flags & __SCROLLWIN))) {
464 		for ( i = 0; i < tlcw; i++ ) {
465 			win->lines[ 0 ]->line[i].ch = topleft.vals[ 0 ];
466 			win->lines[ 0 ]->line[i].attr = topleft.attributes;
467 			np = win->lines[ 0 ]->line[i].nsp;
468 			if (np) {
469 				while ( np ) {
470 					tnp = np->next;
471 					free( np );
472 					np = tnp;
473 				}
474 				win->lines[ 0 ]->line[i].nsp = NULL;
475 			}
476 			if ( i )
477 				SET_WCOL( win->lines[ 0 ]->line[ i ], -i );
478 			else {
479 				SET_WCOL( win->lines[ 0 ]->line[ i ], tlcw );
480 				if ( topleft.elements > 1 ) {
481 					for ( k = 1; k < topleft.elements;
482 							k++ ) {
483 						np = (nschar_t *)malloc(sizeof(nschar_t));
484 						if (!np)
485 							return ERR;
486 						np->ch = topleft.vals[ k ];
487 						np->next = win->lines[ 0 ]->line[i].nsp;
488 						win->lines[ 0 ]->line[i].nsp
489 							= np;
490 					}
491 				}
492 			}
493 		}
494 		for ( i = endx - trcw + 1; i <= endx; i++ ) {
495 			win->lines[ 0 ]->line[i].ch = topright.vals[ 0 ];
496 			win->lines[ 0 ]->line[i].attr = topright.attributes;
497 			np = win->lines[ 0 ]->line[i].nsp;
498 			if (np) {
499 				while ( np ) {
500 					tnp = np->next;
501 					free( np );
502 					np = tnp;
503 				}
504 				win->lines[ 0 ]->line[i].nsp = NULL;
505 			}
506 			if ( i == endx - trcw + 1 ) {
507 				SET_WCOL( win->lines[ 0 ]->line[ i ], trcw );
508 				if ( topright.elements > 1 ) {
509 					for ( k = 1; k < topright.elements;
510 							k++ ) {
511 						np = (nschar_t *)malloc(sizeof(nschar_t));
512 						if (!np)
513 							return ERR;
514 						np->ch = topright.vals[ k ];
515 						np->next = win->lines[0]->line[i].nsp;
516 						win->lines[ 0 ]->line[i].nsp
517 							= np;
518 					}
519 				}
520 			} else
521 				SET_WCOL( win->lines[ 0 ]->line[ i ],
522 					  endx - trcw + 1 - i );
523 		}
524 		for ( i = 0; i < blcw; i++ ) {
525 			win->lines[ endy ]->line[i].ch = botleft.vals[ 0 ];
526 			win->lines[ endy ]->line[i].attr = botleft.attributes;
527 			np = win->lines[ endy ]->line[i].nsp;
528 			if (np) {
529 				while ( np ) {
530 					tnp = np->next;
531 					free( np );
532 					np = tnp;
533 				}
534 				win->lines[ endy ]->line[i].nsp = NULL;
535 			}
536 			if ( i )
537 				SET_WCOL( win->lines[endy]->line[i], -i );
538 			else {
539 				SET_WCOL( win->lines[endy]->line[i], blcw );
540 				if ( botleft.elements > 1 ) {
541 					for ( k = 1; k < botleft.elements;
542 							k++ ) {
543 						np = (nschar_t *)malloc(sizeof(nschar_t));
544 						if (!np)
545 							return ERR;
546 						np->ch = botleft.vals[ k ];
547 						np->next = win->lines[endy]->line[i].nsp;
548 						win->lines[endy]->line[i].nsp
549 							= np;
550 					}
551 				}
552 			}
553 		}
554 		for ( i = endx - brcw + 1; i <= endx; i++ ) {
555 			win->lines[ endy ]->line[i].ch = botright.vals[ 0 ];
556 			win->lines[ endy ]->line[i].attr = botright.attributes;
557 			np = win->lines[ endy ]->line[i].nsp;
558 			if (np) {
559 				while ( np ) {
560 					tnp = np->next;
561 					free( np );
562 					np = tnp;
563 				}
564 				win->lines[ endy ]->line[i].nsp = NULL;
565 			}
566 			if ( i == endx - brcw + 1 ) {
567 				SET_WCOL( win->lines[ endy ]->line[ i ],
568 					  brcw );
569 				if ( botright.elements > 1 ) {
570 					for ( k = 1; k < botright.elements; k++ ) {
571 						np = (nschar_t *)malloc(sizeof(nschar_t));
572 						if (!np)
573 							return ERR;
574 						np->ch = botright.vals[ k ];
575 						np->next = win->lines[endy]->line[i].nsp;
576 						win->lines[endy]->line[i].nsp
577 							= np;
578 					}
579 				}
580 			} else
581 				SET_WCOL( win->lines[ endy ]->line[ i ],
582 					endx - brcw + 1 - i );
583 		}
584 	}
585 	__touchwin(win);
586 	return (OK);
587 #endif /* HAVE_WCHAR */
588 }
589