[BACK]Return to getch.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libcurses

Annotation of src/lib/libcurses/getch.c, Revision 1.33

1.33    ! blymn       1: /*     $NetBSD: getch.c,v 1.32 2000/09/23 09:34:07 itojun Exp $        */
1.8       mikel       2:
1.1       cgd         3: /*
1.7       cgd         4:  * Copyright (c) 1981, 1993, 1994
1.5       cgd         5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.8       mikel      36: #include <sys/cdefs.h>
1.1       cgd        37: #ifndef lint
1.8       mikel      38: #if 0
1.7       cgd        39: static char sccsid[] = "@(#)getch.c    8.2 (Berkeley) 5/4/94";
1.8       mikel      40: #else
1.33    ! blymn      41: __RCSID("$NetBSD: getch.c,v 1.32 2000/09/23 09:34:07 itojun Exp $");
1.8       mikel      42: #endif
1.10      mrg        43: #endif                                 /* not lint */
1.1       cgd        44:
1.10      mrg        45: #include <string.h>
                     46: #include <stdlib.h>
                     47: #include <unistd.h>
                     48: #include <stdio.h>
1.7       cgd        49: #include "curses.h"
1.16      blymn      50: #include "curses_private.h"
1.1       cgd        51:
1.27      blymn      52: /* defined in setterm.c */
                     53: extern struct tinfo *_cursesi_genbuf;
                     54:
1.10      mrg        55: #define DEFAULT_DELAY 2                        /* default delay for timeout() */
                     56:
                     57: /*
                     58:  * Keyboard input handler.  Do this by snarfing
                     59:  * all the info we can out of the termcap entry for TERM and putting it
                     60:  * into a set of keymaps.  A keymap is an array the size of all the possible
                     61:  * single characters we can get, the contents of the array is a structure
                     62:  * that contains the type of entry this character is (i.e. part/end of a
                     63:  * multi-char sequence or a plain char) and either a pointer which will point
                     64:  * to another keymap (in the case of a multi-char sequence) OR the data value
                     65:  * that this key should return.
                     66:  *
                     67:  */
                     68:
                     69: /* private data structures for holding the key definitions */
                     70: typedef struct keymap keymap_t;
                     71: typedef struct key_entry key_entry_t;
                     72:
                     73: struct key_entry {
                     74:        short   type;           /* type of key this is */
                     75:        union {
                     76:                keymap_t *next; /* next keymap is key is multi-key sequence */
1.16      blymn      77:                wchar_t   symbol;       /* key symbol if key is a leaf entry */
1.12      pk         78:        } value;
1.10      mrg        79: };
                     80: /* Types of key structures we can have */
                     81: #define KEYMAP_MULTI  1                /* part of a multi char sequence */
                     82: #define KEYMAP_LEAF   2                /* key has a symbol associated with it, either
                     83:                                 * it is the end of a multi-char sequence or a
                     84:                                 * single char key that generates a symbol */
                     85:
1.20      blymn      86: /* allocate this many key_entry structs at once to speed start up must
                     87:  * be a power of 2.
                     88:  */
                     89: #define KEYMAP_ALLOC_CHUNK 4
                     90:
1.10      mrg        91: /* The max number of different chars we can receive */
                     92: #define MAX_CHAR 256
                     93:
                     94: struct keymap {
1.12      pk         95:        int     count;          /* count of number of key structs allocated */
                     96:        short   mapping[MAX_CHAR]; /* mapping of key to allocated structs */
1.20      blymn      97:        key_entry_t **key;      /* dynamic array of keys */
                     98: };
1.10      mrg        99:
                    100:
                    101: /* Key buffer */
                    102: #define INBUF_SZ 16            /* size of key buffer - must be larger than
                    103:                                 * longest multi-key sequence */
1.16      blymn     104: static wchar_t  inbuf[INBUF_SZ];
1.13      simonb    105: static int     start, end, working; /* pointers for manipulating inbuf data */
1.10      mrg       106:
1.12      pk        107: #define INC_POINTER(ptr)  do { \
                    108:        (ptr)++;                \
                    109:        ptr %= INBUF_SZ;        \
1.10      mrg       110: } while(/*CONSTCOND*/0)
                    111:
