Annotation of tme/generic/keyboard.c, revision 1.1.1.1

1.1       root        1: /* $Id: keyboard.c,v 1.6 2003/10/16 02:48:18 fredette Exp $ */
                      2: 
                      3: /* generic/keyboard.c - generic keyboard implementation support: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2003 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
                     37: _TME_RCSID("$Id: keyboard.c,v 1.6 2003/10/16 02:48:18 fredette Exp $");
                     38: 
                     39: /* includes: */
                     40: #include <tme/generic/keyboard.h>
                     41: #include <tme/hash.h>
                     42: #include <tme/misc.h>
                     43: #include <stdlib.h>
                     44: 
                     45: /* macros: */
                     46: 
                     47: /* the shortest possible time, in milliseconds, between two human
                     48:    transitions on the same key: */
                     49: #define TME_KEYBOARD_SHORTEST_DOUBLE_MSEC      (80)
                     50: 
                     51: /* input stage zero uses a slightly expanded set of event types: */
                     52: #define TME_KEYBOARD_EVENT_IN0_RELEASE_USER    (0)
                     53: #define TME_KEYBOARD_EVENT_IN0_PRESS_USER      (1)
                     54: #define TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO    (2)
                     55: #define TME_KEYBOARD_EVENT_IN0_PRESS_AUTO      (3)
                     56: #if TME_KEYBOARD_EVENT_RELEASE != TME_KEYBOARD_EVENT_IN0_RELEASE_USER
                     57: #error "TME_KEYBOARD_EVENT_RELEASE must be 0"
                     58: #endif
                     59: #if TME_KEYBOARD_EVENT_PRESS != TME_KEYBOARD_EVENT_IN0_PRESS_USER
                     60: #error "TME_KEYBOARD_EVENT_PRESS must be 1"
                     61: #endif
                     62: 
                     63: /* this macro turns an input stage zero pressed value into the
                     64:    corresponding release event type: */
                     65: #define TME_KEYBOARD_IN0_RELEASE_EVENT(pressed)        ((pressed) ^ 1)
                     66: 
                     67: /* these macros evaluate to nonzero iff a keyval is pressed in the
                     68:    different stages: */
                     69: #define TME_KEYBOARD_PRESSED_IN0(keysym)       \
                     70:   ((keysym)->tme_keysym_state_in0_pressed)
                     71: #define TME_KEYBOARD_PRESSED_IN1(keysym)       \
                     72:   ((keysym)->tme_keysym_state_in1_keymode.tme_keymode_state_pressed)
                     73: #define _TME_KEYBOARD_PRESSED_IN2(keysym, prev)        \
                     74:   ((keysym)->tme_keysym_state_in2_pressed      \
                     75:    || (!(keysym)->tme_keysym_state_in2_released        \
                     76:        && prev))
                     77: #define TME_KEYBOARD_PRESSED_IN2(keysym)       \
                     78:   _TME_KEYBOARD_PRESSED_IN2(keysym, TME_KEYBOARD_PRESSED_IN1(keysym))
                     79: #define _TME_KEYBOARD_PRESSED_OUT0(keysym, prev)\
                     80:   ((keysym)->tme_keysym_state_out0_pressed     \
                     81:    || (!(keysym)->tme_keysym_state_out0_released\
                     82:        && prev))
                     83: #define TME_KEYBOARD_PRESSED_OUT0(keysym)      \
                     84:   _TME_KEYBOARD_PRESSED_OUT0(keysym, TME_KEYBOARD_PRESSED_IN2(keysym))
                     85: #define TME_KEYBOARD_PRESSED_OUT1(keycode)     \
                     86:   ((keycode)->tme_keycode_state_keymode.tme_keymode_state_pressed)
                     87: 
                     88: /* types: */
                     89: 
                     90: struct tme_keyboard_buffer_int;
                     91: struct tme_keysym_state;
                     92: 
                     93: /* keymode state: */
                     94: struct tme_keymode_state {
                     95: 
                     96:   /* keys that may be autorepeating are kept on a linked list: */
                     97:   struct tme_keymode_state *tme_keymode_state_next;
                     98: 
                     99:   /* the state for this keysym.  technically, since output stage one
                    100:      deals in keycodes, this really should be a void * and point to
                    101:      the keysym state for input stage one, and point to the keycode
                    102:      state for output stage one.  
                    103: 
                    104:      however, avoiding the void * allows us to avoid some function
                    105:      pointer casting, and in the output stage one case we don't care
                    106:      which of the many keysyms that may map to the same keycode is
                    107:      stored here - we just immediately grab the keycode state out of
                    108:      that keysym: */
                    109:   struct tme_keysym_state *tme_keymode_state_keysym;
                    110: 
                    111:   /* the keymode mode: */
                    112:   int tme_keymode_state_mode;
                    113: 
                    114:   /* this is nonzero iff the key is pressed in the physical sense: */
                    115:   int tme_keymode_state_pressed;
                    116: 
                    117:   /* the last time this key was released: */
                    118:   tme_uint32_t tme_keymode_state_last_release;
                    119: 
                    120:   /* this is nonzero iff a genuine release should be ignored: */
                    121:   int tme_keymode_state_ignore_release;
                    122: };
                    123: 
                    124: /* a keymode stage: */
                    125: struct tme_keymode_stage {
                    126: 
                    127:   /* the global keymode: */
                    128:   int tme_keymode_stage_global_mode;
                    129: 
                    130:   /* the list of keymode states for keys that must not autorepeat: */
                    131:   struct tme_keymode_state *tme_keymode_stage_no_autorepeats;
                    132: 
                    133:   /* the next stage: */
                    134:   int (*tme_keymode_stage_next) _TME_P((struct tme_keyboard_buffer_int *,
                    135:                                        struct tme_keysym_state *,
                    136:                                        tme_uint32_t));
                    137: };
                    138: 
                    139: /* keycode state: */
                    140: struct tme_keycode_state {
                    141: 
                    142:   /* the keycode: */
                    143:   tme_keyboard_keyval_t tme_keycode_state_keycode;
                    144: 
                    145:   /* the keycode keymode state: */
                    146:   struct tme_keymode_state tme_keycode_state_keymode;
                    147: };
                    148: 
                    149: /* keysym state.  one of these is kept for every keysym controlled by
                    150:    one or more input or output stages: */
                    151: struct tme_keysym_state {
                    152: 
                    153:   /* this keysym: */
                    154:   tme_keyboard_keyval_t tme_keysym_state_keysym;
                    155: 
                    156:   /* input stage zero: */
                    157: 
                    158:   /* if greater than TME_KEYBOARD_MODIFIER_NONE, this is the modifier
                    159:      that this keysym is attached to in input stage zero: */
                    160:   int tme_keysym_state_in0_modifier;
                    161: 
                    162:   /* the keysym states for all keys attached to the same modifier in
                    163:      input stage zero are kept on a linked list: */
                    164:   struct tme_keysym_state *tme_keysym_state_in0_modifier_next;
                    165: 
                    166:   /* this is nonzero iff the keysym is being pressed in input stage
                    167:      zero.  it's really either FALSE, or
                    168:      TME_KEYBOARD_EVENT_IN0_PRESS_USER, or
                    169:      TME_KEYBOARD_EVENT_IN0_PRESS_AUTO, which is why the last two are
                    170:      nonzero: */
                    171:   unsigned int tme_keysym_state_in0_pressed;
                    172: 
                    173:   /* the last time this keysym was pressed in input stage zero.  this
                    174:      is a time in milliseconds: */
                    175:   tme_uint32_t tme_keysym_state_in0_press_time;
                    176: 
                    177:   /* input stage one: */
                    178:   
                    179:   /* the input stage one keymode state: */
                    180:   struct tme_keymode_state tme_keysym_state_in1_keymode;
                    181: 
                    182:   /* input stage two: */
                    183: 
                    184:   /* this is nonzero iff the keysym is being released in input stage
                    185:      two: */
                    186:   unsigned int tme_keysym_state_in2_released;
                    187: 
                    188:   /* this is nonzero iff the keysym is being pressed in input stage
                    189:      two: */
                    190:   unsigned int tme_keysym_state_in2_pressed;
                    191: 
                    192:   /* output stage zero: */
                    193: 
                    194:   /* if non-NULL, this is the keycode that this keysym is mapped to in
                    195:      output stage zero: */
                    196:   struct tme_keycode_state *tme_keysym_state_out0_keycode;
                    197: 
                    198:   /* if this keysym is not attached to any modifier on the output
                    199:      stage zero, it may require that certain output side modifiers be
                    200:      set or clear in order for the keycode to mean the given keysym: */
                    201:   tme_keyboard_modifiers_t tme_keysym_state_out0_modifiers_set;
                    202:   tme_keyboard_modifiers_t tme_keysym_state_out0_modifiers_clear;
                    203: 
                    204:   /* iff greater than TME_KEYBOARD_MODIFIER_NONE, this is the modifier
                    205:      that this keysym is attached to in output stage zero: */
                    206:   int tme_keysym_state_out0_modifier;
                    207: 
                    208:   /* the keysym states for all keys attached to the same modifier in
                    209:      output stage zero are kept on a linked list: */
                    210:   struct tme_keysym_state *tme_keysym_state_out0_modifier_next;
                    211: 
                    212:   /* this is nonzero iff the keysym is being released in output stage
                    213:      zero: */
                    214:   unsigned int tme_keysym_state_out0_released;
                    215: 
                    216:   /* this is nonzero iff the keysym is being pressed in output stage
                    217:      zero: */
                    218:   unsigned int tme_keysym_state_out0_pressed;
                    219: 
                    220:   /* if this keysym is pressed in the output stage zero but required
                    221:      output stage zero modifier changes to be so, this is the list of
                    222:      those changes.  since most keyboards generate the same keysym
                    223:      using the same modifier(s), this list will usually be empty: */
                    224:   struct tme_keysym_state **tme_keysym_state_out0_keysyms;
                    225:   unsigned int *tme_keysym_state_out0_press_flags;
                    226: 
                    227:   /* output stage one: */
                    228:   
                    229:   /* this is nonzero iff the next release seen by output stage one 
                    230:      will not affect the output modifiers mask: */
                    231:   int tme_keysym_state_out1_ignore_release;
                    232: };
                    233: 
                    234: /* keyboard macros are necessary because it's almost certain that the
                    235:    keyboard you want to emulate has keysyms that your keyboard doesn't
                    236:    have.  one keyboard macro takes a *sequence* of one or more pressed
                    237:    keysyms to a *set* of one or more released and pressed keysyms.
                    238: 
                    239:    all keysym macros are kept in a single tree, where a single branch
                    240:    represents the next keysym in the sequences for one or more macros.
                    241: 
                    242:    a node in the macros tree is active iff the keysyms on the path
                    243:    from the root node have been pressed in sequence and remain
                    244:    pressed.  if there are any macros at all, the root node is always
                    245:    active: */
                    246: struct tme_keyboard_macro {
                    247: 
                    248:   /* a pointer up to our parent node, and the keysym on the branch
                    249:      from our parent to us.  for the root node, these are NULL and
                    250:      TME_KEYBOARD_KEYVAL_UNDEF, respectively: */
                    251:   struct tme_keyboard_macro *tme_keyboard_macro_parent;
                    252:   tme_keyboard_keyval_t tme_keyboard_macro_keysym;
                    253: 
                    254:   /* all active nodes are on a list.  the root node is always active,
                    255:      and it must be the last node on this list - making the is-active
                    256:      test for all other nodes as simple as testing this pointer
                    257:      against NULL: */
                    258:   struct tme_keyboard_macro *tme_keyboard_macro_active_next;
                    259: 
                    260:   /* non-leaf nodes branch out by keysym: */
                    261:   tme_hash_t tme_keyboard_macro_branches;
                    262: 
                    263:   /* leaf nodes contain the set of keysyms that the recognized
                    264:      sequence maps to.  in addition to presses of one or more new
                    265:      keysyms, this will normally include releases of some or all of
                    266:      the keysyms in the original sequence: */
                    267:   unsigned int tme_keyboard_macro_length;
                    268:   struct tme_keysym_state **tme_keyboard_macro_keysyms;
                    269:   unsigned int *tme_keyboard_macro_press_flags;
                    270: };
                    271: 
                    272: /* an internal keyboard buffer: */
                    273: struct tme_keyboard_buffer_int {
                    274: 
                    275:   /* the public keyboard buffer.  this must be first: */
                    276:   struct tme_keyboard_buffer tme_keyboard_buffer;
                    277: #define tme_keyboard_buffer_int_size tme_keyboard_buffer.tme_keyboard_buffer_size
                    278: #define tme_keyboard_buffer_int_head tme_keyboard_buffer.tme_keyboard_buffer_head
                    279: #define tme_keyboard_buffer_int_tail tme_keyboard_buffer.tme_keyboard_buffer_tail
                    280: #define tme_keyboard_buffer_int_events tme_keyboard_buffer.tme_keyboard_buffer_events
                    281: #define tme_keyboard_buffer_int_log_handle tme_keyboard_buffer.tme_keyboard_buffer_log_handle
                    282: 
                    283:   /* the keysyms state, common to all stages: */
                    284:   tme_hash_t tme_keyboard_buffer_int_keysyms_state;
                    285: 
                    286:   /* input stage zero: */
                    287: 
                    288:   /* this is nonzero iff input stage zero has modifier information,
                    289:      and it's actually the mask of modifiers that we have keysyms for: */
                    290:   unsigned int tme_keyboard_buffer_int_in0_have_modifiers;
                    291: 
                    292:   /* the lists of keysyms that are attached to input stage zero
                    293:      modifiers: */
                    294:   struct tme_keysym_state *tme_keyboard_buffer_int_in0_modkeys[TME_KEYBOARD_MODIFIER_MAX + 1];
                    295: 
                    296:   /* the current input stage zero modifiers mask: */
                    297:   tme_keyboard_modifiers_t tme_keyboard_buffer_int_in0_modifiers;
                    298: 
                    299:   /* the current input stage zero pressed keycodes, mapped to their
                    300:      corresponding struct tme_keysym_states: */
                    301:   tme_hash_t tme_keyboard_buffer_int_in0_keycodes;
                    302: 
                    303:   /* input stage one: */
                    304: 
                    305:   /* the input stage one keymode stage: */
                    306:   struct tme_keymode_stage tme_keyboard_buffer_int_in1_keymode_stage;
                    307: 
                    308:   /* input stage two: */
                    309: 
                    310:   /* this is NULL iff input stage two is a passthrough, else this is
                    311:      the list of active nodes in the input stage two keysym macros
                    312:      tree: */
                    313:   struct tme_keyboard_macro *tme_keyboard_buffer_int_in2_macros_active;
                    314: 
                    315:   /* the root of the input stage two keysym macros tree: */
                    316:   struct tme_keyboard_macro tme_keyboard_buffer_int_in2_macros_root;
                    317: 
                    318:   /* output stage zero: */
                    319: 
                    320:   /* this is nonzero iff output stage zero is just a passthrough: */
                    321:   unsigned int tme_keyboard_buffer_int_out0_passthrough;
                    322: 
                    323:   /* the output stage zero keycodes: */
                    324:   tme_hash_t tme_keyboard_buffer_int_out0_keycodes;
                    325: 
                    326:   /* this is nonzero iff the output stage zero lock modifier is to be
                    327:      treated as caps lock: */
                    328:   int tme_keyboard_buffer_int_out0_lock_is_caps;
                    329: 
                    330:   /* any output stage zero modifier that the Num_Lock keysym is
                    331:      attached to: */
                    332:   int tme_keyboard_buffer_int_out0_mod_num_lock;
                    333: 
                    334:   /* the lists of keysyms that are output stage zero modifiers: */
                    335:   struct tme_keysym_state *tme_keyboard_buffer_int_out0_modkeys[TME_KEYBOARD_MODIFIER_MAX + 1];
                    336: 
                    337:   /* the current output stage zero modifiers mask: */
                    338:   tme_keyboard_modifiers_t tme_keyboard_buffer_int_out0_modifiers;
                    339: 
                    340:   /* output stage one: */
                    341: 
                    342:   /* the output stage one keymode stage: */
                    343:   struct tme_keymode_stage tme_keyboard_buffer_int_out1_keymode_stage;
                    344: };
                    345: 
                    346: /* prototypes: */
                    347: static int _tme_keyboard_buffer_in2 _TME_P((struct tme_keyboard_buffer_int *, 
                    348:                                            struct tme_keysym_state *,
                    349:                                            tme_uint32_t));
                    350: static int _tme_keyboard_buffer_out1_bottom _TME_P((struct tme_keyboard_buffer_int *,
                    351:                                                    struct tme_keysym_state *,
                    352:                                                    tme_uint32_t));
                    353: 
                    354: /* this is for debugging only: */
                    355: #if 0
                    356: static void
                    357: _tme_keyboard_debug(const struct tme_keyboard_buffer_int *buffer,
                    358:                    const char *stage,
                    359:                    tme_keyboard_keyval_t keyval,
                    360:                    int is_press,
                    361:                    tme_uint32_t event_time)
                    362: {
                    363:   struct tme_log_handle *handle;
                    364:   const char *string;
                    365:   extern const char *_tme_gtk_keyboard_keyval_name _TME_P((tme_keyboard_keyval_t));
                    366: 
                    367:   handle = buffer->tme_keyboard_buffer_int_log_handle;
                    368:   if (handle == NULL) {
                    369:     return;
                    370:   }
                    371: 
                    372:   string = _tme_gtk_keyboard_keyval_name(keyval);
                    373:   if (string == NULL) {
                    374:     string = "???";
                    375:   }
                    376: 
                    377:   tme_log(handle, 100, TME_OK,
                    378:          (handle,
                    379:           "%s event: time %lu key %lu (%s) %s",
                    380:           stage,
                    381:           (unsigned long) event_time,
                    382:           (unsigned long) keyval,
                    383:           string,
                    384:           (is_press
                    385:            ? "press"
                    386:            : "release")));
                    387: }
                    388: #else
                    389: #define _tme_keyboard_debug(b, s, k, p, t) \
                    390:   do { } while(/* CONSTCOND */ 0)        
                    391: #endif
                    392: 
                    393: /* this creates a new keyboard buffer: */
                    394: struct tme_keyboard_buffer *
                    395: tme_keyboard_buffer_new(unsigned int size)
                    396: {
                    397:   struct tme_keyboard_buffer_int *buffer;
                    398:   struct tme_keymode_stage *stage;
                    399:   struct tme_keyboard_macro *root;
                    400:   int modifier;
                    401: 
                    402:   /* round the buffer size up to a power of two: */
                    403:   if (size & (size - 1)) {
                    404:     do {
                    405:       size &= (size - 1);
                    406:     } while (size & (size - 1));
                    407:     size <<= 1;
                    408:   }
                    409: 
                    410:   /* allocate the buffer: */
                    411:   buffer = tme_new0(struct tme_keyboard_buffer_int, 1);
                    412: 
                    413:   /* set the buffer size: */
                    414:   buffer->tme_keyboard_buffer_int_size = size;
                    415: 
                    416:   /* set the head and tail pointers: */
                    417:   buffer->tme_keyboard_buffer_int_head = 0;
                    418:   buffer->tme_keyboard_buffer_int_tail = 0;
                    419: 
                    420:   /* allocate the buffer events: */
                    421:   buffer->tme_keyboard_buffer_int_events
                    422:     = tme_new(struct tme_keyboard_event, size);
                    423: 
                    424:   /* for now there is no log handle: */
                    425:   buffer->tme_keyboard_buffer_int_log_handle = NULL;
                    426: 
                    427:   /* create the common keysyms state: */
                    428:   buffer->tme_keyboard_buffer_int_keysyms_state
                    429:     = tme_hash_new(tme_direct_hash,
                    430:                   tme_direct_compare,
                    431:                   (tme_hash_data_t) NULL);
                    432: 
                    433:   /* input stage zero begins with no modifiers: */
                    434:   buffer->tme_keyboard_buffer_int_in0_have_modifiers = FALSE;
                    435: 
                    436:   /* initialize the input stage zero modifier keys lists: */
                    437:   for (modifier = 0;
                    438:        modifier <= TME_KEYBOARD_MODIFIER_MAX;
                    439:        modifier++) {
                    440:     buffer->tme_keyboard_buffer_int_in0_modkeys[modifier] = NULL;
                    441:   }
                    442: 
                    443:   /* initialize the input stage zero modifiers mask: */
                    444:   buffer->tme_keyboard_buffer_int_in0_modifiers = 0;
                    445: 
                    446:   /* initialize the input stage one keycodes hash: */
                    447:   buffer->tme_keyboard_buffer_int_in0_keycodes
                    448:     = tme_hash_new(tme_direct_hash,
                    449:                   tme_direct_compare,
                    450:                   (tme_hash_data_t) NULL);
                    451: 
                    452:   /* initialize the input stage one keymode stage: */
                    453:   stage = &buffer->tme_keyboard_buffer_int_in1_keymode_stage;
                    454:   stage->tme_keymode_stage_global_mode = 0;
                    455:   stage->tme_keymode_stage_no_autorepeats = NULL;
                    456:   stage->tme_keymode_stage_next = _tme_keyboard_buffer_in2;
                    457: 
                    458:   /* input stage two begins with no macros, so not even the root of
                    459:      the macros tree is active: */
                    460:   buffer->tme_keyboard_buffer_int_in2_macros_active = NULL;
                    461:   
                    462:   /* create the root of the input stage two keysym macros tree: */
                    463:   root = &buffer->tme_keyboard_buffer_int_in2_macros_root;
                    464:   root->tme_keyboard_macro_parent = NULL;
                    465:   root->tme_keyboard_macro_keysym = TME_KEYBOARD_KEYVAL_UNDEF;
                    466:   root->tme_keyboard_macro_active_next = NULL;
                    467:   root->tme_keyboard_macro_branches
                    468:     = tme_hash_new(tme_direct_hash,
                    469:                   tme_direct_compare,
                    470:                   (tme_hash_data_t) NULL);
                    471: 
                    472:   /* output stage zero begins as a passthrough: */
                    473:   buffer->tme_keyboard_buffer_int_out0_passthrough = TRUE;
                    474: 
                    475:   /* initialize the output stage zero keycodes: */
                    476:   buffer->tme_keyboard_buffer_int_out0_keycodes
                    477:     = tme_hash_new(tme_direct_hash,
                    478:                   tme_direct_compare,
                    479:                   (tme_hash_data_t) NULL);
                    480: 
                    481:   /* the output stage zero lock modifier is assumed to be a Shift lock: */
                    482:   buffer->tme_keyboard_buffer_int_out0_lock_is_caps
                    483:     = FALSE;
                    484: 
                    485:   /* initialize the output stage zero modifier that the Num_Lock
                    486:      keysym is attached to: */
                    487:   buffer->tme_keyboard_buffer_int_out0_mod_num_lock
                    488:     = TME_KEYBOARD_MODIFIER_NONE;
                    489: 
                    490:   /* initialize the output stage zero modifier keys lists: */
                    491:   for (modifier = 0;
                    492:        modifier <= TME_KEYBOARD_MODIFIER_MAX;
                    493:        modifier++) {
                    494:     buffer->tme_keyboard_buffer_int_out0_modkeys[modifier] = NULL;
                    495:   }
                    496: 
                    497:   /* initialize the output stage zero modifiers mask: */
                    498:   buffer->tme_keyboard_buffer_int_out0_modifiers = 0;
                    499: 
                    500:   /* initialize the output stage one keymode stage: */
                    501:   stage = &buffer->tme_keyboard_buffer_int_out1_keymode_stage;
                    502:   stage->tme_keymode_stage_global_mode = 0;
                    503:   stage->tme_keymode_stage_no_autorepeats = NULL;
                    504:   stage->tme_keymode_stage_next = _tme_keyboard_buffer_out1_bottom;
                    505: 
                    506:   /* done: */
                    507:   return (&buffer->tme_keyboard_buffer);
                    508: }
                    509: 
                    510: /* this destroys an entry in the common keysyms state: */
                    511: static void
                    512: _tme_keysym_state_destroy(tme_hash_data_t __keysym,
                    513:                          tme_hash_data_t _keysym,
                    514:                          void *_junk)
                    515: {
                    516:   struct tme_keysym_state *keysym;
                    517: 
                    518:   /* recover the keysym state: */
                    519:   keysym = (struct tme_keysym_state *) _keysym;
                    520: 
                    521:   /* if this keysym state has output stage zero keysym changes, free
                    522:      them: */
                    523:   if (keysym->tme_keysym_state_out0_keysyms != NULL) {
                    524:     tme_free(keysym->tme_keysym_state_out0_keysyms);
                    525:     tme_free(keysym->tme_keysym_state_out0_press_flags);
                    526:   }
                    527: 
                    528:   /* free the state itself: */
                    529:   tme_free(keysym);
                    530: }
                    531: 
                    532: /* this recursively destroys the input stage two keysym macros tree: */
                    533: static void
                    534: _tme_keyboard_macro_destroy(tme_hash_data_t _keysym,
                    535:                            tme_hash_data_t _macro, 
                    536:                            void *_junk)
                    537: {
                    538:   struct tme_keyboard_macro *macro;
                    539: 
                    540:   /* get this macro: */
                    541:   macro = (struct tme_keyboard_macro *) _macro;
                    542: 
                    543:   /* if this is a leaf node: */
                    544:   if (macro->tme_keyboard_macro_branches == NULL) {
                    545: 
                    546:     /* free the keysyms and flags: */
                    547:     tme_free(macro->tme_keyboard_macro_keysyms);
                    548:     tme_free(macro->tme_keyboard_macro_press_flags);
                    549:   }
                    550: 
                    551:   /* otherwise, recurse: */
                    552:   else {
                    553:     tme_hash_foreach(macro->tme_keyboard_macro_branches,
                    554:                     _tme_keyboard_macro_destroy,
                    555:                     NULL);
                    556:     tme_hash_destroy(macro->tme_keyboard_macro_branches);
                    557:   }
                    558: 
                    559:   /* free this tree node: */
                    560:   tme_free(macro);
                    561: }
                    562: 
                    563: /* this destroys an entry in the output stage zero keycodes state: */
                    564: static void
                    565: _tme_keycode_state_destroy(tme_hash_data_t __keycode,
                    566:                           tme_hash_data_t _keycode,
                    567:                           void *_junk)
                    568: {
                    569:   struct tme_keycode_state *keycode;
                    570: 
                    571:   /* recover the keycode state: */
                    572:   keycode = (struct tme_keycode_state *) _keycode;
                    573: 
                    574:   /* free the state itself: */
                    575:   tme_free(keycode);
                    576: }
                    577: 
                    578: /* this destroys a keyboard buffer: */
                    579: void
                    580: tme_keyboard_buffer_destroy(struct tme_keyboard_buffer *_buffer)
                    581: {
                    582:   struct tme_keyboard_buffer_int *buffer;
                    583: 
                    584:   /* recover our data structure: */
                    585:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                    586: 
                    587:   /* free the events: */
                    588:   tme_free(buffer->tme_keyboard_buffer_int_events);
                    589: 
                    590:   /* destroy the common keysyms state: */
                    591:   tme_hash_foreach(buffer->tme_keyboard_buffer_int_keysyms_state,
                    592:                   _tme_keysym_state_destroy,
                    593:                   NULL);
                    594:   tme_hash_destroy(buffer->tme_keyboard_buffer_int_keysyms_state);
                    595: 
                    596:   /* destroy the input stage two keysym macros tree: */
                    597:   tme_hash_foreach(buffer->tme_keyboard_buffer_int_in2_macros_root.tme_keyboard_macro_branches,
                    598:                   _tme_keyboard_macro_destroy,
                    599:                   NULL);
                    600:   tme_hash_destroy(buffer->tme_keyboard_buffer_int_in2_macros_root.tme_keyboard_macro_branches);
                    601: 
                    602:   /* destroy the output stage zero keycodes: */
                    603:   tme_hash_foreach(buffer->tme_keyboard_buffer_int_out0_keycodes,
                    604:                   _tme_keycode_state_destroy,
                    605:                   NULL);
                    606:   tme_hash_destroy(buffer->tme_keyboard_buffer_int_out0_keycodes);
                    607: 
                    608:   /* destroy the buffer itself: */
                    609:   tme_free(buffer);
                    610: }
                    611: 
                    612: /* this gets the state for a keysym, creating a new state if one
                    613:    doesn't exists yet: */
                    614: static struct tme_keysym_state *
                    615: _tme_keysym_state_get(struct tme_keyboard_buffer_int *buffer,
                    616:                      tme_keyboard_keyval_t _keysym)
                    617: {
                    618:   struct tme_keysym_state *keysym;
                    619: 
                    620:   /* look up the state for this keysym: */
                    621:   keysym
                    622:     = ((struct tme_keysym_state *)
                    623:        tme_hash_lookup(buffer->tme_keyboard_buffer_int_keysyms_state,
                    624:                       (tme_hash_data_t) _keysym));
                    625: 
                    626:   /* if the state doesn't exist, allocate it: */
                    627:   if (keysym == NULL) {
                    628:     keysym = tme_new0(struct tme_keysym_state, 1);
                    629: 
                    630:     /* initialize all fields that might not be properly initialized as
                    631:        all-bits-zero: */
                    632:     keysym->tme_keysym_state_keysym = _keysym;
                    633:     keysym->tme_keysym_state_in0_modifier = TME_KEYBOARD_MODIFIER_NONE;
                    634:     keysym->tme_keysym_state_in1_keymode.tme_keymode_state_keysym = keysym;
                    635:     keysym->tme_keysym_state_out0_keycode = NULL;
                    636:     keysym->tme_keysym_state_out0_modifier = TME_KEYBOARD_MODIFIER_NONE;
                    637:     keysym->tme_keysym_state_out0_keysyms = NULL;
                    638:     keysym->tme_keysym_state_out0_press_flags = NULL;
                    639: 
                    640:     /* insert this state into the hash: */
                    641:     tme_hash_insert(buffer->tme_keyboard_buffer_int_keysyms_state,
                    642:                    (tme_hash_data_t) _keysym,
                    643:                    (tme_hash_data_t) keysym);
                    644:   }
                    645: 
                    646:   /* done: */
                    647:   return (keysym);
                    648: }
                    649: 
                    650: /* this changes the set of keysyms that are attached to an input stage
                    651:    zero modifier: */
                    652: int
                    653: tme_keyboard_buffer_in_modifier(struct tme_keyboard_buffer *_buffer,
                    654:                                int modifier,
                    655:                                const tme_keyboard_keyval_t *modkeys)
                    656: {
                    657:   struct tme_keyboard_buffer_int *buffer;
                    658:   struct tme_keysym_state *mod_keysym, **_mod_keysym;
                    659:   tme_keyboard_keyval_t keysym;
                    660: 
                    661:   /* recover our data structure: */
                    662:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                    663: 
                    664:   /* this must be a valid modifier: */
                    665:   assert (modifier > TME_KEYBOARD_MODIFIER_NONE
                    666:          && modifier <= TME_KEYBOARD_MODIFIER_MAX);
                    667: 
                    668:   /* remove all currently attached keysyms from this modifier: */
                    669:   for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier];
                    670:        mod_keysym != NULL;
                    671:        mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) {
                    672:     mod_keysym->tme_keysym_state_in0_modifier
                    673:       = TME_KEYBOARD_MODIFIER_NONE;
                    674:   }
                    675: 
                    676:   /* attach all of these new keysyms to this modifier: */
                    677:   _mod_keysym = &buffer->tme_keyboard_buffer_int_in0_modkeys[modifier];
                    678:   for (; (keysym = *(modkeys++)) != TME_KEYBOARD_KEYVAL_UNDEF; ) {
                    679:     mod_keysym = _tme_keysym_state_get(buffer, keysym);
                    680:     mod_keysym->tme_keysym_state_in0_modifier = modifier;
                    681:     *_mod_keysym = mod_keysym;
                    682:     _mod_keysym = &mod_keysym->tme_keysym_state_in0_modifier_next;
                    683:   }
                    684:   *_mod_keysym = NULL;
                    685: 
                    686:   /* input stage zero now has modifier information: */
                    687:   buffer->tme_keyboard_buffer_int_in0_have_modifiers
                    688:     |= (1 << modifier);
                    689: 
                    690:   return (TME_OK);
                    691: }
                    692: 
                    693: /* this changes a keysym's input stage one keymode: */
                    694: int
                    695: tme_keyboard_buffer_in_mode(struct tme_keyboard_buffer *_buffer,
                    696:                            tme_keyboard_keyval_t _keysym, int mode)
                    697: {
                    698:   struct tme_keyboard_buffer_int *buffer;
                    699:   struct tme_keysym_state *keysym;
                    700:   
                    701:   /* recover our data structure: */
                    702:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                    703: 
                    704:   /* there's no such thing as a global input keymode: */
                    705:   assert (_keysym != TME_KEYBOARD_KEYVAL_UNDEF);
                    706: 
                    707:   /* TME_KEYBOARD_MODE_UNLOCK and TME_KEYBOARD_MODE_LOCK cannot be
                    708:      combined with any other bits: */
                    709:   if ((mode
                    710:        & (TME_KEYBOARD_MODE_UNLOCK
                    711:          | TME_KEYBOARD_MODE_LOCK))
                    712:       && (mode
                    713:          & (mode - 1))) {
                    714:     return (EINVAL);
                    715:   }
                    716:   
                    717:   /* none of the TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS,
                    718:      TME_KEYBOARD_MODE_FLAG_NO_RELEASES, and
                    719:      TME_KEYBOARD_MODE_FLAG_LOCK_SOFT flags can be set
                    720:      without TME_KEYBOARD_MODE_PASSTHROUGH: */
                    721:   if ((mode
                    722:        & (TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS
                    723:          | TME_KEYBOARD_MODE_FLAG_NO_RELEASES
                    724:          | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT))
                    725:       && !(mode
                    726:           & TME_KEYBOARD_MODE_PASSTHROUGH)) {
                    727:     return (EINVAL);
                    728:   }
                    729: 
                    730:   /* you cannot specify that an input key must not release, or
                    731:      that it soft locks: */
                    732:   if (mode
                    733:       & (TME_KEYBOARD_MODE_FLAG_NO_RELEASES
                    734:         | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT)) {
                    735:     return (EINVAL);
                    736:   }
                    737: 
                    738:   /* look up this keysym and set the input stage one mode: */
                    739:   keysym = _tme_keysym_state_get(buffer, _keysym);
                    740:   keysym->tme_keysym_state_in1_keymode.tme_keymode_state_mode = mode;
                    741:   return (TME_OK);
                    742: }
                    743: 
                    744: /* this adds an input stage two keysym macro: */
                    745: int
                    746: tme_keyboard_buffer_in_macro(struct tme_keyboard_buffer *_buffer,
                    747:                             const tme_keyboard_keyval_t *keysyms_lhs,
                    748:                             const tme_keyboard_keyval_t *keysyms_rhs)
                    749: {
                    750:   struct tme_keyboard_buffer_int *buffer;
                    751:   unsigned int count_lhs, count_rhs;
                    752:   unsigned int keysym_i, keysym_j, keysym_count;
                    753:   tme_keyboard_keyval_t keysym;
                    754:   struct tme_keysym_state **keysyms;
                    755:   unsigned int *press_flags;
                    756:   int rc;
                    757:   struct tme_keyboard_macro *macro, *macro_next;
                    758: 
                    759:   /* recover our data structure: */
                    760:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                    761: 
                    762:   /* count the number of keysyms on both sides: */
                    763:   for (count_lhs = 0;
                    764:        keysyms_lhs[count_lhs] != TME_KEYBOARD_KEYVAL_UNDEF;
                    765:        count_lhs++);
                    766:   for (count_rhs = 0;
                    767:        keysyms_rhs[count_rhs] != TME_KEYBOARD_KEYVAL_UNDEF;
                    768:        count_rhs++);
                    769: 
                    770:   /* there must be some left-hand side and some right-hand side: */
                    771:   if (count_lhs == 0
                    772:       || count_rhs == 0) {
                    773:     return (EINVAL);
                    774:   }
                    775: 
                    776:   /* create the final keysyms and press-flags arrays for the macro.  any
                    777:      keysym on the left hand side that is also on the right hand side
                    778:      becomes a press, else a release, and any keysym on the right hand
                    779:      side that isn't on the left hand side becomes a press: */
                    780:   keysyms = tme_new(struct tme_keysym_state *, count_lhs + count_rhs);
                    781:   press_flags = tme_new(unsigned int, count_lhs + count_rhs);
                    782:   keysym_count = 0;
                    783:   for (keysym_i = 0; 
                    784:        keysym_i < count_lhs; 
                    785:        keysym_i++) {
                    786:     keysym = keysyms_lhs[keysym_i];
                    787:   
                    788:     /* see if this keysym is on the right hand side: */
                    789:     for (keysym_j = 0;
                    790:         keysym_j < count_rhs;
                    791:         keysym_j++) {
                    792:       if (keysym == keysyms_rhs[keysym_j]) {
                    793:        break;
                    794:       }
                    795:     }
                    796: 
                    797:     /* set this keysym and press-flags: */
                    798:     keysyms[keysym_count] = _tme_keysym_state_get(buffer, keysym);
                    799:     press_flags[keysym_count] = (keysym_j < count_rhs);
                    800:     keysym_count++;
                    801:   }
                    802:   for (keysym_j = 0;
                    803:        keysym_j < count_rhs;
                    804:        keysym_j++) {
                    805:     keysym = keysyms_rhs[keysym_j];
                    806: 
                    807:     /* see if this keysym is on the left hand side: */
                    808:     for (keysym_i = 0;
                    809:         keysym_i < count_lhs;
                    810:         keysym_i++) {
                    811:       if (keysym == keysyms_lhs[keysym_i]) {
                    812:        break;
                    813:       }
                    814:     }
                    815: 
                    816:     /* set this keysym and press-flags: */
                    817:     if (keysym_i == count_lhs) {
                    818:       keysyms[keysym_count] = _tme_keysym_state_get(buffer, keysym);
                    819:       press_flags[keysym_count] = TRUE;
                    820:       keysym_count++;
                    821:     }
                    822:   }
                    823:   
                    824:   /* the last keysym in any macro's right hand side must be a press: */
                    825:   if (!press_flags[keysym_count - 1]) {
                    826:     tme_free(keysyms);
                    827:     tme_free(press_flags);
                    828:     return (EINVAL);
                    829:   }
                    830:   
                    831:   /* add this keysym macro to the macros tree.  this macro's sequence
                    832:      (i.e., its left-hand side) cannot be strictly longer, or strictly
                    833:      shorter, or the same as any existing macro's sequence: */
                    834:   macro = &buffer->tme_keyboard_buffer_int_in2_macros_root;
                    835:   rc = TME_OK;
                    836:   for (keysym_i = 0;
                    837:        ;
                    838:        keysym_i++) {
                    839: 
                    840:     /* if we handled all left-hand side keysyms: */
                    841:     if (keysym_i == count_lhs) {
                    842:       
                    843:       /* if this node is already a non-leaf node, then this macro's
                    844:         sequence is strictly shorter than an existing macro's
                    845:         sequence: */
                    846:       if (macro->tme_keyboard_macro_branches != NULL) {
                    847:        rc = EEXIST;
                    848:       }
                    849: 
                    850:       /* otherwise, if this node is already a leaf node, then this
                    851:         macro's sequence is the same as an existing macro's sequence: */
                    852:       else if (macro->tme_keyboard_macro_length > 0) {
                    853:        rc = EEXIST;
                    854:       }
                    855: 
                    856:       /* stop no matter what: */
                    857:       break;
                    858:     }
                    859: 
                    860:     /* if this node has no branch set: */
                    861:     if (macro->tme_keyboard_macro_branches == NULL) {
                    862: 
                    863:       /* if this node is already a leaf node, then this macro's
                    864:         sequence is strictly longer than an existing macro's
                    865:         sequence: */
                    866:       if (macro->tme_keyboard_macro_length > 0) {
                    867:        rc = EEXIST;
                    868:        break;
                    869:       }
                    870: 
                    871:       /* otherwise, create a branch set for this node: */
                    872:       macro->tme_keyboard_macro_branches
                    873:        = tme_hash_new(tme_direct_hash,
                    874:                       tme_direct_compare,
                    875:                       (tme_hash_data_t) NULL);
                    876:     }
                    877:       
                    878:     /* get the keysym: */
                    879:     keysym = keysyms_lhs[keysym_i];
                    880: 
                    881:     /* look up this keysym in the branch set for this node: */
                    882:     macro_next
                    883:       = ((struct tme_keyboard_macro *)
                    884:         tme_hash_lookup(macro->tme_keyboard_macro_branches, (tme_hash_data_t) keysym));
                    885: 
                    886:     /* if this keysym is a new branch, create a new macros tree node: */
                    887:     if (macro_next == NULL) {
                    888:       macro_next = tme_new0(struct tme_keyboard_macro, 1);
                    889:       macro_next->tme_keyboard_macro_parent = macro;
                    890:       macro_next->tme_keyboard_macro_keysym = keysym;
                    891:       tme_hash_insert(macro->tme_keyboard_macro_branches, 
                    892:                      (tme_hash_data_t) keysym,
                    893:                      (tme_hash_data_t) macro_next);
                    894:     }
                    895: 
                    896:     /* advance in the tree: */
                    897:     macro = macro_next;
                    898:   }
                    899: 
                    900:   /* if this sequence couldn't be added to the sequences tree: */
                    901:   if (rc != TME_OK) {
                    902:     tme_free(keysyms);
                    903:     tme_free(press_flags);
                    904:     return (rc);
                    905:   }
                    906: 
                    907:   /* finish this leaf node in the macros tree: */
                    908:   macro->tme_keyboard_macro_length = keysym_count;
                    909:   macro->tme_keyboard_macro_keysyms = keysyms;
                    910:   macro->tme_keyboard_macro_press_flags = press_flags;
                    911: 
                    912:   /* if this is the first keysym macro added, set the root of the
                    913:      keysym macros tree as active, making input stage two no longer a
                    914:      passthrough: */
                    915:   if (buffer->tme_keyboard_buffer_int_in2_macros_active
                    916:       == NULL) {
                    917:     buffer->tme_keyboard_buffer_int_in2_macros_active
                    918:       = &buffer->tme_keyboard_buffer_int_in2_macros_root;
                    919:   }
                    920: 
                    921:   return (TME_OK);
                    922: }
                    923: 
                    924: /* this adds a single output stage zero keysym map entry: */
                    925: int
                    926: tme_keyboard_buffer_out_map(struct tme_keyboard_buffer *_buffer,
                    927:                            _tme_const struct tme_keyboard_map *map)
                    928: {
                    929:   struct tme_keyboard_buffer_int *buffer;
                    930:   struct tme_keysym_state *keysym;
                    931:   struct tme_keycode_state *keycode;
                    932:   struct tme_keymode_state *keymode;
                    933:   int modifier;
                    934:   tme_keyboard_modifiers_t modifiers_set, modifiers_clear;
                    935:   
                    936:   /* recover our data structure: */
                    937:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                    938: 
                    939:   /* the keysym must be defined: */
                    940:   assert (map->tme_keyboard_map_keysym
                    941:          != TME_KEYBOARD_KEYVAL_UNDEF);
                    942: 
                    943:   /* get the state for this keysym: */
                    944:   keysym = _tme_keysym_state_get(buffer, map->tme_keyboard_map_keysym);
                    945: 
                    946:   /* this keysym must not already have an output side keycode: */
                    947:   if (keysym->tme_keysym_state_out0_keycode != NULL) {
                    948:     return (EEXIST);
                    949:   }
                    950: 
                    951:   /* lookup this keycode: */
                    952:   keycode
                    953:     = ((struct tme_keycode_state *)
                    954:        tme_hash_lookup(buffer->tme_keyboard_buffer_int_out0_keycodes,
                    955:                       (tme_hash_data_t) map->tme_keyboard_map_keycode));
                    956: 
                    957:   /* if this keycode is new, allocate, initialize and add a structure
                    958:      for it: */
                    959:   if (keycode == NULL) {
                    960: 
                    961:     /* allocate the keycode state: */
                    962:     keycode = tme_new0(struct tme_keycode_state, 1);
                    963: 
                    964:     /* initialize any parts of the keycode state that might not be
                    965:        properly initialized as all-bits-zero.  note that the keysym
                    966:        stored in the keycode keymode state is the first keysym mapped
                    967:        to the keycode: */
                    968:     keycode->tme_keycode_state_keycode = map->tme_keyboard_map_keycode;
                    969:     keymode = &keycode->tme_keycode_state_keymode;
                    970:     keymode->tme_keymode_state_keysym = keysym;
                    971: 
                    972:     /* add the keycode structure: */
                    973:     tme_hash_insert(buffer->tme_keyboard_buffer_int_out0_keycodes,
                    974:                    (tme_hash_data_t) map->tme_keyboard_map_keycode,
                    975:                    (tme_hash_data_t) keycode);
                    976:   }
                    977: 
                    978:   /* set this keycode on this keysym: */
                    979:   keysym->tme_keysym_state_out0_keycode = keycode;
                    980:      
                    981:   /* if this keysym is attached to an output side modifier: */
                    982:   modifier = map->tme_keyboard_map_modifier;
                    983:   if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
                    984: 
                    985:     /* attach this keysym to the output side modifier: */
                    986:     keysym->tme_keysym_state_out0_modifier
                    987:       = modifier;
                    988:     keysym->tme_keysym_state_out0_modifier_next
                    989:       = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier];
                    990:     buffer->tme_keyboard_buffer_int_out0_modkeys[modifier]
                    991:       = keysym;
                    992: 
                    993:     /* dispatch on any special keysym note: */
                    994:     switch (map->tme_keyboard_map_keysym_note) {
                    995:     default: assert(FALSE);
                    996:     case TME_KEYBOARD_KEYSYM_NOTE_UNDEF:
                    997:       break;
                    998:     case TME_KEYBOARD_KEYSYM_NOTE_CAPS_LOCK:
                    999:       if (modifier == TME_KEYBOARD_MODIFIER_LOCK) {
                   1000:        buffer->tme_keyboard_buffer_int_out0_lock_is_caps = TRUE;
                   1001:       }
                   1002:       break;
                   1003:     case TME_KEYBOARD_KEYSYM_NOTE_SHIFT_LOCK:
                   1004:       break;
                   1005:     case TME_KEYBOARD_KEYSYM_NOTE_NUM_LOCK:
                   1006:       buffer->tme_keyboard_buffer_int_out0_mod_num_lock = modifier;
                   1007:       break;
                   1008:     }
                   1009: 
                   1010:     /* this keysym cannot require any output side modifiers to be set
                   1011:        or clear: */
                   1012:     assert (map->tme_keyboard_map_modifiers_set == 0
                   1013:            && map->tme_keyboard_map_modifiers_clear == 0);
                   1014:   }
                   1015: 
                   1016:   /* remember the output stage zero modifiers that must be set or
                   1017:      clear for this mapping to work: */
                   1018:   modifiers_set = map->tme_keyboard_map_modifiers_set;
                   1019:   modifiers_clear = map->tme_keyboard_map_modifiers_clear;
                   1020:   assert ((modifiers_set & modifiers_clear) == 0);
                   1021: 
                   1022:   /* if this keysym is lowercase, it also requires the shift modifier
                   1023:      to be clear: */
                   1024:   if (modifiers_clear
                   1025:       & (1 << TME_KEYBOARD_MODIFIER_LOCK)) {
                   1026:     modifiers_clear
                   1027:       |= (1 << TME_KEYBOARD_MODIFIER_SHIFT);
                   1028:   }
                   1029: 
                   1030:   keysym->tme_keysym_state_out0_modifiers_set = modifiers_set;
                   1031:   keysym->tme_keysym_state_out0_modifiers_clear = modifiers_clear;
                   1032: 
                   1033:   /* output stage zero is no longer a passthrough: */
                   1034:   buffer->tme_keyboard_buffer_int_out0_passthrough = FALSE;
                   1035: 
                   1036:   return (TME_OK);
                   1037: }
                   1038: 
                   1039: /* this changes a keycode's output stage one mode: */
                   1040: int
                   1041: tme_keyboard_buffer_out_mode(struct tme_keyboard_buffer *_buffer,
                   1042:                             tme_keyboard_keyval_t _keycode, int mode)
                   1043: {
                   1044:   struct tme_keyboard_buffer_int *buffer;
                   1045:   struct tme_keycode_state *keycode;
                   1046:   
                   1047:   /* recover our data structure: */
                   1048:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                   1049: 
                   1050:   /* TME_KEYBOARD_MODE_UNLOCK and TME_KEYBOARD_MODE_LOCK cannot be
                   1051:      combined with any other bits: */
                   1052:   if ((mode
                   1053:        & (TME_KEYBOARD_MODE_UNLOCK
                   1054:          | TME_KEYBOARD_MODE_LOCK))
                   1055:       && (mode
                   1056:          & (mode - 1))) {
                   1057:     return (EINVAL);
                   1058:   }
                   1059:   
                   1060:   /* none of the TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS,
                   1061:      TME_KEYBOARD_MODE_FLAG_NO_RELEASES, and
                   1062:      TME_KEYBOARD_MODE_FLAG_LOCK_SOFT flags can be set
                   1063:      without TME_KEYBOARD_MODE_PASSTHROUGH: */
                   1064:   if ((mode
                   1065:        & (TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS
                   1066:          | TME_KEYBOARD_MODE_FLAG_NO_RELEASES
                   1067:          | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT))
                   1068:       && !(mode
                   1069:           & TME_KEYBOARD_MODE_PASSTHROUGH)) {
                   1070:     return (EINVAL);
                   1071:   }
                   1072: 
                   1073:   /* you cannot specify that an output key must be unlocked: */
                   1074:   if (mode & TME_KEYBOARD_MODE_UNLOCK) {
                   1075:     return (EINVAL);
                   1076:   }
                   1077: 
                   1078:   /* if we are setting the mode on a particular keycode: */
                   1079:   if (_keycode != TME_KEYBOARD_KEYVAL_UNDEF) {
                   1080:     keycode
                   1081:       = ((struct tme_keycode_state *)
                   1082:         tme_hash_lookup(buffer->tme_keyboard_buffer_int_out0_keycodes,
                   1083:                         (tme_hash_data_t) _keycode));
                   1084:     if (keycode == NULL) {
                   1085:       return (ENOENT);
                   1086:     }
                   1087:     keycode->tme_keycode_state_keymode.tme_keymode_state_mode = mode;
                   1088:   }
                   1089: 
                   1090:   /* otherwise, we are setting the mode on the whole keyboard: */
                   1091:   else {
                   1092: 
                   1093:     /* you can't set TME_KEYBOARD_MODE_GLOBAL at the global level: */
                   1094:     if (mode == TME_KEYBOARD_MODE_GLOBAL) {
                   1095:       return (EINVAL);
                   1096:     }
                   1097: 
                   1098:     /* set the output stage one global mode: */
                   1099:     buffer->tme_keyboard_buffer_int_out1_keymode_stage
                   1100:       .tme_keymode_stage_global_mode = mode;
                   1101:   }
                   1102: 
                   1103:   return (TME_OK);
                   1104: }
                   1105: 
                   1106: /* this fixes the keyboard's output stage zero modifiers when they get
                   1107:    out of sync with the emulated software reading the output keyboard: */
                   1108: tme_keyboard_modifiers_t
                   1109: tme_keyboard_buffer_out_modifiers(struct tme_keyboard_buffer *_buffer,
                   1110:                                  tme_keyboard_modifiers_t modifiers_clear,
                   1111:                                  tme_keyboard_modifiers_t modifiers_set)
                   1112: {
                   1113:   struct tme_keyboard_buffer_int *buffer;
                   1114:   
                   1115:   /* recover our data structure: */
                   1116:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                   1117: 
                   1118:   /* update the modifiers: */
                   1119:   return (buffer->tme_keyboard_buffer_int_out0_modifiers
                   1120:          = ((buffer->tme_keyboard_buffer_int_out0_modifiers
                   1121:              & ~modifiers_clear)
                   1122:             | modifiers_set));
                   1123: }
                   1124: 
                   1125: /* this parses a single keysym macro: */
                   1126: int
                   1127: tme_keyboard_parse_macro(const char *string,
                   1128:                         tme_keyboard_keysym_lookup_t keysym_lookup,
                   1129:                         void *keysym_lookup_private,
                   1130:                         tme_keyboard_keyval_t **_keysyms_lhs,
                   1131:                         tme_keyboard_keyval_t **_keysyms_rhs)
                   1132: {
                   1133:   char **tokens;
                   1134:   int tokens_count, equals_token;
                   1135:   int token_i;
                   1136:   tme_keyboard_keyval_t keysym, *keysyms_lhs, *keysyms_rhs;
                   1137:   struct tme_keyboard_lookup lookup;
                   1138:   unsigned int count_lhs, count_rhs;
                   1139:   int rc;
                   1140: 
                   1141:   /* tokenize this line: */
                   1142:   tokens = tme_misc_tokenize(string, '#', &tokens_count);
                   1143:   keysyms_lhs = tme_new(tme_keyboard_keyval_t, tokens_count);
                   1144:   keysyms_rhs = tme_new(tme_keyboard_keyval_t, tokens_count);
                   1145:   count_lhs = 0;
                   1146:   count_rhs = 0;
                   1147: 
                   1148:   /* start the lookup structure: */
                   1149:   lookup.tme_keyboard_lookup_context_length = 0;
                   1150:   lookup.tme_keyboard_lookup_context = NULL;
                   1151: 
                   1152:   /* all of the tokens must be valid keysyms, except for a single
                   1153:      mandatory "=" token, which must not be the first or last token: */
                   1154:   equals_token = -1;
                   1155:   rc = TME_OK;
                   1156:   for (token_i = 0;
                   1157:        token_i < tokens_count;
                   1158:        token_i++) {
                   1159:     
                   1160:     /* check for an "=" token: */
                   1161:     if (!strcmp(tokens[token_i], "=")) {
                   1162:       if (equals_token >= 0
                   1163:          || token_i == 0
                   1164:          || token_i + 1 == tokens_count) {
                   1165:        rc = EINVAL;
                   1166:        break;
                   1167:       }
                   1168:       equals_token = token_i;
                   1169:       continue;
                   1170:     }
                   1171: 
                   1172:     /* a token on the left hand side must be a keysym that the 
                   1173:        caller can generate directly: */
                   1174:     if (equals_token < 0) {
                   1175: 
                   1176:       /* get the keysym for this token: */
                   1177:       lookup.tme_keyboard_lookup_string = tokens[token_i];
                   1178:       lookup.tme_keyboard_lookup_flags = TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT;
                   1179:       keysym = (*keysym_lookup)(keysym_lookup_private, &lookup);
                   1180:       if (keysym == TME_KEYBOARD_KEYVAL_UNDEF) {
                   1181:        rc = ENOENT;
                   1182:        break;
                   1183:       }
                   1184:       keysyms_lhs[count_lhs++] = keysym;
                   1185:     }
                   1186: 
                   1187:     /* otherwise, a token on the right hand side is either a keysym
                   1188:        that the caller can generate directly, or the caller must
                   1189:        be able to allocate a unique value for it: */
                   1190:     else {
                   1191: 
                   1192:       /* get the keysym for this token: */
                   1193:       lookup.tme_keyboard_lookup_string = tokens[token_i];
                   1194:       lookup.tme_keyboard_lookup_flags = (TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT
                   1195:                                          | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC
                   1196:                                          | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC_NOW);
                   1197:       keysym = (*keysym_lookup)(keysym_lookup_private, &lookup);
                   1198:       assert (keysym != TME_KEYBOARD_KEYVAL_UNDEF);
                   1199:       keysyms_rhs[count_rhs++] = keysym;
                   1200:     }
                   1201:   }
                   1202: 
                   1203:   /* if this macro didn't parse correctly: */
                   1204:   if (rc != TME_OK) {
                   1205:     tme_free_string_array(tokens, -1);
                   1206:     tme_free(keysyms_lhs);
                   1207:     tme_free(keysyms_rhs);
                   1208:     return (rc);
                   1209:   }
                   1210: 
                   1211:   /* finish the sides of the macro: */
                   1212:   keysyms_lhs[count_lhs] = TME_KEYBOARD_KEYVAL_UNDEF;
                   1213:   keysyms_rhs[count_rhs] = TME_KEYBOARD_KEYVAL_UNDEF;
                   1214: 
                   1215:   /* done: */
                   1216:   *_keysyms_lhs = keysyms_lhs;
                   1217:   *_keysyms_rhs = keysyms_rhs;
                   1218:   tme_free_string_array(tokens, -1);
                   1219:   return (TME_OK);
                   1220: }
                   1221: 
                   1222: /* this parses a single keysym map entry: */
                   1223: int
                   1224: tme_keyboard_parse_map(const char *string,
                   1225:                       tme_keyboard_keysym_lookup_t keysym_lookup,
                   1226:                       void *keysym_lookup_private,
                   1227:                       struct tme_keyboard_map *map)
                   1228: {
                   1229:   char **tokens, *p1, c;
                   1230:   int tokens_count;
                   1231:   int token_i;
                   1232:   tme_keyboard_keyval_t keycode;
                   1233:   int modifier, attached_modifier;
                   1234:   tme_keyboard_modifiers_t modifiers_set, modifiers_clear;
                   1235:   struct tme_keyboard_lookup lookup;
                   1236:   int rc;
                   1237: 
                   1238:   /* tokenize this line: */
                   1239:   tokens = tme_misc_tokenize(string, '#', &tokens_count);
                   1240:   rc = TME_OK;
                   1241: 
                   1242:   /* there must be at least three tokens.  the second token must be an
                   1243:      equals sign, and the third token must be an integer that isn't
                   1244:      TME_KEYBOARD_KEYVAL_UNDEF: */
                   1245:   if (tokens_count < 3
                   1246:       || strcmp(tokens[1], "=")
                   1247:       || ((keycode = strtoul(tokens[2], &p1, 0))
                   1248:          == TME_KEYBOARD_KEYVAL_UNDEF)
                   1249:       || p1 == tokens[2]
                   1250:       || *p1 != '\0') {
                   1251:     rc = EINVAL;
                   1252:   }
                   1253:   
                   1254:   /* any tokens after the third must all be modifier names: */  
                   1255:   else {
                   1256:     attached_modifier = TME_KEYBOARD_MODIFIER_NONE;
                   1257:     modifiers_set = 0;
                   1258:     modifiers_clear = 0;
                   1259:     for (token_i = 3;
                   1260:         token_i < tokens_count;
                   1261:         token_i++) {
                   1262: 
                   1263:       /* a token might be prefixed with '+' or '!': */
                   1264:       p1 = tokens[token_i];
                   1265:       c = *p1;
                   1266:       if (c == '+'
                   1267:          || c == '!') {
                   1268:        p1++;
                   1269:       }
                   1270: 
                   1271:       /* turn this token into a real modifier: */
                   1272:       if (!strcmp(p1, "shift")) {
                   1273:        modifier = TME_KEYBOARD_MODIFIER_SHIFT;
                   1274:       }
                   1275:       else if (!strcmp(p1, "lock")) {
                   1276:        modifier = TME_KEYBOARD_MODIFIER_LOCK;
                   1277:       }
                   1278:       else if (!strcmp(p1, "control")) {
                   1279:        modifier = TME_KEYBOARD_MODIFIER_CONTROL;
                   1280:       }
                   1281:       else if (!strcmp(p1, "mod1")) {
                   1282:        modifier = TME_KEYBOARD_MODIFIER_MOD1;
                   1283:       }
                   1284:       else if (!strcmp(p1, "mod2")) {
                   1285:        modifier = TME_KEYBOARD_MODIFIER_MOD2;
                   1286:       }
                   1287:       else if (!strcmp(p1, "mod3")) {
                   1288:        modifier = TME_KEYBOARD_MODIFIER_MOD3;
                   1289:       }
                   1290:       else if (!strcmp(p1, "mod4")) {
                   1291:        modifier = TME_KEYBOARD_MODIFIER_MOD4;
                   1292:       }
                   1293:       else if (!strcmp(p1, "mod5")) {
                   1294:        modifier = TME_KEYBOARD_MODIFIER_MOD5;
                   1295:       }
                   1296:       else {
                   1297:        rc = EINVAL;
                   1298:        break;
                   1299:       }
                   1300:     
                   1301:       /* if a modifier is prefixed with '+', it must be the only
                   1302:         modifier token in the map entry, and it indicates that the
                   1303:         keycode is attached to that modifier in this map: */
                   1304:       if (c == '+') {
                   1305: 
                   1306:        /* if this is not the only modifier token in the map entry: */
                   1307:        if (tokens_count != 4) {
                   1308:          rc = EINVAL;
                   1309:          break;
                   1310:        }
                   1311: 
                   1312:        attached_modifier = modifier;
                   1313:       }
                   1314:       
                   1315:       /* otherwise, if a modifier name is prefixed with '!', this
                   1316:         modifier must be clear for this keycode to mean this keysym: */
                   1317:       else if (c == '!') {
                   1318:        modifiers_clear |= (1 << modifier);
                   1319:       }
                   1320: 
                   1321:       /* otherwise, this modifier must be set for this keycode to mean
                   1322:         this keysym: */
                   1323:       else {
                   1324:        modifiers_set |= (1 << modifier);
                   1325:       }
                   1326:     }
                   1327: 
                   1328:     /* the modifiers that must be set and the modifiers that must be
                   1329:        clear cannot overlap: */
                   1330:     if (modifiers_set & modifiers_clear) {
                   1331:       rc = EINVAL;
                   1332:     }
                   1333: 
                   1334:     /* if no error has been encountered yet: */
                   1335:     if (rc == TME_OK) {
                   1336: 
                   1337:       /* make the keyboard map entry.  we very deliberately set all
                   1338:         bytes not allocated to structure members to all-bits-zero, so
                   1339:         that identical keysym contexts truly are identical: */
                   1340:       memset(map, 0, sizeof(*map));
                   1341:       map->tme_keyboard_map_keycode = keycode;
                   1342:       map->tme_keyboard_map_modifier = attached_modifier;
                   1343:       map->tme_keyboard_map_modifiers_set = modifiers_set;
                   1344:       map->tme_keyboard_map_modifiers_clear = modifiers_clear;
                   1345: 
                   1346:       /* take note of a special keysym: */
                   1347:       if (!strcmp(tokens[0], "Caps_Lock")) {
                   1348:        map->tme_keyboard_map_keysym_note
                   1349:          = TME_KEYBOARD_KEYSYM_NOTE_CAPS_LOCK;
                   1350:       }
                   1351:       else if (!strcmp(tokens[0], "Shift_Lock")) {
                   1352:        map->tme_keyboard_map_keysym_note
                   1353:          = TME_KEYBOARD_KEYSYM_NOTE_SHIFT_LOCK;
                   1354:       }
                   1355:       else if (!strcmp(tokens[0], "Num_Lock")) {
                   1356:        map->tme_keyboard_map_keysym_note
                   1357:          = TME_KEYBOARD_KEYSYM_NOTE_NUM_LOCK;
                   1358:       }
                   1359:       else {
                   1360:        map->tme_keyboard_map_keysym_note
                   1361:          = TME_KEYBOARD_KEYSYM_NOTE_UNDEF;
                   1362:       }
                   1363: 
                   1364:       /* the caller must be able to either directly generate this
                   1365:         keysym or have allocated a value for it already (because a
                   1366:         macro was previously added than can generate it).  if neither
                   1367:         is true, the lookup function must return
                   1368:         TME_KEYBOARD_KEYVAL_UNDEF, but this function still does not
                   1369:         fail.  it is up to the caller to not add a map entry with an
                   1370:         undefined keysym: */
                   1371:       lookup.tme_keyboard_lookup_string
                   1372:        = tokens[0];
                   1373:       lookup.tme_keyboard_lookup_flags
                   1374:        = (TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT
                   1375:           | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC);
                   1376:       lookup.tme_keyboard_lookup_context_length
                   1377:        = sizeof(*map);
                   1378:       lookup.tme_keyboard_lookup_context
                   1379:        = (tme_uint8_t *) map;
                   1380:       map->tme_keyboard_map_keysym
                   1381:        = (*keysym_lookup)(keysym_lookup_private, &lookup);
                   1382:     }
                   1383:   }
                   1384: 
                   1385:   /* free the tokens: */
                   1386:   tme_free_string_array(tokens, -1);
                   1387: 
                   1388:   /* return the parsed map: */
                   1389:   return (rc);
                   1390: }
                   1391: 
                   1392: /* this adds an event to the event buffer: */
                   1393: static int
                   1394: _tme_keyboard_buffer_copyin(struct tme_keyboard_buffer_int *buffer,
                   1395:                            _tme_const struct tme_keyboard_event *event)
                   1396: {
                   1397:   unsigned int buffer_head, buffer_size_mask;
                   1398: 
                   1399:   buffer_head = buffer->tme_keyboard_buffer_int_head;
                   1400:   buffer_size_mask = buffer->tme_keyboard_buffer_int_size - 1;
                   1401: 
                   1402:   /* if the buffer is full: */
                   1403:   if (((buffer_head + 1) & buffer_size_mask)
                   1404:       == buffer->tme_keyboard_buffer_int_tail) {
                   1405:     return (EAGAIN);
                   1406:   }
                   1407: 
                   1408:   /* put this event into the buffer: */
                   1409:   buffer->tme_keyboard_buffer_int_events[buffer_head]
                   1410:     = *event;
                   1411: 
                   1412:   /* advance the head: */
                   1413:   buffer->tme_keyboard_buffer_int_head
                   1414:     = (buffer_head + 1) & buffer_size_mask;
                   1415: 
                   1416:   return (TME_OK);
                   1417: }
                   1418: 
                   1419: /* this adds a difference to an event time, avoiding a result of
                   1420:    TME_KEYBOARD_EVENT_TIME_UNDEF: */
                   1421: static tme_uint32_t
                   1422: _tme_keyboard_event_time_diff(tme_uint32_t event_time,
                   1423:                              tme_int32_t diff)
                   1424: {
                   1425:   event_time += (tme_uint32_t) diff;
                   1426:   if (event_time == TME_KEYBOARD_EVENT_TIME_UNDEF) {
                   1427:     assert (diff != 0);
                   1428:     event_time += (diff < 0 ? -1 : 1);
                   1429:   }
                   1430:   return (event_time);
                   1431: }
                   1432: 
                   1433: /* this subtracts event_time1 from event_time0, handling the wrapping
                   1434:    of the tme_uint32_t milliseconds values as best as possible: */
                   1435: static tme_int32_t
                   1436: _tme_keyboard_event_time_subtract(tme_uint32_t event_time0,
                   1437:                                  tme_uint32_t event_time1)
                   1438: {
                   1439:   tme_uint32_t event_time0_less_least;
                   1440:   tme_uint32_t event_time_diff_unwrapped;
                   1441:   tme_uint32_t event_time_diff_wrapped;
                   1442:   
                   1443:   /* if the two times are equal: */
                   1444:   if (event_time0 == event_time1) {
                   1445:     return (0);
                   1446:   }
                   1447: 
                   1448:   /* calculate the unwrapped and wrapped differences between the
                   1449:      two times: */
                   1450:   if (event_time0 < event_time1) {
                   1451:     event_time_diff_unwrapped = event_time1 - event_time0;
                   1452:     event_time_diff_wrapped = 0 - event_time_diff_unwrapped;
                   1453:   }
                   1454:   else {
                   1455:     event_time_diff_unwrapped = event_time0 - event_time1;
                   1456:     event_time_diff_wrapped = 0 - event_time_diff_unwrapped;
                   1457:   }
                   1458: 
                   1459:   /* calculate the event time that is the most in the past without
                   1460:      being confused as being later than event_time0: */
                   1461:   event_time0_less_least
                   1462:     = (event_time0 - (((tme_uint32_t) -1) >> 1));
                   1463: 
                   1464:   /* if event_time0_less_least is literally greater than event_time0,
                   1465:      the event time space that represents "less than event_time0" is
                   1466:      not a single region in the tme_uint32_t space: */
                   1467:   if (event_time0_less_least < event_time0) {
                   1468:     return ((event_time0_less_least <= event_time1
                   1469:             && event_time1 < event_time0)
                   1470:            /* event_time1 is less than event_time0: */
                   1471:            ? event_time_diff_unwrapped
                   1472:            /* event_time1 is greater than event_time0: */
                   1473:            : (event_time1 > event_time0
                   1474:               ? 0 - event_time_diff_unwrapped
                   1475:               : 0 - event_time_diff_wrapped));
                   1476:   }
                   1477: 
                   1478:   /* otherwise, the event time space that represents "less than
                   1479:      event_time0" is two regions in the tme_uint32_t space: */
                   1480:   else {
                   1481:     return ((event_time0_less_least <= event_time1
                   1482:             || event_time1 < event_time0)
                   1483:            /* event_time1 is less than event_time0: */
                   1484:            ? (event_time1 < event_time0
                   1485:               ? event_time_diff_unwrapped
                   1486:               : event_time_diff_wrapped)
                   1487:            /* event_time1 is greater than event_time0: */
                   1488:            : 0 - event_time_diff_unwrapped);
                   1489:   }
                   1490: }
                   1491: 
                   1492: /* this runs a keymode stage.  this is used for input stage one,
                   1493:    and output stage one.  roughly, a keymode stage tries to
                   1494:    guarantee that a key has a specific press/release behavior
                   1495:    (or "mode") for later stages.  the particular modes are described
                   1496:    in the case below: */
                   1497: static int
                   1498: _tme_keymode_stage(struct tme_keyboard_buffer_int *buffer,
                   1499:                   struct tme_keymode_stage *stage,
                   1500:                   struct tme_keymode_state *keymode,
                   1501:                   int is_press,
                   1502:                   tme_uint32_t event_time)
                   1503: {
                   1504:   struct tme_keymode_state **_auto_keymode, *auto_keymode;
                   1505:   int pressed_old, mode;
                   1506:   int rc;
                   1507: 
                   1508:   /* check all keys on the no-autorepeats list: */
                   1509:   for (_auto_keymode = &stage->tme_keymode_stage_no_autorepeats;
                   1510:        (auto_keymode = *_auto_keymode) != NULL; ) {
                   1511: 
                   1512:     /* if the time of the last release from the earlier stages is
                   1513:        undefined, that means that the last event from the earlier
                   1514:        stages was a press: */
                   1515:     if (auto_keymode->tme_keymode_state_last_release
                   1516:        == TME_KEYBOARD_EVENT_TIME_UNDEF) {
                   1517: 
                   1518:       /* if the key we're checking happens to be the key that the
                   1519:         earlier stages are calling us for: */
                   1520:       if (auto_keymode == keymode) {
                   1521: 
                   1522:        /* this must be a release on this key: */
                   1523:        assert (!is_press);
                   1524: 
                   1525:        /* set the release time on this key: */
                   1526:        auto_keymode->tme_keymode_state_last_release = event_time;
                   1527: 
                   1528:        /* we've taken care of this call: */
                   1529:        keymode = NULL;
                   1530:       }
                   1531:     }
                   1532: 
                   1533:     /* otherwise, the last event from the earlier stages was a release.
                   1534:        if enough time has elapsed since then without a press from
                   1535:        earlier stages: */
                   1536:     else if (_tme_keyboard_event_time_subtract(event_time,
                   1537:                                               auto_keymode->tme_keymode_state_last_release)
                   1538:             > TME_KEYBOARD_SHORTEST_DOUBLE_MSEC) {
                   1539: 
                   1540:       /* now we're sure that the key has genuinely released.
                   1541:         remove this key from the autorepeats list: */
                   1542:       *_auto_keymode = auto_keymode->tme_keymode_state_next;
                   1543:       auto_keymode->tme_keymode_state_next = NULL;
                   1544: 
                   1545:       /* if we're supposed to ignore the genuine release: */
                   1546:       if (auto_keymode->tme_keymode_state_ignore_release) {
                   1547:        auto_keymode->tme_keymode_state_ignore_release = FALSE;
                   1548:       }
                   1549: 
                   1550:       /* otherwise, we're not supposed to ignore the genuine release: */
                   1551:       else {
                   1552: 
                   1553:        /* flip the pressed state of the key: */
                   1554:        auto_keymode->tme_keymode_state_pressed
                   1555:          = !auto_keymode->tme_keymode_state_pressed;
                   1556: 
                   1557:        /* if this key is now pressed, or if we're allowed to
                   1558:           pass releases, run the next stage: */
                   1559:        mode = auto_keymode->tme_keymode_state_mode;
                   1560:        if (mode == TME_KEYBOARD_MODE_GLOBAL) {
                   1561:          mode = stage->tme_keymode_stage_global_mode;
                   1562:        }
                   1563:        if (auto_keymode->tme_keymode_state_pressed
                   1564:            || !(mode
                   1565:                 & TME_KEYBOARD_MODE_FLAG_NO_RELEASES)) {
                   1566:          rc = (*stage->tme_keymode_stage_next)
                   1567:            (buffer,
                   1568:             auto_keymode->tme_keymode_state_keysym,
                   1569:             _tme_keyboard_event_time_diff(event_time, -1));
                   1570:          assert (rc == TME_OK);
                   1571:        }
                   1572:       }
                   1573: 
                   1574:       /* continue now - by removing this key from the autorepeats
                   1575:         list we've already advanced our position in the list for
                   1576:         the next iteration: */
                   1577:       continue;
                   1578:     }
                   1579: 
                   1580:     /* otherwise, if the key we're checking happens to be the key that
                   1581:        the earlier stages are calling us for: */
                   1582:     else if (auto_keymode == keymode) {
                   1583: 
                   1584:       /* this must be a press on this key: */
                   1585:       assert (is_press);
                   1586: 
                   1587:       /* now we're sure that this key is autorepeating.  clear
                   1588:         the last-release time: */
                   1589:       auto_keymode->tme_keymode_state_last_release
                   1590:        = TME_KEYBOARD_EVENT_TIME_UNDEF;
                   1591: 
                   1592:       /* we've taken care of this call: */
                   1593:       keymode = NULL;
                   1594:     }
                   1595:       
                   1596:     /* continue: */
                   1597:     _auto_keymode = &auto_keymode->tme_keymode_state_next;
                   1598:   }
                   1599:       
                   1600:   /* return now if we already finished processing this event: */
                   1601:   if (keymode == NULL) {
                   1602:     return (TME_OK);
                   1603:   }
                   1604: 
                   1605:   /* get this key's mode: */
                   1606:   mode = keymode->tme_keymode_state_mode;
                   1607:   if (mode == TME_KEYBOARD_MODE_GLOBAL) {
                   1608:     mode = stage->tme_keymode_stage_global_mode;
                   1609:   }
                   1610:   
                   1611:   /* remember if this key was pressed in this stage before: */
                   1612:   pressed_old = keymode->tme_keymode_state_pressed;
                   1613: 
                   1614:   /* unlock mode unlocks a key by turning every transition into a
                   1615:      press transition and a release transition.  think of a Caps Lock
                   1616:      key on an input keyboard that *physically* locks down when you
                   1617:      press it down - this is a nice property, because there's no
                   1618:      mistaking that when you get a key press event, you know the key
                   1619:      is both physically and *semantically* down until you get a key
                   1620:      release, at which time you know just the opposite.
                   1621:      
                   1622:      however, this is a best case.  many keyboards have Caps Lock, Num
                   1623:      Lock, and other keys where their semantic pressed/release state
                   1624:      doesn't match their physical pressed/release state.  to make
                   1625:      everything uniform, we need to bring the best-case keyboards down
                   1626:      to the worst-case level: */
                   1627:   if (mode == TME_KEYBOARD_MODE_UNLOCK) {
                   1628: 
                   1629:     /* we must not have this key as pressed: */
                   1630:     assert (!pressed_old);
                   1631: 
                   1632:     /* press this key and run the next stage: */
                   1633:     keymode->tme_keymode_state_pressed = TRUE;
                   1634:     rc = (*stage->tme_keymode_stage_next)
                   1635:       (buffer,
                   1636:        keymode->tme_keymode_state_keysym,
                   1637:        _tme_keyboard_event_time_diff(event_time, -1));
                   1638:     assert (rc == TME_OK);
                   1639:     
                   1640:     /* release this key, and make sure the next stage
                   1641:        gets run at the end of this function: */
                   1642:     keymode->tme_keymode_state_pressed = FALSE;
                   1643:     pressed_old = TRUE;
                   1644:   }
                   1645: 
                   1646:   /* lock mode makes the key lock in the physical sense, like the
                   1647:      best-case Caps Lock described above.  since our events from
                   1648:      earlier stages are worst-case, we need to ignore autorepeats, and
                   1649:      each press/release pair must toggle our notion of whether or not
                   1650:      the key is physically pressed: */
                   1651:   else if (mode == TME_KEYBOARD_MODE_LOCK) {
                   1652: 
                   1653:     /* this must be a press: */
                   1654:     assert (is_press);
                   1655: 
                   1656:     /* put this key on the no-autorepeats list: */
                   1657:     keymode->tme_keymode_state_last_release
                   1658:       = TME_KEYBOARD_EVENT_TIME_UNDEF;
                   1659:     keymode->tme_keymode_state_next
                   1660:       = stage->tme_keymode_stage_no_autorepeats;
                   1661:     stage->tme_keymode_stage_no_autorepeats = keymode;
                   1662:     
                   1663:     /* if we have the key as pressed (locked): */
                   1664:     if (pressed_old) {
                   1665:       
                   1666:       /* don't ignore the genuine release, when it is determined to
                   1667:         have happened.  if this mode has
                   1668:         TME_KEYBOARD_MODE_FLAG_NO_RELEASES set, the genuine release
                   1669:         code will handle it then: */
                   1670:       keymode->tme_keymode_state_ignore_release = FALSE;
                   1671:     }
                   1672:     
                   1673:     /* otherwise, we have the key as released (unlocked): */
                   1674:     else {
                   1675:       
                   1676:       /* press this key: */
                   1677:       keymode->tme_keymode_state_pressed = TRUE;
                   1678:       
                   1679:       /* ignore the genuine release, when it is determined
                   1680:         to have happened: */
                   1681:       keymode->tme_keymode_state_ignore_release = TRUE;
                   1682:     }
                   1683:   }
                   1684: 
                   1685:   /* passthrough mode generally passes events through: */
                   1686:   else {
                   1687: 
                   1688:     assert (!pressed_old != !is_press);
                   1689: 
                   1690:     /* if this is a press: */
                   1691:     if (is_press) {
                   1692: 
                   1693:       /* press this key: */
                   1694:       keymode->tme_keymode_state_pressed = TRUE;
                   1695: 
                   1696:       /* if we must not pass through autorepeats: */
                   1697:       if (mode & TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS) {
                   1698: 
                   1699:        /* put this key on the no-autorepeats list: */
                   1700:        keymode->tme_keymode_state_last_release
                   1701:          = TME_KEYBOARD_EVENT_TIME_UNDEF;
                   1702:        keymode->tme_keymode_state_next
                   1703:          = stage->tme_keymode_stage_no_autorepeats;
                   1704:        stage->tme_keymode_stage_no_autorepeats = keymode;
                   1705: 
                   1706:        /* don't ignore the genuine release, when it is
                   1707:           determined to have happened.  if this mode has
                   1708:           TME_KEYBOARD_MODE_FLAG_NO_RELEASES set, the 
                   1709:           genuine release code will handle it then: */
                   1710:        keymode->tme_keymode_state_ignore_release = FALSE;
                   1711:       }
                   1712:     }
                   1713: 
                   1714:     /* otherwise, this is a release: */
                   1715:     else {
                   1716: 
                   1717:       /* release this key: */
                   1718:       keymode->tme_keymode_state_pressed = FALSE;
                   1719: 
                   1720:       /* if this mode has TME_KEYBOARD_MODE_FLAG_NO_RELEASES set,
                   1721:         we'll handle it below when we go to run the next stage: */
                   1722:     }
                   1723:   }
                   1724: 
                   1725:   /* stop processing this event now if the key's pressed state
                   1726:      in this stage has not changed, or if the key is now released
                   1727:      and we're not allowed to pass releases.  otherwise, run the
                   1728:      next stage: */
                   1729:   return ((keymode->tme_keymode_state_pressed
                   1730:           ? pressed_old
                   1731:           : (!pressed_old
                   1732:              || (mode
                   1733:                  & TME_KEYBOARD_MODE_FLAG_NO_RELEASES)))
                   1734:          ? TME_OK
                   1735:          : ((*stage->tme_keymode_stage_next)
                   1736:             (buffer,
                   1737:              keymode->tme_keymode_state_keysym,
                   1738:              event_time)));
                   1739: }
                   1740: 
                   1741: /* this is the bottom half of output stage one.  this half does
                   1742:    nothing except finally buffer an event for a keycode, and update
                   1743:    the output modifiers mask: */
                   1744: static int
                   1745: _tme_keyboard_buffer_out1_bottom(struct tme_keyboard_buffer_int *buffer,
                   1746:                                 struct tme_keysym_state *keysym,
                   1747:                                 tme_uint32_t event_time)
                   1748: {
                   1749:   struct tme_keycode_state *keycode;
                   1750:   struct tme_keyboard_event event_buffer;
                   1751:   int modifier;
                   1752:   int is_press;
                   1753: 
                   1754:   /* get the keycode: */
                   1755:   keycode = keysym->tme_keysym_state_out0_keycode;
                   1756: 
                   1757:   /* get whether or not this is a press: */
                   1758:   is_press = TME_KEYBOARD_PRESSED_OUT1(keycode);
                   1759: 
                   1760:   _tme_keyboard_debug(buffer,
                   1761:                      "out1-bottom",
                   1762:                      keysym->tme_keysym_state_keysym,
                   1763:                      is_press,
                   1764:                      event_time);
                   1765: 
                   1766:   /* if this keysym is attached to a modifier, update the output
                   1767:      modifiers mask: */
                   1768:   /* XXX there might be a cleaner way to work the output modifier
                   1769:      mask.  it's suspicious that stages zero and one need to share the
                   1770:      modifiers mask and the keysym to modifier mapping: */
                   1771:   modifier = keysym->tme_keysym_state_out0_modifier;
                   1772:   if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
                   1773: 
                   1774:     /* if this is a press: */
                   1775:     if (is_press) {
                   1776: 
                   1777:       /* if the modifier is currently clear: */
                   1778:       if (!(buffer->tme_keyboard_buffer_int_out0_modifiers
                   1779:            & (1 << modifier))) {
                   1780: 
                   1781:        /* set the modifier: */
                   1782:        buffer->tme_keyboard_buffer_int_out0_modifiers
                   1783:          |= (1 << modifier);
                   1784: 
                   1785:        /* iff this keysym soft-locks, the next release will not
                   1786:           affect the output modifiers mask: */
                   1787:        keysym->tme_keysym_state_out1_ignore_release
                   1788:          = (keycode->tme_keycode_state_keymode.tme_keymode_state_mode
                   1789:             & TME_KEYBOARD_MODE_FLAG_LOCK_SOFT);
                   1790:       }
                   1791: 
                   1792:       /* otherwise, the modifier is currently set: */
                   1793:       else {
                   1794:        
                   1795:        /* nothing to do.  even if this keysym soft-locks, we won't
                   1796:           clear the modifier until the release: */
                   1797:       }
                   1798:     }
                   1799: 
                   1800:     /* otherwise, this is a release: */
                   1801:     else {
                   1802: 
                   1803:       /* if we're supposed to ignore this release: */
                   1804:       if (keysym->tme_keysym_state_out1_ignore_release) {
                   1805:        keysym->tme_keysym_state_out1_ignore_release = FALSE;
                   1806:       }
                   1807: 
                   1808:       /* otherwise, if the modifier is currently set: */
                   1809:       else if (buffer->tme_keyboard_buffer_int_out0_modifiers
                   1810:               & (1 << modifier)) {
                   1811: 
                   1812:        /* clear the modifier: */
                   1813:        buffer->tme_keyboard_buffer_int_out0_modifiers
                   1814:          &= ~(1 << modifier);
                   1815:       }
                   1816: 
                   1817:       /* otherwise, the modifier is currently clear: */
                   1818:       else {
                   1819: 
                   1820:        /* nothing to do.  a release would never set a modifier: */
                   1821:       }
                   1822:     }
                   1823:   }
                   1824: 
                   1825:   /* finally buffer this keycode: */
                   1826:   event_buffer.tme_keyboard_event_type
                   1827:     = (is_press
                   1828:        ? TME_KEYBOARD_EVENT_PRESS
                   1829:        : TME_KEYBOARD_EVENT_RELEASE);
                   1830:   event_buffer.tme_keyboard_event_keyval
                   1831:     = keycode->tme_keycode_state_keycode;
                   1832:   event_buffer.tme_keyboard_event_time
                   1833:     = event_time;
                   1834:   event_buffer.tme_keyboard_event_modifiers
                   1835:     = buffer->tme_keyboard_buffer_int_out0_modifiers;
                   1836:   return (_tme_keyboard_buffer_copyin(buffer, &event_buffer));
                   1837: }
                   1838: 
                   1839: /* this is the top half of output stage one.  it is the last output
                   1840:    stage, that gives each keycode the specific behavior that it must
                   1841:    have on the output keyboard: */
                   1842: static int
                   1843: _tme_keyboard_buffer_out1(struct tme_keyboard_buffer_int *buffer,
                   1844:                          struct tme_keysym_state *keysym,
                   1845:                          tme_uint32_t event_time)
                   1846: {
                   1847:   struct tme_keycode_state *keycode;
                   1848: 
                   1849:   _tme_keyboard_debug(buffer,
                   1850:                      "out1-top",
                   1851:                      keysym->tme_keysym_state_keysym,
                   1852:                      TME_KEYBOARD_PRESSED_OUT0(keysym),
                   1853:                      event_time);
                   1854: 
                   1855:   /* get the keycode state: */
                   1856:   keycode = keysym->tme_keysym_state_out0_keycode;
                   1857: 
                   1858:   /* run the keymode stage function: */
                   1859:   return (_tme_keymode_stage(buffer,
                   1860:                             &buffer->tme_keyboard_buffer_int_out1_keymode_stage,
                   1861:                             &keycode->tme_keycode_state_keymode,
                   1862:                             TME_KEYBOARD_PRESSED_OUT0(keysym),
                   1863:                             event_time));
                   1864: }
                   1865: 
                   1866: /* this is output stage zero.  at this point, we have the final
                   1867:    keysyms from the input keyboard, and this stage maps those keysyms
                   1868:    to keycodes on the output keyboard.  
                   1869: 
                   1870:    sometimes, the input keyboard may generate keysyms for which the
                   1871:    output keyboard requires that certain modifiers be set or clear, at
                   1872:    a time when the output modifiers mask isn't suitable.  for example,
                   1873:    this can happen when the input keyboard can generate a certain
                   1874:    keysym without shifting, when the output keyboard requires
                   1875:    shifting.
                   1876: 
                   1877:    when this happens, this stage is responsible for simulating presses
                   1878:    or releases of modifiers on the output keyboard as needed to make
                   1879:    sure that the keysym is properly obtained when the mapped keycode
                   1880:    is pressed, and for undoing those changes when the mapped keycode
                   1881:    is released: */
                   1882: static int
                   1883: _tme_keyboard_buffer_out0(struct tme_keyboard_buffer_int *buffer,
                   1884:                          struct tme_keysym_state *keysym,
                   1885:                          tme_uint32_t event_time)
                   1886: {
                   1887:   struct tme_keyboard_event event_buffer;
                   1888:   tme_keyboard_modifiers_t modifiers, modifiers_set, modifiers_clear;
                   1889:   int num_lock_on;
                   1890:   int is_press, mod_pressed_old, modifier;
                   1891:   struct tme_keysym_state *mod_keysym, **keysyms;
                   1892:   unsigned int *press_flags;
                   1893:   int keysym_count;
                   1894:   int modifier_stuck;
                   1895:   int rc;
                   1896: 
                   1897:   _tme_keyboard_debug(buffer,
                   1898:                      "out0",
                   1899:                      keysym->tme_keysym_state_keysym,
                   1900:                      TME_KEYBOARD_PRESSED_IN2(keysym),
                   1901:                      event_time);
                   1902: 
                   1903:   /* get whether or not this is a press from earlier stages: */
                   1904:   is_press = TME_KEYBOARD_PRESSED_IN2(keysym);
                   1905: 
                   1906:   /* if output stage zero is a passthrough, just buffer an event for
                   1907:      the keysym and we're done processing this event: */
                   1908:   if (buffer->tme_keyboard_buffer_int_out0_passthrough) {
                   1909: 
                   1910:     /* otherwise, simply buffer this event: */
                   1911:     event_buffer.tme_keyboard_event_type
                   1912:       = (is_press
                   1913:         ? TME_KEYBOARD_EVENT_PRESS
                   1914:         : TME_KEYBOARD_EVENT_RELEASE);
                   1915:     event_buffer.tme_keyboard_event_keyval
                   1916:       = keysym->tme_keysym_state_keysym;
                   1917:     event_buffer.tme_keyboard_event_time
                   1918:       = event_time;
                   1919:     event_buffer.tme_keyboard_event_modifiers
                   1920:       = 0;
                   1921:     return (_tme_keyboard_buffer_copyin(buffer, &event_buffer));
                   1922:   }
                   1923: 
                   1924:   /* if this keysym is not mapped to a keycode on the output keyboard,
                   1925:      we don't have to process this event any more: */
                   1926:   if (keysym->tme_keysym_state_out0_keycode == NULL) {
                   1927:     return (TME_OK);
                   1928:   }
                   1929:   
                   1930:   /* if this is a press from earlier stages: */
                   1931:   if (is_press) {
                   1932: 
                   1933:     /* this keysym can't have any changes attached to it already: */
                   1934:     assert (keysym->tme_keysym_state_out0_keysyms == NULL);
                   1935:     keysyms = NULL;
                   1936:     press_flags = NULL;
                   1937:     keysym_count = 0;
                   1938: 
                   1939:     /* get the current output stage zero modifiers: */
                   1940:     modifiers = buffer->tme_keyboard_buffer_int_out0_modifiers;
                   1941: 
                   1942:     /* get the sets of modifiers that must be clear and set for this
                   1943:        keysym: */
                   1944:     modifiers_clear = keysym->tme_keysym_state_out0_modifiers_clear;
                   1945:     modifiers_set = keysym->tme_keysym_state_out0_modifiers_set;
                   1946:     assert ((modifiers_clear & modifiers_set) == 0);
                   1947:     assert ((modifiers_clear | modifiers_set) == 0
                   1948:            || (keysym->tme_keysym_state_out0_modifier
                   1949:                == TME_KEYBOARD_MODIFIER_NONE));
                   1950: 
                   1951:     /* if this keysym is uppercase, but the current modifiers are such
                   1952:        that a lowercase keysym *might* be generated: */
                   1953:     if ((modifiers_set & (1 << TME_KEYBOARD_MODIFIER_LOCK))
                   1954:        && !(modifiers & (1 << TME_KEYBOARD_MODIFIER_LOCK))) {
                   1955: 
                   1956:       /* if shift is down, we must be generating uppercase keysyms, so
                   1957:         forget about the lock modifier in this instance: */
                   1958:       if (modifiers & (1 << TME_KEYBOARD_MODIFIER_SHIFT)) {
                   1959:        modifiers_set &= ~(1 << TME_KEYBOARD_MODIFIER_LOCK);
                   1960:       }
                   1961: 
                   1962:       /* otherwise, neither shift nor lock are down, so we are
                   1963:         generating lowercase keysyms.  since this keyboard might not
                   1964:         have a lock modifier at all (and since it seems more
                   1965:         reasonable to do it this way anyways), require the shift
                   1966:         modifier to be set instead of the lock modifier in this
                   1967:         instance: */
                   1968:       else {
                   1969:        modifiers_set &= ~(1 << TME_KEYBOARD_MODIFIER_LOCK);
                   1970:        modifiers_set |= (1 << TME_KEYBOARD_MODIFIER_SHIFT);
                   1971:       }
                   1972:     }
                   1973:       
                   1974:     /* if this output keyboard has a Num_Lock key, and this keysym is
                   1975:        sensitive to the Num_Lock setting, but the appropriate Num_Lock
                   1976:        setting is already in effect, forget about Num_Lock for this
                   1977:        instance: */
                   1978:     modifier = buffer->tme_keyboard_buffer_int_out0_mod_num_lock;
                   1979:     if (modifier != TME_KEYBOARD_MODIFIER_NONE
                   1980:        && ((modifiers_clear
                   1981:             | modifiers_set)
                   1982:            & (1 << modifier))) {
                   1983: 
                   1984:       /* determine what Num_Lock setting is currently in effect.  it
                   1985:         is active if Num_Lock is pressed and there is no shifting
                   1986:         active, or if Num_Lock is released and there is shifting
                   1987:         active.  NB that if the lock modifier is attached only to a
                   1988:         Shift_Lock, that modifier also counts as shifting: */
                   1989:       num_lock_on
                   1990:        = (
                   1991: 
                   1992:           /* this term is 0 iff Num_Lock is pressed, else 1: */
                   1993:           !(modifiers
                   1994:             & (1 << modifier))
                   1995: 
                   1996:           !=
                   1997: 
                   1998:           /* this term is 0 iff shifting is active, else 1: */
                   1999:           !(modifiers
                   2000:             & ((1 << TME_KEYBOARD_MODIFIER_SHIFT)
                   2001:                | (buffer->tme_keyboard_buffer_int_out0_lock_is_caps
                   2002:                   ? 0
                   2003:                   : (1 << TME_KEYBOARD_MODIFIER_LOCK)))));
                   2004: 
                   2005:       /* if this keysym requires Num_Lock to be clear, but it is
                   2006:         not in effect, forget about Num_Lock for this instance: */
                   2007:       if ((modifiers_clear & (1 << modifier))
                   2008:          && !num_lock_on) {
                   2009:        modifiers_clear &= ~(1 << modifier);
                   2010:       }
                   2011: 
                   2012:       /* if this keysym requires Num_Lock to be set, but it is
                   2013:         in effect, forget about Num_Lock for this instance: */
                   2014:       if ((modifiers_set & (1 << modifier))
                   2015:          && num_lock_on) {
                   2016:        modifiers_set &= ~(1 << modifier);
                   2017:       }
                   2018:     }
                   2019: 
                   2020:     /* finish the set of modifiers that must be clear and set for this
                   2021:        keysym, but aren't: */
                   2022:     modifiers_clear &= modifiers;
                   2023:     modifiers_set &= ~modifiers;
                   2024: 
                   2025:     /* try to generate release events for all keysyms attached to
                   2026:        output modifiers that are set, but that need to be clear: */
                   2027:     if (modifiers_clear != 0) {
                   2028:       
                   2029:       /* loop over the modifiers that need clearing: */
                   2030:       for (modifier = 0;
                   2031:           modifier <= TME_KEYBOARD_MODIFIER_MAX;
                   2032:           modifier++) {
                   2033:        if (!(modifiers_clear & (1 << modifier))) {
                   2034:          continue;
                   2035:        }
                   2036:        
                   2037:        /* try to release all of the keysyms attached to this modifier
                   2038:           that are pressed: */
                   2039:        modifier_stuck = FALSE;
                   2040:        for (mod_keysym = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier];
                   2041:             mod_keysym != NULL;
                   2042:             mod_keysym = mod_keysym->tme_keysym_state_out0_modifier_next) {
                   2043:        
                   2044:          /* XXX this is broken for modifiers that soft-lock. */
                   2045: 
                   2046:          /* ignore this keysym if it isn't pressed: */
                   2047:          if (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym)) {
                   2048:            continue;
                   2049:          }
                   2050: 
                   2051:          /* grow the keysyms and press flags arrays.  the keysyms
                   2052:             array always has one extra entry, which will be filled
                   2053:             with NULL to terminate the array: */
                   2054:          if (keysym_count == 0) {
                   2055:            keysyms = tme_new(struct tme_keysym_state *, 2);
                   2056:            press_flags = tme_new(unsigned int, 1);
                   2057:          }
                   2058:          else {
                   2059:            keysyms = tme_renew(struct tme_keysym_state *, keysyms, keysym_count + 2);
                   2060:            press_flags = tme_renew(unsigned int, press_flags, keysym_count + 1);
                   2061:          }
                   2062:          
                   2063:          /* add this keysym to those arrays: */
                   2064:          keysyms[keysym_count] = mod_keysym;
                   2065:          press_flags[keysym_count] = FALSE;
                   2066:          keysym_count++;
                   2067: 
                   2068:          /* release this modifier key.  if this actually
                   2069:             releases the key, run the next stage: */
                   2070:          mod_keysym->tme_keysym_state_out0_released++;
                   2071:          if (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym)) {
                   2072:            rc = _tme_keyboard_buffer_out1(buffer,
                   2073:                                           mod_keysym,
                   2074:                                           _tme_keyboard_event_time_diff(event_time, -1));
                   2075:            assert (rc == TME_OK);
                   2076:          }
                   2077: 
                   2078:          /* otherwise, this modifier is stuck on: */
                   2079:          else {
                   2080:            modifier_stuck = TRUE;
                   2081:          }
                   2082:        }
                   2083: 
                   2084:        /* if we were able to release all keysyms attached to this
                   2085:           modifier, clear the modifier in the output keyboard mask: */
                   2086:        if (!modifier_stuck) {
                   2087:          buffer->tme_keyboard_buffer_int_out0_modifiers
                   2088:            &= ~(1 << modifier);
                   2089:        }
                   2090:       }
                   2091:     }
                   2092: 
                   2093:     /* try to generate press events for single keysyms attached to
                   2094:        output modifiers that are clear, but that need to be set: */
                   2095:     if (modifiers_set != 0) {
                   2096:       
                   2097:       /* loop over the modifiers that need setting: */
                   2098:       for (modifier = 0;
                   2099:           modifier <= TME_KEYBOARD_MODIFIER_MAX;
                   2100:           modifier++) {
                   2101:        if (!(modifiers_set & (1 << modifier))) {
                   2102:          continue;
                   2103:        }
                   2104:        
                   2105:        /* try to press a single keysym attached to this modifier: */
                   2106:        mod_keysym = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier];
                   2107:        assert (mod_keysym != NULL);
                   2108:        
                   2109:        /* this keysym can't pressed - if it is, the modifier
                   2110:           should be set: */
                   2111:        assert (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym));
                   2112: 
                   2113:        /* grow the keysyms and press flags arrays.  the keysyms
                   2114:           array always has one extra entry, which will be filled
                   2115:           with NULL to terminate the array: */
                   2116:        if (keysym_count == 0) {
                   2117:          keysyms = tme_new(struct tme_keysym_state *, 2);
                   2118:          press_flags = tme_new(unsigned int, 1);
                   2119:        }
                   2120:        else {
                   2121:          keysyms = tme_renew(struct tme_keysym_state *, keysyms, keysym_count + 2);
                   2122:          press_flags = tme_renew(unsigned int, press_flags, keysym_count + 1);
                   2123:        }
                   2124:          
                   2125:        /* add this keysym to those arrays: */
                   2126:        keysyms[keysym_count] = mod_keysym;
                   2127:        press_flags[keysym_count] = TRUE;
                   2128:        keysym_count++;
                   2129: 
                   2130:        /* press this modifier key.  this must actually press the key,
                   2131:           so run the next stage: */
                   2132:        mod_keysym->tme_keysym_state_out0_pressed++;
                   2133:        assert (TME_KEYBOARD_PRESSED_OUT0(mod_keysym));
                   2134:        rc = _tme_keyboard_buffer_out1(buffer,
                   2135:                                       mod_keysym,
                   2136:                                       _tme_keyboard_event_time_diff(event_time, -1));
                   2137:        assert (rc == TME_OK);
                   2138: 
                   2139:        /* set the modifier: */
                   2140:        buffer->tme_keyboard_buffer_int_out0_modifiers
                   2141:          |= (1 << modifier);
                   2142:       }
                   2143:     }
                   2144: 
                   2145:     /* remember any changes we made: */
                   2146:     if (keysyms != NULL) {
                   2147:       keysyms[keysym_count] = NULL;
                   2148:     }
                   2149:     keysym->tme_keysym_state_out0_keysyms = keysyms;
                   2150:     keysym->tme_keysym_state_out0_press_flags = press_flags;
                   2151: 
                   2152:     /* run the next stage: */
                   2153:     return (_tme_keyboard_buffer_out1(buffer,
                   2154:                                      keysym,
                   2155:                                      event_time));
                   2156:   }
                   2157: 
                   2158:   /* otherwise, this is a release: */
                   2159:   else {
                   2160:   
                   2161:     /* run the next stage: */
                   2162:     rc = _tme_keyboard_buffer_out1(buffer,
                   2163:                                   keysym,
                   2164:                                   event_time);
                   2165:     assert (rc == TME_OK);
                   2166: 
                   2167:     /* if this keysym tried to make any modifier changes, undo them: */
                   2168:     keysyms = keysym->tme_keysym_state_out0_keysyms;
                   2169:     press_flags = keysym->tme_keysym_state_out0_press_flags;
                   2170:     if (keysyms != NULL) {
                   2171: 
                   2172:       /* loop over all of the modifiers we changed: */
                   2173:       for (; (mod_keysym = *(keysyms++)) != NULL; ) {
                   2174: 
                   2175:        /* see if this modifier is pressed now: */
                   2176:        mod_pressed_old = TME_KEYBOARD_PRESSED_OUT0(mod_keysym);
                   2177: 
                   2178:        /* undo the change we made to this modifier: */
                   2179:        if (*(press_flags++)) {
                   2180:          mod_keysym->tme_keysym_state_out0_pressed--;
                   2181:        }
                   2182:        else {
                   2183:          mod_keysym->tme_keysym_state_out0_released--;
                   2184:        }
                   2185: 
                   2186:        /* if the state of this modifier has changed, run the next
                   2187:           stage: */
                   2188:        if (TME_KEYBOARD_PRESSED_OUT0(mod_keysym) != mod_pressed_old) {
                   2189:          rc = _tme_keyboard_buffer_out1(buffer,
                   2190:                                         mod_keysym,
                   2191:                                         _tme_keyboard_event_time_diff(event_time, +1));
                   2192:          assert (rc == TME_OK);
                   2193:        }
                   2194:       }
                   2195: 
                   2196:       /* forget these modifier changes: */
                   2197:       tme_free(keysym->tme_keysym_state_out0_keysyms);
                   2198:       tme_free(keysym->tme_keysym_state_out0_press_flags);
                   2199:       keysym->tme_keysym_state_out0_keysyms = NULL;
                   2200:       keysym->tme_keysym_state_out0_press_flags = NULL;
                   2201:     }
                   2202:   }
                   2203:       
                   2204:   /* success: */
                   2205:   return (TME_OK);
                   2206: }
                   2207: 
                   2208: /* this is input stage two.  at this point, we have the input keyboard
                   2209:    cleaned up to the point where we can have macros for generating
                   2210:    keysyms that the input keyboard can't generate on its own: */
                   2211: static int
                   2212: _tme_keyboard_buffer_in2(struct tme_keyboard_buffer_int *buffer,
                   2213:                         struct tme_keysym_state *keysym,
                   2214:                         tme_uint32_t event_time)
                   2215: {
                   2216:   tme_keyboard_keyval_t _keysym;
                   2217:   struct tme_keyboard_macro **_macro, *macro, *child, *parent;
                   2218:   int is_press, pressed_old, sub_pressed_old;
                   2219:   int update, keysym_i;
                   2220:   struct tme_keysym_state *sub_keysym;
                   2221:   int rc;
                   2222: 
                   2223:   _tme_keyboard_debug(buffer,
                   2224:                      "in2",
                   2225:                      keysym->tme_keysym_state_keysym,
                   2226:                      TME_KEYBOARD_PRESSED_IN1(keysym),
                   2227:                      event_time);
                   2228: 
                   2229:   /* get the keysym: */
                   2230:   _keysym = keysym->tme_keysym_state_keysym;
                   2231: 
                   2232:   /* get whether or not this is a press from earlier stages: */
                   2233:   is_press = TME_KEYBOARD_PRESSED_IN1(keysym);
                   2234: 
                   2235:   /* remember if this keysym was pressed in this stage before: */
                   2236:   pressed_old = _TME_KEYBOARD_PRESSED_IN2(keysym, !is_press);
                   2237: 
                   2238:   /* visit all active macros tree nodes: */
                   2239:   for (_macro = &buffer->tme_keyboard_buffer_int_in2_macros_active;
                   2240:        (macro = *_macro) != NULL; ) {
                   2241: 
                   2242:     /* if this is a press, see if it advances this macro's sequence: */
                   2243:     if (is_press) {
                   2244: 
                   2245:       /* ignore this macros tree node if it's a leaf, or if this
                   2246:         keysym is not a branch out of this node to some child node: */
                   2247:       if (macro->tme_keyboard_macro_branches == NULL
                   2248:          || (child
                   2249:              = ((struct tme_keyboard_macro *)
                   2250:                 tme_hash_lookup(macro->tme_keyboard_macro_branches,
                   2251:                                 (tme_hash_data_t) _keysym))) == NULL) {
                   2252:        _macro = &macro->tme_keyboard_macro_active_next;
                   2253:        continue;
                   2254:       }
                   2255:        
                   2256:       /* the child node cannot already be active.  if it is, that
                   2257:         means that earlier stages didn't give us a release for this
                   2258:         keysym: */
                   2259:       assert (child->tme_keyboard_macro_active_next == NULL);
                   2260:       
                   2261:       /* make the child node active: */
                   2262:       child->tme_keyboard_macro_active_next = macro;
                   2263:       *_macro = child;
                   2264:       _macro = &macro->tme_keyboard_macro_active_next;
                   2265:       macro = child;
                   2266:     }
                   2267: 
                   2268:     /* otherwise, this is a release, so see if this release cancels
                   2269:        any sequence: */
                   2270:     else {
                   2271: 
                   2272:       /* ignore this macros tree node if this is not a release of a
                   2273:         keysym somewhere on the path from the root to this node: */
                   2274:       if (_keysym != macro->tme_keyboard_macro_keysym) {
                   2275:        for (parent = macro->tme_keyboard_macro_parent;
                   2276:             parent != NULL;
                   2277:             parent = parent->tme_keyboard_macro_parent) {
                   2278:          if (_keysym == parent->tme_keyboard_macro_keysym) {
                   2279:            break;
                   2280:          }
                   2281:        }
                   2282:        if (parent == NULL) {
                   2283:          _macro = &macro->tme_keyboard_macro_active_next;
                   2284:          continue;
                   2285:        }
                   2286:       }
                   2287:       
                   2288:       /* make this macros tree node no longer active: */
                   2289:       *_macro = macro->tme_keyboard_macro_active_next;
                   2290:       macro->tme_keyboard_macro_active_next = NULL;
                   2291:     }
                   2292:     
                   2293:     /* if this macro is not a leaf node, continue: */
                   2294:     if (macro->tme_keyboard_macro_branches != NULL) {
                   2295:       continue;
                   2296:     }
                   2297: 
                   2298:     /* otherwise, this event has either activated or deactivated a
                   2299:        macro.  either do or undo this macro's presses and releases: */
                   2300:     update = (is_press ? 1 : -1);
                   2301:     for (keysym_i = macro->tme_keyboard_macro_length;
                   2302:         keysym_i-- > 0; ) {
                   2303: 
                   2304:       /* get this keysym's state: */
                   2305:       sub_keysym = macro->tme_keyboard_macro_keysyms[keysym_i];
                   2306: 
                   2307:       /* remember if this keysym was pressed in this stage before: */
                   2308:       sub_pressed_old = TME_KEYBOARD_PRESSED_IN2(sub_keysym);
                   2309: 
                   2310:       /* update this keysym's state: */
                   2311:       if (macro->tme_keyboard_macro_press_flags[keysym_i]) {
                   2312:        sub_keysym->tme_keysym_state_in2_pressed += update;
                   2313:       }
                   2314:       else {
                   2315:        sub_keysym->tme_keysym_state_in2_released += update;
                   2316:       }
                   2317: 
                   2318:       /* if this keysym's pressed state in this stage has changed, 
                   2319:         run the next stage, unless this is the keysym that we
                   2320:         were called with, in which case we'll handle this later: */
                   2321:       if (sub_keysym != keysym
                   2322:          && TME_KEYBOARD_PRESSED_IN2(sub_keysym) != sub_pressed_old) {
                   2323:        rc = _tme_keyboard_buffer_out0(buffer, sub_keysym, event_time);
                   2324:        assert (rc == TME_OK);
                   2325:       }
                   2326:     }
                   2327:   }
                   2328: 
                   2329:   /* if this keysym's pressed state in this stage has changed, run
                   2330:      the next stage, otherwise stop processing this event now: */
                   2331:   return ((TME_KEYBOARD_PRESSED_IN2(keysym) != pressed_old)
                   2332:          ? _tme_keyboard_buffer_out0(buffer, keysym, event_time)
                   2333:          : TME_OK);
                   2334: }
                   2335: 
                   2336: /* this is input stage one.  at this point, the input keyboard is
                   2337:    slightly cleaned up - consecutive presses have had a release
                   2338:    inserted in between, releases of unpressed keys have been dropped,
                   2339:    and as many inferred lost events as possible have been generated.
                   2340: 
                   2341:    this stage finishes cleaning up the input keyboard to the point
                   2342:    where macros are useful.  usually, the only keysyms that will have
                   2343:    specific behaviors enforced here will be keysyms that are used like
                   2344:    modifiers in input stage two macros, but that don't behave like
                   2345:    modifiers on the input keyboard (i.e., they autorepeat) and so
                   2346:    aren't good for use in multiple-key macros: */
                   2347: static int
                   2348: _tme_keyboard_buffer_in1(struct tme_keyboard_buffer_int *buffer,
                   2349:                         struct tme_keysym_state *keysym,
                   2350:                         tme_uint32_t event_time)
                   2351: {
                   2352: 
                   2353:   _tme_keyboard_debug(buffer,
                   2354:                      "in1",
                   2355:                      keysym->tme_keysym_state_keysym,
                   2356:                      TME_KEYBOARD_PRESSED_IN0(keysym),
                   2357:                      event_time);
                   2358: 
                   2359:   /* run the keymode stage function: */
                   2360:   return (_tme_keymode_stage(buffer,
                   2361:                             &buffer->tme_keyboard_buffer_int_in1_keymode_stage,
                   2362:                             &keysym->tme_keysym_state_in1_keymode,
                   2363:                             TME_KEYBOARD_PRESSED_IN0(keysym),
                   2364:                             event_time));
                   2365: }
                   2366: 
                   2367: /* this is the bottom half of input stage zero.  at this point, events
                   2368:    inferred by modifier changes have been generated, but otherwise the
                   2369:    input keyboard hasn't been cleaned up.
                   2370: 
                   2371:    this half drops releases of keys that we don't think are pressed,
                   2372:    generates a release in between two consecutive presses, and tracks
                   2373:    the input modifier mask: */
                   2374: static int
                   2375: _tme_keyboard_buffer_in0_bottom(struct tme_keyboard_buffer_int *buffer,
                   2376:                                struct tme_keysym_state *keysym,
                   2377:                                const struct tme_keyboard_event *event)
                   2378: {
                   2379:   struct tme_keysym_state *mod_keysym;
                   2380:   struct tme_keyboard_event event_pseudo;
                   2381:   int modifier, pressed_old;
                   2382:   int rc;
                   2383: 
                   2384:   _tme_keyboard_debug(buffer,
                   2385:                      "in0-bottom",
                   2386:                      keysym->tme_keysym_state_keysym,
                   2387:                      (event->tme_keyboard_event_type
                   2388:                       & TME_KEYBOARD_EVENT_IN0_PRESS_USER),
                   2389:                      event->tme_keyboard_event_time);
                   2390: 
                   2391:   /* NB: event->tme_keyboard_event_modifiers is always the modifiers
                   2392:      *mask from immediately before* the event, i.e., if this event is
                   2393:      *for a modifier keysym, it does not reflect any change the press
                   2394:      *or release of this keysym will cause: */
                   2395: 
                   2396:   /* remember if this keysym was pressed in this stage before: */
                   2397:   pressed_old = TME_KEYBOARD_PRESSED_IN0(keysym);
                   2398: 
                   2399:   /* see if this keysym is attached to any known modifier: */
                   2400:   modifier = (buffer->tme_keyboard_buffer_int_in0_have_modifiers
                   2401:              ? keysym->tme_keysym_state_in0_modifier
                   2402:              : TME_KEYBOARD_MODIFIER_NONE);
                   2403: 
                   2404:   /* dispatch on the event type: */
                   2405:   switch (event->tme_keyboard_event_type) {
                   2406:     
                   2407:     /* an automatic input stage zero press: */
                   2408:   case TME_KEYBOARD_EVENT_IN0_PRESS_AUTO:
                   2409:     /* this keysym must not be pressed at all: */
                   2410:     assert (!pressed_old);
                   2411:     /* FALLTHROUGH */
                   2412:     
                   2413:     /* a user input stage zero press: */
                   2414:   case TME_KEYBOARD_EVENT_IN0_PRESS_USER:
                   2415: 
                   2416:     /* if this keysym was already pressed, inject a release first -
                   2417:        you can't press a key twice without releasing it in between: */
                   2418:     if (pressed_old) {
                   2419: 
                   2420:       /* make the pseudoevent.  assume that the release we dropped
                   2421:         happened as soon as humanly possible after the press, but
                   2422:         never after this new press: */
                   2423:       event_pseudo.tme_keyboard_event_type
                   2424:        = TME_KEYBOARD_IN0_RELEASE_EVENT(keysym->tme_keysym_state_in0_pressed);
                   2425:       event_pseudo.tme_keyboard_event_time
                   2426:        = _tme_keyboard_event_time_diff(keysym->tme_keysym_state_in0_press_time,
                   2427:                                        TME_KEYBOARD_SHORTEST_DOUBLE_MSEC);
                   2428:       if (_tme_keyboard_event_time_subtract(event_pseudo.tme_keyboard_event_time,
                   2429:                                            event->tme_keyboard_event_time) <= 0) {
                   2430:        event_pseudo.tme_keyboard_event_time
                   2431:          = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1);
                   2432:       }
                   2433:       event_pseudo.tme_keyboard_event_modifiers
                   2434:        = buffer->tme_keyboard_buffer_int_in0_modifiers;
                   2435: 
                   2436:       /* recurse with this pseudoevent: */
                   2437:       rc = _tme_keyboard_buffer_in0_bottom(buffer,
                   2438:                                           keysym,
                   2439:                                           &event_pseudo);
                   2440:       assert (rc == TME_OK);
                   2441:     }
                   2442:     
                   2443:     /* this keysym is now pressed: */
                   2444:     keysym->tme_keysym_state_in0_pressed = event->tme_keyboard_event_type;
                   2445:     keysym->tme_keysym_state_in0_press_time = event->tme_keyboard_event_time;
                   2446: 
                   2447:     /* set any modifier in the mask: */
                   2448:     assert (buffer->tme_keyboard_buffer_int_in0_modifiers
                   2449:            == event->tme_keyboard_event_modifiers);
                   2450:     if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
                   2451:       buffer->tme_keyboard_buffer_int_in0_modifiers |= (1 << modifier);
                   2452:     }
                   2453:     break;
                   2454:        
                   2455:     /* an automatic input stage zero release :*/
                   2456:   case TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO:
                   2457:     assert (pressed_old == TME_KEYBOARD_EVENT_IN0_PRESS_AUTO);
                   2458:     /* FALLTHROUGH */
                   2459: 
                   2460:     /* a user input stage zero release: */
                   2461:   case TME_KEYBOARD_EVENT_IN0_RELEASE_USER:
                   2462:       
                   2463:     /* if this keysym wasn't already pressed, stop processing this
                   2464:        event: */
                   2465:     if (!pressed_old) {
                   2466:       return (TME_OK);
                   2467:     }
                   2468: 
                   2469:     /* this keysym is no longer pressed: */
                   2470:     keysym->tme_keysym_state_in0_pressed = FALSE;
                   2471: 
                   2472:     /* if this keysym is attached to a modifier: */
                   2473:     if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
                   2474: 
                   2475:       /* if we can find no keysym attached to this modifier that is
                   2476:         still pressed, clear the modifier in the mask: */
                   2477:       for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier];
                   2478:           mod_keysym != NULL;
                   2479:           mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) {
                   2480:        if (mod_keysym->tme_keysym_state_in0_pressed) {
                   2481:          break;
                   2482:        }
                   2483:       }
                   2484:       if (mod_keysym == NULL) {
                   2485:        buffer->tme_keyboard_buffer_int_in0_modifiers &= ~(1 << modifier);
                   2486:       }
                   2487:     }
                   2488:     break;
                   2489:       
                   2490:   default:
                   2491:     abort();
                   2492:   }
                   2493: 
                   2494:   /* run the next stage: */
                   2495:   return (_tme_keyboard_buffer_in1(buffer,
                   2496:                                   keysym,
                   2497:                                   event->tme_keyboard_event_time));
                   2498: }
                   2499: 
                   2500: /* this is the top half of input stage zero.  this gets raw
                   2501:    events from the input keyboard.  if we get a modifiers mask with
                   2502:    each event, and we know which input keyboard keysyms are attached
                   2503:    to which modifiers, we can often infer presses and releases of
                   2504:    these keysyms when our caller has missed those events.  
                   2505: 
                   2506:    For example, this works well under X11 when the Caps_Lock or
                   2507:    Num_Lock key "locks" and its state changes while our window doesn't
                   2508:    have focus.  When we do regain focus, we don't get press or release
                   2509:    events for those changes, but we can get the current modifiers
                   2510:    mask: */
                   2511: static int
                   2512: _tme_keyboard_buffer_in0(struct tme_keyboard_buffer_int *buffer,
                   2513:                         const struct tme_keyboard_event *event)
                   2514: {
                   2515:   struct tme_keysym_state *keysym, *mod_keysym, *other_keysym;
                   2516:   struct tme_keyboard_event event_pseudo;
                   2517:   int modifier;
                   2518:   tme_keyboard_modifiers_t modifiers, modifiers_set, modifiers_clear;
                   2519:   int rc;
                   2520: 
                   2521:   _tme_keyboard_debug(buffer,
                   2522:                      "in0-top",
                   2523:                      event->tme_keyboard_event_keyval,
                   2524:                      (event->tme_keyboard_event_type
                   2525:                       == TME_KEYBOARD_EVENT_PRESS),
                   2526:                      event->tme_keyboard_event_time);
                   2527: 
                   2528:   assert (event->tme_keyboard_event_time
                   2529:          != TME_KEYBOARD_EVENT_TIME_UNDEF);
                   2530: 
                   2531:   /* look up this keysym: */
                   2532:   keysym
                   2533:     = ((struct tme_keysym_state *)
                   2534:        tme_hash_lookup(buffer->tme_keyboard_buffer_int_keysyms_state,
                   2535:                       (tme_hash_data_t) event->tme_keyboard_event_keyval));
                   2536: 
                   2537: 
                   2538:   /* if input stage zero has modifier information: */
                   2539:   if (buffer->tme_keyboard_buffer_int_in0_have_modifiers) {
                   2540: 
                   2541:     /* NB: event->tme_keyboard_event_modifiers is always the modifiers
                   2542:        mask from immediately *before* the event, i.e., if this event
                   2543:        is for a modifier keysym, it does not reflect any change this
                   2544:        press or release of this keysym will cause to that mask: */
                   2545:     modifiers = event->tme_keyboard_event_modifiers;
                   2546: 
                   2547:     /* get the mask of modifiers that been cleared and set unbeknownst
                   2548:        to us before this event: */
                   2549:     modifiers_clear =
                   2550:       (buffer->tme_keyboard_buffer_int_in0_modifiers
                   2551:        & ~modifiers
                   2552:        & buffer->tme_keyboard_buffer_int_in0_have_modifiers);
                   2553:     modifiers_set =
                   2554:       (modifiers
                   2555:        & ~buffer->tme_keyboard_buffer_int_in0_modifiers
                   2556:        & buffer->tme_keyboard_buffer_int_in0_have_modifiers);
                   2557: 
                   2558:     /* generate the appropriate release events for all keysyms
                   2559:        attached to modifiers that have been cleared: */
                   2560:     if (modifiers_clear != 0) {
                   2561: 
                   2562:       /* loop over the modifiers that need clearing: */
                   2563:       for (modifier = 0;
                   2564:           modifier <= TME_KEYBOARD_MODIFIER_MAX;
                   2565:           modifier++) {
                   2566:        if (!(modifiers_clear & (1 << modifier))) {
                   2567:          continue;
                   2568:        }
                   2569: 
                   2570:        /* release all of the keysyms: */
                   2571:        for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier];
                   2572:             mod_keysym != NULL;
                   2573:             mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) {
                   2574: 
                   2575:          /* ignore this keysym if it isn't pressed: */
                   2576:          if (!mod_keysym->tme_keysym_state_in0_pressed) {
                   2577:            continue;
                   2578:          }
                   2579: 
                   2580:          /* make the pseudoevent: */
                   2581:          event_pseudo.tme_keyboard_event_type
                   2582:            = TME_KEYBOARD_IN0_RELEASE_EVENT(mod_keysym->tme_keysym_state_in0_pressed);
                   2583:          event_pseudo.tme_keyboard_event_time
                   2584:            = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1);
                   2585:          event_pseudo.tme_keyboard_event_modifiers
                   2586:            = buffer->tme_keyboard_buffer_int_in0_modifiers;
                   2587: 
                   2588:          /* call the bottom half with this pseudoevent: */
                   2589:          rc = _tme_keyboard_buffer_in0_bottom(buffer,
                   2590:                                               mod_keysym,
                   2591:                                               &event_pseudo);
                   2592:          assert (rc == TME_OK);
                   2593:        }
                   2594:       }
                   2595: 
                   2596:       /* all of the modifiers that needed clearing must now be clear: */
                   2597:       assert ((buffer->tme_keyboard_buffer_int_in0_modifiers
                   2598:               & modifiers_clear) == 0);
                   2599:     }
                   2600: 
                   2601:     /* generate a press event for a single keysym attached to each
                   2602:        modifier that has been set: */
                   2603:     if (modifiers_set != 0) {
                   2604: 
                   2605:       /* loop over the modifiers that need setting: */
                   2606:       for (modifier = 0;
                   2607:           modifier <= TME_KEYBOARD_MODIFIER_MAX;
                   2608:           modifier++) {
                   2609:        if (!(modifiers_set & (1 << modifier))) {
                   2610:          continue;
                   2611:        }
                   2612: 
                   2613:        /* press the first keysym attached to this modifier: */
                   2614:        mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier];
                   2615:        assert (mod_keysym != NULL);
                   2616:        
                   2617:        /* make the pseudoevent: */
                   2618:        event_pseudo.tme_keyboard_event_type
                   2619:          = TME_KEYBOARD_EVENT_IN0_PRESS_AUTO;
                   2620:        event_pseudo.tme_keyboard_event_time
                   2621:          = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1);
                   2622:        event_pseudo.tme_keyboard_event_modifiers
                   2623:          = buffer->tme_keyboard_buffer_int_in0_modifiers;
                   2624: 
                   2625:        /* call the bottom half with this pseudoevent: */
                   2626:        rc = _tme_keyboard_buffer_in0_bottom(buffer,
                   2627:                                             mod_keysym,
                   2628:                                             &event_pseudo);
                   2629:        assert (rc == TME_OK);
                   2630:       }
                   2631: 
                   2632:       /* all of the modifiers that needed setting must now be set: */
                   2633:       assert ((buffer->tme_keyboard_buffer_int_in0_modifiers
                   2634:               & modifiers_set) == modifiers_set);
                   2635:     }
                   2636: 
                   2637:     /* if the keysym in the event is undefined, we don't need to
                   2638:        process this event any more.  events with an undefined keysym
                   2639:        can be used whenever the caller thinks that it has dropped
                   2640:        keyboard events, and wants to do what it can to update the
                   2641:        keyboard, and it can at least get the true current modifiers
                   2642:        mask.  this is common under X11: */
                   2643:     if (event->tme_keyboard_event_keyval
                   2644:        == TME_KEYBOARD_KEYVAL_UNDEF) {
                   2645:       return (TME_OK);
                   2646:     }
                   2647:   }
                   2648: 
                   2649:   /* we must have a defined keysym: */
                   2650:   assert (event->tme_keyboard_event_keyval
                   2651:          != TME_KEYBOARD_KEYVAL_UNDEF);
                   2652: 
                   2653:   /* if we have no state for the keysym in this event, this keysym
                   2654:      isn't controlled by any of the input stages: */
                   2655:   if (keysym == NULL) {
                   2656: 
                   2657:     /* if there are output stages, having no state for this keysym
                   2658:        means that this keysym doesn't exist on the output keyboard.
                   2659:        we can stop processing this event now: */
                   2660:     if (!buffer->tme_keyboard_buffer_int_out0_passthrough) {
                   2661:       return (TME_OK);
                   2662:     }
                   2663: 
                   2664:     /* otherwise, simply buffer this event: */
                   2665:     event_pseudo = *event;
                   2666:     switch (event->tme_keyboard_event_type) {
                   2667:     case TME_KEYBOARD_EVENT_IN0_PRESS_USER:
                   2668:     case TME_KEYBOARD_EVENT_IN0_PRESS_AUTO:
                   2669:       event_pseudo.tme_keyboard_event_type = TME_KEYBOARD_EVENT_PRESS;
                   2670:       break;
                   2671:     case TME_KEYBOARD_EVENT_IN0_RELEASE_USER:
                   2672:     case TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO:
                   2673:       event_pseudo.tme_keyboard_event_type = TME_KEYBOARD_EVENT_RELEASE;
                   2674:       break;
                   2675:     default: abort();
                   2676:     }
                   2677:     event_pseudo.tme_keyboard_event_modifiers = 0;
                   2678:     return (_tme_keyboard_buffer_copyin(buffer, &event_pseudo));
                   2679:   }
                   2680: 
                   2681:   /* if this event has a keycode: */
                   2682:   if (event->tme_keyboard_event_keycode
                   2683:       != TME_KEYBOARD_KEYVAL_UNDEF) {
                   2684: 
                   2685:     /* see if this keycode is already pressed in this stage: */
                   2686:     other_keysym
                   2687:       = ((struct tme_keysym_state *)
                   2688:         tme_hash_lookup(buffer->tme_keyboard_buffer_int_in0_keycodes,
                   2689:                         (tme_hash_data_t) event->tme_keyboard_event_keycode));
                   2690: 
                   2691:     /* if this keycode is already pressed by another keysym in this
                   2692:        stage, release the other keysym first: */
                   2693:     if (other_keysym != NULL
                   2694:        && other_keysym != keysym
                   2695:        && TME_KEYBOARD_PRESSED_IN0(other_keysym)) {
                   2696:       
                   2697:       /* make the pseudoevent: */
                   2698:       event_pseudo.tme_keyboard_event_type
                   2699:        = TME_KEYBOARD_IN0_RELEASE_EVENT(other_keysym->tme_keysym_state_in0_pressed);
                   2700:       event_pseudo.tme_keyboard_event_time
                   2701:        = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1);
                   2702:       event_pseudo.tme_keyboard_event_modifiers
                   2703:        = buffer->tme_keyboard_buffer_int_in0_modifiers;
                   2704:       
                   2705:       /* call the bottom half with this pseudoevent: */
                   2706:       rc = _tme_keyboard_buffer_in0_bottom(buffer,
                   2707:                                           other_keysym,
                   2708:                                           &event_pseudo);
                   2709:       assert (rc == TME_OK);
                   2710:     }
                   2711: 
                   2712:     /* if this is a press, remember that this keycode is pressed,
                   2713:        else forget that this keycode is pressed: */
                   2714:     if (event->tme_keyboard_event_type == TME_KEYBOARD_EVENT_PRESS) {
                   2715:       tme_hash_insert(buffer->tme_keyboard_buffer_int_in0_keycodes,
                   2716:                      (tme_hash_data_t) event->tme_keyboard_event_keycode,
                   2717:                      (tme_hash_data_t) keysym);
                   2718:     }
                   2719:     else {
                   2720:       tme_hash_remove(buffer->tme_keyboard_buffer_int_in0_keycodes,
                   2721:                      (tme_hash_data_t) event->tme_keyboard_event_keycode);
                   2722:     }
                   2723:   }
                   2724: 
                   2725:   /* call the bottom half with this event: */
                   2726:   return (_tme_keyboard_buffer_in0_bottom(buffer,
                   2727:                                          keysym,
                   2728:                                          event));
                   2729: }
                   2730: 
                   2731: /* this copies a keyboard event into the buffer: */
                   2732: int
                   2733: tme_keyboard_buffer_copyin(struct tme_keyboard_buffer *_buffer,
                   2734:                           const struct tme_keyboard_event *event)
                   2735: {
                   2736:   struct tme_keyboard_buffer_int *buffer;
                   2737: 
                   2738:   /* recover our data structure: */
                   2739:   buffer = (struct tme_keyboard_buffer_int *) _buffer;
                   2740: 
                   2741:   /* run input stage zero: */
                   2742:   return (_tme_keyboard_buffer_in0(buffer, event));
                   2743: }
                   2744: 
                   2745: /* this copies a keyval out of a keyboard buffer: */
                   2746: int
                   2747: tme_keyboard_buffer_copyout(struct tme_keyboard_buffer *buffer,
                   2748:                            struct tme_keyboard_event *event)
                   2749: {
                   2750:   unsigned int buffer_tail, buffer_size_mask;
                   2751: 
                   2752:   buffer_tail = buffer->tme_keyboard_buffer_tail;
                   2753:   buffer_size_mask = buffer->tme_keyboard_buffer_size - 1;
                   2754: 
                   2755:   /* if the buffer is empty: */
                   2756:   if (buffer_tail == buffer->tme_keyboard_buffer_head) {
                   2757:     return (EAGAIN);
                   2758:   }
                   2759: 
                   2760:   /* get an event out of the buffer: */
                   2761:   *event = buffer->tme_keyboard_buffer_events[buffer_tail];
                   2762: 
                   2763:   /* advance the tail: */
                   2764:   buffer->tme_keyboard_buffer_tail = (buffer_tail + 1) & buffer_size_mask;
                   2765:   return (TME_OK);
                   2766: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.