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