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