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

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

unix.superglobalmegacorp.com

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