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
NCURSES_EXPORT(int)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)
idcok(WINDOW * win,bool flag)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)
NCURSES_SP_NAME(halfdelay)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)
halfdelay(int t)103 halfdelay(int t)
104 {
105 return NCURSES_SP_NAME(halfdelay) (CURRENT_SCREEN, t);
106 }
107 #endif
108
109 NCURSES_EXPORT(int)
nodelay(WINDOW * win,bool flag)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)
notimeout(WINDOW * win,bool f)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)
wtimeout(WINDOW * win,int delay)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)
keypad(WINDOW * win,bool flag)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)
meta(WINDOW * win GCC_UNUSED,bool flag)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)
NCURSES_SP_NAME(curs_set)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)
curs_set(int vis)237 curs_set(int vis)
238 {
239 return (NCURSES_SP_NAME(curs_set) (CURRENT_SCREEN, vis));
240 }
241 #endif
242
243 NCURSES_EXPORT(int)
NCURSES_SP_NAME(typeahead)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)
typeahead(int fd)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
has_key_internal(int keycode,TRIES * tp)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)
TINFO_HAS_KEY(SCREEN * sp,int keycode)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)
NCURSES_SP_NAME(has_key)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)
has_key(int keycode)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)
NCURSES_SP_NAME(_nc_putp_flush)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)
_nc_keypad(SCREEN * sp,int flag)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