1.13      simonb    112: static short   state;          /* state of the inkey function */
1.10      mrg       113:
1.12      pk        114: #define INKEY_NORM      0      /* no key backlog to process */
1.10      mrg       115: #define INKEY_ASSEMBLING 1     /* assembling a multi-key sequence */
1.12      pk        116: #define INKEY_BACKOUT   2      /* recovering from an unrecognised key */
                    117: #define INKEY_TIMEOUT   3      /* multi-key sequence timeout */
1.10      mrg       118:
                    119: /* The termcap data we are interested in and the symbols they map to */
                    120: struct tcdata {
1.20      blymn     121:        const char      *name;  /* name of termcap entry */
1.16      blymn     122:        wchar_t symbol;         /* the symbol associated with it */
1.10      mrg       123: };
                    124:
1.13      simonb    125: static const struct tcdata tc[] = {
1.25      jdc       126:        {"!1", KEY_SSAVE},
                    127:        {"!2", KEY_SSUSPEND},
                    128:        {"!3", KEY_SUNDO},
                    129:        {"#1", KEY_SHELP},
                    130:        {"#2", KEY_SHOME},
                    131:        {"#3", KEY_SIC},
                    132:        {"#4", KEY_SLEFT},
                    133:        {"%0", KEY_REDO},
                    134:        {"%1", KEY_HELP},
                    135:        {"%2", KEY_MARK},
                    136:        {"%3", KEY_MESSAGE},
                    137:        {"%4", KEY_MOVE},
                    138:        {"%5", KEY_NEXT},
                    139:        {"%6", KEY_OPEN},
                    140:        {"%7", KEY_OPTIONS},
                    141:        {"%8", KEY_PREVIOUS},
                    142:        {"%9", KEY_PRINT},
                    143:        {"%a", KEY_SMESSAGE},
                    144:        {"%b", KEY_SMOVE},
                    145:        {"%c", KEY_SNEXT},
                    146:        {"%d", KEY_SOPTIONS},
                    147:        {"%e", KEY_SPREVIOUS},
                    148:        {"%f", KEY_SPRINT},
                    149:        {"%g", KEY_SREDO},
                    150:        {"%h", KEY_SREPLACE},
                    151:        {"%i", KEY_SRIGHT},
                    152:        {"%j", KEY_SRSUME},
                    153:        {"&0", KEY_SCANCEL},
                    154:        {"&1", KEY_REFERENCE},
                    155:        {"&2", KEY_REFRESH},
                    156:        {"&3", KEY_REPLACE},
                    157:        {"&4", KEY_RESTART},
                    158:        {"&5", KEY_RESUME},
                    159:        {"&6", KEY_SAVE},
                    160:        {"&7", KEY_SUSPEND},
                    161:        {"&8", KEY_UNDO},
                    162:        {"&9", KEY_SBEG},
                    163:        {"*0", KEY_SFIND},
                    164:        {"*1", KEY_SCOMMAND},
                    165:        {"*2", KEY_SCOPY},
                    166:        {"*3", KEY_SCREATE},
                    167:        {"*4", KEY_SDC},
                    168:        {"*5", KEY_SDL},
                    169:        {"*6", KEY_SELECT},
                    170:        {"*7", KEY_SEND},
                    171:        {"*8", KEY_SEOL},
                    172:        {"*9", KEY_SEXIT},
                    173:        {"@0", KEY_FIND},
                    174:        {"@1", KEY_BEG},
                    175:        {"@2", KEY_CANCEL},
                    176:        {"@3", KEY_CLOSE},
                    177:        {"@4", KEY_COMMAND},
                    178:        {"@5", KEY_COPY},
                    179:        {"@6", KEY_CREATE},
                    180:        {"@7", KEY_END},
                    181:        {"@8", KEY_ENTER},
                    182:        {"@9", KEY_EXIT},
                    183:        {"F1", KEY_F(11)},
                    184:        {"F2", KEY_F(12)},
                    185:        {"F3", KEY_F(13)},
                    186:        {"F4", KEY_F(14)},
                    187:        {"F5", KEY_F(15)},
                    188:        {"F6", KEY_F(16)},
                    189:        {"F7", KEY_F(17)},
                    190:        {"F8", KEY_F(18)},
                    191:        {"F9", KEY_F(19)},
                    192:        {"FA", KEY_F(20)},
                    193:        {"FB", KEY_F(21)},
                    194:        {"FC", KEY_F(22)},
                    195:        {"FD", KEY_F(23)},
                    196:        {"FE", KEY_F(24)},
                    197:        {"FF", KEY_F(25)},
                    198:        {"FG", KEY_F(26)},
                    199:        {"FH", KEY_F(27)},
                    200:        {"FI", KEY_F(28)},
                    201:        {"FJ", KEY_F(29)},
                    202:        {"FK", KEY_F(30)},
                    203:        {"FL", KEY_F(31)},
                    204:        {"FM", KEY_F(32)},
                    205:        {"FN", KEY_F(33)},
                    206:        {"FO", KEY_F(34)},
                    207:        {"FP", KEY_F(35)},
                    208:        {"FQ", KEY_F(36)},
                    209:        {"FR", KEY_F(37)},
                    210:        {"FS", KEY_F(38)},
                    211:        {"FT", KEY_F(39)},
                    212:        {"FU", KEY_F(40)},
                    213:        {"FV", KEY_F(41)},
                    214:        {"FW", KEY_F(42)},
                    215:        {"FX", KEY_F(43)},
                    216:        {"FY", KEY_F(44)},
                    217:        {"FZ", KEY_F(45)},
                    218:        {"Fa", KEY_F(46)},
                    219:        {"Fb", KEY_F(47)},
                    220:        {"Fc", KEY_F(48)},
                    221:        {"Fd", KEY_F(49)},
                    222:        {"Fe", KEY_F(50)},
                    223:        {"Ff", KEY_F(51)},
                    224:        {"Fg", KEY_F(52)},
                    225:        {"Fh", KEY_F(53)},
                    226:        {"Fi", KEY_F(54)},
                    227:        {"Fj", KEY_F(55)},
                    228:        {"Fk", KEY_F(56)},
                    229:        {"Fl", KEY_F(57)},
                    230:        {"Fm", KEY_F(58)},
                    231:        {"Fn", KEY_F(59)},
                    232:        {"Fo", KEY_F(60)},
                    233:        {"Fp", KEY_F(61)},
                    234:        {"Fq", KEY_F(62)},
                    235:        {"Fr", KEY_F(63)},
1.10      mrg       236:        {"K1", KEY_A1},
                    237:        {"K2", KEY_B2},
                    238:        {"K3", KEY_A3},
                    239:        {"K4", KEY_C1},
                    240:        {"K5", KEY_C3},
1.25      jdc       241:        {"Km", KEY_MOUSE},
1.10      mrg       242:        {"k0", KEY_F0},
                    243:        {"k1", KEY_F(1)},
                    244:        {"k2", KEY_F(2)},
                    245:        {"k3", KEY_F(3)},
                    246:        {"k4", KEY_F(4)},
                    247:        {"k5", KEY_F(5)},
                    248:        {"k6", KEY_F(6)},
                    249:        {"k7", KEY_F(7)},
                    250:        {"k8", KEY_F(8)},
                    251:        {"k9", KEY_F(9)},
1.25      jdc       252:        {"k;", KEY_F(10)},
1.10      mrg       253:        {"kA", KEY_IL},
                    254:        {"ka", KEY_CATAB},
1.25      jdc       255:        {"kB", KEY_BTAB},
1.10      mrg       256:        {"kb", KEY_BACKSPACE},
                    257:        {"kC", KEY_CLEAR},
                    258:        {"kD", KEY_DC},
                    259:        {"kd", KEY_DOWN},
                    260:        {"kE", KEY_EOL},
                    261:        {"kF", KEY_SF},
                    262:        {"kH", KEY_LL},
                    263:        {"kh", KEY_HOME},
                    264:        {"kI", KEY_IC},
                    265:        {"kL", KEY_DL},
                    266:        {"kl", KEY_LEFT},
1.25      jdc       267:        {"kM", KEY_EIC},
1.10      mrg       268:        {"kN", KEY_NPAGE},
                    269:        {"kP", KEY_PPAGE},
                    270:        {"kR", KEY_SR},
                    271:        {"kr", KEY_RIGHT},
                    272:        {"kS", KEY_EOS},
                    273:        {"kT", KEY_STAB},
                    274:        {"kt", KEY_CTAB},
                    275:        {"ku", KEY_UP}
                    276: };
                    277: /* Number of TC entries .... */
