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