HexDisplayer:
CEDAR
PROGRAM
IMPORTS AMTypes, AMBridge, Convert, Process, Rope, VFonts, ViewRec =
BEGIN
hexHandler: ViewRec.SimpleHandler =
NEW [ViewRec.SimpleHandlerRep ← [
Parse: ParseHex,
UnParse: UnParseHex,
Max: MaxHex,
Butt: NIL]];
hexWordInstance: REF Dragon.HexWord = NEW[Dragon.HexWord];
tvHexWordInstance: AMTypes.TypedVariable;
wordMax: REF Dragon.HexWord = NEW[Dragon.HexWord ← LAST[Dragon.HexWord]];
byteMax: REF Dragon.HexWord = NEW[Dragon.HexWord ← LAST[Dragon.HexByte]];
ParseHex:
PROC [asRope: Rope.
ROPE, tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData:
REF
ANY]
RETURNS [ok:
BOOLEAN]
-- ViewRec.ParseProc -- =
BEGIN
ok ← TRUE;
hexWordInstance^ ← Convert.CardFromWholeNumberLiteral[asRope !Convert.Error => {ok ← FALSE; CONTINUE}];
IF NARROW[handlerData, REF Dragon.HexWord]^ < hexWordInstance^ THEN ok ← FALSE;
IF ok
THEN
BEGIN
AMTypes.Assign[tv, tvHexWordInstance !AMTypes.Error =>
{ok ← FALSE; CONTINUE}];
END;
END;
UnParseHex:
PROC [tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData:
REF
ANY]
RETURNS [asRope: Rope.
ROPE]
-- ViewRec.UnParseProc -- =
BEGIN
AMTypes.Assign[tvHexWordInstance, tv];
asRope ← Convert.RopeFromCard[from: hexWordInstance^, base: 16, showRadix: TRUE];
END;
MaxHex:
PROC [tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData:
REF
ANY]
RETURNS [maxWidthNeeded:
INTEGER, lines:
REAL ← 1]
-- ViewRec.MaxProc -- =
BEGIN
maxWidthNeeded ← VFonts.StringWidth[Convert.RopeFromCard[from: NARROW[handlerData, REF Dragon.HexWord]^, base: 16, showRadix: TRUE]];
END;
HexRecognizer:
PROC [
t: AMTypes.Type, --unreduced
onlyRecognize: BOOLEAN,--don't bother to produce the handler and handlerData
specs: ViewRec.BindingList, --what will apply to this element
createOptions: ViewRec.CreateOptions--for aggregate containing this elt
]
RETURNS [
IKnowYou: BOOLEAN,
handler: ViewRec.Handler,
handlerData: REF ANY ← NIL] -- ViewRec.Recognizer -- =
BEGIN
handler ← hexHandler;
IKnowYou ← FALSE;
WHILE
NOT IKnowYou
DO
name: Rope.ROPE = AMTypes.TypeToName[t];
SELECT
TRUE
FROM
Rope.Equal[name, "HexWord"] => {IKnowYou ← TRUE; handlerData ← wordMax};
Rope.Equal[name, "HexByte"] => {IKnowYou ← TRUE; handlerData ← byteMax};
AMTypes.TypeClass[t] = definition => t ← AMTypes.Ground[t];
AMTypes.TypeClass[t] = subrange => t ← AMTypes.Ground[t];
ENDCASE => EXIT;
ENDLOOP;
END;
Calculator:
TYPE =
RECORD [
byteAddressHex: Dragon.HexWord ← 0,
byteAddressDec: Dragon.Word ← 0,
wordAddressHex: Dragon.HexWord ← 0,
wordAddressDec: Dragon.Word ← 0,
byteOffset: [0..4) ← 0
];
calc: REF Calculator = NEW[Calculator ← []];
CalculatorUpdater:
PROC =
BEGIN
maxBytesInWords: Dragon.Word = Dragon.Word[32768]*Dragon.Word[32768]; -- 2^30
byte: [0..4) ← 0;
word: Dragon.Word ← 0;
DO
SELECT
TRUE
FROM
(calc.wordAddressHex # word) OR (calc.byteOffset # byte) => {word ← calc.wordAddressHex; byte ← calc.byteOffset};
(calc.wordAddressDec # word) OR (calc.byteOffset # byte) => {word ← calc.wordAddressDec; byte ← calc.byteOffset};
((calc.byteAddressHex/4) # (word
MOD maxBytesInWords))
OR ((calc.byteAddressHex
MOD 4) # byte) =>
{word ← calc.byteAddressHex/4; byte ← calc.byteAddressHex MOD 4};
((calc.byteAddressDec/4) # (word
MOD maxBytesInWords))
OR ((calc.byteAddressDec
MOD 4) # byte) =>
{word ← calc.byteAddressDec/4; byte ← calc.byteAddressDec MOD 4};
ENDCASE => NULL;
calc.byteAddressHex ← calc.byteAddressDec ← 4*(word MOD maxBytesInWords)+byte;
calc.wordAddressHex ← calc.wordAddressDec ← word;
calc.byteOffset ← byte;
Process.Pause[Process.MsecToTicks[500]];
ENDLOOP;
END;
TRUSTED {tvHexWordInstance ← AMBridge.TVForReferent[hexWordInstance]};
ViewRec.RegisterRecognizerBeforeReductions[r: HexRecognizer, end: Front, applyBefore: EquivalenceClass];
[] ← ViewRec.ViewRef[agg: calc, label: "Dragon radix calculator "];
TRUSTED {Process.Detach[FORK CalculatorUpdater[]]};
END.