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