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