Home | History | Annotate | Line # | Download | only in libcurses
resize.c revision 1.14.4.1
      1 /*	$NetBSD: resize.c,v 1.14.4.1 2007/11/06 23:11:26 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.1 2007/11/06 23:11:26 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 (win->begy + nlines > LINES)
     78 				nlines = 0;
     79 			if (nlines <= 0)
     80 				nlines += LINES - win->begy;
     81 			if (win->begx + ncols > COLS)
     82 				ncols = 0;
     83 			if (ncols <= 0)
     84 				ncols += COLS - win->begx;
     85 		}
     86 	} else {
     87 		/* subwins must fit inside the parent - check this */
     88 		if (win->begy + nlines > win->orig->begy + win->orig->maxy)
     89 			nlines = 0;
     90 		if (nlines <= 0)
     91 			nlines += win->orig->begy + win->orig->maxy - win->begy;
     92 		if (win->begx + ncols > win->orig->begx + win->orig->maxx)
     93 			ncols = 0;
     94 		if (ncols <= 0)
     95 			ncols += win->orig->begx + win->orig->maxx - win->begx;
     96 	}
     97 
     98 	if ((__resizewin(win, nlines, ncols)) == ERR)
     99 		return ERR;
    100 
    101 	win->reqy = req_nlines;
    102 	win->reqx = req_ncols;
    103 
    104 	/* If someone resizes curscr, we must also resize __virtscr */
    105 	if (win == curscr) {
    106 		if ((__resizewin(__virtscr, nlines, ncols)) == ERR)
    107 			return ERR;
    108 		__virtscr->reqy = req_nlines;
    109 		__virtscr->reqx = req_ncols;
    110 	}
    111 
    112 	return OK;
    113 }
    114 
    115 /*
    116  * resizeterm --
    117  *	Resize the terminal window, resizing the dependent windows.
    118  */
    119 int
    120 resizeterm(int nlines, int ncols)
    121 {
    122 	WINDOW *win;
    123 	struct __winlist *list;
    124 
    125 	  /* don't worry if things have not changed... we would like to
    126 	     do this but some bastard programs update LINES and COLS before
    127 	     calling resizeterm thus negating it's effect.
    128 	if ((nlines == LINES) && (ncols == COLS))
    129 	return OK;*/
    130 
    131 #ifdef	DEBUG
    132 	__CTRACE(__CTRACE_WINDOW, "resizeterm: (%d, %d)\n", nlines, ncols);
    133 #endif
    134 
    135 	if (__resizeterm(curscr, nlines, ncols) == ERR)
    136 		return ERR;
    137 	if (__resizeterm(__virtscr, nlines, ncols) == ERR)
    138 		return ERR;
    139 	if (__resizeterm(stdscr, nlines, ncols) == ERR)
    140 		return ERR;
    141 
    142 	LINES = nlines;
    143 	COLS = ncols;
    144 
    145 	  /* tweak the flags now that we have updated the LINES and COLS */
    146 	for (list = _cursesi_screen->winlistp; list != NULL; list = list->nextp) {
    147 		win = list->winp;
    148 
    149 		if (!(win->flags & __ISPAD))
    150 			__swflags(win);
    151 	}
    152 
    153 	wrefresh(curscr);
    154 	return OK;
    155 }
    156 
    157 /*
    158  * __resizeterm
    159  *	Setup window for resizing.
    160  */
    161 static int
    162 __resizeterm(WINDOW *win, int nlines, int ncols)
    163 {
    164 	int newlines, newcols;
    165 
    166 	newlines = win->reqy;
    167 	if (win->begy + newlines >= nlines)
    168 		newlines = 0;
    169 	if (newlines == 0)
    170 		newlines = nlines - win->begy;
    171 
    172 	newcols = win->reqx;
    173 	if (win->begx + newcols >= ncols)
    174 		newcols = 0;
    175 	if (newcols == 0)
    176 		newcols = ncols - win->begx;
    177 
    178 	return __resizewin(win, newlines, newcols);
    179 }
    180 
    181 /*
    182  * __resizewin --
    183  *	Resize the given window.
    184  */
    185 static int
    186 __resizewin(WINDOW *win, int nlines, int ncols)
    187 {
    188 	__LINE			*lp, *olp, **newlines, *newlspace;
    189 	__LDATA			*sp;
    190 	__LDATA			*newwspace;
    191 	int			 i, j;
    192 	int			 y, x;
    193 	WINDOW			*swin;
    194 
    195 #ifdef	DEBUG
    196 	__CTRACE(__CTRACE_WINDOW, "resize: (%p, %d, %d)\n", win, nlines, ncols);
    197 	__CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr);
    198 	__CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags);
    199 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy);
    200 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx);
    201 	__CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy);
    202 	__CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx);
    203 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t);
    204 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b);
    205 #endif
    206 
    207 	/*
    208 	 * free up any non-spacing storage before we lose the
    209 	 * pointers...
    210 	 */
    211 #ifdef HAVE_WCHAR
    212 	__cursesi_win_free_nsp(win);
    213 #endif
    214 
    215 	if (nlines <= 0 || ncols <= 0)
    216 		nlines = ncols = 0;
    217 	else {
    218 		/* Reallocate line pointer array and line space. */
    219 		newlines = realloc(win->lines, nlines * sizeof(__LINE *));
    220 		if (newlines == NULL)
    221 			return ERR;
    222 		win->lines = newlines;
    223 
    224 		newlspace = realloc(win->lspace, nlines * sizeof(__LINE));
    225 		if (newlspace == NULL)
    226 			return ERR;
    227 		win->lspace = newlspace;
    228 	}
    229 
    230 	/* Don't allocate window and line space if it's a subwindow */
    231 	if (win->orig == NULL) {
    232 		/*
    233 		 * Allocate window space in one chunk.
    234 		 */
    235 		if (ncols != 0) {
    236 			newwspace = realloc(win->wspace,
    237 					    ncols * nlines * sizeof(__LDATA));
    238 			if (newwspace == NULL)
    239 				return ERR;
    240 			win->wspace = newwspace;
    241 		}
    242 
    243 		/*
    244 		 * Point line pointers to line space, and lines themselves into
    245 		 * window space.
    246 		 */
    247 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    248 			win->lines[i] = lp;
    249 			lp->line = &win->wspace[i * ncols];
    250 #ifdef DEBUG
    251 			lp->sentinel = SENTINEL_VALUE;
    252 #endif
    253 			lp->firstchp = &lp->firstch;
    254 			lp->lastchp = &lp->lastch;
    255 			lp->firstch = 0;
    256 			lp->lastch = ncols - 1;
    257 			lp->flags = __ISDIRTY;
    258 		}
    259 	} else {
    260 
    261 		win->ch_off = win->begx - win->orig->begx;
    262 		  /* Point line pointers to line space. */
    263 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    264 			win->lines[i] = lp;
    265 			olp = win->orig->lines[i + win->begy - win->orig->begy];
    266 			lp->line = &olp->line[win->ch_off];
    267 #ifdef DEBUG
    268 			lp->sentinel = SENTINEL_VALUE;
    269 #endif
    270 			lp->firstchp = &olp->firstch;
    271 			lp->lastchp = &olp->lastch;
    272 			lp->flags = __ISDIRTY;
    273 		}
    274 	}
    275 
    276 
    277 	win->cury = win->curx = 0;
    278 	win->maxy = nlines;
    279 	win->maxx = ncols;
    280 	win->scr_b = win->maxy - 1;
    281 	__swflags(win);
    282 
    283 	  /*
    284 	   * we must zot the window contents otherwise lines may pick
    285 	   * up attributes from the previous line when the window is
    286 	   * made smaller.  The client will redraw the window anyway
    287 	   * so this is no big deal.
    288 	   */
    289 	for (i = 0; i < win->maxy; i++) {
    290 		lp = win->lines[i];
    291 		for (sp = lp->line, j = 0; j < win->maxx; j++, sp++) {
    292 			sp->attr = 0;
    293 #ifndef HAVE_WCHAR
    294 			sp->ch = win->bch;
    295 #else
    296 			sp->ch = ( wchar_t )btowc(( int ) win->bch );
    297 			sp->nsp = NULL;
    298 			if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
    299 				return ERR;
    300 			SET_WCOL( *sp, 1 );
    301 #endif /* HAVE_WCHAR */
    302 		}
    303 		lp->hash = __hash((char *)(void *)lp->line,
    304 				  (size_t) (ncols * __LDATASIZE));
    305 	}
    306 
    307 #ifdef DEBUG
    308 	__CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr);
    309 	__CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags);
    310 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy);
    311 	__CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx);
    312 	__CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy);
    313 	__CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx);
    314 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t);
    315 	__CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b);
    316 #endif
    317 
    318 	if (win->orig == NULL) {
    319 		/* bound subwindows to new size and fixup their pointers */
    320 		for (swin = win->nextp; swin != win; swin = swin->nextp) {
    321 			y = swin->reqy;
    322 			if (swin->begy + y > win->begy + win->maxy)
    323 				y = 0;
    324 			if (y <= 0)
    325 				y += win->begy + win->maxy - swin->begy;
    326 			x = swin->reqx;
    327 			if (swin->begx + x > win->begx + win->maxx)
    328 				x = 0;
    329 			if (x <= 0)
    330 				x += win->begy + win->maxx - swin->begx;
    331 			__resizewin(swin, y, x);
    332 		}
    333 	}
    334 
    335 	return OK;
    336 }
    337