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