1.13      simonb    278: static const int num_tcs = (sizeof(tc) / sizeof(struct tcdata));
1.10      mrg       279:
                    280: /* The root keymap */
                    281:
1.13      simonb    282: static keymap_t *base_keymap;
1.10      mrg       283:
                    284: /* prototypes for private functions */
1.20      blymn     285: static key_entry_t *add_new_key(keymap_t *current, char chr, int key_type,
                    286:                                int symbol);
1.13      simonb    287: static keymap_t                *new_keymap(void);      /* create a new keymap */
                    288: static key_entry_t     *new_key(void);         /* create a new key entry */
1.20      blymn     289: static wchar_t         inkey(int to, int delay);
                    290:
                    291: /*
                    292:  * Add a new key entry to the keymap pointed to by current.  Entry
                    293:  * contains the character to add to the keymap, type is the type of
                    294:  * entry to add (either multikey or leaf) and symbol is the symbolic
                    295:  * value for a leaf type entry.  The function returns a pointer to the
                    296:  * new keymap entry.
                    297:  */
                    298: static key_entry_t *
                    299: add_new_key(keymap_t *current, char chr, int key_type, int symbol)
                    300: {
                    301:        key_entry_t *the_key;
                    302:         int i;
                    303:
                    304: #ifdef DEBUG
                    305:        __CTRACE("Adding character %s of type %d, symbol 0x%x\n", unctrl(chr),
                    306:                 key_type, symbol);
                    307: #endif
1.33    ! blymn     308:        if (current->mapping[(unsigned char) chr] < 0) {
1.20      blymn     309:                  /* first time for this char */
1.33    ! blymn     310:                current->mapping[(unsigned char) chr] = current->count; /* map new entry */
1.20      blymn     311:                  /* make sure we have room in the key array first */
                    312:                if ((current->count & (KEYMAP_ALLOC_CHUNK - 1)) == 0)
                    313:                {
                    314:                        if ((current->key =
                    315:                             realloc(current->key,
                    316:                                     (current->count) * sizeof(key_entry_t *)
                    317:                                     + KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t *))) == NULL) {
                    318:                                fprintf(stderr,
                    319:                                        "Could not malloc for key entry\n");
                    320:                                exit(1);
                    321:                        }
                    322:
                    323:                        the_key = new_key();
                    324:                         for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) {
                    325:                                 current->key[current->count + i]
                    326:                                        = &the_key[i];
                    327:                         }
                    328:                 }
                    329:
                    330:                   /* point at the current key array element to use */
                    331:                 the_key = current->key[current->count];
                    332:
                    333:                the_key->type = key_type;
                    334:
                    335:                switch (key_type) {
                    336:                  case KEYMAP_MULTI:
                    337:                            /* need for next key */
                    338: #ifdef DEBUG
                    339:                          __CTRACE("Creating new keymap\n");
                    340: #endif
                    341:                          the_key->value.next = new_keymap();
                    342:                          break;
                    343:
                    344:                  case KEYMAP_LEAF:
                    345:                                /* the associated symbol for the key */
                    346: #ifdef DEBUG
                    347:                          __CTRACE("Adding leaf key\n");
                    348: #endif
                    349:                          the_key->value.symbol = symbol;
                    350:                          break;
                    351:
                    352:                  default:
                    353:                          fprintf(stderr, "add_new_key: bad type passed\n");
                    354:                          exit(1);
                    355:                }
                    356:
                    357:                current->count++;
                    358:        } else {
                    359:                  /* the key is already known - just return the address. */
                    360: #ifdef DEBUG
                    361:                __CTRACE("Keymap already known\n");
                    362: #endif
1.33    ! blymn     363:                the_key = current->key[current->mapping[(unsigned char) chr]];
1.20      blymn     364:        }
                    365:
                    366:         return the_key;
                    367: }
