10e3d5408SPeter Wemm /****************************************************************************
2d8977eafSRong-En Fan  * Copyright 2020 Thomas E. Dickey                                          *
30e3d5408SPeter Wemm  * Copyright 1998-2015,2016 Free Software Foundation, Inc.                  *
40e3d5408SPeter Wemm  *                                                                          *
50e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
60e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
70e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
80e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
90e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
100e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
110e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
120e3d5408SPeter Wemm  *                                                                          *
130e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
140e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
150e3d5408SPeter Wemm  *                                                                          *
160e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
170e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
180e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
190e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
200e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
210e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
220e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
230e3d5408SPeter Wemm  *                                                                          *
240e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
250e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
260e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
270e3d5408SPeter Wemm  * authorization.                                                           *
280e3d5408SPeter Wemm  ****************************************************************************/
290e3d5408SPeter Wemm 
304a1a9510SRong-En Fan /****************************************************************************
310e3d5408SPeter Wemm  *  Author: Thomas E. Dickey                                                *
320e3d5408SPeter Wemm  *     and: Juergen Pfeifer                                                 *
330e3d5408SPeter Wemm  ****************************************************************************/
340e3d5408SPeter Wemm 
350e3d5408SPeter Wemm /*
360e3d5408SPeter Wemm  * This is an extension to the curses library.  It provides callers with a hook
370e3d5408SPeter Wemm  * into the NCURSES data to resize windows, primarily for use by programs
380e3d5408SPeter Wemm  * running in an X Window terminal (e.g., xterm).  I abstracted this module
390e3d5408SPeter Wemm  * from my application library for NCURSES because it must be compiled with
400e3d5408SPeter Wemm  * the private data structures -- T.Dickey 1995/7/4.
410e3d5408SPeter Wemm  */
420e3d5408SPeter Wemm 
430e3d5408SPeter Wemm #include <curses.priv.h>
44aa59d4d4SRong-En Fan 
454a1a9510SRong-En Fan #ifndef CUR
464a1a9510SRong-En Fan #define CUR SP_TERMTYPE
474a1a9510SRong-En Fan #endif
485ca44d1cSRong-En Fan 
495ca44d1cSRong-En Fan MODULE_ID("$Id: resizeterm.c,v 1.50 2020/02/02 23:34:34 tom Exp $")
505ca44d1cSRong-En Fan 
515ca44d1cSRong-En Fan /*
525ca44d1cSRong-En Fan  * If we're trying to be reentrant, do not want any local statics.
535ca44d1cSRong-En Fan  */
545ca44d1cSRong-En Fan #if USE_REENTRANT
554a1a9510SRong-En Fan #define EXTRA_ARGS ,     CurLines,     CurCols
564a1a9510SRong-En Fan #define EXTRA_DCLS , int CurLines, int CurCols
575ca44d1cSRong-En Fan #else
585ca44d1cSRong-En Fan static int current_lines;
595ca44d1cSRong-En Fan static int current_cols;
605ca44d1cSRong-En Fan #define CurLines current_lines
615ca44d1cSRong-En Fan #define CurCols  current_cols
624a1a9510SRong-En Fan #define EXTRA_ARGS		/* nothing */
634a1a9510SRong-En Fan #define EXTRA_DCLS		/* nothing */
644a1a9510SRong-En Fan #endif
654a1a9510SRong-En Fan 
664a1a9510SRong-En Fan #if NCURSES_SP_FUNCS && !defined(USE_SP_WINDOWLIST)
674a1a9510SRong-En Fan #define UNUSED_SP  (void) sp
684a1a9510SRong-En Fan #else
695ca44d1cSRong-En Fan #define UNUSED_SP		/* nothing */
704a1a9510SRong-En Fan #endif
714a1a9510SRong-En Fan 
72aa59d4d4SRong-En Fan #ifdef TRACE
734a1a9510SRong-En Fan static void
show_window_sizes(const char * name)744a1a9510SRong-En Fan show_window_sizes(const char *name)
754a1a9510SRong-En Fan {
764a1a9510SRong-En Fan     SCREEN *sp;
774a1a9510SRong-En Fan     WINDOWLIST *wp;
784a1a9510SRong-En Fan 
794a1a9510SRong-En Fan     _nc_lock_global(curses);
805ca44d1cSRong-En Fan     for (each_screen(sp)) {
814a1a9510SRong-En Fan 	_tracef("%s resizing: %p: %2d x %2d (%2d x %2d)", name, (void *) sp,
824a1a9510SRong-En Fan 		*(ptrLines(sp)),
8339f2269fSPeter Wemm 		*(ptrCols(sp)),
84d8977eafSRong-En Fan 		screen_lines(sp), screen_columns(sp));
85d8977eafSRong-En Fan 	for (each_window(sp, wp)) {
86d8977eafSRong-En Fan 	    _tracef("  window %p is %2ld x %2ld at %2ld,%2ld",
87d8977eafSRong-En Fan 		    (void *) &(wp->win),
8839f2269fSPeter Wemm 		    (long) wp->win._maxy + 1,
8939f2269fSPeter Wemm 		    (long) wp->win._maxx + 1,
9039f2269fSPeter Wemm 		    (long) wp->win._begy,
914a1a9510SRong-En Fan 		    (long) wp->win._begx);
924a1a9510SRong-En Fan 	}
934a1a9510SRong-En Fan     }
944a1a9510SRong-En Fan     _nc_unlock_global(curses);
954a1a9510SRong-En Fan }
964a1a9510SRong-En Fan #endif
974a1a9510SRong-En Fan 
984a1a9510SRong-En Fan /*
99d8977eafSRong-En Fan  * Return true if the given dimensions do not match the internal terminal
100d8977eafSRong-En Fan  * structure's size.
101d8977eafSRong-En Fan  */
102d8977eafSRong-En Fan NCURSES_EXPORT(bool)
NCURSES_SP_NAME(is_term_resized)103d8977eafSRong-En Fan NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_DCLx int ToLines, int ToCols)
104d8977eafSRong-En Fan {
105d8977eafSRong-En Fan     T((T_CALLED("is_term_resized(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols));
106d8977eafSRong-En Fan     returnCode(ToLines > 0
107aa59d4d4SRong-En Fan 	       && ToCols > 0
108d8977eafSRong-En Fan 	       && (ToLines != screen_lines(SP_PARM)
109d8977eafSRong-En Fan 		   || ToCols != screen_columns(SP_PARM)));
110d8977eafSRong-En Fan }
111d8977eafSRong-En Fan 
112d8977eafSRong-En Fan #if NCURSES_SP_FUNCS
113d8977eafSRong-En Fan NCURSES_EXPORT(bool)
is_term_resized(int ToLines,int ToCols)114d8977eafSRong-En Fan is_term_resized(int ToLines, int ToCols)
115d8977eafSRong-En Fan {
116d8977eafSRong-En Fan     return NCURSES_SP_NAME(is_term_resized) (CURRENT_SCREEN, ToLines, ToCols);
117d8977eafSRong-En Fan }
118d8977eafSRong-En Fan #endif
119d8977eafSRong-En Fan 
120d8977eafSRong-En Fan /*
121d8977eafSRong-En Fan  */
122d8977eafSRong-En Fan static ripoff_t *
ripped_window(WINDOW * win)123d8977eafSRong-En Fan ripped_window(WINDOW *win)
124d8977eafSRong-En Fan {
125d8977eafSRong-En Fan     ripoff_t *result = 0;
126d8977eafSRong-En Fan     ripoff_t *rop;
127d8977eafSRong-En Fan 
128aa59d4d4SRong-En Fan     if (win != 0) {
129d8977eafSRong-En Fan #ifdef USE_SP_RIPOFF
130d8977eafSRong-En Fan 	SCREEN *sp = _nc_screen_of(win);
131d8977eafSRong-En Fan #endif
132d8977eafSRong-En Fan 	for (each_ripoff(rop)) {
133d8977eafSRong-En Fan 	    if (rop->win == win && rop->line != 0) {
134d8977eafSRong-En Fan 		result = rop;
135d8977eafSRong-En Fan 		break;
136d8977eafSRong-En Fan 	    }
137d8977eafSRong-En Fan 	}
138d8977eafSRong-En Fan     }
139d8977eafSRong-En Fan     return result;
140d8977eafSRong-En Fan }
1414a1a9510SRong-En Fan 
1424a1a9510SRong-En Fan /*
1434a1a9510SRong-En Fan  * Returns the number of lines from the bottom for the beginning of a ripped
1444a1a9510SRong-En Fan  * off window.
1454a1a9510SRong-En Fan  */
1464a1a9510SRong-En Fan static int
ripped_bottom(WINDOW * win)1474a1a9510SRong-En Fan ripped_bottom(WINDOW *win)
1484a1a9510SRong-En Fan {
1494a1a9510SRong-En Fan     int result = 0;
1504a1a9510SRong-En Fan 
151aa59d4d4SRong-En Fan     if (win != 0) {
1524a1a9510SRong-En Fan 	ripoff_t *rop;
1534a1a9510SRong-En Fan 
1544a1a9510SRong-En Fan #ifdef USE_SP_RIPOFF
1554a1a9510SRong-En Fan 	SCREEN *sp = _nc_screen_of(win);
1564a1a9510SRong-En Fan #endif
1574a1a9510SRong-En Fan 	for (each_ripoff(rop)) {
1584a1a9510SRong-En Fan 	    if (rop->line < 0) {
1594a1a9510SRong-En Fan 		result -= rop->line;
1604a1a9510SRong-En Fan 		if (rop->win == win) {
1614a1a9510SRong-En Fan 		    break;
1624a1a9510SRong-En Fan 		}
1634a1a9510SRong-En Fan 	    }
1644a1a9510SRong-En Fan 	}
1654a1a9510SRong-En Fan     }
1664a1a9510SRong-En Fan     return result;
1674a1a9510SRong-En Fan }
1684a1a9510SRong-En Fan 
1694a1a9510SRong-En Fan /*
1704a1a9510SRong-En Fan  * Return the number of levels of child-windows under the current window.
1714a1a9510SRong-En Fan  */
1724a1a9510SRong-En Fan static int
child_depth(WINDOW * cmp)1734a1a9510SRong-En Fan child_depth(WINDOW *cmp)
1744a1a9510SRong-En Fan {
1754a1a9510SRong-En Fan     int depth = 0;
1764a1a9510SRong-En Fan 
1774a1a9510SRong-En Fan     if (cmp != 0) {
1784a1a9510SRong-En Fan #ifdef USE_SP_WINDOWLIST
1794a1a9510SRong-En Fan 	SCREEN *sp = _nc_screen_of(cmp);
1804a1a9510SRong-En Fan #endif
1814a1a9510SRong-En Fan 	WINDOWLIST *wp;
1824a1a9510SRong-En Fan 
1834a1a9510SRong-En Fan 	for (each_window(sp, wp)) {
1845ca44d1cSRong-En Fan 	    WINDOW *tst = &(wp->win);
1854a1a9510SRong-En Fan 	    if (tst->_parent == cmp) {
1864a1a9510SRong-En Fan 		depth = 1 + child_depth(tst);
1875ca44d1cSRong-En Fan 		break;
1884a1a9510SRong-En Fan 	    }
1894a1a9510SRong-En Fan 	}
190d8977eafSRong-En Fan     }
1914a1a9510SRong-En Fan     return depth;
192d8977eafSRong-En Fan }
1934a1a9510SRong-En Fan 
194d8977eafSRong-En Fan /*
195d8977eafSRong-En Fan  * Return the number of levels of parent-windows above the current window.
196d8977eafSRong-En Fan  */
1974a1a9510SRong-En Fan static int
parent_depth(WINDOW * cmp)198d8977eafSRong-En Fan parent_depth(WINDOW *cmp)
1994a1a9510SRong-En Fan {
200d8977eafSRong-En Fan     int depth = 0;
201d8977eafSRong-En Fan 
202d8977eafSRong-En Fan     if (cmp != 0) {
203d8977eafSRong-En Fan 	WINDOW *tst;
204d8977eafSRong-En Fan 	while ((tst = cmp->_parent) != 0) {
205d8977eafSRong-En Fan 	    ++depth;
206d8977eafSRong-En Fan 	    cmp = tst;
207d8977eafSRong-En Fan 	}
208d8977eafSRong-En Fan     }
209d8977eafSRong-En Fan     return depth;
210d8977eafSRong-En Fan }
2115ca44d1cSRong-En Fan 
2124a1a9510SRong-En Fan /*
213d8977eafSRong-En Fan  * FIXME: must adjust position so it's within the parent!
214d8977eafSRong-En Fan  */
2154a1a9510SRong-En Fan static int
adjust_window(WINDOW * win,int ToLines,int ToCols,int stolen EXTRA_DCLS)216d8977eafSRong-En Fan adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS)
217d8977eafSRong-En Fan {
218d8977eafSRong-En Fan     int result;
219d8977eafSRong-En Fan     int bottom = CurLines + _nc_screen_of(win)->_topstolen - stolen;
220d8977eafSRong-En Fan     int myLines = win->_maxy + 1;
221d8977eafSRong-En Fan     int myCols = win->_maxx + 1;
222d8977eafSRong-En Fan     ripoff_t *rop = ripped_window(win);
2234a1a9510SRong-En Fan 
2244a1a9510SRong-En Fan     T((T_CALLED("adjust_window(%p,%d,%d)%s depth %d/%d currently %ldx%ld at %ld,%ld"),
2254a1a9510SRong-En Fan        (void *) win, ToLines, ToCols,
2264a1a9510SRong-En Fan        (rop != 0) ? " (rip)" : "",
2274a1a9510SRong-En Fan        parent_depth(win),
2284a1a9510SRong-En Fan        child_depth(win),
2295ca44d1cSRong-En Fan        (long) getmaxy(win), (long) getmaxx(win),
2305ca44d1cSRong-En Fan        (long) getbegy(win) + win->_yoffset, (long) getbegx(win)));
2314a1a9510SRong-En Fan 
2324a1a9510SRong-En Fan     if (rop != 0 && rop->line < 0) {
2334a1a9510SRong-En Fan 	/*
2344a1a9510SRong-En Fan 	 * If it is a ripped-off window at the bottom of the screen, simply
2354a1a9510SRong-En Fan 	 * move it to the same relative position.
2364a1a9510SRong-En Fan 	 */
2374a1a9510SRong-En Fan 	win->_begy = (NCURSES_SIZE_T) (ToLines - ripped_bottom(win) - 0 - win->_yoffset);
2384a1a9510SRong-En Fan 	if (rop->hook == _nc_slk_initialize)
2394a1a9510SRong-En Fan 	    _nc_format_slks(
2404a1a9510SRong-En Fan #if NCURSES_SP_FUNCS
2414a1a9510SRong-En Fan 			       _nc_screen_of(win),
2425ca44d1cSRong-En Fan #endif
2434a1a9510SRong-En Fan 			       ToCols);
2444a1a9510SRong-En Fan     } else if (win->_begy >= bottom) {
2454a1a9510SRong-En Fan 	/*
2464a1a9510SRong-En Fan 	 * If it is below the bottom of the new screen, move up by the same
2474a1a9510SRong-En Fan 	 * amount that the screen shrank.
2484a1a9510SRong-En Fan 	 */
2494a1a9510SRong-En Fan 	win->_begy = (NCURSES_SIZE_T) (win->_begy + (ToLines - CurLines));
2504a1a9510SRong-En Fan     } else {
2514a1a9510SRong-En Fan 	if (myLines == (CurLines - stolen)
2524a1a9510SRong-En Fan 	    && ToLines != CurLines) {
2534a1a9510SRong-En Fan 	    myLines = ToLines - stolen;
254aa59d4d4SRong-En Fan 	} else if (myLines == CurLines
2554a1a9510SRong-En Fan 		   && ToLines != CurLines) {
2564a1a9510SRong-En Fan 	    myLines = ToLines;
2574a1a9510SRong-En Fan 	}
2584a1a9510SRong-En Fan     }
2594a1a9510SRong-En Fan 
2605ca44d1cSRong-En Fan     if (myLines > ToLines) {
2615ca44d1cSRong-En Fan 	myLines = ToLines;
2624a1a9510SRong-En Fan     }
2634a1a9510SRong-En Fan 
2644a1a9510SRong-En Fan     if (myCols > ToCols)
2654a1a9510SRong-En Fan 	myCols = ToCols;
2664a1a9510SRong-En Fan 
2674a1a9510SRong-En Fan     if (myCols == CurCols
2684a1a9510SRong-En Fan 	&& ToCols != CurCols)
2694a1a9510SRong-En Fan 	myCols = ToCols;
2704a1a9510SRong-En Fan 
2714a1a9510SRong-En Fan     result = wresize(win, myLines, myCols);
2724a1a9510SRong-En Fan     returnCode(result);
2734a1a9510SRong-En Fan }
2744a1a9510SRong-En Fan 
2754a1a9510SRong-En Fan /*
2765ca44d1cSRong-En Fan  * If we're decreasing size, recursively search for windows that have no
2774a1a9510SRong-En Fan  * children, decrease those to fit, then decrease the containing window, etc.
2784a1a9510SRong-En Fan  */
2794a1a9510SRong-En Fan static int
decrease_size(NCURSES_SP_DCLx int ToLines,int ToCols,int stolen EXTRA_DCLS)2804a1a9510SRong-En Fan decrease_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS)
2814a1a9510SRong-En Fan {
2824a1a9510SRong-En Fan     bool found;
2834a1a9510SRong-En Fan     int depth = 0;
2844a1a9510SRong-En Fan     WINDOWLIST *wp;
2854a1a9510SRong-En Fan 
2864a1a9510SRong-En Fan     T((T_CALLED("decrease_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols));
2874a1a9510SRong-En Fan     UNUSED_SP;
288aa59d4d4SRong-En Fan 
2894a1a9510SRong-En Fan     do {
2904a1a9510SRong-En Fan 	found = FALSE;
2914a1a9510SRong-En Fan 	TR(TRACE_UPDATE, ("decreasing size of windows to %dx%d, depth=%d",
2924a1a9510SRong-En Fan 			  ToLines, ToCols, depth));
2934a1a9510SRong-En Fan 	for (each_window(SP_PARM, wp)) {
2945ca44d1cSRong-En Fan 	    WINDOW *win = &(wp->win);
2955ca44d1cSRong-En Fan 
2964a1a9510SRong-En Fan 	    if (!(win->_flags & _ISPAD)) {
2974a1a9510SRong-En Fan 		if (child_depth(win) == depth) {
2984a1a9510SRong-En Fan 		    found = TRUE;
2994a1a9510SRong-En Fan 		    if (adjust_window(win, ToLines, ToCols,
3004a1a9510SRong-En Fan 				      stolen EXTRA_ARGS) != OK)
3014a1a9510SRong-En Fan 			returnCode(ERR);
3024a1a9510SRong-En Fan 		}
30339f2269fSPeter Wemm 	    }
3040e3d5408SPeter Wemm 	}
3050e3d5408SPeter Wemm 	++depth;
30639f2269fSPeter Wemm     } while (found);
30739f2269fSPeter Wemm     returnCode(OK);
3080e3d5408SPeter Wemm }
3097a69bbfbSPeter Wemm 
31039f2269fSPeter Wemm /*
3110e3d5408SPeter Wemm  * If we're increasing size, recursively search for windows that have no
3125ca44d1cSRong-En Fan  * parent, increase those to fit, then increase the contained window, etc.
3135ca44d1cSRong-En Fan  */
3140e3d5408SPeter Wemm static int
increase_size(NCURSES_SP_DCLx int ToLines,int ToCols,int stolen EXTRA_DCLS)31539f2269fSPeter Wemm increase_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS)
3160e3d5408SPeter Wemm {
3170e3d5408SPeter Wemm     bool found;
3180e3d5408SPeter Wemm     int depth = 0;
3195ca44d1cSRong-En Fan     WINDOWLIST *wp;
3205ca44d1cSRong-En Fan 
3215ca44d1cSRong-En Fan     T((T_CALLED("increase_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols));
3225ca44d1cSRong-En Fan     UNUSED_SP;
3235ca44d1cSRong-En Fan 
3245ca44d1cSRong-En Fan     do {
3255ca44d1cSRong-En Fan 	found = FALSE;
32639f2269fSPeter Wemm 	TR(TRACE_UPDATE, ("increasing size of windows to %dx%d, depth=%d",
3275ca44d1cSRong-En Fan 			  ToLines, ToCols, depth));
3285ca44d1cSRong-En Fan 	for (each_window(SP_PARM, wp)) {
3290e3d5408SPeter Wemm 	    WINDOW *win = &(wp->win);
3304a1a9510SRong-En Fan 
3315ca44d1cSRong-En Fan 	    if (!(win->_flags & _ISPAD)) {
3324a1a9510SRong-En Fan 		if (parent_depth(win) == depth) {
3335ca44d1cSRong-En Fan 		    found = TRUE;
3345ca44d1cSRong-En Fan 		    if (adjust_window(win, ToLines, ToCols,
3354a1a9510SRong-En Fan 				      stolen EXTRA_ARGS) != OK)
3364a1a9510SRong-En Fan 			returnCode(ERR);
3375ca44d1cSRong-En Fan 		}
3385ca44d1cSRong-En Fan 	    }
3395ca44d1cSRong-En Fan 	}
3400e3d5408SPeter Wemm 	++depth;
3410e3d5408SPeter Wemm     } while (found);
3424a1a9510SRong-En Fan     returnCode(OK);
3435ca44d1cSRong-En Fan }
3445ca44d1cSRong-En Fan 
3455ca44d1cSRong-En Fan /*
3464a1a9510SRong-En Fan  * This function reallocates NCURSES window structures, with no side-effects
3470e3d5408SPeter Wemm  * such as ungetch().
3484a1a9510SRong-En Fan  */
3494a1a9510SRong-En Fan NCURSES_EXPORT(int)
NCURSES_SP_NAME(resize_term)3505ca44d1cSRong-En Fan NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols)
3510e3d5408SPeter Wemm {
3520e3d5408SPeter Wemm     int result = OK EXTRA_ARGS;
3530e3d5408SPeter Wemm     int was_stolen;
3540e3d5408SPeter Wemm 
3550e3d5408SPeter Wemm     T((T_CALLED("resize_term(%p,%d,%d) old(%d,%d)"),
3564a1a9510SRong-En Fan        (void *) SP_PARM, ToLines, ToCols,
3570e3d5408SPeter Wemm        (SP_PARM == 0) ? -1 : screen_lines(SP_PARM),
3587a69bbfbSPeter Wemm        (SP_PARM == 0) ? -1 : screen_columns(SP_PARM)));
3597a69bbfbSPeter Wemm 
3607a69bbfbSPeter Wemm     if (SP_PARM == 0 || ToLines <= 0 || ToCols <= 0) {
3617a69bbfbSPeter Wemm 	returnCode(ERR);
3627a69bbfbSPeter Wemm     }
3637a69bbfbSPeter Wemm 
3644a1a9510SRong-En Fan     _nc_nonsp_lock_global(curses);
3655ca44d1cSRong-En Fan 
3665ca44d1cSRong-En Fan     was_stolen = (screen_lines(SP_PARM) - SP_PARM->_lines_avail);
3675ca44d1cSRong-En Fan     if (NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_ARGx ToLines, ToCols)) {
3684a1a9510SRong-En Fan 	int myLines = CurLines = screen_lines(SP_PARM);
3695ca44d1cSRong-En Fan 	int myCols = CurCols = screen_columns(SP_PARM);
3704a1a9510SRong-En Fan 
3714a1a9510SRong-En Fan #ifdef TRACE
3720e3d5408SPeter Wemm 	if (USE_TRACEF(TRACE_UPDATE)) {
3730e3d5408SPeter Wemm 	    show_window_sizes("before");
3740e3d5408SPeter Wemm 	    _nc_unlock_global(tracef);
3750e3d5408SPeter Wemm 	}
3760e3d5408SPeter Wemm #endif
3770e3d5408SPeter Wemm 	if (ToLines > screen_lines(SP_PARM)) {
3785ca44d1cSRong-En Fan 	    result = increase_size(NCURSES_SP_ARGx
3795ca44d1cSRong-En Fan 				   myLines = ToLines,
3805ca44d1cSRong-En Fan 				   myCols,
3815ca44d1cSRong-En Fan 				   was_stolen EXTRA_ARGS);
3820e3d5408SPeter Wemm 	    CurLines = myLines;
3834a1a9510SRong-En Fan 	    CurCols = myCols;
3840e3d5408SPeter Wemm 	}
38539f2269fSPeter Wemm 
38639f2269fSPeter Wemm 	if ((result == OK)
38739f2269fSPeter Wemm 	    && (ToCols > screen_columns(SP_PARM))) {
38839f2269fSPeter Wemm 	    result = increase_size(NCURSES_SP_ARGx
38939f2269fSPeter Wemm 				   myLines,
39039f2269fSPeter Wemm 				   myCols = ToCols,
39139f2269fSPeter Wemm 				   was_stolen EXTRA_ARGS);
39239f2269fSPeter Wemm 	    CurLines = myLines;
39339f2269fSPeter Wemm 	    CurCols = myCols;
39439f2269fSPeter Wemm 	}
39539f2269fSPeter Wemm 
39639f2269fSPeter Wemm 	if ((result == OK)
3975ca44d1cSRong-En Fan 	    && (ToLines < myLines ||
39839f2269fSPeter Wemm 		ToCols < myCols)) {
39939f2269fSPeter Wemm 	    result = decrease_size(NCURSES_SP_ARGx
40039f2269fSPeter Wemm 				   ToLines,
40139f2269fSPeter Wemm 				   ToCols,
40239f2269fSPeter Wemm 				   was_stolen EXTRA_ARGS);
4035ca44d1cSRong-En Fan 	}
4045ca44d1cSRong-En Fan 
4055ca44d1cSRong-En Fan 	if (result == OK) {
4065ca44d1cSRong-En Fan 	    screen_lines(SP_PARM) = (NCURSES_SIZE_T) ToLines;
40739f2269fSPeter Wemm 	    screen_columns(SP_PARM) = (NCURSES_SIZE_T) ToCols;
408d8977eafSRong-En Fan 
409d8977eafSRong-En Fan #ifdef USE_TERM_DRIVER
410d8977eafSRong-En Fan 	    CallDriver_2(SP_PARM, td_setsize, ToLines, ToCols);
411d8977eafSRong-En Fan #else
412d8977eafSRong-En Fan 	    lines = (NCURSES_SIZE_T) ToLines;
413d8977eafSRong-En Fan 	    columns = (NCURSES_SIZE_T) ToCols;
414d8977eafSRong-En Fan #endif
415d8977eafSRong-En Fan 
416d8977eafSRong-En Fan 	    SP_PARM->_lines_avail = (NCURSES_SIZE_T) (ToLines - was_stolen);
417d8977eafSRong-En Fan 
418d8977eafSRong-En Fan 	    if (SP_PARM->oldhash) {
41939f2269fSPeter Wemm 		FreeAndNull(SP_PARM->oldhash);
42039f2269fSPeter Wemm 	    }
42139f2269fSPeter Wemm 	    if (SP_PARM->newhash) {
42239f2269fSPeter Wemm 		FreeAndNull(SP_PARM->newhash);
42339f2269fSPeter Wemm 	    }
424d8977eafSRong-En Fan #ifdef TRACE
425d8977eafSRong-En Fan 	    if (USE_TRACEF(TRACE_UPDATE)) {
426d8977eafSRong-En Fan 		SET_LINES(ToLines - was_stolen);
427d8977eafSRong-En Fan 		SET_COLS(ToCols);
428d8977eafSRong-En Fan 		show_window_sizes("after");
429d8977eafSRong-En Fan 		_nc_unlock_global(tracef);
430d8977eafSRong-En Fan 	    }
431aa59d4d4SRong-En Fan #endif
432d8977eafSRong-En Fan 	}
433d8977eafSRong-En Fan     }
434d8977eafSRong-En Fan 
435d8977eafSRong-En Fan     if (result == OK) {
436d8977eafSRong-En Fan 	/*
437d8977eafSRong-En Fan 	 * Always update LINES, to allow for call from lib_doupdate.c which
438d8977eafSRong-En Fan 	 * needs to have the count adjusted by the stolen (ripped off) lines.
439d8977eafSRong-En Fan 	 */
440d8977eafSRong-En Fan 	SET_LINES(ToLines - was_stolen);
441d8977eafSRong-En Fan 	SET_COLS(ToCols);
442d8977eafSRong-En Fan     }
443d8977eafSRong-En Fan 
444d8977eafSRong-En Fan     _nc_nonsp_unlock_global(curses);
445d8977eafSRong-En Fan 
446d8977eafSRong-En Fan     returnCode(result);
447d8977eafSRong-En Fan }
448d8977eafSRong-En Fan 
449d8977eafSRong-En Fan #if NCURSES_SP_FUNCS
450d8977eafSRong-En Fan NCURSES_EXPORT(int)
resize_term(int ToLines,int ToCols)45139f2269fSPeter Wemm resize_term(int ToLines, int ToCols)
4525ca44d1cSRong-En Fan {
45339f2269fSPeter Wemm     int res;
45439f2269fSPeter Wemm     _nc_sp_lock_global(curses);
45539f2269fSPeter Wemm     res = NCURSES_SP_NAME(resize_term) (CURRENT_SCREEN, ToLines, ToCols);
456     _nc_sp_unlock_global(curses);
457     return (res);
458 }
459 #endif
460 
461 /*
462  * This function reallocates NCURSES window structures.  It is invoked in
463  * response to a SIGWINCH interrupt.  Other user-defined windows may also need
464  * to be reallocated.
465  *
466  * Because this performs memory allocation, it should not (in general) be
467  * invoked directly from the signal handler.
468  */
469 NCURSES_EXPORT(int)
NCURSES_SP_NAME(resizeterm)470 NCURSES_SP_NAME(resizeterm) (NCURSES_SP_DCLx int ToLines, int ToCols)
471 {
472     int result = ERR;
473 
474     T((T_CALLED("resizeterm(%p, %d,%d) old(%d,%d)"),
475        (void *) SP_PARM, ToLines, ToCols,
476        (SP_PARM == 0) ? -1 : screen_lines(SP_PARM),
477        (SP_PARM == 0) ? -1 : screen_columns(SP_PARM)));
478 
479     if (SP_PARM != 0 && ToLines > 0 && ToCols > 0) {
480 	result = OK;
481 	SP_PARM->_sig_winch = FALSE;
482 
483 	if (NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_ARGx ToLines, ToCols)) {
484 #if USE_SIGWINCH
485 	    ripoff_t *rop;
486 	    bool slk_visible = (SP_PARM != 0
487 				&& SP_PARM->_slk != 0
488 				&& !(SP_PARM->_slk->hidden));
489 
490 	    if (slk_visible) {
491 		slk_clear();
492 	    }
493 #endif
494 	    result = NCURSES_SP_NAME(resize_term) (NCURSES_SP_ARGx ToLines, ToCols);
495 
496 #if USE_SIGWINCH
497 	    clearok(CurScreen(SP_PARM), TRUE);	/* screen contents are unknown */
498 
499 	    /* ripped-off lines are a special case: if we did not lengthen
500 	     * them, we haven't moved them either.  repaint them, too.
501 	     *
502 	     * for the rest - stdscr and other windows - the client has to
503 	     * decide which to repaint, since without panels, ncurses does
504 	     * not know which are really on top.
505 	     */
506 	    for (each_ripoff(rop)) {
507 		if (rop->win != StdScreen(SP_PARM)
508 		    && rop->win != 0
509 		    && rop->line < 0) {
510 
511 		    if (rop->hook != _nc_slk_initialize) {
512 			touchwin(rop->win);
513 			wnoutrefresh(rop->win);
514 		    }
515 		}
516 	    }
517 
518 	    /* soft-keys are a special case: we _know_ how to repaint them */
519 	    if (slk_visible) {
520 		NCURSES_SP_NAME(slk_restore) (NCURSES_SP_ARG);
521 		NCURSES_SP_NAME(slk_touch) (NCURSES_SP_ARG);
522 		NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_ARG);
523 	    }
524 #endif
525 	}
526 #if USE_SIGWINCH
527 	safe_ungetch(SP_PARM, KEY_RESIZE);	/* so application can know this */
528 #endif
529     }
530 
531     returnCode(result);
532 }
533 
534 #if NCURSES_SP_FUNCS
535 NCURSES_EXPORT(int)
resizeterm(int ToLines,int ToCols)536 resizeterm(int ToLines, int ToCols)
537 {
538     return NCURSES_SP_NAME(resizeterm) (CURRENT_SCREEN, ToLines, ToCols);
539 }
540 #endif
541