xref: /netbsd-src/lib/libcurses/screen.c (revision 2be3a5a42dd10542bf09b1d4f989beb59ed92dcc)
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