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