ncurses 4.1
[ncurses.git] / ncurses / lib_options.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22
23 /*
24 **      lib_options.c
25 **
26 **      The routines to handle option setting.
27 **
28 */
29
30 #include <curses.priv.h>
31
32 #include <term.h>       /* keypad_xmit, keypad_local, meta_on, meta_off */
33                         /* cursor_visible,cursor_normal,cursor_invisible */
34
35 MODULE_ID("$Id: lib_options.c,v 1.22 1997/05/01 23:46:18 Alexander.V.Lukyanov Exp $")
36
37 int has_ic(void)
38 {
39         T((T_CALLED("has_ic()")));
40         returnCode((insert_character || parm_ich
41            ||  (enter_insert_mode && exit_insert_mode))
42            &&  (delete_character || parm_dch));
43 }
44
45 int has_il(void)
46 {
47         T((T_CALLED("has_il()")));
48         returnCode((insert_line || parm_insert_line)
49                 && (delete_line || parm_delete_line));
50 }
51
52 int idlok(WINDOW *win,  bool flag)
53 {
54         T((T_CALLED("idlok(%p,%d)"), win, flag));
55
56         _nc_idlok = win->_idlok = flag && (has_il() || change_scroll_region);
57         returnCode(OK);
58 }
59
60
61 void idcok(WINDOW *win, bool flag)
62 {
63         T((T_CALLED("idcok(%p,%d)"), win, flag));
64
65         _nc_idcok = win->_idcok = flag && has_ic();
66
67         returnVoid;
68 }
69
70
71 int clearok(WINDOW *win, bool flag)
72 {
73         T((T_CALLED("clearok(%p,%d)"), win, flag));
74
75         win->_clear = flag;
76         returnCode(OK);
77 }
78
79
80 void immedok(WINDOW *win, bool flag)
81 {
82         T((T_CALLED("immedok(%p,%d)"), win, flag));
83
84         win->_immed = flag;
85
86         returnVoid;
87 }
88
89 int leaveok(WINDOW *win, bool flag)
90 {
91         T((T_CALLED("leaveok(%p,%d)"), win, flag));
92
93         win->_leaveok = flag;
94         if (flag == TRUE)
95                 curs_set(0);
96         else
97                 curs_set(1);
98         returnCode(OK);
99 }
100
101
102 int scrollok(WINDOW *win, bool flag)
103 {
104         T((T_CALLED("scrollok(%p,%d)"), win, flag));
105
106         win->_scroll = flag;
107         returnCode(OK);
108 }
109
110 int halfdelay(int t)
111 {
112         T((T_CALLED("halfdelay(%d)"), t));
113
114         if (t < 1 || t > 255)
115                 returnCode(ERR);
116
117         cbreak();
118         SP->_cbreak = t+1;
119         returnCode(OK);
120 }
121
122 int nodelay(WINDOW *win, bool flag)
123 {
124         T((T_CALLED("nodelay(%p,%d)"), win, flag));
125
126         if (flag == TRUE)
127                 win->_delay = 0;
128         else win->_delay = -1;
129         returnCode(OK);
130 }
131
132 int notimeout(WINDOW *win, bool f)
133 {
134         T((T_CALLED("notimout(%p,%d)"), win, f));
135
136         win->_notimeout = f;
137         returnCode(OK);
138 }
139
140 int wtimeout(WINDOW *win, int delay)
141 {
142         T((T_CALLED("wtimeout(%p,%d)"), win, delay));
143
144         win->_delay = delay;
145         returnCode(OK);
146 }
147
148 static void init_keytry(void);
149 static void add_to_try(char *, short);
150
151 /* Turn the keypad on/off
152  *
153  * Note:  we flush the output because changing this mode causes some terminals
154  * to emit different escape sequences for cursor and keypad keys.  If we don't
155  * flush, then the next wgetch may get the escape sequence that corresponds to
156  * the terminal state _before_ switching modes.
157  */
158 int _nc_keypad(bool flag)
159 {
160         if (flag  &&  keypad_xmit)
161         {
162             TPUTS_TRACE("keypad_xmit");
163             putp(keypad_xmit);
164             (void) fflush(SP->_ofp);
165         }
166         else if (! flag  &&  keypad_local)
167         {
168             TPUTS_TRACE("keypad_local");
169             putp(keypad_local);
170             (void) fflush(SP->_ofp);
171         }
172
173         if (SP->_keytry == UNINITIALISED)
174             init_keytry();
175         return(OK);
176 }
177
178 int keypad(WINDOW *win, bool flag)
179 {
180         T((T_CALLED("keypad(%p,%d)"), win, flag));
181
182         win->_use_keypad = flag;
183         returnCode(_nc_keypad(flag));
184 }
185
186
187 int meta(WINDOW *win GCC_UNUSED, bool flag)
188 {
189         T((T_CALLED("meta(%p,%d)"), win, flag));
190
191         SP->_use_meta = flag;
192
193         if (flag  &&  meta_on)
194         {
195             TPUTS_TRACE("meta_on");
196             putp(meta_on);
197         }
198         else if (! flag  &&  meta_off)
199         {
200             TPUTS_TRACE("meta_off");
201             putp(meta_off);
202         }
203         returnCode(OK);
204 }
205
206 /* curs_set() moved here to narrow the kernel interface */
207
208 int curs_set(int vis)
209 {
210 int cursor = SP->_cursor;
211
212         T((T_CALLED("curs_set(%d)"), vis));
213
214         if (vis < 0 || vis > 2)
215                 returnCode(ERR);
216
217         if (vis == cursor)
218                 returnCode(cursor);
219
220         switch(vis) {
221         case 2:
222                 if (cursor_visible)
223                 {
224                         TPUTS_TRACE("cursor_visible");
225                         putp(cursor_visible);
226                 }
227                 else
228                         returnCode(ERR);
229                 break;
230         case 1:
231                 if (cursor_normal)
232                 {
233                         TPUTS_TRACE("cursor_normal");
234                         putp(cursor_normal);
235                 }
236                 else
237                         returnCode(ERR);
238                 break;
239         case 0:
240                 if (cursor_invisible)
241                 {
242                         TPUTS_TRACE("cursor_invisible");
243                         putp(cursor_invisible);
244                 }
245                 else
246                         returnCode(ERR);
247                 break;
248         }
249         SP->_cursor = vis;
250         (void) fflush(SP->_ofp);
251
252         returnCode(cursor==-1 ? 1 : cursor);
253 }
254
255 /*
256 **      init_keytry()
257 **
258 **      Construct the try for the current terminal's keypad keys.
259 **
260 */
261
262
263 static struct  tries *newtry;
264
265 static void init_keytry(void)
266 {
267         newtry = 0;
268
269 /* LINT_PREPRO
270 #if 0*/
271 #include <keys.tries>
272 /* LINT_PREPRO
273 #endif*/
274
275         SP->_keytry = newtry;
276 }
277
278
279 static void add_to_try(char *str, short code)
280 {
281 static bool     out_of_memory = FALSE;
282 struct tries    *ptr, *savedptr;
283
284         if (! str  ||  out_of_memory)
285                 return;
286
287         if (newtry != 0) {
288                 ptr = savedptr = newtry;
289
290                 for (;;) {
291                         while (ptr->ch != (unsigned char) *str
292                                &&  ptr->sibling != 0)
293                                 ptr = ptr->sibling;
294         
295                         if (ptr->ch == (unsigned char) *str) {
296                                 if (*(++str)) {
297                                         if (ptr->child != 0)
298                                                 ptr = ptr->child;
299                                         else
300                                                 break;
301                                 } else {
302                                         ptr->value = code;
303                                         return;
304                                 }
305                         } else {
306                                 if ((ptr->sibling = typeCalloc(struct tries,1)) == 0) {
307                                         out_of_memory = TRUE;
308                                         return;
309                                 }
310
311                                 savedptr = ptr = ptr->sibling;
312                                 if (*str == '\200')
313                                         ptr->ch = '\0';
314                                 else
315                                         ptr->ch = (unsigned char) *str;
316                                 str++;
317                                 ptr->value = 0;
318
319                                 break;
320                         }
321                 } /* end for (;;) */
322         } else {   /* newtry == 0 :: First sequence to be added */
323                 savedptr = ptr = newtry = typeCalloc(struct tries,1);
324
325                 if (ptr == 0) {
326                         out_of_memory = TRUE;
327                                 return;
328                 }
329
330                 if (*str == '\200')
331                         ptr->ch = '\0';
332                 else
333                         ptr->ch = (unsigned char) *str;
334                 str++;
335                 ptr->value = 0;
336         }
337
338             /* at this point, we are adding to the try.  ptr->child == 0 */
339
340         while (*str) {
341                 ptr->child = typeCalloc(struct tries,1);
342
343                 ptr = ptr->child;
344
345                 if (ptr == 0) {
346                         out_of_memory = TRUE;
347
348                         ptr = savedptr;
349                         while (ptr != 0) {
350                                 savedptr = ptr->child;
351                                 free(ptr);
352                                 ptr = savedptr;
353                         }
354
355                         return;
356                 }
357
358                 if (*str == '\200')
359                         ptr->ch = '\0';
360                 else
361                         ptr->ch = (unsigned char) *str;
362                 str++;
363                 ptr->value = 0;
364         }
365
366         ptr->value = code;
367         return;
368 }
369
370 int typeahead(int fd)
371 {
372         T((T_CALLED("typeahead(%d)"), fd));
373         SP->_checkfd = fd;
374         returnCode(OK);
375 }
376
377 /*
378 **      has_key()
379 **
380 **      Return TRUE if the current terminal has the given key
381 **
382 */
383
384
385 static int has_key_internal(int keycode, struct tries *tp)
386 {
387     if (!tp)
388         return(FALSE);
389     else if (tp->value == keycode)
390         return(TRUE);
391     else
392         return(has_key_internal(keycode, tp->child)
393                || has_key_internal(keycode, tp->sibling));
394 }
395
396 int has_key(int keycode)
397 {
398     T((T_CALLED("has_key(%d)"), keycode));
399     returnCode(has_key_internal(keycode, SP->_keytry));
400 }