1/****************************************************************************
2 * Copyright (c) 1998-2006,2008 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 ****************************************************************************/
34
35/*
36**	lib_options.c
37**
38**	The routines to handle option setting.
39**
40*/
41
42#include <curses.priv.h>
43
44#include <term.h>
45
46MODULE_ID("$Id: lib_options.c,v 1.58 2008/08/16 21:20:48 Werner.Fink Exp $")
47
48static int _nc_curs_set(SCREEN *, int);
49static int _nc_meta(SCREEN *, bool);
50
51NCURSES_EXPORT(int)
52idlok(WINDOW *win, bool flag)
53{
54    T((T_CALLED("idlok(%p,%d)"), win, flag));
55
56    if (win) {
57	_nc_idlok = win->_idlok = (flag && (has_il() || change_scroll_region));
58	returnCode(OK);
59    } else
60	returnCode(ERR);
61}
62
63NCURSES_EXPORT(void)
64idcok(WINDOW *win, bool flag)
65{
66    T((T_CALLED("idcok(%p,%d)"), win, flag));
67
68    if (win)
69	_nc_idcok = win->_idcok = (flag && has_ic());
70
71    returnVoid;
72}
73
74NCURSES_EXPORT(int)
75halfdelay(int t)
76{
77    T((T_CALLED("halfdelay(%d)"), t));
78
79    if (t < 1 || t > 255 || SP == 0)
80	returnCode(ERR);
81
82    cbreak();
83    SP->_cbreak = t + 1;
84    returnCode(OK);
85}
86
87NCURSES_EXPORT(int)
88nodelay(WINDOW *win, bool flag)
89{
90    T((T_CALLED("nodelay(%p,%d)"), win, flag));
91
92    if (win) {
93	if (flag == TRUE)
94	    win->_delay = 0;
95	else
96	    win->_delay = -1;
97	returnCode(OK);
98    } else
99	returnCode(ERR);
100}
101
102NCURSES_EXPORT(int)
103notimeout(WINDOW *win, bool f)
104{
105    T((T_CALLED("notimeout(%p,%d)"), win, f));
106
107    if (win) {
108	win->_notimeout = f;
109	returnCode(OK);
110    } else
111	returnCode(ERR);
112}
113
114NCURSES_EXPORT(void)
115wtimeout(WINDOW *win, int delay)
116{
117    T((T_CALLED("wtimeout(%p,%d)"), win, delay));
118
119    if (win) {
120	win->_delay = delay;
121    }
122    returnVoid;
123}
124
125NCURSES_EXPORT(int)
126keypad(WINDOW *win, bool flag)
127{
128    T((T_CALLED("keypad(%p,%d)"), win, flag));
129
130    if (win) {
131	win->_use_keypad = flag;
132	returnCode(_nc_keypad(SP, flag));
133    } else
134	returnCode(ERR);
135}
136
137NCURSES_EXPORT(int)
138meta(WINDOW *win GCC_UNUSED, bool flag)
139{
140    int result;
141
142    /* Ok, we stay relaxed and don't signal an error if win is NULL */
143    T((T_CALLED("meta(%p,%d)"), win, flag));
144    result = _nc_meta(SP, flag);
145    returnCode(result);
146}
147
148/* curs_set() moved here to narrow the kernel interface */
149
150NCURSES_EXPORT(int)
151curs_set(int vis)
152{
153    int result;
154
155    T((T_CALLED("curs_set(%d)"), vis));
156    result = _nc_curs_set(SP, vis);
157    returnCode(result);
158}
159
160NCURSES_EXPORT(int)
161typeahead(int fd)
162{
163    T((T_CALLED("typeahead(%d)"), fd));
164    if (SP != 0) {
165	SP->_checkfd = fd;
166	returnCode(OK);
167    } else {
168	returnCode(ERR);
169    }
170}
171
172/*
173**      has_key()
174**
175**      Return TRUE if the current terminal has the given key
176**
177*/
178
179#if NCURSES_EXT_FUNCS
180static int
181has_key_internal(int keycode, TRIES * tp)
182{
183    if (tp == 0)
184	return (FALSE);
185    else if (tp->value == keycode)
186	return (TRUE);
187    else
188	return (has_key_internal(keycode, tp->child)
189		|| has_key_internal(keycode, tp->sibling));
190}
191
192NCURSES_EXPORT(int)
193has_key(int keycode)
194{
195    T((T_CALLED("has_key(%d)"), keycode));
196    returnCode(SP != 0 ? has_key_internal(keycode, SP->_keytry) : FALSE);
197}
198#endif /* NCURSES_EXT_FUNCS */
199
200/*
201 * Internal entrypoints use SCREEN* parameter to obtain capabilities rather
202 * than cur_term.
203 */
204#undef CUR
205#define CUR (sp->_term)->type.
206
207static int
208_nc_putp(const char *name GCC_UNUSED, const char *value)
209{
210    int rc = ERR;
211
212    if (value) {
213	TPUTS_TRACE(name);
214	rc = putp(value);
215    }
216    return rc;
217}
218
219static int
220_nc_putp_flush(const char *name, const char *value)
221{
222    int rc = _nc_putp(name, value);
223    if (rc != ERR) {
224	_nc_flush();
225    }
226    return rc;
227}
228
229/* Turn the keypad on/off
230 *
231 * Note:  we flush the output because changing this mode causes some terminals
232 * to emit different escape sequences for cursor and keypad keys.  If we don't
233 * flush, then the next wgetch may get the escape sequence that corresponds to
234 * the terminal state _before_ switching modes.
235 */
236NCURSES_EXPORT(int)
237_nc_keypad(SCREEN *sp, bool flag)
238{
239    int rc = ERR;
240
241    if (sp != 0) {
242#ifdef USE_PTHREADS
243	/*
244	 * We might have this situation in a multithreaded application that
245	 * has wgetch() reading in more than one thread.  putp() and below
246	 * may use SP explicitly.
247	 */
248	if (_nc_use_pthreads && sp != SP) {
249	    SCREEN *save_sp;
250
251	    /* cannot use use_screen(), since that is not in tinfo library */
252	    _nc_lock_global(curses);
253	    save_sp = SP;
254	    _nc_set_screen(sp);
255	    rc = _nc_keypad(sp, flag);
256	    _nc_set_screen(save_sp);
257	    _nc_unlock_global(curses);
258	} else
259#endif
260	{
261	    if (flag) {
262		(void) _nc_putp_flush("keypad_xmit", keypad_xmit);
263	    } else if (!flag && keypad_local) {
264		(void) _nc_putp_flush("keypad_local", keypad_local);
265	    }
266
267	    if (flag && !sp->_tried) {
268		_nc_init_keytry(sp);
269		sp->_tried = TRUE;
270	    }
271	    sp->_keypad_on = flag;
272	    rc = OK;
273	}
274    }
275    return (rc);
276}
277
278static int
279_nc_curs_set(SCREEN *sp, int vis)
280{
281    int result = ERR;
282
283    T((T_CALLED("curs_set(%d)"), vis));
284    if (sp != 0 && vis >= 0 && vis <= 2) {
285	int cursor = sp->_cursor;
286
287	if (vis == cursor) {
288	    result = cursor;
289	} else {
290	    switch (vis) {
291	    case 2:
292		result = _nc_putp_flush("cursor_visible", cursor_visible);
293		break;
294	    case 1:
295		result = _nc_putp_flush("cursor_normal", cursor_normal);
296		break;
297	    case 0:
298		result = _nc_putp_flush("cursor_invisible", cursor_invisible);
299		break;
300	    }
301	    if (result != ERR)
302		result = (cursor == -1 ? 1 : cursor);
303	    sp->_cursor = vis;
304	}
305    }
306    returnCode(result);
307}
308
309static int
310_nc_meta(SCREEN *sp, bool flag)
311{
312    int result = ERR;
313
314    /* Ok, we stay relaxed and don't signal an error if win is NULL */
315
316    if (SP != 0) {
317	SP->_use_meta = flag;
318
319	if (flag) {
320	    _nc_putp("meta_on", meta_on);
321	} else {
322	    _nc_putp("meta_off", meta_off);
323	}
324	result = OK;
325    }
326    return result;
327}
328