1*2be3a5a4Sblymn /* $NetBSD: screen.c,v 1.40 2024/07/11 07:13:41 blymn Exp $ */
2c84d91aaSblymn
3c84d91aaSblymn /*
4c84d91aaSblymn * Copyright (c) 1981, 1993, 1994
5c84d91aaSblymn * The Regents of the University of California. All rights reserved.
6c84d91aaSblymn *
7c84d91aaSblymn * Redistribution and use in source and binary forms, with or without
8c84d91aaSblymn * modification, are permitted provided that the following conditions
9c84d91aaSblymn * are met:
10c84d91aaSblymn * 1. Redistributions of source code must retain the above copyright
11c84d91aaSblymn * notice, this list of conditions and the following disclaimer.
12c84d91aaSblymn * 2. Redistributions in binary form must reproduce the above copyright
13c84d91aaSblymn * notice, this list of conditions and the following disclaimer in the
14c84d91aaSblymn * documentation and/or other materials provided with the distribution.
15eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors
16c84d91aaSblymn * may be used to endorse or promote products derived from this software
17c84d91aaSblymn * without specific prior written permission.
18c84d91aaSblymn *
19c84d91aaSblymn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20c84d91aaSblymn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21c84d91aaSblymn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22c84d91aaSblymn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23c84d91aaSblymn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24c84d91aaSblymn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25c84d91aaSblymn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26c84d91aaSblymn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27c84d91aaSblymn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28c84d91aaSblymn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29c84d91aaSblymn * SUCH DAMAGE.
30c84d91aaSblymn */
31c84d91aaSblymn
32c84d91aaSblymn #include <sys/cdefs.h>
33c84d91aaSblymn #ifndef lint
34c84d91aaSblymn #if 0
35c84d91aaSblymn static char sccsid[] = "@(#)screen.c 8.2 (blymn) 11/27/2001";
36c84d91aaSblymn #else
37*2be3a5a4Sblymn __RCSID("$NetBSD: screen.c,v 1.40 2024/07/11 07:13:41 blymn Exp $");
38c84d91aaSblymn #endif
39c84d91aaSblymn #endif /* not lint */
40c84d91aaSblymn
41c84d91aaSblymn #include <stdlib.h>
42c84d91aaSblymn
43c84d91aaSblymn #include "curses.h"
44c84d91aaSblymn #include "curses_private.h"
45c84d91aaSblymn
461c3d3283Sroy static int filtered;
471c3d3283Sroy
48c77e1d01Sroy static void __delscreen(SCREEN *);
4925445577Sroy
5025445577Sroy /*
513cd3ec3cSroy * filter has to be called before either initscr or newterm.
523cd3ec3cSroy */
533cd3ec3cSroy void
filter(void)543cd3ec3cSroy filter(void)
553cd3ec3cSroy {
563cd3ec3cSroy
573cd3ec3cSroy filtered = TRUE;
583cd3ec3cSroy }
593cd3ec3cSroy
603cd3ec3cSroy /*
61c84d91aaSblymn * set_term --
62c84d91aaSblymn * Change the term to the given screen.
63c84d91aaSblymn *
64c84d91aaSblymn */
65c84d91aaSblymn SCREEN *
set_term(SCREEN * new)66c84d91aaSblymn set_term(SCREEN *new)
67c84d91aaSblymn {
684118c456Sblymn SCREEN *old_screen = _cursesi_screen;
69c84d91aaSblymn
70c84d91aaSblymn if (_cursesi_screen != NULL) {
71c84d91aaSblymn /* save changes made to the current screen... */
72c84d91aaSblymn old_screen->echoit = __echoit;
73c84d91aaSblymn old_screen->pfast = __pfast;
74c84d91aaSblymn old_screen->rawmode = __rawmode;
75c84d91aaSblymn old_screen->noqch = __noqch;
76c84d91aaSblymn old_screen->COLS = COLS;
77d34c5681Sroy old_screen->LINES = LINES;
788dcd50a6Sroy old_screen->ESCDELAY = ESCDELAY;
798dcd50a6Sroy old_screen->TABSIZE = TABSIZE;
80c84d91aaSblymn old_screen->COLORS = COLORS;
81c84d91aaSblymn old_screen->COLOR_PAIRS = COLOR_PAIRS;
82c84d91aaSblymn old_screen->GT = __GT;
83c84d91aaSblymn old_screen->NONL = __NONL;
84c84d91aaSblymn old_screen->UPPERCASE = __UPPERCASE;
85c84d91aaSblymn }
86c84d91aaSblymn
87c84d91aaSblymn _cursesi_screen = new;
88c84d91aaSblymn
89c84d91aaSblymn __echoit = new->echoit;
90c84d91aaSblymn __pfast = new->pfast;
91c84d91aaSblymn __rawmode = new->rawmode;
92c84d91aaSblymn __noqch = new->noqch;
93c84d91aaSblymn COLS = new->COLS;
94d34c5681Sroy LINES = new->LINES;
958dcd50a6Sroy ESCDELAY = new->ESCDELAY;
968dcd50a6Sroy TABSIZE = new->TABSIZE;
97c84d91aaSblymn COLORS = new->COLORS;
98c84d91aaSblymn COLOR_PAIRS = new->COLOR_PAIRS;
99c84d91aaSblymn __GT = new->GT;
100c84d91aaSblymn __NONL = new->NONL;
101c84d91aaSblymn __UPPERCASE = new->UPPERCASE;
102c84d91aaSblymn
103c84d91aaSblymn _cursesi_resetterm(new);
104c84d91aaSblymn
105c84d91aaSblymn curscr = new->curscr;
106c84d91aaSblymn clearok(curscr, new->clearok);
107c84d91aaSblymn stdscr = new->stdscr;
108c84d91aaSblymn __virtscr = new->__virtscr;
109c84d91aaSblymn
110c84d91aaSblymn _cursesi_reset_acs(new);
111e124de36Sblymn #ifdef HAVE_WCHAR
112e124de36Sblymn _cursesi_reset_wacs(new);
113e124de36Sblymn #endif /* HAVE_WCHAR */
114c84d91aaSblymn
1151f221324Sjdc __CTRACE(__CTRACE_SCREEN, "set_term: LINES = %d, COLS = %d\n",
1161f221324Sjdc LINES, COLS);
117c84d91aaSblymn
118c84d91aaSblymn return old_screen;
119c84d91aaSblymn }
120c84d91aaSblymn
121c84d91aaSblymn /*
122c84d91aaSblymn * newterm --
123c84d91aaSblymn * Set up a new screen.
124c84d91aaSblymn *
125c84d91aaSblymn */
126c84d91aaSblymn SCREEN *
newterm(const char * type,FILE * outfd,FILE * infd)127a9c500b2Suwe newterm(const char *type, FILE *outfd, FILE *infd)
128c84d91aaSblymn {
129c84d91aaSblymn SCREEN *new_screen;
130a9c500b2Suwe const char *sp;
131c84d91aaSblymn
132c84d91aaSblymn sp = type;
13350a63ac8Sroy if (type == NULL && (sp = getenv("TERM")) == NULL)
134c84d91aaSblymn return NULL;
135c84d91aaSblymn
1364bded220Sdholland if ((new_screen = calloc(1, sizeof(SCREEN))) == NULL)
137c84d91aaSblymn return NULL;
138c84d91aaSblymn
139e124de36Sblymn __CTRACE(__CTRACE_INIT, "newterm\n");
140e124de36Sblymn
141c84d91aaSblymn new_screen->infd = infd;
1420d7cbb25Sroy /*
1430d7cbb25Sroy * POSIX standard says this should be set to infd by default,
1440d7cbb25Sroy * but this seems to break nvi by leaving an unrefreshed screen.
1450d7cbb25Sroy * Also, the line breakout optimisation advertised in ncurses
1460d7cbb25Sroy * doesn't actually do anything, so explicitly disabling it here makes
1470d7cbb25Sroy * sense for the time being.
1480d7cbb25Sroy * A caller can always enable it by calling typeahead(3) anyway.
1490d7cbb25Sroy */
1500d7cbb25Sroy new_screen->checkfd = -1; // fileno(infd);
151c84d91aaSblymn new_screen->outfd = outfd;
152e6800497Sjdc new_screen->echoit = new_screen->nl = 1;
153c84d91aaSblymn new_screen->pfast = new_screen->rawmode = new_screen->noqch = 0;
1541c3d3283Sroy new_screen->filtered = filtered;
1552fa7e141Sandvar filtered = FALSE; /* filter() must precede each newterm() */
156c84d91aaSblymn new_screen->nca = A_NORMAL;
157c84d91aaSblymn new_screen->color_type = COLOR_NONE;
1584eb3ef3dSjdc new_screen->COLOR_PAIRS = 0;
159*2be3a5a4Sblymn new_screen->curpair = -1;
160463a9e2dSuwe new_screen->old_mode = 1;
161c84d91aaSblymn new_screen->stdbuf = NULL;
162c84d91aaSblymn new_screen->stdscr = NULL;
163c84d91aaSblymn new_screen->curscr = NULL;
164c84d91aaSblymn new_screen->__virtscr = NULL;
165c84d91aaSblymn new_screen->curwin = 0;
1662f69e2e1Sitojun new_screen->notty = FALSE;
167efc30049Sjdc new_screen->resized = 0;
1687cc6075bSjdc new_screen->unget_len = 32;
1697cc6075bSjdc
1707cc6075bSjdc if ((new_screen->unget_list =
17125445577Sroy malloc(sizeof(wchar_t) * new_screen->unget_len)) == NULL)
17225445577Sroy {
1737cc6075bSjdc goto error_exit;
1747cc6075bSjdc }
1757cc6075bSjdc new_screen->unget_pos = 0;
176c84d91aaSblymn
177c84d91aaSblymn if (_cursesi_gettmode(new_screen) == ERR)
178c84d91aaSblymn goto error_exit;
179c84d91aaSblymn
180a9c500b2Suwe if (_cursesi_setterm(sp, new_screen) == ERR)
181c84d91aaSblymn goto error_exit;
182c84d91aaSblymn
183c84d91aaSblymn /* Need either homing or cursor motion for refreshes */
18498eb8895Sroy if (!t_cursor_home(new_screen->term) &&
18598eb8895Sroy !t_cursor_address(new_screen->term))
186c84d91aaSblymn goto error_exit;
187c84d91aaSblymn
188c84d91aaSblymn new_screen->winlistp = NULL;
189c84d91aaSblymn
190d75ec818Sdsl if ((new_screen->curscr = __newwin(new_screen, 0,
191d34c5681Sroy 0, 0, 0, FALSE, FALSE)) == NULL)
192c84d91aaSblymn goto error_exit;
193c84d91aaSblymn
19425445577Sroy if ((new_screen->__virtscr = __newwin(new_screen, 0,
195d34c5681Sroy 0, 0, 0, FALSE, FALSE)) == NULL)
196c84d91aaSblymn goto error_exit;
197c84d91aaSblymn
198a2ac1ce4Sroy /* If Soft Label Keys are setup, they will ripoffline. */
199a2ac1ce4Sroy if (__slk_init(new_screen) == ERR)
200a2ac1ce4Sroy goto error_exit;
201a2ac1ce4Sroy
202d34c5681Sroy if (__ripoffscreen(new_screen) == ERR)
20325445577Sroy goto error_exit;
204c77e1d01Sroy
205d34c5681Sroy new_screen->stdscr = __newwin(new_screen, 0, 0, 0, 0, FALSE, TRUE);
206c77e1d01Sroy if (new_screen->stdscr == NULL)
207c77e1d01Sroy goto error_exit;
20825445577Sroy
20960f70094Sjdc clearok(new_screen->stdscr, 1);
21060f70094Sjdc
211c84d91aaSblymn __init_getch(new_screen);
212c84d91aaSblymn __init_acs(new_screen);
213e124de36Sblymn #ifdef HAVE_WCHAR
214e124de36Sblymn __init_get_wch(new_screen);
215e124de36Sblymn __init_wacs(new_screen);
216e124de36Sblymn #endif /* HAVE_WCHAR */
217c84d91aaSblymn
218c84d91aaSblymn __set_stophandler();
219efc30049Sjdc __set_winchhandler();
220c84d91aaSblymn
221c84d91aaSblymn /*
222c84d91aaSblymn * bleh - it seems that apps expect the first newterm to set
223c84d91aaSblymn * up the curses screen.... emulate this.
224c84d91aaSblymn */
225d7893fc4Sblymn if (_cursesi_screen == NULL || _cursesi_screen->endwin) {
226c84d91aaSblymn set_term(new_screen);
227c84d91aaSblymn }
228c84d91aaSblymn
2291f221324Sjdc __CTRACE(__CTRACE_SCREEN, "newterm: LINES = %d, COLS = %d\n",
2301f221324Sjdc LINES, COLS);
231c84d91aaSblymn __startwin(new_screen);
232c84d91aaSblymn
233c84d91aaSblymn return new_screen;
234c84d91aaSblymn
235c84d91aaSblymn error_exit:
236c77e1d01Sroy __delscreen(new_screen);
237600fe0a3Schristos free(new_screen->unget_list);
238600fe0a3Schristos
239c84d91aaSblymn free(new_screen);
240c84d91aaSblymn return NULL;
241c84d91aaSblymn }
242c84d91aaSblymn
243c84d91aaSblymn /*
244c84d91aaSblymn * delscreen --
245c84d91aaSblymn * Free resources used by the given screen and destroy it.
246c84d91aaSblymn *
247c84d91aaSblymn */
248c84d91aaSblymn void
delscreen(SCREEN * screen)249c84d91aaSblymn delscreen(SCREEN *screen)
250c84d91aaSblymn {
251c84d91aaSblymn
2521f221324Sjdc __CTRACE(__CTRACE_SCREEN, "delscreen(%p)\n", screen);
253c84d91aaSblymn
254c77e1d01Sroy __delscreen(screen);
255c84d91aaSblymn
256c84d91aaSblymn /* free the storage of the keymaps */
257c84d91aaSblymn _cursesi_free_keymap(screen->base_keymap);
258c84d91aaSblymn
259a2ac1ce4Sroy /* free the Soft Label Keys */
260a2ac1ce4Sroy __slk_free(screen);
261a2ac1ce4Sroy
262c84d91aaSblymn free(screen->stdbuf);
263600fe0a3Schristos free(screen->unget_list);
264ed312f07Sjdc if (_cursesi_screen == screen)
265ed312f07Sjdc _cursesi_screen = NULL;
266c84d91aaSblymn free(screen);
267c84d91aaSblymn }
268c77e1d01Sroy
269c77e1d01Sroy static void
__delscreen(SCREEN * screen)270c77e1d01Sroy __delscreen(SCREEN *screen)
271c77e1d01Sroy {
272c77e1d01Sroy struct __winlist *list;
273c77e1d01Sroy
274c77e1d01Sroy /* free up the terminfo stuff */
275c77e1d01Sroy if (screen->term != NULL)
276c77e1d01Sroy del_curterm(screen->term);
277c77e1d01Sroy
278c77e1d01Sroy /* walk the window list and kill all the parent windows */
279c77e1d01Sroy while ((list = screen->winlistp) != NULL) {
280c77e1d01Sroy delwin(list->winp);
281c77e1d01Sroy if (list == screen->winlistp)
282c77e1d01Sroy /* sanity - abort if window didn't remove itself */
283c77e1d01Sroy break;
284c77e1d01Sroy }
285c77e1d01Sroy }
286