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