1.10      mrg       368:
                    369: /*
                    370:  * Init_getch - initialise all the pointers & structures needed to make
                    371:  * getch work in keypad mode.
                    372:  *
                    373:  */
                    374: void
1.27      blymn     375: __init_getch(void)
1.10      mrg       376: {
1.27      blymn     377:        char entry[1024], *p;
1.20      blymn     378:        int     i, j, length, key_ent;
                    379:        size_t limit;
                    380:        key_entry_t *tmp_key;
1.10      mrg       381:        keymap_t *current;
1.31      itojun    382:        char *cp;
1.20      blymn     383: #ifdef DEBUG
                    384:        int k;
                    385: #endif
1.10      mrg       386:
                    387:        /* init the inkey state variable */
                    388:        state = INKEY_NORM;
                    389:
                    390:        /* init the base keymap */
                    391:        base_keymap = new_keymap();
                    392:
                    393:        /* key input buffer pointers */
                    394:        start = end = working = 0;
                    395:
                    396:        /* now do the termcap snarfing ... */
1.27      blymn     397:        for (i = 0; i < num_tcs; i++) {
                    398:                p = entry;
                    399:                limit = 1023;
1.31      itojun    400:                cp = t_getstr(_cursesi_genbuf, tc[i].name, &p, &limit);
                    401:                if (cp != NULL) {
                    402:                        free(cp);
1.27      blymn     403:                        current = base_keymap;  /* always start with
                    404:                                                 * base keymap. */
                    405:                        length = (int) strlen(entry);
1.20      blymn     406: #ifdef DEBUG
1.27      blymn     407:                        __CTRACE("Processing termcap entry %s, sequence ",
                    408:                                 tc[i].name);
                    409:                        for (k = 0; k <= length -1; k++)
                    410:                                __CTRACE("%s", unctrl(entry[k]));
                    411:                        __CTRACE("\n");
                    412: #endif
                    413:                        for (j = 0; j < length - 1; j++) {
                    414:                                  /* add the entry to the struct */
                    415:                                tmp_key = add_new_key(current,
                    416:                                                      entry[j],
                    417:                                                      KEYMAP_MULTI, 0);
1.20      blymn     418:
1.27      blymn     419:                                  /* index into the key array - it's
                    420:                                     clearer if we stash this */
                    421:                                key_ent = current->mapping[
1.33    ! blymn     422:                                        (unsigned char) entry[j]];
1.27      blymn     423:
                    424:                                current->key[key_ent] = tmp_key;
                    425:
                    426:                                  /* next key uses this map... */
                    427:                                current = current->key[key_ent]->value.next;
                    428:                        }
1.14      simonb    429:
1.20      blymn     430:                                /* this is the last key in the sequence (it
                    431:                                 * may have been the only one but that does
                    432:                                 * not matter) this means it is a leaf key and
                    433:                                 * should have a symbol associated with it.
                    434:                                 */
1.27      blymn     435:                        tmp_key = add_new_key(current,
                    436:                                              entry[length - 1],
                    437:                                              KEYMAP_LEAF,
                    438:                                              tc[i].symbol);
                    439:                        current->key[
                    440:                                current->mapping[(int)entry[length - 1]]] =
                    441:                        tmp_key;
1.12      pk        442:                }
1.10      mrg       443:        }
                    444: }
                    445:
                    446:
                    447: /*
                    448:  * new_keymap - allocates & initialises a new keymap structure.  This
                    449:  * function returns a pointer to the new keymap.
                    450:  *
                    451:  */
