Annotation of driverkit/libDriver/Kernel/KeyMap.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: /*     Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
        !            25:  *
        !            26:  * KeyMap.m - Generic keymap string parser and keycode translator.
        !            27:  *
        !            28:  * HISTORY
        !            29:  * 19 June 1992    Mike Paquette at NeXT
        !            30:  *      Created. 
        !            31:  * 5  Aug 1993   Erik Kay at NeXT
        !            32:  *     minor API cleanup
        !            33:  * 11 Nov 1993   Erik Kay at NeXT
        !            34:  *     fix to allow prevent long sequences from overflowing the event queue
        !            35:  */
        !            36: 
        !            37: #import <machkit/NXLock.h>
        !            38: #import <bsd/dev/event.h>
        !            39: #import <driverkit/KeyMap.h>
        !            40: 
        !            41: @implementation KeyMap: Object
        !            42: 
        !            43: 
        !            44: /*
        !            45:  * Common KeyMap initialization
        !            46:  */
        !            47: - initFromKeyMapping   :(const unsigned char *)mapping
        !            48:                length  :(int)len
        !            49:                canFree :(BOOL)canFree
        !            50: {
        !            51:        [super init];
        !            52:        
        !            53:        if ( keyMappingLock == nil )
        !            54:            keyMappingLock = [NXLock new];
        !            55:        
        !            56:        if ( [self setKeyMapping:mapping length:len canFree:canFree] == nil )
        !            57:                return [self free];
        !            58:        return self;
        !            59: }
        !            60: 
        !            61: /*
        !            62:  * Load a new keymapping.  Returns nil if the map is invalid.
        !            63:  */
        !            64: - setKeyMapping        :(const unsigned char *)mapping
        !            65:                length  :(int)len
        !            66:                canFree :(BOOL)canFree
        !            67: {
        !            68:        NXParsedKeyMapping newMapping;
        !            69: 
        !            70:        if ([self _parseKeyMapping:mapping length:len into:&newMapping] == nil)
        !            71:                return nil;
        !            72: 
        !            73:        [keyMappingLock lock];
        !            74:        if (    curMapping.mapping != (unsigned char *)NULL
        !            75:            &&  canFreeMapping == YES )
        !            76:        {
        !            77:                IOFree( curMapping.mapping, curMapping.mappingLen );
        !            78:        }
        !            79:        bcopy( &newMapping, &curMapping, sizeof curMapping );
        !            80:        canFreeMapping = canFree;
        !            81:        [keyMappingLock unlock];
        !            82:        return self;
        !            83: }
        !            84: 
        !            85: - (const unsigned char *)keyMapping:(int *)len
        !            86: {
        !            87:        if ( len != (int *)0 )
        !            88:                *len = curMapping.mappingLen;
        !            89:        return (const unsigned char *)curMapping.mapping;
        !            90: }
        !            91: 
        !            92: - (int)keyMappingLength
        !            93: {
        !            94:        return curMapping.mappingLen;
        !            95: }
        !            96: 
        !            97: - free
        !            98: {
        !            99:        id lock;
        !           100:        [keyMappingLock lock];
        !           101:        lock = keyMappingLock;
        !           102:        keyMappingLock = nil;
        !           103:        if (    curMapping.mapping != (unsigned char *)NULL
        !           104:            &&  canFreeMapping == YES )
        !           105:        {
        !           106:                IOFree( curMapping.mapping, curMapping.mappingLen );
        !           107:                curMapping.mapping = (unsigned char *)NULL;
        !           108:        }
        !           109:        [lock unlock];
        !           110:        [lock free];
        !           111:        return [super free];
        !           112: }
        !           113: 
        !           114: - setDelegate:(id)newDelegate
        !           115: {
        !           116:        if ( [newDelegate conformsTo:@protocol(KeyMapDelegate)] )
        !           117:                delegate = newDelegate;
        !           118:        else
        !           119:                IOLog( "KeyMap setDelegate: new delegate [%s] does not "
        !           120:                        "implement KeyMapDelegate protocol.\n",
        !           121:                        object_getClassName(newDelegate) );
        !           122:        return self;
        !           123: }
        !           124: 
        !           125: - delegate
        !           126: {
        !           127:        return delegate;
        !           128: }
        !           129: 
        !           130: //
        !           131: // Perform the mapping of 'key' moving in the specified direction
        !           132: // into events.
        !           133: //
        !           134: // On entry, the _kbdListLock should be held.
        !           135: //
        !           136: - doKeyboardEvent:(unsigned)key
        !           137:        direction:(BOOL)down
        !           138:        keyBits :(kbdBitVector)keyBits
        !           139: {
        !           140:     unsigned char thisBits;
        !           141: 
        !           142:     [keyMappingLock lock];
        !           143:     if ( curMapping.mapping == (unsigned char *)NULL )
        !           144:     {
        !           145:        [keyMappingLock unlock];
        !           146:        return self;            // No map set up yet
        !           147:     }
        !           148:     /* Do mod bit update and char generation in useful order */
        !           149:     thisBits = curMapping.keyBits[key];
        !           150:     if ( down == YES )
        !           151:     {
        !           152:        EVK_KEYDOWN( key, keyBits );
        !           153:        if (thisBits & NX_MODMASK)
        !           154:                [self _doModCalc:key keyBits:keyBits];
        !           155:        if (thisBits & NX_CHARGENMASK)
        !           156:                [self _doCharGen:key direction:down];
        !           157:     }
        !           158:     else
        !           159:     {
        !           160:        EVK_KEYUP( key, keyBits );
        !           161:        if (thisBits & NX_CHARGENMASK)
        !           162:                [self _doCharGen:key direction:down];
        !           163:        if (thisBits & NX_MODMASK)
        !           164:                [self _doModCalc:key keyBits:keyBits];
        !           165:     }
        !           166:     [keyMappingLock unlock];
        !           167: 
        !           168:     return self;
        !           169: }
        !           170: 
        !           171: 
        !           172: //
        !           173: // Support goop for parseKeyMapping.  These routines are
        !           174: // used to walk through the keymapping string.  The string
        !           175: // may be composed of bytes or shorts.  If using shorts, it
        !           176: // MUST always be aligned to use short boundries.
        !           177: //
        !           178: typedef struct _NewMappingData {
        !           179:     unsigned const char *bp;
        !           180:     unsigned const char *endPtr;
        !           181:     int shorts;
        !           182: } NewMappingData;
        !           183: 
        !           184: static unsigned int NextNum(NewMappingData *nmd)
        !           185: {
        !           186:     if (nmd->bp >= nmd->endPtr)
        !           187:        return(0);
        !           188:     if (nmd->shorts)
        !           189:        return(*((unsigned short *)nmd->bp)++);
        !           190:     else
        !           191:        return(*((unsigned char *)nmd->bp)++);
        !           192: }
        !           193: 
        !           194: //
        !           195: // perform the actual parsing operation on a keymap.
        !           196: // Returns self, or nil on failure.
        !           197: //
        !           198: - _parseKeyMapping:(const unsigned char *)mapping
        !           199:        length:(int)mappingLen
        !           200:        into:(NXParsedKeyMapping *)newMapping
        !           201: {
        !           202:        NewMappingData nmd;
        !           203:        int i, j, k, l, n;
        !           204:        unsigned int m;
        !           205:        int keyMask, numMods;
        !           206:        int maxSeqNum = -1;
        !           207:  
        !           208:        /* Initialize the new map. */
        !           209:        bzero( newMapping, sizeof (NXParsedKeyMapping) );
        !           210:        newMapping->maxMod = -1;
        !           211:        newMapping->numDefs = -1;
        !           212:        newMapping->numSeqs = -1;
        !           213: 
        !           214:        nmd.endPtr = mapping + mappingLen;
        !           215:        nmd.bp = mapping;
        !           216:        nmd.shorts = 1;         // First value, the size, is always a short
        !           217: 
        !           218:        /* Start filling it in with the new data */
        !           219:        newMapping->mapping = (unsigned char *)mapping;
        !           220:        newMapping->mappingLen = mappingLen;
        !           221:        newMapping->shorts = nmd.shorts = NextNum(&nmd);
        !           222: 
        !           223:        /* Walk through the modifier definitions */
        !           224:        numMods = NextNum(&nmd);
        !           225:        for(i=0; i<numMods; i++)
        !           226:        {
        !           227:            /* Get bit number */
        !           228:            if ((j = NextNum(&nmd)) >= NX_NUMMODIFIERS)
        !           229:                return nil;
        !           230: 
        !           231:            /* Check maxMod */
        !           232:            if (j > newMapping->maxMod)
        !           233:                newMapping->maxMod = j;
        !           234: 
        !           235:            /* record position of this def */
        !           236:            newMapping->modDefs[j] = (unsigned char *)nmd.bp;
        !           237: 
        !           238:            /* Loop through each key assigned to this bit */
        !           239:            for(k=0,n = NextNum(&nmd);k<n;k++)
        !           240:            {
        !           241:                /* Check that key code is valid */
        !           242:                if ((l = NextNum(&nmd)) >= NX_NUMKEYCODES)
        !           243:                    return nil;
        !           244:                /* Make sure the key's not already assigned */
        !           245:                if (newMapping->keyBits[l] & NX_MODMASK)
        !           246:                        return nil;
        !           247:                /* Set bit for modifier and which one */
        !           248:                newMapping->keyBits[l] |= NX_MODMASK | (j & NX_WHICHMODMASK);
        !           249:            }
        !           250:        }
        !           251: 
        !           252:        /* Walk through each key definition */
        !           253:        newMapping->numDefs = NextNum(&nmd);
        !           254:        n = newMapping->numDefs;
        !           255:        for( i=0; i < NX_NUMKEYCODES; i++)
        !           256:        {
        !           257:            if (i < n)
        !           258:            {
        !           259:                newMapping->keyDefs[i] = (unsigned char *)nmd.bp;
        !           260:                if ((keyMask = NextNum(&nmd)) != (nmd.shorts ? 0xFFFF: 0x00FF))
        !           261:                {
        !           262:                    /* Set char gen bit for this guy: not a no-op */
        !           263:                    newMapping->keyBits[i] |= NX_CHARGENMASK;
        !           264:                    /* Check key defs to find max sequence number */
        !           265:                    for(j=0, k=1; j<=newMapping->maxMod; j++, keyMask>>=1)
        !           266:                    {
        !           267:                            if (keyMask & 0x01)
        !           268:                                k*= 2;
        !           269:                    }
        !           270:                    for(j=0; j<k; j++)
        !           271:                    {
        !           272:                        m = NextNum(&nmd);
        !           273:                        l = NextNum(&nmd);
        !           274:                        if (m == (nmd.shorts ? 0xFFFF: 0x00FF))
        !           275:                            if (((int)l) > maxSeqNum)
        !           276:                                maxSeqNum = l;  /* Update expected # of seqs */
        !           277:                    }
        !           278:                }
        !           279:                else /* unused code within active range */
        !           280:                    newMapping->keyDefs[i] = NULL;
        !           281:            }
        !           282:            else /* Unused code past active range */
        !           283:            {
        !           284:                newMapping->keyDefs[i] = NULL;
        !           285:            }
        !           286:        }
        !           287:        /* Walk through sequence defs */
        !           288:        newMapping->numSeqs = NextNum(&nmd);
        !           289:        /* If the map calls more sequences than are declared, bail out */
        !           290:        if (newMapping->numSeqs <= maxSeqNum)
        !           291:            return nil;
        !           292: 
        !           293:        /* Walk past all sequences */
        !           294:        for(i = 0; i < newMapping->numSeqs; i++)
        !           295:        {
        !           296:            newMapping->seqDefs[i] = (unsigned char *)nmd.bp;
        !           297:            /* Walk thru entries in a seq. */
        !           298:            for(j=0, l=NextNum(&nmd); j<l; j++)
        !           299:            {
        !           300:                NextNum(&nmd);
        !           301:                NextNum(&nmd);
        !           302:            }
        !           303:        }
        !           304:        /* Install Special device keys.  These override default values. */
        !           305:        numMods = NextNum(&nmd);        /* Zero on old style keymaps */
        !           306:        if ( numMods > NX_NUMSPECIALKEYS )
        !           307:            return nil;
        !           308:        if ( numMods )
        !           309:        {
        !           310:            for ( i = 0; i < NX_NUMSPECIALKEYS; ++i )
        !           311:                newMapping->specialKeys[i] = NX_NOSPECIALKEY;
        !           312:            for ( i = 0; i < numMods; ++i )
        !           313:            {
        !           314:                j = NextNum(&nmd);      /* Which modifier key? */
        !           315:                l = NextNum(&nmd);      /* Scancode for modifier key */
        !           316:                if ( j >= NX_NUMSPECIALKEYS )
        !           317:                    return nil;
        !           318:                newMapping->specialKeys[j] = l;
        !           319:            }
        !           320:        }
        !           321:        else  /* No special keys defs implies an old style keymap */
        !           322:        {
        !           323:                return nil;     /* Old style keymaps are guaranteed to do */
        !           324:                                /* the wrong thing on ADB keyboards */
        !           325:        }
        !           326:        /* Install bits for Special device keys */
        !           327:        for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++)
        !           328:        {
        !           329:            if ( newMapping->specialKeys[i] != NX_NOSPECIALKEY )
        !           330:            {
        !           331:                newMapping->keyBits[newMapping->specialKeys[i]] |=
        !           332:                    (NX_CHARGENMASK | NX_SPECIALKEYMASK);
        !           333:            }
        !           334:        }
        !           335:     
        !           336:        return self;
        !           337: }
        !           338: 
        !           339: 
        !           340: #undef NEXTNUM
        !           341: #define NEXTNUM() (shorts ?    *((short *)mapping)++ : \
        !           342:                                *((unsigned char *)mapping)++ )
        !           343: //
        !           344: // Look up in the keymapping each key associated with the modifier bit.
        !           345: // Look in the device state to see if that key is down.
        !           346: // Return 1 if a key for modifier 'bit' is down.  Return 0 if none is down
        !           347: //
        !           348: static inline int IsModifierDown(NXParsedKeyMapping *curMapping,
        !           349:                                kbdBitVector keyBits,
        !           350:                                int bit )
        !           351: {
        !           352:     int i, n;
        !           353:     char *mapping;
        !           354:     unsigned key;
        !           355:     short shorts = curMapping->shorts;
        !           356: 
        !           357:     if ( (mapping = curMapping->modDefs[bit]) != 0 ) {
        !           358:        for(i=0, n=NEXTNUM(); i<n; i++)
        !           359:        {
        !           360:            key = NEXTNUM();
        !           361:            if ( EVK_IS_KEYDOWN(key, keyBits) )
        !           362:                return 1;
        !           363:        }
        !           364:     }
        !           365:     return 0;
        !           366: }
        !           367: 
        !           368: - (void)_calcModBit    :(int)bit
        !           369:                keyBits :(kbdBitVector)keyBits
        !           370: {
        !           371:        int             bitMask,i,n;
        !           372:        unsigned        myFlags;
        !           373: 
        !           374:        bitMask = 1<<(bit+16);
        !           375: 
        !           376:        /* Initially clear bit, as if key-up */
        !           377:        myFlags = [delegate deviceFlags] & (~bitMask);
        !           378:        /* Set bit if any associated keys are down */
        !           379:        if ( IsModifierDown( &curMapping, keyBits, bit ) )
        !           380:                myFlags |= bitMask;
        !           381: 
        !           382:        /* If this was the shift bit... */
        !           383:        if (bit == NX_MODIFIERKEY_SHIFT)
        !           384:        {
        !           385:            /*
        !           386:             * And CMD is already down, and we don't have a Caps Lock key,
        !           387:             * and we don't have a NX_KEYTYPE_CAPS_LOCK special key...
        !           388:             * We check both the CAPS LOCK modifier and the CAPS LOCK
        !           389:             * special key since only one or the other might be in use.
        !           390:             * We use the CAPS LOCK special key by itself for keyboards on
        !           391:             * which the CAPS LOCK key does not lock.
        !           392:             */
        !           393:            if (   (myFlags & NX_COMMANDMASK) != 0
        !           394:                && !curMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]
        !           395:                && (curMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] == 
        !           396:                    NX_NOSPECIALKEY) )
        !           397:            {
        !           398:                /*
        !           399:                 * On the SHIFT key down, clear the active char key if any,
        !           400:                 * and on SHIFT key up, if no char key has been pressed,
        !           401:                 * toggle the state of the Alpha Lock. This lets us do upper-
        !           402:                 * case command keys without toggling Alpha Lock.
        !           403:                 */
        !           404:                if ( myFlags & bitMask ) // SHIFT key down event
        !           405:                    [delegate setCharKeyActive:NO];
        !           406:                else if ( [delegate charKeyActive] == NO )
        !           407:                    [delegate setAlphaLock:([delegate alphaLock] == NO)];
        !           408:            }
        !           409:            /* Set NX_ALPHASHIFTMASK based on alphaLock OR shift active */
        !           410:            myFlags = (myFlags & ~NX_ALPHASHIFTMASK)
        !           411:                        | (([delegate alphaLock]==YES)<<16)
        !           412:                        | ((myFlags & NX_SHIFTMASK)>>1);
        !           413:        }
        !           414:        else if ( bit == NX_MODIFIERKEY_ALPHALOCK ) /* Caps Lock key */
        !           415:            [delegate setAlphaLock:(myFlags & NX_ALPHASHIFTMASK) ? YES : NO];
        !           416: 
        !           417:        [delegate setDeviceFlags:myFlags];
        !           418: }
        !           419: 
        !           420: 
        !           421: //
        !           422: // Perform flag state update and generate flags changed events for this key.
        !           423: //
        !           424: - (void)_doModCalc:(int)key keyBits:(kbdBitVector)keyBits
        !           425: {
        !           426:     int thisBits;
        !           427:     thisBits = curMapping.keyBits[key];
        !           428:     if (thisBits & NX_MODMASK)
        !           429:     {
        !           430:        [self _calcModBit:(thisBits & NX_WHICHMODMASK)
        !           431:                keyBits:keyBits];
        !           432:        /* The driver generates flags-changed events only when there is
        !           433:           no key-down or key-up event generated */
        !           434:        if (!(thisBits & NX_CHARGENMASK))
        !           435:        {
        !           436:                /* Post the flags-changed event */
        !           437:                [delegate keyboardEvent:NX_FLAGSCHANGED
        !           438:                        flags:[delegate eventFlags]
        !           439:                        keyCode:key
        !           440:                        charCode:0
        !           441:                        charSet:0
        !           442:                        originalCharCode:0
        !           443:                        originalCharSet:0];
        !           444:        }
        !           445:        else    /* Update, but don't generate an event */
        !           446:                [delegate updateEventFlags:[delegate eventFlags]];
        !           447:     }
        !           448: }
        !           449: 
        !           450: 
        !           451: #undef NEXTNUM
        !           452: #define NEXTNUM() (shorts ?    *((short *)mapping)++ : \
        !           453:                                *((unsigned char *)mapping)++ )
        !           454: 
        !           455: //
        !           456: // Perform character event generation for this key
        !           457: //
        !           458: - (void)_doCharGen:(int)keyCode
        !           459:                direction:(BOOL)down
        !           460: {
        !           461:     int        i, j, n, eventType, adjust, thisMask, shorts, modifiers, origflags;
        !           462:     unsigned charSet, origCharSet;
        !           463:     unsigned charCode, origCharCode;
        !           464:     unsigned char *mapping;
        !           465:     unsigned eventFlags;
        !           466: 
        !           467:     [delegate setCharKeyActive:YES];   // A character generating key is active
        !           468: 
        !           469:     eventType = (down == YES) ? NX_KEYDOWN : NX_KEYUP;
        !           470:     eventFlags = [delegate eventFlags];
        !           471:     modifiers = eventFlags >> 16;      // machine independent mod bits
        !           472: 
        !           473:     /* Get this key's key mapping */
        !           474:     shorts = curMapping.shorts;
        !           475:     mapping = curMapping.keyDefs[keyCode];
        !           476: 
        !           477:     if ( mapping )
        !           478:     {
        !           479:        /* Build offset for this key */
        !           480:        thisMask = NEXTNUM();
        !           481:        if (thisMask && modifiers)
        !           482:        {
        !           483:            adjust = (shorts ? sizeof(short) : sizeof(char))*2;
        !           484:            for( i = 0; i <= curMapping.maxMod; ++i)
        !           485:            {
        !           486:                if (thisMask & 0x01)
        !           487:                {
        !           488:                    if (modifiers & 0x01)
        !           489:                        mapping += adjust;
        !           490:                    adjust *= 2;
        !           491:                }
        !           492:                thisMask >>= 1;
        !           493:                modifiers >>= 1;
        !           494:            }
        !           495:        }
        !           496:        charSet = NEXTNUM();
        !           497:        charCode = NEXTNUM();
        !           498:        
        !           499:        /* construct "unmodified" character */
        !           500:        mapping = curMapping.keyDefs[keyCode];
        !           501:        modifiers = (eventFlags & (NX_ALPHASHIFTMASK | NX_SHIFTMASK)) >> 16;
        !           502: 
        !           503:        thisMask = NEXTNUM();
        !           504:        if (thisMask && modifiers)
        !           505:        {
        !           506:            adjust = (shorts ? sizeof(short) : sizeof(char)) * 2;
        !           507:            for ( i = 0; i <= curMapping.maxMod; ++i)
        !           508:            {
        !           509:                if (thisMask & 0x01)
        !           510:                {
        !           511:                    if (modifiers & 0x01)
        !           512:                        mapping += adjust;
        !           513:                    adjust *= 2;
        !           514:                }
        !           515:                thisMask >>= 1;
        !           516:                modifiers >>= 1;
        !           517:            }
        !           518:        }
        !           519:        origCharSet = NEXTNUM();
        !           520:        origCharCode = NEXTNUM();
        !           521:        
        !           522:        if (charSet == (shorts ? 0xFFFF : 0x00FF))
        !           523:        {
        !           524:            // Process as a character sequence
        !           525:            // charCode holds the sequence number
        !           526:            mapping = curMapping.seqDefs[charCode];
        !           527:            
        !           528:            origflags = eventFlags;
        !           529:            for(i=0,n=NEXTNUM();i<n;i++)
        !           530:            {
        !           531:                // every 10 characters, give the windowserver a chance to
        !           532:                // actually read the events out of the event queue
        !           533:                if ((i % 10) == 9)
        !           534:                    (void) thread_block();
        !           535:                if ( (charSet = NEXTNUM()) == 0xFF ) /* metakey */
        !           536:                {
        !           537:                    if ( down == YES )  /* down or repeat */
        !           538:                    {
        !           539:                        eventFlags |= (1 << (NEXTNUM() + 16));
        !           540:                        [delegate keyboardEvent:NX_FLAGSCHANGED
        !           541:                                flags:[delegate deviceFlags]
        !           542:                                keyCode:keyCode
        !           543:                                charCode:0
        !           544:                                charSet:0
        !           545:                                originalCharCode:0
        !           546:                                originalCharSet:0];
        !           547:                    }
        !           548:                    else
        !           549:                        NEXTNUM();      /* Skip over value */
        !           550:                }
        !           551:                else
        !           552:                {
        !           553:                    charCode = NEXTNUM();
        !           554:                    [delegate   keyboardEvent:eventType
        !           555:                                flags:eventFlags
        !           556:                                keyCode:keyCode
        !           557:                                charCode:charCode
        !           558:                                charSet:charSet
        !           559:                                originalCharCode:charCode
        !           560:                                originalCharSet:charSet];
        !           561:                }
        !           562:            }
        !           563:            /* Done with macro.  Restore the flags if needed. */
        !           564:            if ( eventFlags != origflags )
        !           565:            {
        !           566:                [delegate keyboardEvent:NX_FLAGSCHANGED
        !           567:                        flags:[delegate deviceFlags]
        !           568:                        keyCode:keyCode
        !           569:                        charCode:0
        !           570:                        charSet:0
        !           571:                        originalCharCode:0
        !           572:                        originalCharSet:0];
        !           573:                eventFlags = origflags;
        !           574:            }
        !           575:        }
        !           576:        else    /* A simple character generating key */
        !           577:        {
        !           578:            [delegate   keyboardEvent:eventType
        !           579:                        flags:eventFlags
        !           580:                        keyCode:keyCode
        !           581:                        charCode:charCode
        !           582:                        charSet:charSet
        !           583:                        originalCharCode:origCharCode
        !           584:                        originalCharSet:origCharSet];
        !           585:        }
        !           586:     } /* if (mapping) */
        !           587:     
        !           588:     /*
        !           589:      * Check for a device control key: note that they always have CHARGEN
        !           590:      * bit set
        !           591:      */
        !           592:     if (curMapping.keyBits[keyCode] & NX_SPECIALKEYMASK)
        !           593:     {
        !           594:        for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++)
        !           595:        {
        !           596:            if ( keyCode == curMapping.specialKeys[i] )
        !           597:            {
        !           598:                [delegate keyboardSpecialEvent:eventType
        !           599:                                flags:eventFlags
        !           600:                                keyCode:keyCode
        !           601:                                specialty:i];
        !           602:                /*
        !           603:                 * Special keys hack for letting an arbitrary (non-locking)
        !           604:                 * key act as a CAPS-LOCK key.  If a special CAPS LOCK key
        !           605:                 * is designated, and there is no key designated for the 
        !           606:                 * AlphaLock function, then we'll let the special key toggle
        !           607:                 * the AlphaLock state.
        !           608:                 */
        !           609:                if (   i == NX_KEYTYPE_CAPS_LOCK
        !           610:                    && !curMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]
        !           611:                    && down == YES )
        !           612:                {
        !           613:                    unsigned myFlags = [delegate deviceFlags];
        !           614:                    BOOL alphaLock = ([delegate alphaLock] == NO);
        !           615:                    // Set delegate's alphaLock state
        !           616:                    [delegate setAlphaLock:alphaLock];
        !           617:                    // Update the delegate's flags
        !           618:                    if ( alphaLock )
        !           619:                        myFlags |= NX_ALPHASHIFTMASK;
        !           620:                    else
        !           621:                        myFlags &= ~NX_ALPHASHIFTMASK;
        !           622:                    [delegate setDeviceFlags:myFlags];
        !           623:                    [delegate keyboardEvent:NX_FLAGSCHANGED
        !           624:                            flags:myFlags
        !           625:                            keyCode:keyCode
        !           626:                            charCode:0
        !           627:                            charSet:0
        !           628:                            originalCharCode:0
        !           629:                            originalCharSet:0];
        !           630:                } 
        !           631:                break;
        !           632:            }
        !           633:        }
        !           634:     }
        !           635: }
        !           636: 
        !           637: @end
        !           638: 

unix.superglobalmegacorp.com

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