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