1.13      simonb    452: static keymap_t *
1.10      mrg       453: new_keymap(void)
                    454: {
                    455:        int     i;
                    456:        keymap_t *new_map;
                    457:
                    458:        if ((new_map = malloc(sizeof(keymap_t))) == NULL) {
                    459:                perror("Inkey: Cannot allocate new keymap");
                    460:                exit(2);
                    461:        }
1.12      pk        462:
                    463:        /* Initialise the new map */
1.10      mrg       464:        new_map->count = 0;
                    465:        for (i = 0; i < MAX_CHAR; i++) {
                    466:                new_map->mapping[i] = -1;       /* no mapping for char */
                    467:        }
                    468:
1.23      thorpej   469:        /* key array will be allocated when first key is added */
                    470:        new_map->key = NULL;
                    471:
1.20      blymn     472:        return new_map;
1.10      mrg       473: }
                    474:
                    475: /*
                    476:  * new_key - allocates & initialises a new key entry.  This function returns
                    477:  * a pointer to the newly allocated key entry.
                    478:  *
                    479:  */
1.13      simonb    480: static key_entry_t *
1.10      mrg       481: new_key(void)
                    482: {
                    483:        key_entry_t *new_one;
1.20      blymn     484:        int i;
                    485:
                    486:        if ((new_one = malloc(KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t)))
                    487:            == NULL) {
                    488:                perror("inkey: Cannot allocate new key entry chunk");
1.10      mrg       489:                exit(2);
                    490:        }
                    491:
