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