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.