1.20      blymn     492:        for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) {
                    493:                new_one[i].type = 0;
                    494:                new_one[i].value.next = NULL;
                    495:        }
                    496:
                    497:        return new_one;
1.10      mrg       498: }
                    499:
                    500: /*
                    501:  * inkey - do the work to process keyboard input, check for multi-key
                    502:  * sequences and return the appropriate symbol if we get a match.
                    503:  *
                    504:  */
                    505:
1.16      blymn     506: wchar_t
1.20      blymn     507: inkey(int to, int delay)
1.10      mrg       508: {
1.21      jdc       509:        wchar_t          k;
1.22      blymn     510:        int              c;
1.21      jdc       511:        keymap_t        *current = base_keymap;
1.10      mrg       512:
1.25      jdc       513:        k = 0;          /* XXX gcc -Wuninitialized */
                    514:
1.10      mrg       515:        for (;;) {              /* loop until we get a complete key sequence */
                    516: reread:
                    517:                if (state == INKEY_NORM) {
                    518:                        if (delay && __timeout(delay) == ERR)
                    519:                                return ERR;
1.22      blymn     520:                        if ((c = getchar()) == EOF) {
                    521:                                clearerr(stdin);
1.10      mrg       522:                                return ERR;
1.22      blymn     523:                        }
                    524:
1.10      mrg       525:                        if (delay && (__notimeout() == ERR))
                    526:                                return ERR;
1.22      blymn     527:
1.16      blymn     528:                        k = (wchar_t) c;
1.10      mrg       529: #ifdef DEBUG
                    530:                        __CTRACE("inkey (state normal) got '%s'\n", unctrl(k));
                    531: #endif
                    532:
                    533:                        working = start;
                    534:                        inbuf[working] = k;
                    535:                        INC_POINTER(working);
                    536:                        end = working;
                    537:                        state = INKEY_ASSEMBLING;       /* go to the assembling
                    538:                                                         * state now */
1.12      pk        539:                } else if (state == INKEY_BACKOUT) {
                    540:                        k = inbuf[working];
                    541:                        INC_POINTER(working);
                    542:                        if (working == end) {   /* see if we have run
                    543:                                                 * out of keys in the
                    544:                                                 * backlog */
                    545:
                    546:                                /* if we have then switch to
                    547:                                   assembling */
                    548:                                state = INKEY_ASSEMBLING;
                    549:                        }
                    550:                } else if (state == INKEY_ASSEMBLING) {
                    551:                        /* assembling a key sequence */
                    552:                        if (delay) {
                    553:                                if (__timeout(to ? DEFAULT_DELAY : delay) == ERR)
1.10      mrg       554:                                                return ERR;
1.12      pk        555:                        } else {
                    556:                                if (to && (__timeout(DEFAULT_DELAY) == ERR))
1.10      mrg       557:                                        return ERR;
1.12      pk        558:                        }
1.22      blymn     559:
                    560:                        c = getchar();
                    561:                        if (ferror(stdin)) {
                    562:                                clearerr(stdin);
1.12      pk        563:                                return ERR;
1.22      blymn     564:                        }
                    565:
1.12      pk        566:                        if ((to || delay) && (__notimeout() == ERR))
1.10      mrg       567:                                        return ERR;
1.14      simonb    568:
1.16      blymn     569:                        k = (wchar_t) c;
1.10      mrg       570: #ifdef DEBUG
1.12      pk        571:                        __CTRACE("inkey (state assembling) got '%s'\n", unctrl(k));
1.10      mrg       572: #endif
1.22      blymn     573:                        if (feof(stdin)) {      /* inter-char timeout,
1.12      pk        574:                                                 * start backing out */
1.22      blymn     575:                                clearerr(stdin);
1.12      pk        576:                                if (start == end)
                    577:                                        /* no chars in the buffer, restart */
                    578:                                        goto reread;
                    579:
                    580:                                k = inbuf[start];
                    581:                                state = INKEY_TIMEOUT;
1.10      mrg       582:                        } else {
1.12      pk        583:                                inbuf[working] = k;
                    584:                                INC_POINTER(working);
                    585:                                end = working;
1.10      mrg       586:                        }
1.12      pk        587:                } else {
                    588:                        fprintf(stderr, "Inkey state screwed - exiting!!!");
                    589:                        exit(2);
                    590:                }
1.10      mrg       591:
                    592:                /* Check key has no special meaning and we have not timed out */
1.20      blymn     593:                if ((state == INKEY_TIMEOUT) || (current->mapping[k] < 0)) {
1.12      pk        594:                        /* return the first key we know about */
                    595:                        k = inbuf[start];
1.10      mrg       596:
                    597:                        INC_POINTER(start);
                    598:                        working = start;
                    599:
                    600:                        if (start == end) {     /* only one char processed */
                    601:                                state = INKEY_NORM;
                    602:                        } else {/* otherwise we must have more than one char
                    603:                                 * to backout */
                    604:                                state = INKEY_BACKOUT;
                    605:                        }
                    606:                        return k;
                    607:                } else {        /* must be part of a multikey sequence */
                    608:                        /* check for completed key sequence */
                    609:                        if (current->key[current->mapping[k]]->type == KEYMAP_LEAF) {
                    610:                                start = working;        /* eat the key sequence
                    611:                                                         * in inbuf */
                    612:
1.12      pk        613:                                /* check if inbuf empty now */
                    614:                                if (start == end) {
                    615:                                        /* if it is go back to normal */
                    616:                                        state = INKEY_NORM;
                    617:                                } else {
                    618:                                        /* otherwise go to backout state */
1.10      mrg       619:                                        state = INKEY_BACKOUT;
                    620:                                }
                    621:
                    622:                                /* return the symbol */
                    623:                                return current->key[current->mapping[k]]->value.symbol;
                    624:
1.12      pk        625:                        } else {
                    626:                                /*
                    627:                                 * Step on to next part of the multi-key
                    628:                                 * sequence.
                    629:                                 */
1.10      mrg       630:                                current = current->key[current->mapping[k]]->value.next;
                    631:                        }
                    632:                }
                    633:        }
                    634: }
                    635:
