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

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

unix.superglobalmegacorp.com

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