Home | History | Annotate | Line # | Download | only in libcurses
resize.c revision 1.14.4.2
      1 /*	$NetBSD: resize.c,v 1.14.4.2 2008/01/09 01:36:24 matt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2001
      5  *	Brett Lymn.
      6  *
      7  * This code has been donated to The NetBSD Foundation by the Author.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by the University of
     20  *	California, Berkeley and its contributors.
     21  * 4. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 #ifndef lint
     40 #if 0
     41 static char sccsid[] = "@(#)resize.c   blymn 2001/08/26";
     42 #else
     43 __RCSID("$NetBSD: resize.c,v 1.14.4.2 2008/01/09 01:36:24 matt Exp $");
     44 #endif
     45 #endif				/* not lint */
     46 
     47 #include <stdlib.h>
     48 
     49 #include "curses.h"
     50 #include "curses_private.h"
     51 
     52 static int __resizeterm(WINDOW *win, int nlines, int ncols);
     53 static int __resizewin(WINDOW *win, int nlines, int ncols);
     54 
     55 /*
     56  * wresize --
     57  *	Resize the given window to the new size.
     58  */
     59 int
     60 wresize(WINDOW *win, int req_nlines, int req_ncols)
     61 {
     62 	int	nlines = req_nlines;
     63 	int	ncols = req_ncols;
     64 
     65 	if (win == NULL)
     66 		return ERR;
     67 
     68 #ifdef	DEBUG
     69 	__CTRACE(__CTRACE_WINDOW, "wresize: (%p, %d, %d)\n",
     70 	    win, nlines, ncols);
     71 #endif
     72 	nlines = req_nlines;
     73 	ncols = req_ncols;
     74 	if (win->orig == NULL) {
     75 		/* bound "our" windows by the screen size */
     76 		if (win == curscr || win == __virtscr || win == stdscr) {
     77 			if (nlines > LINES)
     78 				nlines = LINES;
     79 			if (nlines < 1)
     80 				nlines = 1;
     81 			if (ncols > COLS)
     82 				ncols = COLS;
     83 			if (ncols < 1)
     84 				ncols = 1;
     85 		} else {
     86 			if (win->begy > LINES)
     87 				win->begy = 0;
     88 			if (win->begy + nlines > LINES)
     89 				nlines = 0;
     90 			if (nlines <= 0)
     91 				nlines += LINES - win->begy;
     92 			if (nlines < 1)
     93 				nlines = 1;
     94 			if (win->begx > COLS)
     95 				win->begx = 0;
     96 			if (win->begx + ncols > COLS)
     97 				ncols = 0;
     98 			if (ncols <= 0)
     99 				ncols += COLS - win->begx;
    100 			if (ncols < 1)
    101 				ncols = 1;
    102 		}
    103 	} else {
    104 		/* subwins must fit inside the parent - check this */
    105 		if (win->begy > win->orig->begy + win->orig->maxy)
    106 			win->begy = win->orig->begy + win->orig->maxy - 1;
    107 		if (win->begy + nlines > win->orig->begy + win->orig->maxy)
    108 			nlines = 0;
    109 		if (nlines <= 0)
    110 			nlines += win->orig->begy + win->orig->maxy - win->begy;
    111 		if (nlines < 1)
    112 			nlines = 1;
    113 		if (win->begx > win->orig->begx + win->orig->maxx)
    114 			win->begx = win->orig->begx + win->orig->maxx - 1;
    115 		if (win->begx + ncols > win->orig->begx + win->orig->maxx)
    116 			ncols = 0;
    117 		if (ncols <= 0)
    118 			ncols += win->orig->begx + win->orig->maxx - win->begx;
    119 		if (ncols < 1)
    120 			ncols = 1;
    121 	}
    122 
    123 	if ((__resizewin(win, nlines, ncols)) == ERR)
    124 		return ERR;
    125 
    126 	win->reqy = req_nlines;
    127 	win->reqx = req_ncols;
    128 
    129 	/* If someone resizes curscr, we must also resize __virtscr */
    130 	if (win == curscr) {
    131 		if ((__resizewin(__virtscr, nlines, ncols)) == ERR)
    132 			return ERR;
    133 		__virtscr->reqy = req_nlines;
    134 		__virtscr->reqx = req_ncols;
    135 	}
    136 
    137 	return OK;
    138 }
    139 
    140 /*
    141  * resizeterm --
    142  *	Resize the terminal window, resizing the dependent windows.
    143  */
    144 int
    145 resizeterm(int nlines, int ncols)
    146 {
    147 	WINDOW *win;
    148 	struct __winlist *list;
    149 
    150 	  /* don't worry if things have not changed... we would like to
    151 	     do this but some bastard programs update LINES and COLS before
    152 	     calling resizeterm thus negating it's effect.
    153 	if ((nlines == LINES) && (ncols == COLS))
    154 	return OK;*/
    155 
    156 #ifdef	DEBUG
    157 	__CTRACE(__CTRACE_WINDOW, "resizeterm: (%d, %d)\n", nlines, ncols);
    158 #endif
    159 
    160 	if (__resizeterm(curscr, nlines, ncols) == ERR)
    161 		return ERR;
    162 	if (__resizeterm(__virtscr, nlines, ncols) == ERR)
    163 		return ERR;
    164 	if (__resizeterm(stdscr, nlines, ncols) == ERR)
    165 		return ERR;
    166 
    167 	LINES = nlines;
    168 	COLS = ncols;
    169 
    170 	  /* tweak the flags now that we have updated the LINES and COLS */
    171 	for (list = _cursesi_screen->winlistp; list != NULL; list = list->nextp) {
    172 		win = list->winp;
    173 
    174 		if (!(win->flags & __ISPAD))
    175 			__swflags(win);
    176 	}
    177 
    178 	wrefresh(curscr);
    179 	return OK;
    180 }
    181 
    182 /*
    183  * __resizeterm
    184  *	Setup window for resizing.
    185  */
    186 static int
    187 __resizeterm(WINDOW *win, int nlines, int ncols)
    188 {
    189 	int newlines, newcols;
    190 
    191 	newlines = win->reqy;
    192 	if (win->begy + newlines >= nlines)
    193 		newlines = 0;
    194 	if (newlines == 0)
    195 		newlines = nlines - win->begy;
    196 
    197 	newcols = win->reqx;
    198 	if (win->begx + newcols >= ncols)
    199 		newcols = 0;
    200 	if (newcols == 0)
    201 		newcols = ncols - win->begx;
    202 
    203 	return __resizewin(win, newlines, newcols);
    204 }
    205 
    206 /*
    207  * __resizewin --
    208  *	Resize the given window.
    209  */
    210 static int
    211 __resizewin(WINDOW *win, int nlines, int ncols)
    212 {
    213 	__LINE			*lp, *olp, **newlines, *newlspace;
    214 	__LDATA			*sp;
    215 	__LDATA			*newwspace;
    216 	int			 i, j;
    217 	int			 y, x;
    218 	WINDOW			*swin;
    219 
    220 #ifdef	DEBUG
    221 	__CTRACE(__CTRACE_WINDOW, "resize: (%p, %d, %d)\n", win, nlines, ncols);
    222 	__CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr);
    223 	__CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags);
    224 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy);
    225 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx);
    226 	__CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy);
    227 	__CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx);
    228 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t);
    229 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b);
    230 #endif
    231 
    232 	/*
    233 	 * free up any non-spacing storage before we lose the
    234 	 * pointers...
    235 	 */
    236 #ifdef HAVE_WCHAR
    237 	__cursesi_win_free_nsp(win);
    238 #endif
    239 
    240 	if (nlines <= 0 || ncols <= 0)
    241 		nlines = ncols = 0;
    242 	else {
    243 		/* Reallocate line pointer array and line space. */
    244 		newlines = realloc(win->lines, nlines * sizeof(__LINE *));
    245 		if (newlines == NULL)
    246 			return ERR;
    247 		win->lines = newlines;
    248 
    249 		newlspace = realloc(win->lspace, nlines * sizeof(__LINE));
    250 		if (newlspace == NULL)
    251 			return ERR;
    252 		win->lspace = newlspace;
    253 	}
    254 
    255 	/* Don't allocate window and line space if it's a subwindow */
    256 	if (win->orig == NULL) {
    257 		/*
    258 		 * Allocate window space in one chunk.
    259 		 */
    260 		if (ncols != 0) {
    261 			newwspace = realloc(win->wspace,
    262 					    ncols * nlines * sizeof(__LDATA));
    263 			if (newwspace == NULL)
    264 				return ERR;
    265 			win->wspace = newwspace;
    266 		}
    267 
    268 		/*
    269 		 * Point line pointers to line space, and lines themselves into
    270 		 * window space.
    271 		 */
    272 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    273 			win->lines[i] = lp;
    274 			lp->line = &win->wspace[i * ncols];
    275 #ifdef DEBUG
    276 			lp->sentinel = SENTINEL_VALUE;
    277 #endif
    278 			lp->firstchp = &lp->firstch;
    279 			lp->lastchp = &lp->lastch;
    280 			lp->firstch = 0;
    281 			lp->lastch = ncols - 1;
    282 			lp->flags = __ISDIRTY;
    283 		}
    284 	} else {
    285 
    286 		win->ch_off = win->begx - win->orig->begx;
    287 		  /* Point line pointers to line space. */
    288 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    289 			win->lines[i] = lp;
    290 			olp = win->orig->lines[i + win->begy - win->orig->begy];
    291 			lp->line = &olp->line[win->ch_off];
    292 #ifdef DEBUG
    293 			lp->sentinel = SENTINEL_VALUE;
    294 #endif
    295 			lp->firstchp = &olp->firstch;
    296 			lp->lastchp = &olp->lastch;
    297 			lp->flags = __ISDIRTY;
    298 		}
    299 	}
    300 
    301 
    302 	win->cury = win->curx = 0;
    303 	win->maxy = nlines;
    304 	win->maxx = ncols;
    305 	win->scr_b = win->maxy - 1;
    306 	__swflags(win);
    307 
    308 	  /*
    309 	   * we must zot the window contents otherwise lines may pick
    310 	   * up attributes from the previous line when the window is
    311 	   * made smaller.  The client will redraw the window anyway
    312 	   * so this is no big deal.
    313 	   */
    314 	for (i = 0; i < win->maxy; i++) {
    315 		lp = win->lines[i];
    316 		for (sp = lp->line, j = 0; j < win->maxx; j++, sp++) {
    317 			sp->attr = 0;
    318 #ifndef HAVE_WCHAR
    319 			sp->ch = win->bch;
    320 #else
    321 			sp->ch = ( wchar_t )btowc(( int ) win->bch );
    322 			sp->nsp = NULL;
    323 			if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
    324 				return ERR;
    325 			SET_WCOL( *sp, 1 );
    326 #endif /* HAVE_WCHAR */
    327 		}
    328 		lp->hash = __hash((char *)(void *)lp->line,
    329 				  (size_t) (ncols * __LDATASIZE));
    330 	}
    331 
    332 #ifdef DEBUG
    333 	__CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr);
    334 	__CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags);
    335 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy);
    336 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx);
    337 	__CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy);
    338 	__CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx);
    339 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t);
    340 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b);
    341 #endif
    342 
    343 	if (win->orig == NULL) {
    344 		/* bound subwindows to new size and fixup their pointers */
    345 		for (swin = win->nextp; swin != win; swin = swin->nextp) {
    346 			y = swin->reqy;
    347 			if (swin->begy > win->begy + win->maxy)
    348 				swin->begy = win->begy + win->maxy - 1;
    349 			if (swin->begy + y > win->begy + win->maxy)
    350 				y = 0;
    351 			if (y <= 0)
    352 				y += win->begy + win->maxy - swin->begy;
    353 			if (y < 1)
    354 				y = 1;
    355 			x = swin->reqx;
    356 			if (swin->begx > win->begx + win->maxx)
    357 				swin->begx = win->begx + win->maxx - 1;
    358 			if (swin->begx + x > win->begx + win->maxx)
    359 				x = 0;
    360 			if (x <= 0)
    361 				x += win->begy + win->maxx - swin->begx;
    362 			if (x < 1)
    363 				x = 1;
    364 			__resizewin(swin, y, x);
    365 		}
    366 	}
    367 
    368 	return OK;
    369 }
    370