|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.