xref: /openbsd-src/lib/libcurses/base/wresize.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: wresize.c,v 1.4 2001/01/22 18:01:49 millert Exp $	*/
2 
3 /****************************************************************************
4  * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc.              *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *  Author: Thomas E. Dickey <dickey@clark.net> 1996,1997                   *
33  ****************************************************************************/
34 
35 #include <curses.priv.h>
36 
37 MODULE_ID("$From: wresize.c,v 1.18 2000/12/10 02:43:28 tom Exp $")
38 
39 /*
40  * Reallocate a curses WINDOW struct to either shrink or grow to the specified
41  * new lines/columns.  If it grows, the new character cells are filled with
42  * blanks.  The application is responsible for repainting the blank area.
43  */
44 
45 #define DOALLOC(p,t,n)  typeRealloc(t, n, p)
46 #define	ld_ALLOC(p,n)	DOALLOC(p,struct ldat,n)
47 #define	c_ALLOC(p,n)	DOALLOC(p,chtype,n)
48 
49 NCURSES_EXPORT(int)
50 wresize(WINDOW *win, int ToLines, int ToCols)
51 {
52     register int row;
53     int size_x, size_y;
54     struct ldat *pline;
55     chtype blank;
56 
57 #ifdef TRACE
58     T((T_CALLED("wresize(%p,%d,%d)"), win, ToLines, ToCols));
59     if (win) {
60 	TR(TRACE_UPDATE, ("...beg (%d, %d), max(%d,%d), reg(%d,%d)",
61 			  win->_begy, win->_begx,
62 			  win->_maxy, win->_maxx,
63 			  win->_regtop, win->_regbottom));
64 	if (_nc_tracing & TRACE_UPDATE)
65 	    _tracedump("...before", win);
66     }
67 #endif
68 
69     if (!win || --ToLines < 0 || --ToCols < 0)
70 	returnCode(ERR);
71 
72     size_x = win->_maxx;
73     size_y = win->_maxy;
74 
75     if (ToLines == size_y
76 	&& ToCols == size_x)
77 	returnCode(OK);
78 
79     if ((win->_flags & _SUBWIN)) {
80 	/*
81 	 * Check if the new limits will fit into the parent window's size.  If
82 	 * not, do not resize.  We could adjust the location of the subwindow,
83 	 * but the application may not like that.
84 	 */
85 	if (win->_pary + ToLines > win->_parent->_maxy
86 	    || win->_parx + ToCols > win->_parent->_maxx) {
87 	    returnCode(ERR);
88 	}
89 	pline = win->_parent->_line;
90     } else {
91 	pline = 0;
92     }
93 
94     /*
95      * If the number of lines has changed, adjust the size of the overall
96      * vector:
97      */
98     if (ToLines != size_y) {
99 	if (!(win->_flags & _SUBWIN)) {
100 	    for (row = ToLines + 1; row <= size_y; row++)
101 		free((char *) (win->_line[row].text));
102 	}
103 
104 	win->_line = ld_ALLOC(win->_line, ToLines + 1);
105 	if (win->_line == 0)
106 	    returnCode(ERR);
107 
108 	for (row = size_y + 1; row <= ToLines; row++) {
109 	    win->_line[row].text = 0;
110 	    win->_line[row].firstchar = 0;
111 	    win->_line[row].lastchar = ToCols;
112 	    if ((win->_flags & _SUBWIN)) {
113 		win->_line[row].text =
114 		    &pline[win->_pary + row].text[win->_parx];
115 	    }
116 	}
117     }
118 
119     /*
120      * Adjust the width of the columns:
121      */
122     blank = _nc_background(win);
123     for (row = 0; row <= ToLines; row++) {
124 	chtype *s = win->_line[row].text;
125 	int begin = (s == 0) ? 0 : size_x + 1;
126 	int end = ToCols;
127 
128 	if_USE_SCROLL_HINTS(win->_line[row].oldindex = row);
129 
130 	if (ToCols != size_x || s == 0) {
131 	    if (!(win->_flags & _SUBWIN)) {
132 		win->_line[row].text = s = c_ALLOC(s, ToCols + 1);
133 		if (win->_line[row].text == 0)
134 		    returnCode(ERR);
135 	    } else if (s == 0) {
136 		win->_line[row].text = s =
137 		    &pline[win->_pary + row].text[win->_parx];
138 	    }
139 
140 	    if (end >= begin) {	/* growing */
141 		if (win->_line[row].firstchar < begin)
142 		    win->_line[row].firstchar = begin;
143 		win->_line[row].lastchar = ToCols;
144 		do {
145 		    s[end] = blank;
146 		} while (--end >= begin);
147 	    } else {		/* shrinking */
148 		win->_line[row].firstchar = 0;
149 		win->_line[row].lastchar = ToCols;
150 	    }
151 	}
152     }
153 
154     /*
155      * Finally, adjust the parameters showing screen size and cursor
156      * position:
157      */
158     win->_maxx = ToCols;
159     win->_maxy = ToLines;
160 
161     if (win->_regtop > win->_maxy)
162 	win->_regtop = win->_maxy;
163     if (win->_regbottom > win->_maxy
164 	|| win->_regbottom == size_y)
165 	win->_regbottom = win->_maxy;
166 
167     if (win->_curx > win->_maxx)
168 	win->_curx = win->_maxx;
169     if (win->_cury > win->_maxy)
170 	win->_cury = win->_maxy;
171 
172 #ifdef TRACE
173     TR(TRACE_UPDATE, ("...beg (%d, %d), max(%d,%d), reg(%d,%d)",
174 		      win->_begy, win->_begx,
175 		      win->_maxy, win->_maxx,
176 		      win->_regtop, win->_regbottom));
177     if (_nc_tracing & TRACE_UPDATE)
178 	_tracedump("...after:", win);
179 #endif
180     returnCode(OK);
181 }
182