1.18      blymn     636: #ifndef _CURSES_USE_MACROS
                    637: /*
                    638:  * getch --
                    639:  *     Read in a character from stdscr.
                    640:  */
                    641: int
                    642: getch(void)
                    643: {
                    644:        return wgetch(stdscr);
                    645: }
                    646:
                    647: /*
                    648:  * mvgetch --
                    649:  *      Read in a character from stdscr at the given location.
                    650:  */
                    651: int
                    652: mvgetch(int y, int x)
                    653: {
                    654:        return mvwgetch(stdscr, y, x);
                    655: }
                    656:
                    657: /*
                    658:  * mvwgetch --
                    659:  *      Read in a character from stdscr at the given location in the
                    660:  *      given window.
                    661:  */
                    662: int
                    663: mvwgetch(WINDOW *win, int y, int x)
                    664: {
                    665:        if (wmove(win, y, x) == ERR)
                    666:                return ERR;
                    667:
                    668:        return wgetch(win);
                    669: }
                    670:
                    671: #endif
                    672:
1.1       cgd       673: /*
1.4       mycroft   674:  * wgetch --
                    675:  *     Read in a character from the window.
1.1       cgd       676:  */
1.4       mycroft   677: int
1.18      blymn     678: wgetch(WINDOW *win)
1.4       mycroft   679: {
1.30      itojun    680:        int inp, weset;
                    681:        int c;
1.1       cgd       682:
1.5       cgd       683:        if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
1.10      mrg       684:            && win->curx == win->maxx - 1 && win->cury == win->maxy - 1
                    685:            && __echoit)
