1 1.40 blymn /* $NetBSD: screen.c,v 1.40 2024/07/11 07:13:41 blymn Exp $ */ 2 1.1 blymn 3 1.1 blymn /* 4 1.1 blymn * Copyright (c) 1981, 1993, 1994 5 1.1 blymn * The Regents of the University of California. All rights reserved. 6 1.1 blymn * 7 1.1 blymn * Redistribution and use in source and binary forms, with or without 8 1.1 blymn * modification, are permitted provided that the following conditions 9 1.1 blymn * are met: 10 1.1 blymn * 1. Redistributions of source code must retain the above copyright 11 1.1 blymn * notice, this list of conditions and the following disclaimer. 12 1.1 blymn * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 blymn * notice, this list of conditions and the following disclaimer in the 14 1.1 blymn * documentation and/or other materials provided with the distribution. 15 1.15 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 blymn * may be used to endorse or promote products derived from this software 17 1.1 blymn * without specific prior written permission. 18 1.1 blymn * 19 1.1 blymn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 blymn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 blymn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 blymn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 blymn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 blymn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 blymn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 blymn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 blymn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 blymn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 blymn * SUCH DAMAGE. 30 1.1 blymn */ 31 1.1 blymn 32 1.1 blymn #include <sys/cdefs.h> 33 1.1 blymn #ifndef lint 34 1.1 blymn #if 0 35 1.1 blymn static char sccsid[] = "@(#)screen.c 8.2 (blymn) 11/27/2001"; 36 1.1 blymn #else 37 1.40 blymn __RCSID("$NetBSD: screen.c,v 1.40 2024/07/11 07:13:41 blymn Exp $"); 38 1.1 blymn #endif 39 1.1 blymn #endif /* not lint */ 40 1.1 blymn 41 1.1 blymn #include <stdlib.h> 42 1.1 blymn 43 1.1 blymn #include "curses.h" 44 1.1 blymn #include "curses_private.h" 45 1.1 blymn 46 1.25 roy static int filtered; 47 1.25 roy 48 1.33 roy static void __delscreen(SCREEN *); 49 1.33 roy 50 1.33 roy /* 51 1.33 roy * filter has to be called before either initscr or newterm. 52 1.33 roy */ 53 1.33 roy void 54 1.33 roy filter(void) 55 1.33 roy { 56 1.28 roy 57 1.33 roy filtered = TRUE; 58 1.33 roy } 59 1.28 roy 60 1.28 roy /* 61 1.1 blymn * set_term -- 62 1.1 blymn * Change the term to the given screen. 63 1.1 blymn * 64 1.1 blymn */ 65 1.1 blymn SCREEN * 66 1.1 blymn set_term(SCREEN *new) 67 1.1 blymn { 68 1.4 blymn SCREEN *old_screen = _cursesi_screen; 69 1.1 blymn 70 1.1 blymn if (_cursesi_screen != NULL) { 71 1.1 blymn /* save changes made to the current screen... */ 72 1.1 blymn old_screen->echoit = __echoit; 73 1.1 blymn old_screen->pfast = __pfast; 74 1.1 blymn old_screen->rawmode = __rawmode; 75 1.1 blymn old_screen->noqch = __noqch; 76 1.1 blymn old_screen->COLS = COLS; 77 1.34 roy old_screen->LINES = LINES; 78 1.31 roy old_screen->ESCDELAY = ESCDELAY; 79 1.31 roy old_screen->TABSIZE = TABSIZE; 80 1.1 blymn old_screen->COLORS = COLORS; 81 1.1 blymn old_screen->COLOR_PAIRS = COLOR_PAIRS; 82 1.1 blymn old_screen->GT = __GT; 83 1.1 blymn old_screen->NONL = __NONL; 84 1.1 blymn old_screen->UPPERCASE = __UPPERCASE; 85 1.1 blymn } 86 1.5 blymn 87 1.1 blymn _cursesi_screen = new; 88 1.5 blymn 89 1.1 blymn __echoit = new->echoit; 90 1.1 blymn __pfast = new->pfast; 91 1.1 blymn __rawmode = new->rawmode; 92 1.1 blymn __noqch = new->noqch; 93 1.1 blymn COLS = new->COLS; 94 1.34 roy LINES = new->LINES; 95 1.31 roy ESCDELAY = new->ESCDELAY; 96 1.31 roy TABSIZE = new->TABSIZE; 97 1.1 blymn COLORS = new->COLORS; 98 1.1 blymn COLOR_PAIRS = new->COLOR_PAIRS; 99 1.1 blymn __GT = new->GT; 100 1.1 blymn __NONL = new->NONL; 101 1.1 blymn __UPPERCASE = new->UPPERCASE; 102 1.1 blymn 103 1.1 blymn _cursesi_resetterm(new); 104 1.5 blymn 105 1.1 blymn curscr = new->curscr; 106 1.1 blymn clearok(curscr, new->clearok); 107 1.1 blymn stdscr = new->stdscr; 108 1.1 blymn __virtscr = new->__virtscr; 109 1.1 blymn 110 1.1 blymn _cursesi_reset_acs(new); 111 1.20 blymn #ifdef HAVE_WCHAR 112 1.27 roy _cursesi_reset_wacs(new); 113 1.20 blymn #endif /* HAVE_WCHAR */ 114 1.1 blymn 115 1.19 jdc __CTRACE(__CTRACE_SCREEN, "set_term: LINES = %d, COLS = %d\n", 116 1.19 jdc LINES, COLS); 117 1.1 blymn 118 1.1 blymn return old_screen; 119 1.1 blymn } 120 1.1 blymn 121 1.1 blymn /* 122 1.1 blymn * newterm -- 123 1.1 blymn * Set up a new screen. 124 1.1 blymn * 125 1.1 blymn */ 126 1.1 blymn SCREEN * 127 1.38 uwe newterm(const char *type, FILE *outfd, FILE *infd) 128 1.1 blymn { 129 1.1 blymn SCREEN *new_screen; 130 1.38 uwe const char *sp; 131 1.1 blymn 132 1.1 blymn sp = type; 133 1.27 roy if (type == NULL && (sp = getenv("TERM")) == NULL) 134 1.1 blymn return NULL; 135 1.5 blymn 136 1.23 dholland if ((new_screen = calloc(1, sizeof(SCREEN))) == NULL) 137 1.1 blymn return NULL; 138 1.1 blymn 139 1.20 blymn __CTRACE(__CTRACE_INIT, "newterm\n"); 140 1.20 blymn 141 1.1 blymn new_screen->infd = infd; 142 1.32 roy /* 143 1.32 roy * POSIX standard says this should be set to infd by default, 144 1.32 roy * but this seems to break nvi by leaving an unrefreshed screen. 145 1.32 roy * Also, the line breakout optimisation advertised in ncurses 146 1.32 roy * doesn't actually do anything, so explicitly disabling it here makes 147 1.32 roy * sense for the time being. 148 1.32 roy * A caller can always enable it by calling typeahead(3) anyway. 149 1.32 roy */ 150 1.32 roy new_screen->checkfd = -1; // fileno(infd); 151 1.1 blymn new_screen->outfd = outfd; 152 1.13 jdc new_screen->echoit = new_screen->nl = 1; 153 1.20 blymn new_screen->pfast = new_screen->rawmode = new_screen->noqch = 0; 154 1.25 roy new_screen->filtered = filtered; 155 1.37 andvar filtered = FALSE; /* filter() must precede each newterm() */ 156 1.1 blymn new_screen->nca = A_NORMAL; 157 1.1 blymn new_screen->color_type = COLOR_NONE; 158 1.7 jdc new_screen->COLOR_PAIRS = 0; 159 1.40 blymn new_screen->curpair = -1; 160 1.39 uwe new_screen->old_mode = 1; 161 1.1 blymn new_screen->stdbuf = NULL; 162 1.1 blymn new_screen->stdscr = NULL; 163 1.1 blymn new_screen->curscr = NULL; 164 1.1 blymn new_screen->__virtscr = NULL; 165 1.1 blymn new_screen->curwin = 0; 166 1.6 itojun new_screen->notty = FALSE; 167 1.16 jdc new_screen->resized = 0; 168 1.21 jdc new_screen->unget_len = 32; 169 1.21 jdc 170 1.21 jdc if ((new_screen->unget_list = 171 1.28 roy malloc(sizeof(wchar_t) * new_screen->unget_len)) == NULL) 172 1.28 roy { 173 1.21 jdc goto error_exit; 174 1.21 jdc } 175 1.21 jdc new_screen->unget_pos = 0; 176 1.5 blymn 177 1.1 blymn if (_cursesi_gettmode(new_screen) == ERR) 178 1.1 blymn goto error_exit; 179 1.1 blymn 180 1.38 uwe if (_cursesi_setterm(sp, new_screen) == ERR) 181 1.1 blymn goto error_exit; 182 1.1 blymn 183 1.1 blymn /* Need either homing or cursor motion for refreshes */ 184 1.22 roy if (!t_cursor_home(new_screen->term) && 185 1.22 roy !t_cursor_address(new_screen->term)) 186 1.1 blymn goto error_exit; 187 1.5 blymn 188 1.1 blymn new_screen->winlistp = NULL; 189 1.1 blymn 190 1.12 dsl if ((new_screen->curscr = __newwin(new_screen, 0, 191 1.34 roy 0, 0, 0, FALSE, FALSE)) == NULL) 192 1.1 blymn goto error_exit; 193 1.1 blymn 194 1.28 roy if ((new_screen->__virtscr = __newwin(new_screen, 0, 195 1.34 roy 0, 0, 0, FALSE, FALSE)) == NULL) 196 1.1 blymn goto error_exit; 197 1.1 blymn 198 1.30 roy /* If Soft Label Keys are setup, they will ripoffline. */ 199 1.30 roy if (__slk_init(new_screen) == ERR) 200 1.30 roy goto error_exit; 201 1.30 roy 202 1.34 roy if (__ripoffscreen(new_screen) == ERR) 203 1.29 roy goto error_exit; 204 1.11 jdc 205 1.34 roy new_screen->stdscr = __newwin(new_screen, 0, 0, 0, 0, FALSE, TRUE); 206 1.29 roy if (new_screen->stdscr == NULL) 207 1.1 blymn goto error_exit; 208 1.1 blymn 209 1.28 roy clearok(new_screen->stdscr, 1); 210 1.28 roy 211 1.1 blymn __init_getch(new_screen); 212 1.1 blymn __init_acs(new_screen); 213 1.20 blymn #ifdef HAVE_WCHAR 214 1.30 roy __init_get_wch(new_screen); 215 1.20 blymn __init_wacs(new_screen); 216 1.20 blymn #endif /* HAVE_WCHAR */ 217 1.1 blymn 218 1.1 blymn __set_stophandler(); 219 1.16 jdc __set_winchhandler(); 220 1.1 blymn 221 1.1 blymn /* 222 1.1 blymn * bleh - it seems that apps expect the first newterm to set 223 1.1 blymn * up the curses screen.... emulate this. 224 1.1 blymn */ 225 1.3 blymn if (_cursesi_screen == NULL || _cursesi_screen->endwin) { 226 1.1 blymn set_term(new_screen); 227 1.1 blymn } 228 1.5 blymn 229 1.19 jdc __CTRACE(__CTRACE_SCREEN, "newterm: LINES = %d, COLS = %d\n", 230 1.19 jdc LINES, COLS); 231 1.1 blymn __startwin(new_screen); 232 1.1 blymn 233 1.1 blymn return new_screen; 234 1.1 blymn 235 1.1 blymn error_exit: 236 1.29 roy __delscreen(new_screen); 237 1.24 christos free(new_screen->unget_list); 238 1.24 christos 239 1.1 blymn free(new_screen); 240 1.1 blymn return NULL; 241 1.1 blymn } 242 1.1 blymn 243 1.1 blymn /* 244 1.1 blymn * delscreen -- 245 1.1 blymn * Free resources used by the given screen and destroy it. 246 1.1 blymn * 247 1.1 blymn */ 248 1.1 blymn void 249 1.1 blymn delscreen(SCREEN *screen) 250 1.1 blymn { 251 1.1 blymn 252 1.19 jdc __CTRACE(__CTRACE_SCREEN, "delscreen(%p)\n", screen); 253 1.1 blymn 254 1.29 roy __delscreen(screen); 255 1.5 blymn 256 1.1 blymn /* free the storage of the keymaps */ 257 1.1 blymn _cursesi_free_keymap(screen->base_keymap); 258 1.1 blymn 259 1.30 roy /* free the Soft Label Keys */ 260 1.30 roy __slk_free(screen); 261 1.30 roy 262 1.1 blymn free(screen->stdbuf); 263 1.24 christos free(screen->unget_list); 264 1.18 jdc if (_cursesi_screen == screen) 265 1.18 jdc _cursesi_screen = NULL; 266 1.1 blymn free(screen); 267 1.1 blymn } 268 1.29 roy 269 1.29 roy static void 270 1.29 roy __delscreen(SCREEN *screen) 271 1.29 roy { 272 1.29 roy struct __winlist *list; 273 1.29 roy 274 1.29 roy /* free up the terminfo stuff */ 275 1.29 roy if (screen->term != NULL) 276 1.29 roy del_curterm(screen->term); 277 1.29 roy 278 1.29 roy /* walk the window list and kill all the parent windows */ 279 1.29 roy while ((list = screen->winlistp) != NULL) { 280 1.29 roy delwin(list->winp); 281 1.29 roy if (list == screen->winlistp) 282 1.29 roy /* sanity - abort if window didn't remove itself */ 283 1.29 roy break; 284 1.29 roy } 285 1.29 roy } 286