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