17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d67944fbSScott Rotondo * Common Development and Distribution License (the "License").
6d67944fbSScott Rotondo * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22d67944fbSScott Rotondo * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bd9Sstevel@tonic-gate * The Regents of the University of California
327c478bd9Sstevel@tonic-gate * All Rights Reserved
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
357c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
367c478bd9Sstevel@tonic-gate * contributors.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #include "curses_inc.h"
427c478bd9Sstevel@tonic-gate #include <signal.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
44*9c88ac3aSToomas Soome #ifndef FIONREAD
45*9c88ac3aSToomas Soome #include <fcntl.h>
46*9c88ac3aSToomas Soome #endif /* FIONREAD */
477c478bd9Sstevel@tonic-gate #ifdef DEBUG
487c478bd9Sstevel@tonic-gate #include <ctype.h>
497c478bd9Sstevel@tonic-gate #endif /* DEBUG */
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate * Read a key typed from the terminal
537c478bd9Sstevel@tonic-gate *
547c478bd9Sstevel@tonic-gate * interpret: = 0 for single-char key only
557c478bd9Sstevel@tonic-gate * = 1 for matching function key and macro patterns.
567c478bd9Sstevel@tonic-gate * = 2 same as 1 but no time-out for funckey matching.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate static int _getkey(int, chtype *);
607c478bd9Sstevel@tonic-gate static int _fpk(void);
617c478bd9Sstevel@tonic-gate static int _pk(void);
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate chtype
tgetch(int interpret)647c478bd9Sstevel@tonic-gate tgetch(int interpret)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate int i = 0, j, collapse = 1;
677c478bd9Sstevel@tonic-gate #define WAIT3 333
687c478bd9Sstevel@tonic-gate chtype inp;
697c478bd9Sstevel@tonic-gate chtype *inputQ = cur_term->_input_queue;
707c478bd9Sstevel@tonic-gate char *chars_onQ = &(cur_term->_chars_on_queue);
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate #ifdef SYSV
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * Register the fact that getch is being used so
757c478bd9Sstevel@tonic-gate * that typeahead checking can be done.
767c478bd9Sstevel@tonic-gate * This code should GO AWAY when a poll() or FIONREAD can
777c478bd9Sstevel@tonic-gate * be done on the file descriptor as then the check
787c478bd9Sstevel@tonic-gate * will be non-destructive.
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate cur_term->fl_typeahdok = TRUE;
817c478bd9Sstevel@tonic-gate #endif /* SYSV */
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /* ask for input */
847c478bd9Sstevel@tonic-gate if (cur_term->_ungotten > 0) {
857c478bd9Sstevel@tonic-gate cur_term->_ungotten--;
867c478bd9Sstevel@tonic-gate /* decode an ungetch()'d character */
877c478bd9Sstevel@tonic-gate inp = -inputQ[0];
887c478bd9Sstevel@tonic-gate } else {
897c478bd9Sstevel@tonic-gate /* Only read a character if there is no typeahead/peekahead. */
907c478bd9Sstevel@tonic-gate if (*chars_onQ == 0) {
917c478bd9Sstevel@tonic-gate /* (*chars_onQ)++; MR */
927c478bd9Sstevel@tonic-gate #ifdef FIONREAD
937c478bd9Sstevel@tonic-gate inp = _readchar();
947c478bd9Sstevel@tonic-gate #else /* FIONREAD */
957c478bd9Sstevel@tonic-gate inp = (chtype) _pk();
967c478bd9Sstevel@tonic-gate if ((int)inp == ERR) {
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * interpret is set to 0 so that down below we don't
997c478bd9Sstevel@tonic-gate * drop into getkey since we already know there can't be
1007c478bd9Sstevel@tonic-gate * a key that starts with -1. Also, we don't want to
1017c478bd9Sstevel@tonic-gate * access funckeystarter[-1].
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate interpret = FALSE;
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate #endif /* FIONREAD */
1067c478bd9Sstevel@tonic-gate (*chars_onQ)++;
1077c478bd9Sstevel@tonic-gate } else
1087c478bd9Sstevel@tonic-gate inp = inputQ[0];
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #ifdef DEBUG
1117c478bd9Sstevel@tonic-gate if (outf)
1127c478bd9Sstevel@tonic-gate fprintf(outf, "TGETCH read '%s'\n", unctrl(inp));
1137c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /* Check for arrow and function keys */
1167c478bd9Sstevel@tonic-gate if (interpret && cur_term->funckeystarter[inp])
117d67944fbSScott Rotondo collapse = _getkey(interpret - 1, &inp);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate /* Collapse the input queue to remove the escape */
1217c478bd9Sstevel@tonic-gate /* sequence from the stack. */
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate j = *chars_onQ;
1247c478bd9Sstevel@tonic-gate (*chars_onQ) -= collapse;
1257c478bd9Sstevel@tonic-gate while (collapse < j)
1267c478bd9Sstevel@tonic-gate inputQ[i++] = inputQ[collapse++];
1277c478bd9Sstevel@tonic-gate return (inp);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate #ifdef FIONREAD
1317c478bd9Sstevel@tonic-gate static int
_readchar()1327c478bd9Sstevel@tonic-gate _readchar()
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate int i;
1357c478bd9Sstevel@tonic-gate unsigned char c;
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate if (cur_term->_delay == 0) {
1387c478bd9Sstevel@tonic-gate int arg;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate (void) ioctl(cur_term->_inputfd, FIONREAD, &arg);
1417c478bd9Sstevel@tonic-gate #ifdef DEBUG
1427c478bd9Sstevel@tonic-gate if (outf)
1437c478bd9Sstevel@tonic-gate fprintf(outf, "FIONREAD returns %d\n", arg);
1447c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1457c478bd9Sstevel@tonic-gate if (arg < 1)
1467c478bd9Sstevel@tonic-gate return (-1);
1477c478bd9Sstevel@tonic-gate } else
1487c478bd9Sstevel@tonic-gate if (cur_term->_delay > 0) {
1497c478bd9Sstevel@tonic-gate char c;
1507c478bd9Sstevel@tonic-gate int infd;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate infd = 1 << cur_term->_inputfd;
1537c478bd9Sstevel@tonic-gate t.tv_sec = cur_term->_delay / 1000;
1547c478bd9Sstevel@tonic-gate t.tv_usec = (cur_term->_delay % 1000) * 1000;
1557c478bd9Sstevel@tonic-gate i = select(20, &infd, (int *)NULL, (int *)NULL, &t);
1567c478bd9Sstevel@tonic-gate if (i < 0)
1577c478bd9Sstevel@tonic-gate return (ERR);
1587c478bd9Sstevel@tonic-gate i = read(cur_term->_inputfd, &c, 1);
1597c478bd9Sstevel@tonic-gate } else
1607c478bd9Sstevel@tonic-gate i = read(cur_term->_inputfd, &c, 1);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate #ifdef DEBUG
1637c478bd9Sstevel@tonic-gate if (outf)
1647c478bd9Sstevel@tonic-gate fprintf(outf, "read from %d returns %d chars, first %o\n",
1657c478bd9Sstevel@tonic-gate cur_term->_inputfd, i, c);
1667c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate if (i > 0)
1697c478bd9Sstevel@tonic-gate return (c);
1707c478bd9Sstevel@tonic-gate else
1717c478bd9Sstevel@tonic-gate return (ERR);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate #endif /* !FIONREAD */
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate #ifdef DEBUG
1767c478bd9Sstevel@tonic-gate extern char *_asciify();
1777c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1787c478bd9Sstevel@tonic-gate
179d67944fbSScott Rotondo static int get_xterm_mouse(int, int *);
180d67944fbSScott Rotondo static void _map_button(chtype *);
181d67944fbSScott Rotondo
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * This algorithm is a "learning" algorithm. The premise is
1847c478bd9Sstevel@tonic-gate * that keys used once are like to be used again and again.
1857c478bd9Sstevel@tonic-gate * Since the time for a linear search of the table is so
1867c478bd9Sstevel@tonic-gate * expensive, we move keys that are found up to the top of
1877c478bd9Sstevel@tonic-gate * the list, making the access to a repeated key very fast and
1887c478bd9Sstevel@tonic-gate * keys that have been used before close to the top.
1897c478bd9Sstevel@tonic-gate */
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate static int
_getkey(int blockpeek,chtype * inp)1927c478bd9Sstevel@tonic-gate _getkey(int blockpeek, chtype *inp)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate _KEY_MAP **kp = cur_term->_keys;
1957c478bd9Sstevel@tonic-gate int key, num_keys = cur_term->_ksz;
1967c478bd9Sstevel@tonic-gate int i;
1977c478bd9Sstevel@tonic-gate chtype *inputQ = cur_term->_input_queue;
198d67944fbSScott Rotondo char *chars_onQ = &(cur_term->_chars_on_queue);
199d67944fbSScott Rotondo char flag = cur_term->funckeystarter[*inp];
2007c478bd9Sstevel@tonic-gate int first, collapse = 1;
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate #ifdef DEBUG
2047c478bd9Sstevel@tonic-gate if (outf)
2057c478bd9Sstevel@tonic-gate fprintf(outf, "getkey(): looking in linear table, "
2067c478bd9Sstevel@tonic-gate "inp=%d\n", *inp);
2077c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate if (flag & _KEY)
2107c478bd9Sstevel@tonic-gate key = 0;
2117c478bd9Sstevel@tonic-gate else {
2127c478bd9Sstevel@tonic-gate key = cur_term->_first_macro;
2137c478bd9Sstevel@tonic-gate blockpeek = TRUE;
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate first = key;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate for (; key < num_keys; key++) {
2187c478bd9Sstevel@tonic-gate if (kp[key]->_sends[0] == *inp) {
2197c478bd9Sstevel@tonic-gate for (i = 1; i < INP_QSIZE; i++) {
2207c478bd9Sstevel@tonic-gate /* found it? */
2217c478bd9Sstevel@tonic-gate if (kp[key]->_sends[i] == '\0')
2227c478bd9Sstevel@tonic-gate break;
2237c478bd9Sstevel@tonic-gate /* partial match? peek ahead. */
2247c478bd9Sstevel@tonic-gate if (*chars_onQ == i) {
2257c478bd9Sstevel@tonic-gate (*chars_onQ)++;
2267c478bd9Sstevel@tonic-gate inputQ[i] = (blockpeek) ?
227d67944fbSScott Rotondo _pk() : _fpk();
2287c478bd9Sstevel@tonic-gate switch ((int)inputQ[i]) {
2297c478bd9Sstevel@tonic-gate case -2:
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * Since -2 signifies a timeout we don't really
2327c478bd9Sstevel@tonic-gate * want to put it on the queue so we decrement
2337c478bd9Sstevel@tonic-gate * our counter.
2347c478bd9Sstevel@tonic-gate */
2357c478bd9Sstevel@tonic-gate (*chars_onQ)--;
2367c478bd9Sstevel@tonic-gate #ifdef DEBUG
2377c478bd9Sstevel@tonic-gate if (outf)
2387c478bd9Sstevel@tonic-gate fprintf(outf, "Timed out\n");
2397c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2407c478bd9Sstevel@tonic-gate if (flag & _MACRO) {
2417c478bd9Sstevel@tonic-gate #ifdef DEBUG
2427c478bd9Sstevel@tonic-gate if (outf)
2437c478bd9Sstevel@tonic-gate fprintf(outf,
2447c478bd9Sstevel@tonic-gate "Found macro\n");
2457c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate * We have to decrement one because key will be
2487c478bd9Sstevel@tonic-gate * incremented at the bottom of the out loop.
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate key = (first = blockpeek =
2517c478bd9Sstevel@tonic-gate cur_term->_first_macro) -
2527c478bd9Sstevel@tonic-gate 1;
2537c478bd9Sstevel@tonic-gate goto outerloop;
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate case -1:
2597c478bd9Sstevel@tonic-gate goto ret;
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /* not this one? */
2647c478bd9Sstevel@tonic-gate if (kp[key]->_sends[i] != inputQ[i])
2657c478bd9Sstevel@tonic-gate goto outerloop;
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /* SS-mouse */
2697c478bd9Sstevel@tonic-gate if (kp[key]->_keyval == KEY_MOUSE) {
2707c478bd9Sstevel@tonic-gate MOUSE_STATUS old_mouse;
2717c478bd9Sstevel@tonic-gate int rc;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate old_mouse = Mouse_status;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /* read the mouse status information */
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate if (mouse_info)
2787c478bd9Sstevel@tonic-gate rc = -3; /* NOT IMPLEMENTED */
2797c478bd9Sstevel@tonic-gate else
2807c478bd9Sstevel@tonic-gate rc = get_xterm_mouse(blockpeek, &i);
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate if (rc == -1) /* read error */
2837c478bd9Sstevel@tonic-gate goto ret;
2847c478bd9Sstevel@tonic-gate else if (rc == -2 || rc == -3) /* timeout */
2857c478bd9Sstevel@tonic-gate /* or not mouse */
2867c478bd9Sstevel@tonic-gate goto outerloop;
2877c478bd9Sstevel@tonic-gate else if (rc == 0) /* report mouse pos */
2887c478bd9Sstevel@tonic-gate Mouse_status.changes |= 020;
2897c478bd9Sstevel@tonic-gate else if (rc >= 1 && rc <= 3)
2907c478bd9Sstevel@tonic-gate /* mouse button event */
2917c478bd9Sstevel@tonic-gate Mouse_status.changes =
2927c478bd9Sstevel@tonic-gate (((MOUSE_X_POS != old_mouse.x ||
2937c478bd9Sstevel@tonic-gate MOUSE_Y_POS != old_mouse.y) << 3) |
2947c478bd9Sstevel@tonic-gate ((Mouse_status.button[2] !=
2957c478bd9Sstevel@tonic-gate old_mouse.button[2]) << 2) |
2967c478bd9Sstevel@tonic-gate ((Mouse_status.button[1] !=
2977c478bd9Sstevel@tonic-gate old_mouse.button[1]) << 1) |
2987c478bd9Sstevel@tonic-gate (Mouse_status.button[0] !=
2997c478bd9Sstevel@tonic-gate old_mouse.button[0]));
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /* We found it! Read in any chars left in _sends */
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate if ((collapse = i) == INP_QSIZE)
3057c478bd9Sstevel@tonic-gate for (; kp[key]->_sends[i]; i++)
3067c478bd9Sstevel@tonic-gate (void) _fpk();
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /* move key to top of ordered list */
3097c478bd9Sstevel@tonic-gate if (key != first) {
3107c478bd9Sstevel@tonic-gate _KEY_MAP *savekey = kp[key];
3117c478bd9Sstevel@tonic-gate short *lorder;
3127c478bd9Sstevel@tonic-gate int j;
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate if (key > cur_term->_first_macro)
3157c478bd9Sstevel@tonic-gate lorder = &(cur_term->_lastmacro_ordered);
3167c478bd9Sstevel@tonic-gate else
3177c478bd9Sstevel@tonic-gate lorder = &(cur_term->_lastkey_ordered);
3187c478bd9Sstevel@tonic-gate /*
3197c478bd9Sstevel@tonic-gate * If we're below the last ordered key, swap next unordered
3207c478bd9Sstevel@tonic-gate * key with this one and ripple from there.
3217c478bd9Sstevel@tonic-gate */
3227c478bd9Sstevel@tonic-gate if (key > *lorder)
3237c478bd9Sstevel@tonic-gate kp[key] = kp[(i = ++(*lorder))];
3247c478bd9Sstevel@tonic-gate else
3257c478bd9Sstevel@tonic-gate i = key;
3267c478bd9Sstevel@tonic-gate /* ripple the ordered keys down */
3277c478bd9Sstevel@tonic-gate for (j = i--; j > first; )
3287c478bd9Sstevel@tonic-gate kp[j--] = kp[i--];
3297c478bd9Sstevel@tonic-gate kp[first] = savekey;
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate *inp = kp[first]->_keyval;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * SS-mouse support: if mouse button event
3357c478bd9Sstevel@tonic-gate * occured on top of the soft label, we may
3367c478bd9Sstevel@tonic-gate * have to return the function key corresponding
3377c478bd9Sstevel@tonic-gate * to that soft label
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate if (*inp == KEY_MOUSE && A_BUTTON_CHANGED &&
3417c478bd9Sstevel@tonic-gate (MOUSE_Y_POS == LINES) &&
3427c478bd9Sstevel@tonic-gate (SP->slk != (SLK_MAP *) NULL) &&
3437c478bd9Sstevel@tonic-gate (SP->_map_mbe_to_key != 0)) {
3447c478bd9Sstevel@tonic-gate _map_button(inp);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate goto ret;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate outerloop:
3507c478bd9Sstevel@tonic-gate ;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate ret:
3547c478bd9Sstevel@tonic-gate /* key not found */
3557c478bd9Sstevel@tonic-gate #ifdef DEBUG
3567c478bd9Sstevel@tonic-gate if (outf)
3577c478bd9Sstevel@tonic-gate if (key == num_keys)
3587c478bd9Sstevel@tonic-gate fprintf(outf, "Did not match anything.\n");
3597c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3607c478bd9Sstevel@tonic-gate return (collapse);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate /* SS-mouse */
3657c478bd9Sstevel@tonic-gate /* this function tries to read in information that follows KEY_MOUSE: */
3667c478bd9Sstevel@tonic-gate /* the first character identifies what button is involved (1,2,or 3) */
3677c478bd9Sstevel@tonic-gate /* if the first character is 0, we are dealing with report_mouse_pos */
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate * The routine returns the following:
3707c478bd9Sstevel@tonic-gate * -3: not a mouse button event
3717c478bd9Sstevel@tonic-gate * -2: read timed out
3727c478bd9Sstevel@tonic-gate * -1: the read failed
3737c478bd9Sstevel@tonic-gate * [0, 1, 2, 3] - the first character in the mouse event
3747c478bd9Sstevel@tonic-gate */
3757c478bd9Sstevel@tonic-gate static int
get_xterm_mouse(int blockpeek,int * i)3767c478bd9Sstevel@tonic-gate get_xterm_mouse(int blockpeek, int *i)
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate chtype *inputQ = cur_term->_input_queue; /* ??? */
3797c478bd9Sstevel@tonic-gate /* LINTED */
3807c478bd9Sstevel@tonic-gate chtype *chars_onQ = (chtype *) &(cur_term->_chars_on_queue);
3817c478bd9Sstevel@tonic-gate int j, mx, my;
3827c478bd9Sstevel@tonic-gate int char1, char2, c1, c2;
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /* the first character should be 0, 1, 2, or 4 */
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate char1 = (inputQ[(*i)++] = (blockpeek) ? _pk() : _fpk());
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /* read error or timeout */
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate if (char1 < 0)
3917c478bd9Sstevel@tonic-gate return (char1);
3927c478bd9Sstevel@tonic-gate (*chars_onQ)++;
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate if (char1 < '0' || char1 > '3')
3957c478bd9Sstevel@tonic-gate return (-3);
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /* if the character is 1, 2, or 3 it must be followed by */
3987c478bd9Sstevel@tonic-gate /* P, R, C, D, or T */
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate if (char1 != '0') {
4017c478bd9Sstevel@tonic-gate char2 = (inputQ[(*i)++] = (blockpeek) ? _pk() : _fpk());
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate if (char2 < 0)
4047c478bd9Sstevel@tonic-gate return (char2);
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate (*chars_onQ)++;
4077c478bd9Sstevel@tonic-gate if (char2 != 'P' && char2 != 'R' && char2 != 'C' &&
4087c478bd9Sstevel@tonic-gate char2 != 'D' && char2 != 'T')
4097c478bd9Sstevel@tonic-gate return (-3);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /* read X and Y coordinates of the mouse */
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate for (j = 0; j < 2; j++) {
4157c478bd9Sstevel@tonic-gate c1 = (inputQ[(*i)++] = (blockpeek) ? _pk() : _fpk());
4167c478bd9Sstevel@tonic-gate if (c1 < 0)
4177c478bd9Sstevel@tonic-gate return (c1);
4187c478bd9Sstevel@tonic-gate (*chars_onQ)++;
4197c478bd9Sstevel@tonic-gate if (c1 >= ' ' && c1 <= '~') { /* ascii char */
4207c478bd9Sstevel@tonic-gate if (j == 0)
4217c478bd9Sstevel@tonic-gate mx = c1 - ' ';
4227c478bd9Sstevel@tonic-gate else
4237c478bd9Sstevel@tonic-gate my = c1 - ' ';
4247c478bd9Sstevel@tonic-gate } else if (char1 == 01 || char1 == 02) { /* ^A || ^B */
4257c478bd9Sstevel@tonic-gate c2 = (inputQ[(*i)++] = (blockpeek) ? _pk() : _fpk());
4267c478bd9Sstevel@tonic-gate if (c2 < 0)
4277c478bd9Sstevel@tonic-gate return (c2);
4287c478bd9Sstevel@tonic-gate (*chars_onQ)++;
4297c478bd9Sstevel@tonic-gate if (c2 >= ' ' && c2 <= '~') {
4307c478bd9Sstevel@tonic-gate if (j == 0)
4317c478bd9Sstevel@tonic-gate mx = c1 * (c2 - ' ');
4327c478bd9Sstevel@tonic-gate else
4337c478bd9Sstevel@tonic-gate my = c1 * (c2 - ' ');
4347c478bd9Sstevel@tonic-gate } else
4357c478bd9Sstevel@tonic-gate return (-3);
4367c478bd9Sstevel@tonic-gate } else
4377c478bd9Sstevel@tonic-gate return (-3);
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate /* read complete mouse event: update the Mouse_status structure */
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate MOUSE_X_POS = mx;
4437c478bd9Sstevel@tonic-gate MOUSE_Y_POS = my;
4447c478bd9Sstevel@tonic-gate j = char1 - '0';
4457c478bd9Sstevel@tonic-gate if (j != 0) {
4467c478bd9Sstevel@tonic-gate switch (char2) {
4477c478bd9Sstevel@tonic-gate case 'P':
4487c478bd9Sstevel@tonic-gate BUTTON_STATUS(j) = BUTTON_PRESSED;
4497c478bd9Sstevel@tonic-gate break;
4507c478bd9Sstevel@tonic-gate case 'R':
4517c478bd9Sstevel@tonic-gate BUTTON_STATUS(j) = BUTTON_RELEASED;
4527c478bd9Sstevel@tonic-gate break;
4537c478bd9Sstevel@tonic-gate case 'C':
4547c478bd9Sstevel@tonic-gate BUTTON_STATUS(j) = BUTTON_CLICKED;
4557c478bd9Sstevel@tonic-gate break;
4567c478bd9Sstevel@tonic-gate case 'D':
4577c478bd9Sstevel@tonic-gate BUTTON_STATUS(j) = BUTTON_DOUBLE_CLICKED;
4587c478bd9Sstevel@tonic-gate break;
4597c478bd9Sstevel@tonic-gate case 'T':
4607c478bd9Sstevel@tonic-gate BUTTON_STATUS(j) = BUTTON_TRIPLE_CLICKED;
4617c478bd9Sstevel@tonic-gate break;
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate return (j);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate /* SS-mouse-end */
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * Fast peek key. Like getchar but if the right flags are set, times out
4717c478bd9Sstevel@tonic-gate * quickly if there is nothing waiting, returning -1.
4727c478bd9Sstevel@tonic-gate * f is an output stdio descriptor, we read from the fileno.
4737c478bd9Sstevel@tonic-gate * We wait for long enough for a terminal to send another character
4747c478bd9Sstevel@tonic-gate * (at 15cps repeat rate, this is 67 ms, I'm using 100ms to allow
4757c478bd9Sstevel@tonic-gate * a bit of a fudge factor) and time out more quickly.
4767c478bd9Sstevel@tonic-gate * -2 is returned if we time out, -1 is returned if interrupted, and the
4777c478bd9Sstevel@tonic-gate * character is returned otherwise.
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate #ifndef FIONREAD
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate /*
4837c478bd9Sstevel@tonic-gate * Traditional implementation. The best resolution we have is 1 second,
4847c478bd9Sstevel@tonic-gate * so we set a 1 second alarm and try to read. If we fail for 1 second,
4857c478bd9Sstevel@tonic-gate * we assume there is no key waiting. Problem here is that 1 second is
4867c478bd9Sstevel@tonic-gate * too long; people can type faster than this.
4877c478bd9Sstevel@tonic-gate *
4887c478bd9Sstevel@tonic-gate * Another possible implementation of changing VMIN/VTIME before and
4897c478bd9Sstevel@tonic-gate * after each read does not work because the tty driver's timeout
4907c478bd9Sstevel@tonic-gate * mechanism is too unreliable when the timeouts are changed too quickly.
4917c478bd9Sstevel@tonic-gate */
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate static char sig_caught;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate static
4967c478bd9Sstevel@tonic-gate #ifdef SIGPOLL /* Vr3 and beyond */
4977c478bd9Sstevel@tonic-gate void
4987c478bd9Sstevel@tonic-gate #endif /* SIGPOLL */
4997c478bd9Sstevel@tonic-gate /* The following line causes a lint warning for "dummy" which is not used. */
_catch_alarm(int dummy)5007c478bd9Sstevel@tonic-gate _catch_alarm(int dummy)
5017c478bd9Sstevel@tonic-gate {
5027c478bd9Sstevel@tonic-gate sig_caught = 1;
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate static int
_fpk(void)5067c478bd9Sstevel@tonic-gate _fpk(void)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate unsigned char c;
5097c478bd9Sstevel@tonic-gate int infd = cur_term->_inputfd;
5107c478bd9Sstevel@tonic-gate ssize_t rc;
5117c478bd9Sstevel@tonic-gate #ifdef SIGPOLL /* Vr3 and beyond */
5127c478bd9Sstevel@tonic-gate void (*oldsig)(int);
5137c478bd9Sstevel@tonic-gate #else /* SIGPOLL */
5147c478bd9Sstevel@tonic-gate int (*oldsig)(int);
5157c478bd9Sstevel@tonic-gate #endif /* SIGPOLL */
5167c478bd9Sstevel@tonic-gate unsigned int oldalarm, alarm(unsigned);
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /* turn off any user alarms and set our own */
5197c478bd9Sstevel@tonic-gate oldalarm = alarm(0);
5207c478bd9Sstevel@tonic-gate sig_caught = 0;
5217c478bd9Sstevel@tonic-gate oldsig = signal(SIGALRM, _catch_alarm);
5227c478bd9Sstevel@tonic-gate (void) alarm(1);
5237c478bd9Sstevel@tonic-gate rc = read(cur_term->_inputfd, (char *)&c, 1);
5247c478bd9Sstevel@tonic-gate (void) alarm(0);
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate /*
5277c478bd9Sstevel@tonic-gate * This code is to take care of the possibility of
5287c478bd9Sstevel@tonic-gate * the process getting swapped out in the middle of
5297c478bd9Sstevel@tonic-gate * read() call above. The interrupt will cause the
5307c478bd9Sstevel@tonic-gate * read() call to retur, even if a character is really
5317c478bd9Sstevel@tonic-gate * on the clist. So we do a non-blocking read() to make
5327c478bd9Sstevel@tonic-gate * sure that there really isn't a character there.
5337c478bd9Sstevel@tonic-gate */
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate if (sig_caught && rc != 1)
5367c478bd9Sstevel@tonic-gate if (cur_term->_check_fd != -1)
5377c478bd9Sstevel@tonic-gate rc = read(cur_term->_check_fd, (char *)&c, 1);
5387c478bd9Sstevel@tonic-gate else {
5397c478bd9Sstevel@tonic-gate int fcflags = fcntl(infd, F_GETFL, 0);
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate (void) fcntl(infd, F_SETFL, fcflags | O_NDELAY);
5427c478bd9Sstevel@tonic-gate rc = read(infd, (char *)&c, 1);
5437c478bd9Sstevel@tonic-gate (void) fcntl(infd, F_SETFL, fcflags);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /* restore the user alarms */
5477c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, oldsig);
5487c478bd9Sstevel@tonic-gate if (sig_caught && oldalarm > 1)
549d67944fbSScott Rotondo oldalarm--;
5507c478bd9Sstevel@tonic-gate (void) alarm(oldalarm);
5517c478bd9Sstevel@tonic-gate if (rc == 1) /* got a character */
552d67944fbSScott Rotondo return (c);
5537c478bd9Sstevel@tonic-gate else
554d67944fbSScott Rotondo if (sig_caught) /* timed out */
555d67944fbSScott Rotondo return (-2);
556d67944fbSScott Rotondo else /* EOF or got interrupted */
557d67944fbSScott Rotondo return (-1);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate #else /* FIONREAD */
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * If we have the select system call, we can do much better than the
5627c478bd9Sstevel@tonic-gate * traditional method. Even if we don't have the real 4.2BSD select, we
5637c478bd9Sstevel@tonic-gate * can emulate it with napms and FIONREAD. napms might be done with only
5647c478bd9Sstevel@tonic-gate * 1 second resolution, but this is no worse than what we have in the
5657c478bd9Sstevel@tonic-gate * traditional implementation.
5667c478bd9Sstevel@tonic-gate */
5677c478bd9Sstevel@tonic-gate static
_fpk()5687c478bd9Sstevel@tonic-gate _fpk()
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate int infd, rc;
5717c478bd9Sstevel@tonic-gate int *outfd, *exfd;
5727c478bd9Sstevel@tonic-gate unsigned char c;
5737c478bd9Sstevel@tonic-gate struct timeval t;
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate infd = 1 << cur_term->_inputfd;
5767c478bd9Sstevel@tonic-gate outfd = exfd = (int *)NULL;
5777c478bd9Sstevel@tonic-gate t.tv_sec = 0;
5787c478bd9Sstevel@tonic-gate t.tv_usec = 100000; /* 100 milliseconds */
5797c478bd9Sstevel@tonic-gate rc = select(20, &infd, outfd, exfd, &t);
5807c478bd9Sstevel@tonic-gate if (rc < 0)
5817c478bd9Sstevel@tonic-gate return (-2);
5827c478bd9Sstevel@tonic-gate rc = read(fileno(f), &c, 1);
5837c478bd9Sstevel@tonic-gate return (rc == 1 ? c : -1);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate #endif /* FIONREAD */
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate * Plain peekchar function. Nothing fancy. This is just like _fpk
5897c478bd9Sstevel@tonic-gate * but will wait forever rather than time out.
5907c478bd9Sstevel@tonic-gate */
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate static int
_pk(void)5937c478bd9Sstevel@tonic-gate _pk(void)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate unsigned char c;
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate return ((read(cur_term->_inputfd, (char *)&c, 1) == 1) ? c : ERR);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate * SS-mouse: check if this mouse button event should map into
6037c478bd9Sstevel@tonic-gate * function key
6047c478bd9Sstevel@tonic-gate */
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate static void
_map_button(chtype * inp)6087c478bd9Sstevel@tonic-gate _map_button(chtype *inp)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate SLK_MAP *slk = SP->slk;
6117c478bd9Sstevel@tonic-gate int num = slk->_num;
6127c478bd9Sstevel@tonic-gate int len = slk->_len;
6137c478bd9Sstevel@tonic-gate int i;
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate /* first determine if this mouse button event should be */
6167c478bd9Sstevel@tonic-gate /* mapped into function key */
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate if (!(SP->_map_mbe_to_key &
6197c478bd9Sstevel@tonic-gate ((BUTTON_CHANGED(3) << (10 + BUTTON_STATUS(3))) |
6207c478bd9Sstevel@tonic-gate (BUTTON_CHANGED(2) << (5 + BUTTON_STATUS(2))) |
6217c478bd9Sstevel@tonic-gate (BUTTON_CHANGED(1) << BUTTON_STATUS(1)))))
6227c478bd9Sstevel@tonic-gate return;
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate for (i = 0; i < num; i++) {
6257c478bd9Sstevel@tonic-gate if (MOUSE_X_POS < slk->_labx[i])
6267c478bd9Sstevel@tonic-gate break;
6277c478bd9Sstevel@tonic-gate if (MOUSE_X_POS > slk->_labx[i] + len)
6287c478bd9Sstevel@tonic-gate continue;
6297c478bd9Sstevel@tonic-gate *inp = KEY_F(1) + i;
6307c478bd9Sstevel@tonic-gate break;
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate }
633