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