1 /****************************************************************************
2  * Copyright 2020 Thomas E. Dickey                                          *
3  * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29 
30 /****************************************************************************
31  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
33  *     and: Thomas E. Dickey                        1996-on                 *
34  *     and: Juergen Pfeifer                         2009                    *
35  ****************************************************************************/
36 
37 /*
38 **	lib_options.c
39 **
40 **	The routines to handle option setting.
41 **
42 */
43 
44 #include <curses.priv.h>
45 
46 #ifndef CUR
47 #define CUR SP_TERMTYPE
48 #endif
49 
50 MODULE_ID("$Id: lib_options.c,v 1.81 2020/02/02 23:34:34 tom Exp $")
51 
NCURSES_EXPORT(int)52 NCURSES_EXPORT(int)
53 idlok(WINDOW *win, bool flag)
54 {
55     int res = ERR;
56     T((T_CALLED("idlok(%p,%d)"), (void *) win, flag));
57 
58     if (win) {
59 	SCREEN *sp = _nc_screen_of(win);
60 	if (sp != 0
61 #ifdef USE_TERM_DRIVER
62 	    && IsTermInfo(sp)
63 #endif
64 	    ) {
65 	    sp->_nc_sp_idlok =
66 		win->_idlok = (flag && (NCURSES_SP_NAME(has_il) (NCURSES_SP_ARG)
67 					|| change_scroll_region));
68 	    res = OK;
69 	}
70     }
71     returnCode(res);
72 }
73 
74 NCURSES_EXPORT(void)
idcok(WINDOW * win,bool flag)75 idcok(WINDOW *win, bool flag)
76 {
77     T((T_CALLED("idcok(%p,%d)"), (void *) win, flag));
78 
79     if (win) {
80 	SCREEN *sp = _nc_screen_of(win);
81 	sp->_nc_sp_idcok = win->_idcok = (flag && NCURSES_SP_NAME(has_ic) (NCURSES_SP_ARG));
82     }
83     returnVoid;
84 }
85 
86 NCURSES_EXPORT(int)
NCURSES_SP_NAME(halfdelay)87 NCURSES_SP_NAME(halfdelay) (NCURSES_SP_DCLx int t)
88 {
89     T((T_CALLED("halfdelay(%p,%d)"), (void *) SP_PARM, t));
90 
91     if (t < 1 || t > 255 || !SP_PARM || !IsValidTIScreen(SP_PARM))
92 	returnCode(ERR);
93 
94     NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG);
95     SP_PARM->_cbreak = t + 1;
96     returnCode(OK);
97 }
98 
99 #if NCURSES_SP_FUNCS
100 NCURSES_EXPORT(int)
halfdelay(int t)101 halfdelay(int t)
102 {
103     return NCURSES_SP_NAME(halfdelay) (CURRENT_SCREEN, t);
104 }
105 #endif
106 
107 NCURSES_EXPORT(int)
nodelay(WINDOW * win,bool flag)108 nodelay(WINDOW *win, bool flag)
109 {
110     T((T_CALLED("nodelay(%p,%d)"), (void *) win, flag));
111 
112     if (win) {
113 	if (flag == TRUE)
114 	    win->_delay = 0;
115 	else
116 	    win->_delay = -1;
117 	returnCode(OK);
118     } else
119 	returnCode(ERR);
120 }
121 
122 NCURSES_EXPORT(int)
notimeout(WINDOW * win,bool f)123 notimeout(WINDOW *win, bool f)
124 {
125     T((T_CALLED("notimeout(%p,%d)"), (void *) win, f));
126 
127     if (win) {
128 	win->_notimeout = f;
129 	returnCode(OK);
130     } else
131 	returnCode(ERR);
132 }
133 
134 NCURSES_EXPORT(void)
wtimeout(WINDOW * win,int delay)135 wtimeout(WINDOW *win, int delay)
136 {
137     T((T_CALLED("wtimeout(%p,%d)"), (void *) win, delay));
138 
139     if (win) {
140 	win->_delay = delay;
141     }
142     returnVoid;
143 }
144 
145 NCURSES_EXPORT(int)
keypad(WINDOW * win,bool flag)146 keypad(WINDOW *win, bool flag)
147 {
148     T((T_CALLED("keypad(%p,%d)"), (void *) win, flag));
149 
150     if (win) {
151 	win->_use_keypad = flag;
152 	returnCode(_nc_keypad(_nc_screen_of(win), flag));
153     } else
154 	returnCode(ERR);
155 }
156 
157 NCURSES_EXPORT(int)
meta(WINDOW * win GCC_UNUSED,bool flag)158 meta(WINDOW *win GCC_UNUSED, bool flag)
159 {
160     int result = ERR;
161     SCREEN *sp = (win == 0) ? CURRENT_SCREEN : _nc_screen_of(win);
162 
163     /* Ok, we stay relaxed and don't signal an error if win is NULL */
164     T((T_CALLED("meta(%p,%d)"), (void *) win, flag));
165 
166     /* Ok, we stay relaxed and don't signal an error if win is NULL */
167 
168     if (sp != 0) {
169 	sp->_use_meta = flag;
170 #ifdef USE_TERM_DRIVER
171 	if (IsTermInfo(sp)) {
172 	    if (flag) {
173 		NCURSES_PUTP2("meta_on", meta_on);
174 	    } else {
175 		NCURSES_PUTP2("meta_off", meta_off);
176 	    }
177 	}
178 #else
179 	if (flag) {
180 	    NCURSES_PUTP2("meta_on", meta_on);
181 	} else {
182 	    NCURSES_PUTP2("meta_off", meta_off);
183 	}
184 #endif
185 	result = OK;
186     }
187     returnCode(result);
188 }
189 
190 /* curs_set() moved here to narrow the kernel interface */
191 
192 NCURSES_EXPORT(int)
NCURSES_SP_NAME(curs_set)193 NCURSES_SP_NAME(curs_set) (NCURSES_SP_DCLx int vis)
194 {
195     int code = ERR;
196     T((T_CALLED("curs_set(%p,%d)"), (void *) SP_PARM, vis));
197 
198     if (SP_PARM != 0 && vis >= 0 && vis <= 2) {
199 	int cursor = SP_PARM->_cursor;
200 	if (vis == cursor) {
201 	    code = cursor;
202 	} else {
203 #ifdef USE_TERM_DRIVER
204 	    code = CallDriver_1(SP_PARM, td_cursorSet, vis);
205 #else
206 	    if (IsValidTIScreen(SP_PARM)) {
207 		switch (vis) {
208 		case 2:
209 		    code = NCURSES_PUTP2_FLUSH("cursor_visible",
210 					       cursor_visible);
211 		    break;
212 		case 1:
213 		    code = NCURSES_PUTP2_FLUSH("cursor_normal",
214 					       cursor_normal);
215 		    break;
216 		case 0:
217 		    code = NCURSES_PUTP2_FLUSH("cursor_invisible",
218 					       cursor_invisible);
219 		    break;
220 		}
221 	    } else {
222 		code = ERR;
223 	    }
224 #endif
225 	    if (code != ERR)
226 		code = (cursor == -1 ? 1 : cursor);
227 	    SP_PARM->_cursor = vis;
228 	}
229     }
230     returnCode(code);
231 }
232 
233 #if NCURSES_SP_FUNCS
234 NCURSES_EXPORT(int)
curs_set(int vis)235 curs_set(int vis)
236 {
237     return (NCURSES_SP_NAME(curs_set) (CURRENT_SCREEN, vis));
238 }
239 #endif
240 
241 NCURSES_EXPORT(int)
NCURSES_SP_NAME(typeahead)242 NCURSES_SP_NAME(typeahead) (NCURSES_SP_DCLx int fd)
243 {
244     T((T_CALLED("typeahead(%p, %d)"), (void *) SP_PARM, fd));
245     if (SP_PARM && IsValidTIScreen(SP_PARM)) {
246 	SP_PARM->_checkfd = fd;
247 	returnCode(OK);
248     } else {
249 	returnCode(ERR);
250     }
251 }
252 
253 #if NCURSES_SP_FUNCS
254 NCURSES_EXPORT(int)
typeahead(int fd)255 typeahead(int fd)
256 {
257     return NCURSES_SP_NAME(typeahead) (CURRENT_SCREEN, fd);
258 }
259 #endif
260 
261 /*
262 **      has_key()
263 **
264 **      Return TRUE if the current terminal has the given key
265 **
266 */
267 
268 #if NCURSES_EXT_FUNCS
269 static int
has_key_internal(int keycode,TRIES * tp)270 has_key_internal(int keycode, TRIES * tp)
271 {
272     if (tp == 0)
273 	return (FALSE);
274     else if (tp->value == keycode)
275 	return (TRUE);
276     else
277 	return (has_key_internal(keycode, tp->child)
278 		|| has_key_internal(keycode, tp->sibling));
279 }
280 
281 #ifdef USE_TERM_DRIVER
282 NCURSES_EXPORT(int)
TINFO_HAS_KEY(SCREEN * sp,int keycode)283 TINFO_HAS_KEY(SCREEN *sp, int keycode)
284 {
285     return IsValidTIScreen(sp) ?
286 	has_key_internal(keycode, sp->_keytry) : 0;
287 }
288 #else
289 NCURSES_EXPORT(int)
NCURSES_SP_NAME(has_key)290 NCURSES_SP_NAME(has_key) (NCURSES_SP_DCLx int keycode)
291 {
292     T((T_CALLED("has_key(%p,%d)"), (void *) SP_PARM, keycode));
293     returnCode(SP != 0 ? has_key_internal(keycode, SP_PARM->_keytry) : FALSE);
294 }
295 
296 #if NCURSES_SP_FUNCS
297 NCURSES_EXPORT(int)
has_key(int keycode)298 has_key(int keycode)
299 {
300     return NCURSES_SP_NAME(has_key) (CURRENT_SCREEN, keycode);
301 }
302 #endif
303 #endif
304 #endif /* NCURSES_EXT_FUNCS */
305 
306 NCURSES_EXPORT(int)
NCURSES_SP_NAME(_nc_putp_flush)307 NCURSES_SP_NAME(_nc_putp_flush) (NCURSES_SP_DCLx
308 				 const char *name, const char *value)
309 {
310     int rc = NCURSES_PUTP2(name, value);
311     if (rc != ERR) {
312 	_nc_flush();
313     }
314     return rc;
315 }
316 
317 #if 0 && NCURSES_SP_FUNCS
318 NCURSES_EXPORT(int)
319 _nc_putp_flush(const char *name, const char *value)
320 {
321     return NCURSES_SP_NAME(_nc_putp_flush) (CURRENT_SCREEN, name, value);
322 }
323 #endif
324 
325 /* Turn the keypad on/off
326  *
327  * Note:  we flush the output because changing this mode causes some terminals
328  * to emit different escape sequences for cursor and keypad keys.  If we don't
329  * flush, then the next wgetch may get the escape sequence that corresponds to
330  * the terminal state _before_ switching modes.
331  */
332 NCURSES_EXPORT(int)
_nc_keypad(SCREEN * sp,int flag)333 _nc_keypad(SCREEN *sp, int flag)
334 {
335     int rc = ERR;
336 
337     if (sp != 0) {
338 #ifdef USE_PTHREADS
339 	/*
340 	 * We might have this situation in a multithreaded application that
341 	 * has wgetch() reading in more than one thread.  putp() and below
342 	 * may use SP explicitly.
343 	 */
344 	if (_nc_use_pthreads && sp != CURRENT_SCREEN) {
345 	    SCREEN *save_sp;
346 
347 	    /* cannot use use_screen(), since that is not in tinfo library */
348 	    _nc_lock_global(curses);
349 	    save_sp = CURRENT_SCREEN;
350 	    _nc_set_screen(sp);
351 	    rc = _nc_keypad(sp, flag);
352 	    _nc_set_screen(save_sp);
353 	    _nc_unlock_global(curses);
354 	} else
355 #endif
356 	{
357 #ifdef USE_TERM_DRIVER
358 	    rc = CallDriver_1(sp, td_kpad, flag);
359 	    if (rc == OK)
360 		sp->_keypad_on = flag;
361 #else
362 	    if (flag) {
363 		(void) NCURSES_PUTP2_FLUSH("keypad_xmit", keypad_xmit);
364 	    } else if (!flag && keypad_local) {
365 		(void) NCURSES_PUTP2_FLUSH("keypad_local", keypad_local);
366 	    }
367 
368 	    if (flag && !sp->_tried) {
369 		_nc_init_keytry(sp);
370 		sp->_tried = TRUE;
371 	    }
372 	    sp->_keypad_on = flag;
373 	    rc = OK;
374 #endif
375 	}
376     }
377     return (rc);
378 }
379