1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Thomas E. Dickey 1996-on *
31 * and: Juergen Pfeifer *
32 ****************************************************************************/
34 #include <curses.priv.h>
36 MODULE_ID("$Id: wresize.c,v 1.34 2010/06/05 22:36:26 tom Exp $")
39 cleanup_lines(struct ldat
*data
, int length
)
42 free(data
[length
].text
);
48 * If we have reallocated the ldat structs, we will have to repair pointers
52 repair_subwindows(WINDOW
*cmp
)
55 struct ldat
*pline
= cmp
->_line
;
57 #ifdef USE_SP_WINDOWLIST
58 SCREEN
*sp
= _nc_screen_of(cmp
);
61 _nc_lock_global(curses
);
63 for (each_window(SP_PARM
, wp
)) {
64 WINDOW
*tst
= &(wp
->win
);
66 if (tst
->_parent
== cmp
) {
68 if (tst
->_pary
> cmp
->_maxy
)
69 tst
->_pary
= cmp
->_maxy
;
70 if (tst
->_parx
> cmp
->_maxx
)
71 tst
->_parx
= cmp
->_maxx
;
73 if (tst
->_maxy
+ tst
->_pary
> cmp
->_maxy
)
74 tst
->_maxy
= (NCURSES_SIZE_T
) (cmp
->_maxy
- tst
->_pary
);
75 if (tst
->_maxx
+ tst
->_parx
> cmp
->_maxx
)
76 tst
->_maxx
= (NCURSES_SIZE_T
) (cmp
->_maxx
- tst
->_parx
);
78 for (row
= 0; row
<= tst
->_maxy
; ++row
) {
79 tst
->_line
[row
].text
= &pline
[tst
->_pary
+ row
].text
[tst
->_parx
];
81 repair_subwindows(tst
);
84 _nc_unlock_global(curses
);
88 * Reallocate a curses WINDOW struct to either shrink or grow to the specified
89 * new lines/columns. If it grows, the new character cells are filled with
90 * blanks. The application is responsible for repainting the blank area.
93 wresize(WINDOW
*win
, int ToLines
, int ToCols
)
95 int col
, row
, size_x
, size_y
;
97 struct ldat
*new_lines
= 0;
100 T((T_CALLED("wresize(%p,%d,%d)"), (void *) win
, ToLines
, ToCols
));
102 TR(TRACE_UPDATE
, ("...beg (%ld, %ld), max(%ld,%ld), reg(%ld,%ld)",
103 (long) win
->_begy
, (long) win
->_begx
,
104 (long) win
->_maxy
, (long) win
->_maxx
,
105 (long) win
->_regtop
, (long) win
->_regbottom
));
106 if (USE_TRACEF(TRACE_UPDATE
)) {
107 _tracedump("...before", win
);
108 _nc_unlock_global(tracef
);
113 if (!win
|| --ToLines
< 0 || --ToCols
< 0)
119 if (ToLines
== size_y
123 if ((win
->_flags
& _SUBWIN
)) {
125 * Check if the new limits will fit into the parent window's size. If
126 * not, do not resize. We could adjust the location of the subwindow,
127 * but the application may not like that.
129 if (win
->_pary
+ ToLines
> win
->_parent
->_maxy
130 || win
->_parx
+ ToCols
> win
->_parent
->_maxx
) {
133 pline
= win
->_parent
->_line
;
139 * Allocate new memory as needed. Do the allocations without modifying
140 * the original window, in case an allocation fails. Always allocate
141 * (at least temporarily) the array pointing to the individual lines.
143 new_lines
= typeCalloc(struct ldat
, (unsigned) (ToLines
+ 1));
148 * For each line in the target, allocate or adjust pointers for the
149 * corresponding text, depending on whether this is a window or a
152 for (row
= 0; row
<= ToLines
; ++row
) {
153 int begin
= (row
> size_y
) ? 0 : (size_x
+ 1);
157 if (!(win
->_flags
& _SUBWIN
)) {
159 if (ToCols
!= size_x
) {
160 s
= typeMalloc(NCURSES_CH_T
, (unsigned) ToCols
+ 1);
162 returnCode(cleanup_lines(new_lines
, row
));
163 for (col
= 0; col
<= ToCols
; ++col
) {
164 s
[col
] = (col
<= size_x
165 ? win
->_line
[row
].text
[col
]
169 s
= win
->_line
[row
].text
;
172 s
= typeMalloc(NCURSES_CH_T
, (unsigned) ToCols
+ 1);
174 returnCode(cleanup_lines(new_lines
, row
));
175 for (col
= 0; col
<= ToCols
; ++col
)
176 s
[col
] = win
->_nc_bkgd
;
180 s
= &pline
[win
->_pary
+ row
].text
[win
->_parx
];
183 if_USE_SCROLL_HINTS(new_lines
[row
].oldindex
= row
);
185 new_lines
[row
].firstchar
= win
->_line
[row
].firstchar
;
186 new_lines
[row
].lastchar
= win
->_line
[row
].lastchar
;
188 if ((ToCols
!= size_x
) || (row
> size_y
)) {
189 if (end
>= begin
) { /* growing */
190 if (new_lines
[row
].firstchar
< begin
)
191 new_lines
[row
].firstchar
= (NCURSES_SIZE_T
) begin
;
192 } else { /* shrinking */
193 new_lines
[row
].firstchar
= 0;
195 new_lines
[row
].lastchar
= (NCURSES_SIZE_T
) ToCols
;
197 new_lines
[row
].text
= s
;
201 * Dispose of unwanted memory.
203 if (!(win
->_flags
& _SUBWIN
)) {
204 if (ToCols
== size_x
) {
205 for (row
= ToLines
+ 1; row
<= size_y
; row
++) {
206 free(win
->_line
[row
].text
);
209 for (row
= 0; row
<= size_y
; row
++) {
210 free(win
->_line
[row
].text
);
216 win
->_line
= new_lines
;
219 * Finally, adjust the parameters showing screen size and cursor
222 win
->_maxx
= (NCURSES_SIZE_T
) ToCols
;
223 win
->_maxy
= (NCURSES_SIZE_T
) ToLines
;
225 if (win
->_regtop
> win
->_maxy
)
226 win
->_regtop
= win
->_maxy
;
227 if (win
->_regbottom
> win
->_maxy
228 || win
->_regbottom
== size_y
)
229 win
->_regbottom
= win
->_maxy
;
231 if (win
->_curx
> win
->_maxx
)
232 win
->_curx
= win
->_maxx
;
233 if (win
->_cury
> win
->_maxy
)
234 win
->_cury
= win
->_maxy
;
237 * Check for subwindows of this one, and readjust pointers to our text,
240 repair_subwindows(win
);
243 TR(TRACE_UPDATE
, ("...beg (%ld, %ld), max(%ld,%ld), reg(%ld,%ld)",
244 (long) win
->_begy
, (long) win
->_begx
,
245 (long) win
->_maxy
, (long) win
->_maxx
,
246 (long) win
->_regtop
, (long) win
->_regbottom
));
247 if (USE_TRACEF(TRACE_UPDATE
)) {
248 _tracedump("...after:", win
);
249 _nc_unlock_global(tracef
);