Home | History | Annotate | Line # | Download | only in libcurses
border.c revision 1.8.6.2
      1 /*	$NetBSD: border.c,v 1.8.6.2 2007/01/21 17:43:35 jdc 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.2 2007/01/21 17:43:35 jdc 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 	}
    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(__CTRACE_INPUT, "wborder_set: left = %c, 0x%x\n",
    226 	    left.vals[0], left.attributes );
    227 	__CTRACE(__CTRACE_INPUT, "wborder_set: right = %c, 0x%x\n",
    228 	    right.vals[0], right.attributes );
    229 	__CTRACE(__CTRACE_INPUT, "wborder_set: top = %c, 0x%x\n",
    230 	    top.vals[0], top.attributes );
    231 	__CTRACE(__CTRACE_INPUT, "wborder_set: bottom = %c, 0x%x\n",
    232 	    bottom.vals[0], bottom.attributes );
    233 	__CTRACE(__CTRACE_INPUT, "wborder_set: topleft = %c, 0x%x\n",
    234 	    topleft.vals[0], topleft.attributes );
    235 	__CTRACE(__CTRACE_INPUT, "wborder_set: topright = %c, 0x%x\n",
    236 	    topright.vals[0], topright.attributes );
    237 	__CTRACE(__CTRACE_INPUT, "wborder_set: botleft = %c, 0x%x\n",
    238 	    botleft.vals[0], botleft.attributes );
    239 	__CTRACE(__CTRACE_INPUT, "wborder_set: botright = %c, 0x%x\n",
    240 	    botright.vals[0], 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(__CTRACE_INPUT,
    300 			    "wborder_set: clean out partial char[%d]", j);
    301 #endif /* DEBUG */
    302 			win->lines[i]->line[j].ch = ( wchar_t )btowc(win->bch);
    303 			if (_cursesi_copy_nsp(win->bnsp,
    304 					      &win->lines[i]->line[j]) == ERR)
    305 				return ERR;
    306 			SET_WCOL( win->lines[i]->line[j], 1 );
    307 		}
    308 		/* right border */
    309 		cw = wcwidth( right.vals[ 0 ]);
    310 		pcw = WCOL( win->lines[i]->line[endx - cw]);
    311 		for ( j = endx - cw + 1; j <= endx; j++ ) {
    312 			win->lines[i]->line[j].ch = right.vals[ 0 ];
    313 			win->lines[i]->line[j].attr = right.attributes;
    314 			np = win->lines[i]->line[j].nsp;
    315 			if (np) {
    316 				while ( np ) {
    317 					tnp = np->next;
    318 					free( np );
    319 					np = tnp;
    320 				}
    321 				win->lines[i]->line[j].nsp = NULL;
    322 			}
    323 			if ( j == endx - cw + 1 ) {
    324 				SET_WCOL( win->lines[i]->line[j], cw );
    325 				if ( right.elements > 1 ) {
    326 					for (k = 1; k < right.elements; k++) {
    327 						np = (nschar_t *)malloc(sizeof(nschar_t));
    328 						if (!np)
    329 							return ERR;
    330 						np->ch = right.vals[ k ];
    331 						np->next = win->lines[i]->line[j].nsp;
    332 						win->lines[i]->line[j].nsp
    333 							= np;
    334 					}
    335 				}
    336 			} else
    337 				SET_WCOL( win->lines[i]->line[j],
    338 					endx - cw + 1 - j );
    339 		}
    340 		if ( pcw != 1 ) {
    341 #ifdef DEBUG
    342 			__CTRACE(__CTRACE_INPUT,
    343 			    "wborder_set: clean out partial chars[%d:%d]",
    344 			    endx - cw + pcw, endx - cw );
    345 #endif /* DEBUG */
    346 			k = pcw < 0 ? endx -cw + pcw : endx - cw;
    347 			for ( j = endx - cw; j >= k; j-- ) {
    348 				win->lines[i]->line[j].ch
    349 					= (wchar_t)btowc(win->bch);
    350 				if (_cursesi_copy_nsp(win->bnsp,
    351 					       &win->lines[i]->line[j]) == ERR)
    352 					return ERR;
    353 				win->lines[i]->line[j].attr = win->battr;
    354 				SET_WCOL( win->lines[i]->line[j], 1 );
    355 			}
    356 		}
    357 	}
    358 	tlcw = wcwidth( topleft.vals[ 0 ]);
    359 	blcw = wcwidth( botleft.vals[ 0 ]);
    360 	trcw = wcwidth( topright.vals[ 0 ]);
    361 	brcw = wcwidth( botright.vals[ 0 ]);
    362 	/* upper border */
    363 	cw = wcwidth( top.vals[ 0 ]);
    364 	for (i = tlcw; i <= min( endx - cw, endx - trcw ); i += cw ) {
    365 		for ( j = 0; j < cw; j++ ) {
    366 			win->lines[ 0 ]->line[i + j].ch = top.vals[ 0 ];
    367 			win->lines[ 0 ]->line[i + j].attr = top.attributes;
    368 			np = win->lines[ 0 ]->line[i + j].nsp;
    369 			if (np) {
    370 				while ( np ) {
    371 					tnp = np->next;
    372 					free( np );
    373 					np = tnp;
    374 				}
    375 				win->lines[ 0 ]->line[i + j].nsp = NULL;
    376 			}
    377 			if ( j )
    378 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], -j );
    379 			else {
    380 				SET_WCOL( win->lines[ 0 ]->line[ i + j ], cw );
    381 				if ( top.elements > 1 ) {
    382 					for ( k = 1; k < top.elements; k++ ) {
    383 						np = (nschar_t *)malloc(sizeof(nschar_t));
    384 						if (!np)
    385 							return ERR;
    386 						np->ch = top.vals[ k ];
    387 						np->next = win->lines[0]->line[i + j].nsp;
    388 						win->lines[0]->line[i + j].nsp
    389 							= np;
    390 					}
    391 				}
    392 			}
    393 		}
    394 	}
    395 	while ( i <= endx - trcw ) {
    396 		win->lines[0]->line[i].ch =
    397 			( wchar_t )btowc(( int ) win->bch );
    398 		if (_cursesi_copy_nsp(win->bnsp,
    399 				      &win->lines[0]->line[i]) == ERR)
    400 			return ERR;
    401 		win->lines[ 0 ]->line[ i ].attr = win->battr;
    402 		SET_WCOL( win->lines[ 0 ]->line[ i ], 1 );
    403 		i++;
    404 	}
    405 	/* lower border */
    406 	for (i = blcw; i <= min( endx - cw, endx - brcw ); i += cw ) {
    407 		for ( j = 0; j < cw; j++ ) {
    408 			win->lines[ endy ]->line[i + j].ch = bottom.vals[ 0 ];
    409 			win->lines[endy]->line[i + j].attr = bottom.attributes;
    410 			np = win->lines[ endy ]->line[i + j].nsp;
    411 			if (np) {
    412 				while ( np ) {
    413 					tnp = np->next;
    414 					free( np );
    415 					np = tnp;
    416 				}
    417 				win->lines[ endy ]->line[i + j].nsp = NULL;
    418 			}
    419 			if ( j )
    420 				SET_WCOL( win->lines[endy]->line[i + j], -j);
    421 			else {
    422 				SET_WCOL( win->lines[endy]->line[i + j], cw );
    423 				if ( bottom.elements > 1 ) {
    424 					for ( k = 1; k < bottom.elements;
    425 							k++ ) {
    426 						if ( !( np = ( nschar_t *)malloc( sizeof( nschar_t ))))
    427 							return ERR;
    428 						np->ch = bottom.vals[ k ];
    429 						np->next = win->lines[endy]->line[i + j].nsp;
    430 						win->lines[endy]->line[i + j].nsp = np;
    431 					}
    432 				}
    433 			}
    434 		}
    435 	}
    436 	while ( i <= endx - brcw ) {
    437 		win->lines[endy]->line[i].ch =
    438 			(wchar_t)btowc((int) win->bch );
    439 		if (_cursesi_copy_nsp(win->bnsp,
    440 				      &win->lines[endy]->line[i]) == ERR)
    441 			return ERR;
    442 		win->lines[ endy ]->line[ i ].attr = win->battr;
    443 		SET_WCOL( win->lines[ endy ]->line[ i ], 1 );
    444 		i++;
    445 	}
    446 
    447 	/* Corners */
    448 	if (!(win->maxx == LINES && win->maxy == COLS &&
    449 		(win->flags & __SCROLLOK) && (win->flags & __SCROLLWIN))) {
    450 		for ( i = 0; i < tlcw; i++ ) {
    451 			win->lines[ 0 ]->line[i].ch = topleft.vals[ 0 ];
    452 			win->lines[ 0 ]->line[i].attr = topleft.attributes;
    453 			np = win->lines[ 0 ]->line[i].nsp;
    454 			if (np) {
    455 				while ( np ) {
    456 					tnp = np->next;
    457 					free( np );
    458 					np = tnp;
    459 				}
    460 				win->lines[ 0 ]->line[i].nsp = NULL;
    461 			}
    462 			if ( i )
    463 				SET_WCOL( win->lines[ 0 ]->line[ i ], -i );
    464 			else {
    465 				SET_WCOL( win->lines[ 0 ]->line[ i ], tlcw );
    466 				if ( topleft.elements > 1 ) {
    467 					for ( k = 1; k < topleft.elements;
    468 							k++ ) {
    469 						np = (nschar_t *)malloc(sizeof(nschar_t));
    470 						if (!np)
    471 							return ERR;
    472 						np->ch = topleft.vals[ k ];
    473 						np->next = win->lines[ 0 ]->line[i].nsp;
    474 						win->lines[ 0 ]->line[i].nsp
    475 							= np;
    476 					}
    477 				}
    478 			}
    479 		}
    480 		for ( i = endx - trcw + 1; i <= endx; i++ ) {
    481 			win->lines[ 0 ]->line[i].ch = topright.vals[ 0 ];
    482 			win->lines[ 0 ]->line[i].attr = topright.attributes;
    483 			np = win->lines[ 0 ]->line[i].nsp;
    484 			if (np) {
    485 				while ( np ) {
    486 					tnp = np->next;
    487 					free( np );
    488 					np = tnp;
    489 				}
    490 				win->lines[ 0 ]->line[i].nsp = NULL;
    491 			}
    492 			if ( i == endx - trcw + 1 ) {
    493 				SET_WCOL( win->lines[ 0 ]->line[ i ], trcw );
    494 				if ( topright.elements > 1 ) {
    495 					for ( k = 1; k < topright.elements;
    496 							k++ ) {
    497 						np = (nschar_t *)malloc(sizeof(nschar_t));
    498 						if (!np)
    499 							return ERR;
    500 						np->ch = topright.vals[ k ];
    501 						np->next = win->lines[0]->line[i].nsp;
    502 						win->lines[ 0 ]->line[i].nsp
    503 							= np;
    504 					}
    505 				}
    506 			} else
    507 				SET_WCOL( win->lines[ 0 ]->line[ i ],
    508 					  endx - trcw + 1 - i );
    509 		}
    510 		for ( i = 0; i < blcw; i++ ) {
    511 			win->lines[ endy ]->line[i].ch = botleft.vals[ 0 ];
    512 			win->lines[ endy ]->line[i].attr = botleft.attributes;
    513 			np = win->lines[ endy ]->line[i].nsp;
    514 			if (np) {
    515 				while ( np ) {
    516 					tnp = np->next;
    517 					free( np );
    518 					np = tnp;
    519 				}
    520 				win->lines[ endy ]->line[i].nsp = NULL;
    521 			}
    522 			if ( i )
    523 				SET_WCOL( win->lines[endy]->line[i], -i );
    524 			else {
    525 				SET_WCOL( win->lines[endy]->line[i], blcw );
    526 				if ( botleft.elements > 1 ) {
    527 					for ( k = 1; k < botleft.elements;
    528 							k++ ) {
    529 						np = (nschar_t *)malloc(sizeof(nschar_t));
    530 						if (!np)
    531 							return ERR;
    532 						np->ch = botleft.vals[ k ];
    533 						np->next = win->lines[endy]->line[i].nsp;
    534 						win->lines[endy]->line[i].nsp
    535 							= np;
    536 					}
    537 				}
    538 			}
    539 		}
    540 		for ( i = endx - brcw + 1; i <= endx; i++ ) {
    541 			win->lines[ endy ]->line[i].ch = botright.vals[ 0 ];
    542 			win->lines[ endy ]->line[i].attr = botright.attributes;
    543 			np = win->lines[ endy ]->line[i].nsp;
    544 			if (np) {
    545 				while ( np ) {
    546 					tnp = np->next;
    547 					free( np );
    548 					np = tnp;
    549 				}
    550 				win->lines[ endy ]->line[i].nsp = NULL;
    551 			}
    552 			if ( i == endx - brcw + 1 ) {
    553 				SET_WCOL( win->lines[ endy ]->line[ i ],
    554 					  brcw );
    555 				if ( botright.elements > 1 ) {
    556 					for ( k = 1; k < botright.elements; k++ ) {
    557 						np = (nschar_t *)malloc(sizeof(nschar_t));
    558 						if (!np)
    559 							return ERR;
    560 						np->ch = botright.vals[ k ];
    561 						np->next = win->lines[endy]->line[i].nsp;
    562 						win->lines[endy]->line[i].nsp
    563 							= np;
    564 					}
    565 				}
    566 			} else
    567 				SET_WCOL( win->lines[ endy ]->line[ i ],
    568 					endx - brcw + 1 - i );
    569 		}
    570 	}
    571 	__touchwin(win);
    572 	return (OK);
    573 #endif /* HAVE_WCHAR */
    574 }
    575