Home | History | Annotate | Line # | Download | only in libcurses
border.c revision 1.8.6.1
      1 /*	$NetBSD: border.c,v 1.8.6.1 2007/01/21 11:38:59 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.8.6.1 2007/01/21 11:38:59 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("wborder: left = %c, 0x%x\n", left & __CHARTEXT,
     98 	    left & __ATTRIBUTES);
     99 	__CTRACE("wborder: right = %c, 0x%x\n", right & __CHARTEXT,
    100 	    right & __ATTRIBUTES);
    101 	__CTRACE("wborder: top = %c, 0x%x\n", top & __CHARTEXT,
    102 	    top & __ATTRIBUTES);
    103 	__CTRACE("wborder: bottom = %c, 0x%x\n", bottom & __CHARTEXT,
    104 	    bottom & __ATTRIBUTES);
    105 	__CTRACE("wborder: topleft = %c, 0x%x\n", topleft & __CHARTEXT,
    106 	    topleft & __ATTRIBUTES);
    107 	__CTRACE("wborder: topright = %c, 0x%x\n", topright & __CHARTEXT,
    108 	    topright & __ATTRIBUTES);
    109 	__CTRACE("wborder: botleft = %c, 0x%x\n", botleft & __CHARTEXT,
    110 	    botleft & __ATTRIBUTES);
    111 	__CTRACE("wborder: botright = %c, 0x%x\n", botright & __CHARTEXT,
    112 	    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 	}
    145 	for (i = 1; i < endx; i++) {
    146 		fp[i].ch = (wchar_t) top & __CHARTEXT;
    147 		fp[i].attr = (attr_t) top & __ATTRIBUTES;
    148 		lp[i].ch = (wchar_t) bottom & __CHARTEXT;
    149 		lp[i].attr = (attr_t) bottom & __ATTRIBUTES;
    150 	}
    151 
    152 	/* Corners */
    153 	if (!(win->maxx == LINES && win->maxy == COLS &&
    154 	    (win->flags & __SCROLLOK) && (win->flags & __SCROLLWIN))) {
    155 		fp[0].ch = (wchar_t) topleft & __CHARTEXT;
    156 		fp[0].attr = (attr_t) topleft & __ATTRIBUTES;
    157 		fp[endx].ch = (wchar_t) topright & __CHARTEXT;
    158 		fp[endx].attr = (attr_t) topright & __ATTRIBUTES;
    159 		lp[0].ch = (wchar_t) botleft & __CHARTEXT;
    160 		lp[0].attr = (attr_t) botleft & __ATTRIBUTES;
    161 		lp[endx].ch = (wchar_t) botright & __CHARTEXT;
    162 		lp[endx].attr = (attr_t) botright & __ATTRIBUTES;
    163 	}
    164 	__touchwin(win);
    165 	return (OK);
    166 }
    167 
    168 int border_set(const cchar_t *ls, const cchar_t *rs, const cchar_t *ts,
    169 	   const cchar_t *bs, const cchar_t *tl, const cchar_t *tr,
    170 	   const cchar_t *bl, const cchar_t *br)
    171 {
    172 #ifndef HAVE_WCHAR
    173 	return ERR;
    174 #else
    175 	return wborder_set(stdscr, ls, rs, ts, bs, tl, tr, bl, br);
    176 #endif /* HAVE_WCHAR */
    177 }
    178 
    179 int wborder_set(WINDOW *win, const cchar_t *ls, const cchar_t *rs,
    180 		const cchar_t *ts, const cchar_t *bs,
    181 		const cchar_t *tl, const cchar_t *tr,
    182 		const cchar_t *bl, const cchar_t *br)
    183 {
    184 #ifndef HAVE_WCHAR
    185 	return ERR;
    186 #else
    187 	int	 endy, endx, i, j, k, cw, pcw, tlcw, blcw, trcw, brcw;
    188 	cchar_t left, right, bottom, top, topleft, topright, botleft, botright;
    189 	nschar_t *np, *tnp;
    190 
    191 	if ( ls && wcwidth( ls->vals[ 0 ]))
    192 		memcpy( &left, ls, sizeof( cchar_t ));
    193 	else
    194 		setcchar( &left, &WACS_VLINE, win->wattr, 0, NULL );
    195 	if ( rs && wcwidth( rs->vals[ 0 ]))
    196 		memcpy( &right, rs, sizeof( cchar_t ));
    197 	else
    198 		setcchar( &right, &WACS_VLINE, win->wattr, 0, NULL );
    199 	if ( ts && wcwidth( ts->vals[ 0 ]))
    200 		memcpy( &top, ts, sizeof( cchar_t ));
    201 	else
    202 		setcchar( &top, &WACS_HLINE, win->wattr, 0, NULL );
    203 	if ( bs && wcwidth( bs->vals[ 0 ]))
    204 		memcpy( &bottom, bs, sizeof( cchar_t ));
    205 	else
    206 		setcchar( &bottom, &WACS_HLINE, win->wattr, 0, NULL );
    207 	if ( tl && wcwidth( tl->vals[ 0 ]))
    208 		memcpy( &topleft, tl, sizeof( cchar_t ));
    209 	else
    210 		setcchar( &topleft, &WACS_ULCORNER, win->wattr, 0, NULL );
    211 	if ( tr && wcwidth( tr->vals[ 0 ]))
    212 		memcpy( &topright, tr, sizeof( cchar_t ));
    213 	else
    214 		setcchar( &topright, &WACS_URCORNER, win->wattr, 0, NULL );
    215 	if ( bl && wcwidth( bl->vals[ 0 ]))
    216 		memcpy( &botleft, bl, sizeof( cchar_t ));
    217 	else
    218 		setcchar( &botleft, &WACS_LLCORNER, win->wattr, 0, NULL );
    219 	if ( br && wcwidth( br->vals[ 0 ]))
    220 		memcpy( &botright, br, sizeof( cchar_t ));
    221 	else
    222 		setcchar( &botright, &WACS_LRCORNER, win->wattr, 0, NULL );
    223 
    224 #ifdef DEBUG
    225 	__CTRACE("wborder_set: left = %c, 0x%x\n", left.vals[ 0 ],
    226 		left.attributes );
    227 	__CTRACE("wborder_set: right = %c, 0x%x\n", right.vals[ 0 ],
    228 		right.attributes );
    229 	__CTRACE("wborder_set: top = %c, 0x%x\n", top.vals[ 0 ],
    230 		top.attributes );
    231 	__CTRACE("wborder_set: bottom = %c, 0x%x\n", bottom.vals[ 0 ],
    232 		bottom.attributes );
    233 	__CTRACE("wborder_set: topleft = %c, 0x%x\n", topleft.vals[ 0 ],
    234 		topleft.attributes );
    235 	__CTRACE("wborder_set: topright = %c, 0x%x\n", topright.vals[ 0 ],
    236 		topright.attributes );
    237 	__CTRACE("wborder_set: botleft = %c, 0x%x\n", botleft.vals[ 0 ],
    238 		botleft.attributes );
    239 	__CTRACE("wborder_set: botright = %c, 0x%x\n", botright.vals[ 0 ],
    240 		botright.attributes );
    241 #endif
    242 
    243 	/* Merge window attributes */
    244 	left.attributes |= (left.attributes & __COLOR) ?
    245 		(win->wattr & ~__COLOR) : win->wattr;
    246 	right.attributes |= (right.attributes & __COLOR) ?
    247 		(win->wattr & ~__COLOR) : win->wattr;
    248 	top.attributes |= (top.attributes & __COLOR) ?
    249 		(win->wattr & ~__COLOR) : win->wattr;
    250 	bottom.attributes |= (bottom.attributes & __COLOR) ?
    251 		(win->wattr & ~__COLOR) : win->wattr;
    252 	topleft.attributes |= (topleft.attributes & __COLOR) ?
    253 		(win->wattr & ~__COLOR) : win->wattr;
    254 	topright.attributes |= (topright.attributes & __COLOR) ?
    255 		(win->wattr & ~__COLOR) : win->wattr;
    256 	botleft.attributes |= (botleft.attributes & __COLOR) ?
    257 		(win->wattr & ~__COLOR) : win->wattr;
    258 	botright.attributes |= (botright.attributes & __COLOR) ?
    259 		(win->wattr & ~__COLOR) : win->wattr;
    260 
    261 	endx = win->maxx - 1;
    262 	endy = win->maxy - 1;
    263 
    264 	/* Sides */
    265 	for (i = 1; i < endy; i++) {
    266 		/* left border */
    267 		cw = wcwidth( left.vals[ 0 ]);
    268 		for ( j = 0; j < cw; j++ ) {
    269 			win->lines[i]->line[j].ch = left.vals[ 0 ];
    270 			win->lines[i]->line[j].attr = left.attributes;
    271 			np = win->lines[i]->line[j].nsp;
    272 			if (np) {
    273 				while ( np ) {
    274 					tnp = np->next;
    275 					free( np );
    276 					np = tnp;
    277 				}
    278 				win->lines[i]->line[j].nsp = NULL;
    279 			}
    280 			if ( j )
    281 				SET_WCOL( win->lines[i]->line[j], -j );
    282 			else {
    283 				SET_WCOL( win->lines[i]->line[j], cw );
    284 				if ( left.elements > 1 ) {
    285 					for (k = 1; k < left.elements; k++) {
    286 						np = (nschar_t *)malloc(sizeof(nschar_t));
    287 						if (!np)
    288 							return ERR;
    289 						np->ch = left.vals[ k ];
    290 						np->next = win->lines[i]->line[j].nsp;
    291 						win->lines[i]->line[j].nsp
    292 							= np;
    293 					}
    294 				}
    295 			}
    296 		}
    297 		for ( j = cw; WCOL( win->lines[i]->line[j]) < 0; j++ ) {
    298 #ifdef DEBUG
    299 			__CTRACE("[wborder_set]clean out partial char[%d]", j);
    300 #endif /* DEBUG */
    301 			win->lines[i]->line[j].ch = ( wchar_t )btowc(win->bch);
    302 			if (_cursesi_copy_nsp(win->bnsp,
    303 					      &win->lines[i]->line[j]) == ERR)
    304 				return ERR;
    305 			SET_WCOL( win->lines[i]->line[j], 1 );
    306 		}
    307 		/* right border */
    308 		cw = wcwidth( right.vals[ 0 ]);
    309 		pcw = WCOL( win->lines[i]->line[endx - cw]);
    310 		for ( j = endx - cw + 1; j <= endx; j++ ) {
    311 			win->lines[i]->line[j].ch = right.vals[ 0 ];
    312 			win->lines[i]->line[j].attr = right.attributes;
    313 			np = win->lines[i]->line[j].nsp;
    314 			if (np) {
    315 				while ( np ) {
    316 					tnp = np->next;
    317 					free( np );
    318 					np = tnp;
    319 				}
    320 				win->lines[i]->line[j].nsp = NULL;
    321 			}
    322 			if ( j == endx - cw + 1 ) {
    323 				SET_WCOL( win->lines[i]->line[j], cw );
    324 				if ( right.elements > 1 ) {
    325 					for (k = 1; k < right.elements; k++) {
    326 						np = (nschar_t *)malloc(sizeof(nschar_t));
    327 						if (!np)
    328 							return ERR;
    329 						np->ch = right.vals[ k ];
    330 						np->next = win->lines[i]->line[j].nsp;
    331 						win->lines[i]->line[j].nsp
    332 							= np;
    333 					}
    334 				}
    335 			} else
    336 				SET_WCOL( win->lines[i]->line[j],
    337 					endx - cw + 1 - j );
    338 		}
    339 		if ( pcw != 1 ) {
    340 #ifdef DEBUG
    341 			__CTRACE("[wborder_set]clean out partial chars[%d:%d]",
    342 					endx - cw + pcw, endx - cw );
    343 #endif /* DEBUG */
    344 			k = pcw < 0 ? endx -cw + pcw : endx - cw;
    345 			for ( j = endx - cw; j >= k; j-- ) {
    346 				win->lines[i]->line[j].ch
    347 					= (wchar_t)btowc(win->bch);
    348 				if (_cursesi_copy_nsp(win->bnsp,
    349 					       &win->lines[i]->line[j]) == ERR)
    350 					return ERR;
    351 				win->lines[i]->line[j].attr = win->battr;
    352 				SET_WCOL( win->lines[i]->line[j], 1 );
    353 			}
    354 		}
    355 	}
    356 	tlcw = wcwidth( topleft.vals[ 0 ]);
    357 	blcw = wcwidth( botleft.vals[ 0 ]);
    358 	trcw = wcwidth( topright.vals[ 0 ]);
    359 	brcw = wcwidth( botright.vals[ 0 ]);
    360 	/* upper border */
    361 	cw = wcwidth( top.vals[ 0 ]);
    362 	for (i = tlcw; i <= min( endx - cw, endx - trcw ); i += cw ) {
    363 		for ( j = 0; j < cw; j++ ) {
    364 			win->lines[ 0 ]->line[i + j].ch = top.vals[ 0 ];
    365 			win->lines[ 0 ]->line[i + j].attr = top.attributes;
    366 			np = win->lines[ 0 ]->line[i + j].nsp;
    367 			if (np) {
    368 				while ( np ) {
    369 					tnp = np->next;
    370 					free( np );
    371 					np = tnp;
    372 				}
    373 				win->lines[ 0 ]->line[i + j].nsp = NULL;
    374 			}
    375 			if ( j )
    376 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], -j );
    377 			else {
    378 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], cw );
    379 				if ( top.elements > 1 ) {
    380 					for ( k = 1; k < top.elements; k++ ) {
    381 						np = (nschar_t *)malloc(sizeof(nschar_t));
    382 						if (!np)
    383 							return ERR;
    384 						np->ch = top.vals[ k ];
    385 						np->next = win->lines[0]->line[i + j].nsp;
    386 						win->lines[0]->line[i + j].nsp
    387 							= np;
    388 					}
    389 				}
    390 			}
    391 		}
    392 	}
    393 	while ( i <= endx - trcw ) {
    394 		win->lines[0]->line[i].ch =
    395 			( wchar_t )btowc(( int ) win->bch );
    396 		if (_cursesi_copy_nsp(win->bnsp,
    397 				      &win->lines[0]->line[i]) == ERR)
    398 			return ERR;
    399 		win->lines[ 0 ]->line[ i ].attr = win->battr;
    400 		SET_WCOL( win->lines[ 0 ]->line[ i ], 1 );
    401 		i++;
    402 	}
    403 	/* lower border */
    404 	for (i = blcw; i <= min( endx - cw, endx - brcw ); i += cw ) {
    405 		for ( j = 0; j < cw; j++ ) {
    406 			win->lines[ endy ]->line[i + j].ch = bottom.vals[ 0 ];
    407 			win->lines[endy]->line[i + j].attr = bottom.attributes;
    408 			np = win->lines[ endy ]->line[i + j].nsp;
    409 			if (np) {
    410 				while ( np ) {
    411 					tnp = np->next;
    412 					free( np );
    413 					np = tnp;
    414 				}
    415 				win->lines[ endy ]->line[i + j].nsp = NULL;
    416 			}
    417 			if ( j )
    418 				SET_WCOL( win->lines[endy]->line[i + j], -j);
    419 			else {
    420 				SET_WCOL( win->lines[endy]->line[i + j], cw );
    421 				if ( bottom.elements > 1 ) {
    422 					for ( k = 1; k < bottom.elements;
    423 							k++ ) {
    424 						if ( !( np = ( nschar_t *)malloc( sizeof( nschar_t ))))
    425 							return ERR;
    426 						np->ch = bottom.vals[ k ];
    427 						np->next = win->lines[endy]->line[i + j].nsp;
    428 						win->lines[endy]->line[i + j].nsp = np;
    429 					}
    430 				}
    431 			}
    432 		}
    433 	}
    434 	while ( i <= endx - brcw ) {
    435 		win->lines[endy]->line[i].ch =
    436 			(wchar_t)btowc((int) win->bch );
    437 		if (_cursesi_copy_nsp(win->bnsp,
    438 				      &win->lines[endy]->line[i]) == ERR)
    439 			return ERR;
    440 		win->lines[ endy ]->line[ i ].attr = win->battr;
    441 		SET_WCOL( win->lines[ endy ]->line[ i ], 1 );
    442 		i++;
    443 	}
    444 
    445 	/* Corners */
    446 	if (!(win->maxx == LINES && win->maxy == COLS &&
    447 		(win->flags & __SCROLLOK) && (win->flags & __SCROLLWIN))) {
    448 		for ( i = 0; i < tlcw; i++ ) {
    449 			win->lines[ 0 ]->line[i].ch = topleft.vals[ 0 ];
    450 			win->lines[ 0 ]->line[i].attr = topleft.attributes;
    451 			np = win->lines[ 0 ]->line[i].nsp;
    452 			if (np) {
    453 				while ( np ) {
    454 					tnp = np->next;
    455 					free( np );
    456 					np = tnp;
    457 				}
    458 				win->lines[ 0 ]->line[i].nsp = NULL;
    459 			}
    460 			if ( i )
    461 				SET_WCOL( win->lines[ 0 ]->line[ i ], -i );
    462 			else {
    463 				SET_WCOL( win->lines[ 0 ]->line[ i ], tlcw );
    464 				if ( topleft.elements > 1 ) {
    465 					for ( k = 1; k < topleft.elements;
    466 							k++ ) {
    467 						np = (nschar_t *)malloc(sizeof(nschar_t));
    468 						if (!np)
    469 							return ERR;
    470 						np->ch = topleft.vals[ k ];
    471 						np->next = win->lines[ 0 ]->line[i].nsp;
    472 						win->lines[ 0 ]->line[i].nsp
    473 							= np;
    474 					}
    475 				}
    476 			}
    477 		}
    478 		for ( i = endx - trcw + 1; i <= endx; i++ ) {
    479 			win->lines[ 0 ]->line[i].ch = topright.vals[ 0 ];
    480 			win->lines[ 0 ]->line[i].attr = topright.attributes;
    481 			np = win->lines[ 0 ]->line[i].nsp;
    482 			if (np) {
    483 				while ( np ) {
    484 					tnp = np->next;
    485 					free( np );
    486 					np = tnp;
    487 				}
    488 				win->lines[ 0 ]->line[i].nsp = NULL;
    489 			}
    490 			if ( i == endx - trcw + 1 ) {
    491 				SET_WCOL( win->lines[ 0 ]->line[ i ], trcw );
    492 				if ( topright.elements > 1 ) {
    493 					for ( k = 1; k < topright.elements;
    494 							k++ ) {
    495 						np = (nschar_t *)malloc(sizeof(nschar_t));
    496 						if (!np)
    497 							return ERR;
    498 						np->ch = topright.vals[ k ];
    499 						np->next = win->lines[0]->line[i].nsp;
    500 						win->lines[ 0 ]->line[i].nsp
    501 							= np;
    502 					}
    503 				}
    504 			} else
    505 				SET_WCOL( win->lines[ 0 ]->line[ i ],
    506 					  endx - trcw + 1 - i );
    507 		}
    508 		for ( i = 0; i < blcw; i++ ) {
    509 			win->lines[ endy ]->line[i].ch = botleft.vals[ 0 ];
    510 			win->lines[ endy ]->line[i].attr = botleft.attributes;
    511 			np = win->lines[ endy ]->line[i].nsp;
    512 			if (np) {
    513 				while ( np ) {
    514 					tnp = np->next;
    515 					free( np );
    516 					np = tnp;
    517 				}
    518 				win->lines[ endy ]->line[i].nsp = NULL;
    519 			}
    520 			if ( i )
    521 				SET_WCOL( win->lines[endy]->line[i], -i );
    522 			else {
    523 				SET_WCOL( win->lines[endy]->line[i], blcw );
    524 				if ( botleft.elements > 1 ) {
    525 					for ( k = 1; k < botleft.elements;
    526 							k++ ) {
    527 						np = (nschar_t *)malloc(sizeof(nschar_t));
    528 						if (!np)
    529 							return ERR;
    530 						np->ch = botleft.vals[ k ];
    531 						np->next = win->lines[endy]->line[i].nsp;
    532 						win->lines[endy]->line[i].nsp
    533 							= np;
    534 					}
    535 				}
    536 			}
    537 		}
    538 		for ( i = endx - brcw + 1; i <= endx; i++ ) {
    539 			win->lines[ endy ]->line[i].ch = botright.vals[ 0 ];
    540 			win->lines[ endy ]->line[i].attr = botright.attributes;
    541 			np = win->lines[ endy ]->line[i].nsp;
    542 			if (np) {
    543 				while ( np ) {
    544 					tnp = np->next;
    545 					free( np );
    546 					np = tnp;
    547 				}
    548 				win->lines[ endy ]->line[i].nsp = NULL;
    549 			}
    550 			if ( i == endx - brcw + 1 ) {
    551 				SET_WCOL( win->lines[ endy ]->line[ i ],
    552 					  brcw );
    553 				if ( botright.elements > 1 ) {
    554 					for ( k = 1; k < botright.elements; k++ ) {
    555 						np = (nschar_t *)malloc(sizeof(nschar_t));
    556 						if (!np)
    557 							return ERR;
    558 						np->ch = botright.vals[ k ];
    559 						np->next = win->lines[endy]->line[i].nsp;
    560 						win->lines[endy]->line[i].nsp
    561 							= np;
    562 					}
    563 				}
    564 			} else
    565 				SET_WCOL( win->lines[ endy ]->line[ i ],
    566 					endx - brcw + 1 - i );
    567 		}
    568 	}
    569 	__touchwin(win);
    570 	return (OK);
    571 #endif /* HAVE_WCHAR */
    572 }
    573