1*6348e3f3Sblymn /* $NetBSD: resize.c,v 1.37 2024/12/23 02:58:04 blymn Exp $ */ 29fc03296Sblymn 39fc03296Sblymn /* 49fc03296Sblymn * Copyright (c) 2001 59fc03296Sblymn * Brett Lymn. 69fc03296Sblymn * 79fc03296Sblymn * This code has been donated to The NetBSD Foundation by the Author. 89fc03296Sblymn * 99fc03296Sblymn * Redistribution and use in source and binary forms, with or without 109fc03296Sblymn * modification, are permitted provided that the following conditions 119fc03296Sblymn * are met: 129fc03296Sblymn * 1. Redistributions of source code must retain the above copyright 139fc03296Sblymn * notice, this list of conditions and the following disclaimer. 149fc03296Sblymn * 2. Redistributions in binary form must reproduce the above copyright 159fc03296Sblymn * notice, this list of conditions and the following disclaimer in the 169fc03296Sblymn * documentation and/or other materials provided with the distribution. 179fc03296Sblymn * 189fc03296Sblymn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 199fc03296Sblymn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 209fc03296Sblymn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 219fc03296Sblymn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 229fc03296Sblymn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 239fc03296Sblymn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 249fc03296Sblymn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 259fc03296Sblymn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 269fc03296Sblymn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 279fc03296Sblymn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 289fc03296Sblymn * SUCH DAMAGE. 299fc03296Sblymn */ 309fc03296Sblymn 319fc03296Sblymn #include <sys/cdefs.h> 329fc03296Sblymn #ifndef lint 339fc03296Sblymn #if 0 349fc03296Sblymn static char sccsid[] = "@(#)resize.c blymn 2001/08/26"; 359fc03296Sblymn #else 36*6348e3f3Sblymn __RCSID("$NetBSD: resize.c,v 1.37 2024/12/23 02:58:04 blymn Exp $"); 379fc03296Sblymn #endif 389fc03296Sblymn #endif /* not lint */ 399fc03296Sblymn 409fc03296Sblymn #include <stdlib.h> 419fc03296Sblymn 429fc03296Sblymn #include "curses.h" 439fc03296Sblymn #include "curses_private.h" 449fc03296Sblymn 45c4eef946Sjdc static int __resizeterm(WINDOW *win, int nlines, int ncols); 469fc03296Sblymn static int __resizewin(WINDOW *win, int nlines, int ncols); 479fc03296Sblymn 489fc03296Sblymn /* 499fc03296Sblymn * wresize -- 509fc03296Sblymn * Resize the given window to the new size. 519fc03296Sblymn */ 529fc03296Sblymn int 53d75ec818Sdsl wresize(WINDOW *win, int req_nlines, int req_ncols) 549fc03296Sblymn { 55d75ec818Sdsl int nlines = req_nlines; 56d75ec818Sdsl int ncols = req_ncols; 579fc03296Sblymn 58*6348e3f3Sblymn if (__predict_false(win == NULL)) 599fc03296Sblymn return ERR; 609fc03296Sblymn 6134bea286Sjdc __CTRACE(__CTRACE_WINDOW, "wresize: (%p, %d, %d)\n", 6234bea286Sjdc win, nlines, ncols); 6370294c72Snia if (win->orig != NULL) { 6470294c72Snia /* subwins must fit inside the parent - check this */ 6570294c72Snia if (win->begy > win->orig->begy + win->orig->maxy) 6670294c72Snia win->begy = win->orig->begy + win->orig->maxy - 1; 6770294c72Snia if (win->begy + nlines > win->orig->begy + win->orig->maxy) 6870294c72Snia nlines = 0; 6970294c72Snia if (nlines <= 0) 7070294c72Snia nlines += win->orig->begy + win->orig->maxy - win->begy; 7170294c72Snia if (nlines < 1) 7270294c72Snia nlines = 1; 7370294c72Snia if (win->begx > win->orig->begx + win->orig->maxx) 7470294c72Snia win->begx = win->orig->begx + win->orig->maxx - 1; 7570294c72Snia if (win->begx + ncols > win->orig->begx + win->orig->maxx) 7670294c72Snia ncols = 0; 7770294c72Snia if (ncols <= 0) 7870294c72Snia ncols += win->orig->begx + win->orig->maxx - win->begx; 7970294c72Snia if (ncols < 1) 8070294c72Snia ncols = 1; 8170294c72Snia } else if (!(win->flags & __ISPAD)) { 82c4eef946Sjdc /* bound "our" windows by the screen size */ 83c4eef946Sjdc if (win == curscr || win == __virtscr || win == stdscr) { 8452cd399dSjdc if (nlines > LINES) 8552cd399dSjdc nlines = LINES; 8652cd399dSjdc if (nlines < 1) 8752cd399dSjdc nlines = 1; 8852cd399dSjdc if (ncols > COLS) 8952cd399dSjdc ncols = COLS; 9052cd399dSjdc if (ncols < 1) 9152cd399dSjdc ncols = 1; 9252cd399dSjdc } else { 9352cd399dSjdc if (win->begy > LINES) 9452cd399dSjdc win->begy = 0; 95d75ec818Sdsl if (win->begy + nlines > LINES) 96d75ec818Sdsl nlines = 0; 97d75ec818Sdsl if (nlines <= 0) 98d75ec818Sdsl nlines += LINES - win->begy; 9952cd399dSjdc if (nlines < 1) 10052cd399dSjdc nlines = 1; 10152cd399dSjdc if (win->begx > COLS) 10252cd399dSjdc win->begx = 0; 103d75ec818Sdsl if (win->begx + ncols > COLS) 104d75ec818Sdsl ncols = 0; 105d75ec818Sdsl if (ncols <= 0) 106d75ec818Sdsl ncols += COLS - win->begx; 10752cd399dSjdc if (ncols < 1) 10852cd399dSjdc ncols = 1; 109c4eef946Sjdc } 1109fc03296Sblymn } 1119fc03296Sblymn 1129fc03296Sblymn if ((__resizewin(win, nlines, ncols)) == ERR) 1139fc03296Sblymn return ERR; 1149fc03296Sblymn 115d75ec818Sdsl win->reqy = req_nlines; 116d75ec818Sdsl win->reqx = req_ncols; 1179fc03296Sblymn 11834bea286Sjdc /* If someone resizes curscr, we must also resize __virtscr */ 11934bea286Sjdc if (win == curscr) { 12034bea286Sjdc if ((__resizewin(__virtscr, nlines, ncols)) == ERR) 12134bea286Sjdc return ERR; 12234bea286Sjdc __virtscr->reqy = req_nlines; 12334bea286Sjdc __virtscr->reqx = req_ncols; 12434bea286Sjdc } 12534bea286Sjdc 1269fc03296Sblymn return OK; 1279fc03296Sblymn } 1289fc03296Sblymn 1299fc03296Sblymn /* 1304550c528Sroy * is_term_resized -- 1314550c528Sroy * Return true if the given dimensions do not match the 1324550c528Sroy * internal structures. 1334550c528Sroy */ 1344550c528Sroy bool 1354550c528Sroy is_term_resized(int nlines, int ncols) 1364550c528Sroy { 1374550c528Sroy 13825445577Sroy return (nlines > 0 && ncols > 0 && 139cc74ade3Sroy (nlines != _cursesi_screen->LINES || 14025445577Sroy ncols != _cursesi_screen->COLS)); 1414550c528Sroy } 1424550c528Sroy 1434550c528Sroy /* 1449fc03296Sblymn * resizeterm -- 1459fc03296Sblymn * Resize the terminal window, resizing the dependent windows. 1464550c528Sroy * Handles internal book-keeping. 1479fc03296Sblymn */ 1489fc03296Sblymn int 1499fc03296Sblymn resizeterm(int nlines, int ncols) 1509fc03296Sblymn { 1514550c528Sroy int result; 1524550c528Sroy 1534550c528Sroy __CTRACE(__CTRACE_WINDOW, "resizeterm: (%d, %d)\n", nlines, ncols); 1544550c528Sroy 155e407f0a0Sroy /* Unconditionally inform application screen has been resized. */ 156e407f0a0Sroy _cursesi_screen->resized = 1; 157c77e1d01Sroy 1584550c528Sroy if (!is_term_resized(nlines, ncols)) 1594550c528Sroy return OK; 1604550c528Sroy 161cc74ade3Sroy result = resize_term(nlines, ncols); 162c77e1d01Sroy 163c77e1d01Sroy /* Screen contents are unknown, libcurses is not libpanel, we don't 164c77e1d01Sroy * know the correct draw order. */ 1654550c528Sroy clearok(curscr, TRUE); 166c77e1d01Sroy 167a2ac1ce4Sroy if (result == OK) { 168dd838550Sroy /* Redraw the soft label keys to the new size. */ 169a2ac1ce4Sroy __slk_resize(_cursesi_screen, ncols); 170a2ac1ce4Sroy __slk_noutrefresh(_cursesi_screen); 171a2ac1ce4Sroy } 172a2ac1ce4Sroy 1734550c528Sroy return result; 1744550c528Sroy } 1754550c528Sroy 1764550c528Sroy /* 1774550c528Sroy * resize_term -- 1784550c528Sroy * Resize the terminal window, resizing the dependent windows. 1794550c528Sroy */ 1804550c528Sroy int 1814550c528Sroy resize_term(int nlines, int ncols) 1824550c528Sroy { 183744eb727Schristos WINDOW *win; 1849fc03296Sblymn struct __winlist *list; 185c77e1d01Sroy int rlines; 1869fc03296Sblymn 1874550c528Sroy __CTRACE(__CTRACE_WINDOW, "resize_term: (%d, %d)\n", nlines, ncols); 1889fc03296Sblymn 1894550c528Sroy if (!is_term_resized(nlines, ncols)) 1904550c528Sroy return OK; 1914550c528Sroy 192c4eef946Sjdc if (__resizeterm(curscr, nlines, ncols) == ERR) 1939fc03296Sblymn return ERR; 194c4eef946Sjdc if (__resizeterm(__virtscr, nlines, ncols) == ERR) 195c4eef946Sjdc return ERR; 196d34c5681Sroy rlines = nlines - __rippedlines(_cursesi_screen, 0); 197c77e1d01Sroy if (__resizeterm(stdscr, rlines, ncols) == ERR) 198c4eef946Sjdc return ERR; 1999fc03296Sblymn 200c77e1d01Sroy _cursesi_screen->LINES = nlines; 201c77e1d01Sroy _cursesi_screen->COLS = ncols; 202d34c5681Sroy LINES = nlines; 2039fc03296Sblymn COLS = ncols; 2049fc03296Sblymn 2059fc03296Sblymn /* tweak the flags now that we have updated the LINES and COLS */ 206a04fc5a9Sdsl for (list = _cursesi_screen->winlistp; list != NULL; list = list->nextp) { 207744eb727Schristos win = list->winp; 208744eb727Schristos 20914b491c2Sdsl if (!(win->flags & __ISPAD)) 210744eb727Schristos __swflags(win); 2119fc03296Sblymn } 2129fc03296Sblymn 213dd838550Sroy /* Resize and re-position the ripped off windows. */ 214dd838550Sroy if (__ripoffresize(_cursesi_screen) == ERR) 215dd838550Sroy return ERR; 216dd838550Sroy 2179fc03296Sblymn return OK; 2189fc03296Sblymn } 2199fc03296Sblymn 2209fc03296Sblymn /* 221c4eef946Sjdc * __resizeterm 222c4eef946Sjdc * Setup window for resizing. 223c4eef946Sjdc */ 224c4eef946Sjdc static int 225c4eef946Sjdc __resizeterm(WINDOW *win, int nlines, int ncols) 226c4eef946Sjdc { 227c4eef946Sjdc int newlines, newcols; 228c4eef946Sjdc 229c4eef946Sjdc newlines = win->reqy; 230c4eef946Sjdc if (win->begy + newlines >= nlines) 231c4eef946Sjdc newlines = 0; 232c4eef946Sjdc if (newlines == 0) 233c4eef946Sjdc newlines = nlines - win->begy; 234c4eef946Sjdc 235c4eef946Sjdc newcols = win->reqx; 236c4eef946Sjdc if (win->begx + newcols >= ncols) 237c4eef946Sjdc newcols = 0; 238c4eef946Sjdc if (newcols == 0) 239c4eef946Sjdc newcols = ncols - win->begx; 240c4eef946Sjdc 241c4eef946Sjdc return __resizewin(win, newlines, newcols); 242c4eef946Sjdc } 243c4eef946Sjdc 244c4eef946Sjdc /* 2459fc03296Sblymn * __resizewin -- 2469fc03296Sblymn * Resize the given window. 2479fc03296Sblymn */ 2489fc03296Sblymn static int 2499fc03296Sblymn __resizewin(WINDOW *win, int nlines, int ncols) 2509fc03296Sblymn { 2519fc03296Sblymn __LINE *lp, *olp, **newlines, *newlspace; 252d75ec818Sdsl __LDATA *sp; 2539fc03296Sblymn __LDATA *newwspace; 254d75ec818Sdsl int i, j; 255d75ec818Sdsl int y, x; 256f7a8d65fSdsl WINDOW *swin; 2579fc03296Sblymn 2581f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: (%p, %d, %d)\n", win, nlines, ncols); 2591f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr); 2601f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags); 2611f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy); 2621f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx); 2631f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy); 2641f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx); 2651f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t); 2661f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b); 2679fc03296Sblymn 268e124de36Sblymn /* 269e124de36Sblymn * free up any non-spacing storage before we lose the 270e124de36Sblymn * pointers... 271e124de36Sblymn */ 272e124de36Sblymn #ifdef HAVE_WCHAR 273e124de36Sblymn __cursesi_win_free_nsp(win); 274e124de36Sblymn #endif 275e124de36Sblymn 276d75ec818Sdsl if (nlines <= 0 || ncols <= 0) 277d75ec818Sdsl nlines = ncols = 0; 278d75ec818Sdsl else { 2799fc03296Sblymn /* Reallocate line pointer array and line space. */ 28043d5eb45Sroy newlines = realloc(win->alines, nlines * sizeof(__LINE *)); 281d75ec818Sdsl if (newlines == NULL) 2829fc03296Sblymn return ERR; 28343d5eb45Sroy win->alines = newlines; 2849fc03296Sblymn 285d75ec818Sdsl newlspace = realloc(win->lspace, nlines * sizeof(__LINE)); 286d75ec818Sdsl if (newlspace == NULL) 2879fc03296Sblymn return ERR; 2889fc03296Sblymn win->lspace = newlspace; 289d75ec818Sdsl } 2909fc03296Sblymn 2919fc03296Sblymn /* Don't allocate window and line space if it's a subwindow */ 2929fc03296Sblymn if (win->orig == NULL) { 2939fc03296Sblymn /* 2949fc03296Sblymn * Allocate window space in one chunk. 2959fc03296Sblymn */ 296d75ec818Sdsl if (ncols != 0) { 297d75ec818Sdsl newwspace = realloc(win->wspace, 298d75ec818Sdsl ncols * nlines * sizeof(__LDATA)); 299d75ec818Sdsl if (newwspace == NULL) 3009fc03296Sblymn return ERR; 3019fc03296Sblymn win->wspace = newwspace; 302d75ec818Sdsl } 3039fc03296Sblymn 3049fc03296Sblymn /* 3059fc03296Sblymn * Point line pointers to line space, and lines themselves into 3069fc03296Sblymn * window space. 3079fc03296Sblymn */ 3089fc03296Sblymn for (lp = win->lspace, i = 0; i < nlines; i++, lp++) { 30943d5eb45Sroy win->alines[i] = lp; 3109fc03296Sblymn lp->line = &win->wspace[i * ncols]; 3118d259104Sblymn #ifdef DEBUG 3128d259104Sblymn lp->sentinel = SENTINEL_VALUE; 3138d259104Sblymn #endif 3149fc03296Sblymn lp->firstchp = &lp->firstch; 3159fc03296Sblymn lp->lastchp = &lp->lastch; 3169fc03296Sblymn lp->firstch = 0; 3179fc03296Sblymn lp->lastch = ncols - 1; 3189fc03296Sblymn lp->flags = __ISDIRTY; 3199fc03296Sblymn } 3209fc03296Sblymn } else { 3219fc03296Sblymn 3229fc03296Sblymn win->ch_off = win->begx - win->orig->begx; 3239fc03296Sblymn /* Point line pointers to line space. */ 3249fc03296Sblymn for (lp = win->lspace, i = 0; i < nlines; i++, lp++) { 32543d5eb45Sroy win->alines[i] = lp; 32643d5eb45Sroy olp = win->orig->alines[i + win->begy - win->orig->begy]; 3279fc03296Sblymn lp->line = &olp->line[win->ch_off]; 328f7a8d65fSdsl #ifdef DEBUG 329f7a8d65fSdsl lp->sentinel = SENTINEL_VALUE; 330f7a8d65fSdsl #endif 3319fc03296Sblymn lp->firstchp = &olp->firstch; 3329fc03296Sblymn lp->lastchp = &olp->lastch; 3339fc03296Sblymn lp->flags = __ISDIRTY; 3349fc03296Sblymn } 3359fc03296Sblymn } 3369fc03296Sblymn 3379fc03296Sblymn win->cury = win->curx = 0; 3389fc03296Sblymn win->maxy = nlines; 3399fc03296Sblymn win->maxx = ncols; 3409fc03296Sblymn win->scr_b = win->maxy - 1; 3419fc03296Sblymn __swflags(win); 3429fc03296Sblymn 343d75ec818Sdsl /* 344d75ec818Sdsl * we must zot the window contents otherwise lines may pick 345d75ec818Sdsl * up attributes from the previous line when the window is 346d75ec818Sdsl * made smaller. The client will redraw the window anyway 347d75ec818Sdsl * so this is no big deal. 348d75ec818Sdsl */ 349d75ec818Sdsl for (i = 0; i < win->maxy; i++) { 35043d5eb45Sroy lp = win->alines[i]; 351d75ec818Sdsl for (sp = lp->line, j = 0; j < win->maxx; j++, sp++) { 352d75ec818Sdsl sp->attr = 0; 353ee6c5161Sblymn sp->cflags = CA_BACKGROUND; 354e124de36Sblymn #ifndef HAVE_WCHAR 355e124de36Sblymn sp->ch = win->bch; 356e124de36Sblymn #else 357e124de36Sblymn sp->ch = (wchar_t)btowc((int)win->bch); 358e124de36Sblymn sp->nsp = NULL; 359e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, sp) == ERR) 360e124de36Sblymn return ERR; 361f1942931Sblymn sp->wcols = 1; 362e124de36Sblymn #endif /* HAVE_WCHAR */ 363d75ec818Sdsl } 36443ea4784Srin lp->hash = __hash_line(lp->line, ncols); 365d75ec818Sdsl } 366d75ec818Sdsl 3671f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->wattr = %08x\n", win->wattr); 3681f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->flags = %#.4x\n", win->flags); 3691f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->maxy = %d\n", win->maxy); 3701f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->maxx = %d\n", win->maxx); 3711f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->begy = %d\n", win->begy); 3721f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->begx = %d\n", win->begx); 3731f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->scr_t = %d\n", win->scr_t); 3741f221324Sjdc __CTRACE(__CTRACE_WINDOW, "resize: win->scr_b = %d\n", win->scr_b); 375d75ec818Sdsl 376f7a8d65fSdsl if (win->orig == NULL) { 377d75ec818Sdsl /* bound subwindows to new size and fixup their pointers */ 378d75ec818Sdsl for (swin = win->nextp; swin != win; swin = swin->nextp) { 379d75ec818Sdsl y = swin->reqy; 38052cd399dSjdc if (swin->begy > win->begy + win->maxy) 38152cd399dSjdc swin->begy = win->begy + win->maxy - 1; 382d75ec818Sdsl if (swin->begy + y > win->begy + win->maxy) 383d75ec818Sdsl y = 0; 384d75ec818Sdsl if (y <= 0) 385d75ec818Sdsl y += win->begy + win->maxy - swin->begy; 38652cd399dSjdc if (y < 1) 38752cd399dSjdc y = 1; 388d75ec818Sdsl x = swin->reqx; 38952cd399dSjdc if (swin->begx > win->begx + win->maxx) 39052cd399dSjdc swin->begx = win->begx + win->maxx - 1; 391d75ec818Sdsl if (swin->begx + x > win->begx + win->maxx) 392d75ec818Sdsl x = 0; 393d75ec818Sdsl if (x <= 0) 394a63e44acSblymn x += win->begx + win->maxx - swin->begx; 39552cd399dSjdc if (x < 1) 39652cd399dSjdc x = 1; 397d75ec818Sdsl __resizewin(swin, y, x); 398f7a8d65fSdsl } 399d75ec818Sdsl } 400d75ec818Sdsl 4019fc03296Sblymn return OK; 4029fc03296Sblymn } 403