Home | History | Annotate | Line # | Download | only in libcurses
border.c revision 1.10
      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