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