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