1.4       mycroft   686:                return (ERR);
1.25      jdc       687:
1.32      itojun    688:        if (is_wintouched(win))
                    689:                wrefresh(win);
1.4       mycroft   690: #ifdef DEBUG
1.19      jdc       691:        __CTRACE("wgetch: __echoit = %d, __rawmode = %d, flags = %0.2o\n",
                    692:            __echoit, __rawmode, win->flags);
1.4       mycroft   693: #endif
                    694:        if (__echoit && !__rawmode) {
1.1       cgd       695:                cbreak();
1.4       mycroft   696:                weset = 1;
                    697:        } else
                    698:                weset = 0;
                    699:
1.10      mrg       700:        __save_termios();
                    701:
                    702:        if (win->flags & __KEYPAD) {
                    703:                switch (win->delay)
                    704:                {
                    705:                case -1:
                    706:                        inp = inkey (win->flags & __NOTIMEOUT ? 0 : 1, 0);
                    707:                        break;
                    708:                case 0:
1.19      jdc       709:                        if (__nodelay() == ERR) {
                    710:                                __restore_termios();
                    711:                                return ERR;
                    712:                        }
1.10      mrg       713:                        inp = inkey(0, 0);
                    714:                        break;
                    715:                default:
                    716:                        inp = inkey(win->flags & __NOTIMEOUT ? 0 : 1, win->delay);
                    717:                        break;
                    718:                }
                    719:        } else {
                    720:                switch (win->delay)
                    721:                {
                    722:                case -1:
                    723:                        break;
                    724:                case 0:
                    725:                        if (__nodelay() == ERR) {
                    726:                                __restore_termios();
                    727:                                return ERR;
                    728:                        }
                    729:                        break;
                    730:                default:
                    731:                        if (__timeout(win->delay) == ERR) {
                    732:                                __restore_termios();
                    733:                                return ERR;
                    734:                        }
                    735:                        break;
                    736:                }
1.12      pk        737:
1.22      blymn     738:                c = getchar();
                    739:                if (feof(stdin)) {
                    740:                        clearerr(stdin);
                    741:                        __restore_termios();
                    742:                        return ERR;     /* we have timed out */
                    743:                }
                    744:
                    745:                if (ferror(stdin)) {
                    746:                        clearerr(stdin);
1.10      mrg       747:                        inp = ERR;
1.12      pk        748:                } else {
1.30      itojun    749:                        inp = c;
1.10      mrg       750:                }
                    751:        }
1.4       mycroft   752: #ifdef DEBUG
1.15      simonb    753:        if (inp > 255)
1.20      blymn     754:                  /* we have a key symbol - treat it differently */
                    755:                  /* XXXX perhaps __unctrl should be expanded to include
                    756:                   * XXXX the keysyms in the table....
                    757:                   */
1.15      simonb    758:                __CTRACE("wgetch assembled keysym 0x%x\n", inp);
                    759:        else
                    760:                __CTRACE("wgetch got '%s'\n", unctrl(inp));
1.4       mycroft   761: #endif
1.12      pk        762:        if (win->delay > -1) {
1.10      mrg       763:                if (__delay() == ERR) {
                    764:                        __restore_termios();
                    765:                        return ERR;
                    766:                }
1.12      pk        767:        }
                    768:
1.10      mrg       769:        __restore_termios();
1.27      blymn     770:
1.26      mycroft   771:        if (__echoit)
1.16      blymn     772:                waddch(win, (chtype) inp);
1.27      blymn     773:
1.1       cgd       774:        if (weset)
                    775:                nocbreak();
1.12      pk        776:
1.10      mrg       777:        return ((inp < 0) || (inp == ERR) ? ERR : inp);
1.22      blymn     778: }
                    779:
                    780: /*
                    781:  * ungetch --
                    782:  *     Put the character back into the input queue.
                    783:  */
                    784: int
                    785: ungetch(int c)
                    786: {
                    787:        return ((ungetc(c, stdin) == EOF) ? ERR : OK);
1.1       cgd       788: }

CVSweb <webmaster@jp.NetBSD.org>