KeyMappingImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Christian Jacobi, February 13, 1992 11:37 am PST
Christian Jacobi, February 19, 1992 9:49 am PST
DIRECTORY CardTab, KeyMapping, KeyMappingPrivate, KeyMappingTypes, KeyTypes;
KeyMappingImpl: CEDAR MONITOR
IMPORTS CardTab
EXPORTS KeyMapping, KeyMappingTypes ~
BEGIN OPEN KeyMapping;
MappingRep: PUBLIC TYPE = KeyMappingPrivate.MappingRep;
CountKeySyms: PUBLIC PROC [mapping: Mapping, keyCode: KeyCode] RETURNS [count: NAT ¬ 0] = {
IF mapping#NIL AND keyCode<=mapping.maxCode THEN {
keySyms: KeySyms ~ mapping.keyTable[keyCode];
IF keySyms#NIL THEN RETURN [keySyms.n]
};
};
GetKeySym: PUBLIC PROC [mapping: Mapping, keyCode: KeyCode, i: NAT] RETURNS [keySym: KeySym ¬ [0]] = {
IF mapping#NIL AND keyCode<=mapping.maxCode THEN {
keySyms: KeySyms ~ mapping.keyTable[keyCode];
IF keySyms#NIL AND i<keySyms.n THEN RETURN [keySyms[i]]
};
};
noKeySyms: KeySyms ~ NEW[KeySymsRep[0]];
GetKeySyms: PUBLIC PROC [mapping: Mapping, keyCode: KeyCode] RETURNS [keySyms: KeySyms] = {
IF mapping#NIL AND keyCode<=mapping.maxCode THEN {
keySyms ¬ mapping.keyTable[keyCode];
IF keySyms#NIL THEN RETURN [keySyms]
};
RETURN [noKeySyms]
};
noKeyCodes: KeyCodes ~ NEW[KeyCodesRep[0]];
KeyCodesFromKeySym: PUBLIC PROC [mapping: Mapping, keySym: KeySym] RETURNS [keyCodes: KeyCodes] = {
val: CardTab.Val;
found: BOOL ¬ FALSE;
IF mapping#NIL THEN {
IF mapping.inverseKeyTable=NIL THEN ComputeInverse[mapping];
[found, val] ¬ CardTab.Fetch[mapping.inverseKeyTable, keySym];
IF found THEN RETURN [ NARROW[val] ];
};
RETURN [noKeyCodes];
};
WalkKeySyms: PUBLIC PROC [mapping: Mapping, walkProc: WalkKeySymsProc] RETURNS [aborted: BOOL ¬ FALSE] = {
ForEachKeySym: CardTab.EachPairAction = {
keySym: KeySym ~ LOOPHOLE[key];
IF walkProc[keySym] THEN RETURN[TRUE];
};
IF mapping#NIL THEN {
IF mapping.inverseKeyTable=NIL THEN ComputeInverse[mapping];
aborted ¬ CardTab.Pairs[mapping.inverseKeyTable, ForEachKeySym];
};
};
NewMapping: PUBLIC PROC [keyTable: KeyTable, maxCode: KeyCode ¬ KeyCode.LAST] RETURNS [mapping: Mapping] = {
mapping ¬ NEW[MappingRep ¬ [
maxCode: maxCode,
keyTable: keyTable,
inverseKeyTable: NIL
]];
};
ComputeInverse: PROC [mapping: Mapping] = {
inverse: CardTab.Ref ~ CardTab.Create[ORD[mapping.maxCode]*2+1];
firstSym, thisSym: KeySym;
AddKeySym: PROC [keySym: KeySym, keyCode: KeyCode, index: NAT] = {
keyVal: REF;
found: BOOL ¬ FALSE;
Update: CardTab.UpdateAction = {
keys: REF KeyCodesRep;
IF found
THEN {
oldKeys: REF KeyCodesRep ~ NARROW[val];
oldCount: NAT ~ oldKeys.n;
keys ¬ NEW[KeyCodesRep[oldCount+1]];
FOR i: NAT IN [0..oldCount) DO
keys[i] ¬ oldKeys[i];
ENDLOOP;
keys[oldCount] ¬ [keyCode, index];
}
ELSE {
keys ¬ NEW[KeyCodesRep[1]];
keys[0] ¬ [keyCode, index];
};
new ¬ keys;
op ¬ store;
};
CardTab.Update[inverse, LOOPHOLE[keySym], Update];
};
keyTable: KeyTable ~ mapping.keyTable;
FOR i: KeyCode IN [keycode0..mapping.maxCode] DO
keySyms: KeySyms ~ keyTable[i];
IF keySyms#NIL AND keySyms.n>0 THEN {
firstSym ¬ keySyms[0];
AddKeySym[firstSym, i, 0];
FOR j: NAT IN [0..keySyms.n) DO
thisSym ¬ keySyms[j];
IF thisSym # firstSym THEN AddKeySym[thisSym, i, j];
ENDLOOP;
};
ENDLOOP;
--idempotent; locking not required
mapping.inverseKeyTable ¬ inverse;
};
END.