Home | History | Annotate | Line # | Download | only in libcurses
resize.c revision 1.12.4.2
      1 /*	$NetBSD: resize.c,v 1.12.4.2 2007/09/01 07:43:40 pavel 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.12.4.2 2007/09/01 07:43:40 pavel 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("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("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("resize: (%p, %d, %d)\n", win, nlines, ncols);
    184 	__CTRACE("resize: win->wattr = %08x\n", win->wattr);
    185 	__CTRACE("resize: win->flags = %#.4x\n", win->flags);
    186 	__CTRACE("resize: win->maxy = %d\n", win->maxy);
    187 	__CTRACE("resize: win->maxx = %d\n", win->maxx);
    188 	__CTRACE("resize: win->begy = %d\n", win->begy);
    189 	__CTRACE("resize: win->begx = %d\n", win->begx);
    190 	__CTRACE("resize: win->scr_t = %d\n", win->scr_t);
    191 	__CTRACE("resize: win->scr_b = %d\n", win->scr_b);
    192 #endif
    193 
    194 	if (nlines <= 0 || ncols <= 0)
    195 		nlines = ncols = 0;
    196 	else {
    197 		/* Reallocate line pointer array and line space. */
    198 		newlines = realloc(win->lines, nlines * sizeof(__LINE *));
    199 		if (newlines == NULL)
    200 			return ERR;
    201 		win->lines = newlines;
    202 
    203 		newlspace = realloc(win->lspace, nlines * sizeof(__LINE));
    204 		if (newlspace == NULL)
    205 			return ERR;
    206 		win->lspace = newlspace;
    207 	}
    208 
    209 	/* Don't allocate window and line space if it's a subwindow */
    210 	if (win->orig == NULL) {
    211 		/*
    212 		 * Allocate window space in one chunk.
    213 		 */
    214 		if (ncols != 0) {
    215 			newwspace = realloc(win->wspace,
    216 					    ncols * nlines * sizeof(__LDATA));
    217 			if (newwspace == NULL)
    218 				return ERR;
    219 			win->wspace = newwspace;
    220 		}
    221 
    222 		/*
    223 		 * Point line pointers to line space, and lines themselves into
    224 		 * window space.
    225 		 */
    226 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    227 			win->lines[i] = lp;
    228 			lp->line = &win->wspace[i * ncols];
    229 #ifdef DEBUG
    230 			lp->sentinel = SENTINEL_VALUE;
    231 #endif
    232 			lp->firstchp = &lp->firstch;
    233 			lp->lastchp = &lp->lastch;
    234 			lp->firstch = 0;
    235 			lp->lastch = ncols - 1;
    236 			lp->flags = __ISDIRTY;
    237 		}
    238 	} else {
    239 
    240 		win->ch_off = win->begx - win->orig->begx;
    241 		  /* Point line pointers to line space. */
    242 		for (lp = win->lspace, i = 0; i < nlines; i++, lp++) {
    243 			win->lines[i] = lp;
    244 			olp = win->orig->lines[i + win->begy
    245 					      - win->orig->begy];
    246 			lp->line = &olp->line[win->ch_off];
    247 #ifdef DEBUG
    248 			lp->sentinel = SENTINEL_VALUE;
    249 #endif
    250 			lp->firstchp = &olp->firstch;
    251 			lp->lastchp = &olp->lastch;
    252 			lp->flags = __ISDIRTY;
    253 		}
    254 	}
    255 
    256 
    257 	win->cury = win->curx = 0;
    258 	win->maxy = nlines;
    259 	win->maxx = ncols;
    260 	win->scr_b = win->maxy - 1;
    261 	__swflags(win);
    262 
    263 	  /*
    264 	   * we must zot the window contents otherwise lines may pick
    265 	   * up attributes from the previous line when the window is
    266 	   * made smaller.  The client will redraw the window anyway
    267 	   * so this is no big deal.
    268 	   */
    269 	for (i = 0; i < win->maxy; i++) {
    270 		lp = win->lines[i];
    271 		for (sp = lp->line, j = 0; j < win->maxx; j++, sp++) {
    272 			sp->ch = ' ';
    273 			sp->attr = 0;
    274 		}
    275 		lp->hash = __hash((char *)(void *)lp->line,
    276 				  (size_t) (ncols * __LDATASIZE));
    277 	}
    278 
    279 #ifdef DEBUG
    280 	__CTRACE("resize: win->wattr = %08x\n", win->wattr);
    281 	__CTRACE("resize: win->flags = %#.4x\n", win->flags);
    282 	__CTRACE("resize: win->maxy = %d\n", win->maxy);
    283 	__CTRACE("resize: win->maxx = %d\n", win->maxx);
    284 	__CTRACE("resize: win->begy = %d\n", win->begy);
    285 	__CTRACE("resize: win->begx = %d\n", win->begx);
    286 	__CTRACE("resize: win->scr_t = %d\n", win->scr_t);
    287 	__CTRACE("resize: win->scr_b = %d\n", win->scr_b);
    288 #endif
    289 
    290 	if (win->orig == NULL) {
    291 		/* bound subwindows to new size and fixup their pointers */
    292 		for (swin = win->nextp; swin != win; swin = swin->nextp) {
    293 			y = swin->reqy;
    294 			if (swin->begy + y > win->begy + win->maxy)
    295 				y = 0;
    296 			if (y <= 0)
    297 				y += win->begy + win->maxy - swin->begy;
    298 			x = swin->reqx;
    299 			if (swin->begx + x > win->begx + win->maxx)
    300 				x = 0;
    301 			if (x <= 0)
    302 				x += win->begy + win->maxx - swin->begx;
    303 			__resizewin(swin, y, x);
    304 		}
    305 	}
    306 
    307 	return OK;
    308 }
    309 
    310