[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.36.2.1

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

CVSweb <webmaster@jp.NetBSD.org>