ScreenBreakImpl.mesa
Copyright (C) 1985 by Xerox Corporation. All rights reserved.
Michael Plass, May 9, 1985 11:38:48 am PDT
DIRECTORY BcdDefs, Rope, PrincOps, AMModel, AMModelLocation, FastBreak, WorldVM, ImagerPixelMap, Terminal, Commander, LFBoundingBox, InterminalBackdoor;
ScreenBreakImpl: CEDAR MONITOR
IMPORTS Rope, AMModel, AMModelLocation, FastBreak, WorldVM, ImagerPixelMap, Terminal, Commander, LFBoundingBox, InterminalBackdoor
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
Break: TYPE = REF BreakRec;
BreakRec: TYPE = RECORD [
exit: BOOLEAN,
index: FastBreak.FastBreakId,
condProc: FastBreak.FastBreakProc,
data: REF,
pc: PrincOps.BytePC,
section: AMModel.Section
];
breaks: LIST OF Break;
SectionFromName: PROC [name: ROPE, sourceIndex: INT ← 0] RETURNS [section: AMModel.Section] = TRUSTED {
dotIndex: INT;
module: AMModel.Section;
moduleContext: AMModel.Context;
moduleName, procName: ROPE;
FindProcedure: UNSAFE PROC [proc: AMModel.Section] RETURNS [stop: BOOL] = {
name: Rope.ROPE ← AMModel.SectionName[proc];
RETURN[Rope.Equal[name, procName]]};
IF sourceIndex # 0 THEN {
source: AMModel.Source ← NEW[AMModel.SourceObj ← [name, statement, BcdDefs.NullVersion, field[sourceIndex, sourceIndex]]];
section ← AMModel.SourceSection[source, AMModel.RootContext[WorldVM.LocalWorld[]]].section;
RETURN;
};
dotIndex ← Rope.Find[name, "."];
IF dotIndex < 0 THEN RETURN[NIL];
moduleName ← name.Substr[0, dotIndex];
procName ← name.Substr[dotIndex+1, name.Length[]-dotIndex-1];
moduleContext ← AMModel.MostRecentNamedContext[moduleName, AMModel.RootContext[WorldVM.LocalWorld[]]];
IF moduleContext = NIL THEN RETURN[NIL];
module ← AMModel.ContextSection[moduleContext];
IF module = NIL THEN RETURN[NIL];
section ← AMModel.SectionChildren[module, FindProcedure];
};
SetBreak: ENTRY PROC [procName: ROPE, condProc: FastBreak.FastBreakProc, data: REFNIL, onExit: BOOLTRUE] RETURNS [newBreaks: LIST OF Break] = TRUSTED {
ENABLE UNWIND => NULL;
exit: BOOLEANFALSE;
locList: LIST OF AMModelLocation.CodeLocation;
section: AMModel.Section ← SectionFromName[procName];
index: FastBreak.FastBreakId ← NIL;
SELECT AMModel.SectionClass[section] FROM
proc => IF onExit
THEN {locList ← AMModelLocation.ExitLocations[section].list; exit ← TRUE}
ELSE locList ← AMModelLocation.EntryLocations[section].list;
ENDCASE => RETURN[NIL];
UNTIL locList = NIL DO
index: FastBreak.FastBreakId ~ FastBreak.SetFastBreak[LOOPHOLE[locList.first.codeBase], locList.first.pc, condProc, LOOPHOLE[data]];
IF index # NIL THEN {
break: Break ~ NEW[BreakRec ← [
exit: exit,
index: index,
condProc: condProc,
data: data,
pc: locList.first.pc,
section: section
]];
breaks ← CONS[break, breaks];
newBreaks ← CONS[break, newBreaks];
};
locList ← locList.rest;
ENDLOOP;
};
GetDataRef: ENTRY PROC [dataPointer: LONG POINTER] RETURNS [REF] = TRUSTED {
ENABLE UNWIND => NULL;
FOR b: LIST OF Break ← breaks, b.rest UNTIL b = NIL DO
data: REF ~ b.first.data;
IF dataPointer = LOOPHOLE[data, LONG POINTER] THEN RETURN [data];
ENDLOOP;
RETURN [NIL];
};
ClearBreaks: ENTRY PROC RETURNS [v: RECORD[numberCleared: INT ← 0]] = TRUSTED {
ENABLE UNWIND => NULL;
WHILE breaks # NIL DO
break: Break ~ breaks.first;
IF FastBreak.ClearFastBreak[break.index, break.condProc, LOOPHOLE[break.data]] THEN v.numberCleared ← v.numberCleared+1;
breaks ← breaks.rest;
ENDLOOP;
};
PaintTrap: TYPE ~ REF PaintTrapRep;
PaintTrapRep: TYPE ~ RECORD [
watchForChange: BOOL,
matchedBefore: BOOL,
hit: BOOL,
screen: ImagerPixelMap.PixelMap,
target: ImagerPixelMap.PixelMap
];
PrePaintBreak: FastBreak.FastBreakProc = {
dataRef: REF ~ GetDataRef[data];
WITH dataRef SELECT FROM
p: PaintTrap => IF NOT p.hit THEN {
IF p.watchForChange THEN p.target.Transfer[p.screen]
ELSE p.matchedBefore ← p.target.Equal[p.screen.Clip[p.target.Window]];
};
ENDCASE => NULL;
};
PostPaintBreak: FastBreak.FastBreakProc = {
dataRef: REF ~ GetDataRef[data];
breakHere: BOOLFALSE;
WITH dataRef SELECT FROM
p: PaintTrap => {
IF p.hit THEN breakHere ← FALSE
ELSE {
match: BOOL ~ p.target.Equal[p.screen.Clip[p.target.Window]];
IF p.watchForChange THEN {
breakHere ← NOT match;
}
ELSE {
breakHere ← match AND NOT p.matchedBefore;
};
p.hit ← breakHere;
};
};
ENDCASE => NULL;
IF breakHere THEN useOldBreak ← TRUE;
};
PixelMapFromTerminal: PUBLIC PROC [vt: Terminal.Virtual] RETURNS [ImagerPixelMap.PixelMap] ~ {
frameBuffer: Terminal.FrameBuffer ~ Terminal.GetBWFrameBuffer[vt];
refRep: REF ImagerPixelMap.PixelMapRep ~ NEW[ImagerPixelMap.PixelMapRep ← [
ref: frameBuffer,
pointer: frameBuffer.base, words: LONG[frameBuffer.wordsPerLine]*frameBuffer.height,
lgBitsPerPixel: 0, rast: frameBuffer.wordsPerLine, lines: frameBuffer.height
]];
frame: ImagerPixelMap.PixelMap ~ [
sOrigin: 0, fOrigin: 0, sMin: 0, fMin: 0,
sSize: frameBuffer.height, fSize: frameBuffer.width, refRep: refRep
];
RETURN [frame]
};
SetPaintTrap: PROC [vt: Terminal.Virtual, area: ImagerPixelMap.DeviceRectangle, watchForChange: BOOL] RETURNS [list: LIST OF Break] = {
Record: PROC [b: LIST OF Break] ~ {
WHILE b#NIL DO
list ← CONS[b.first, list];
b ← b.rest;
ENDLOOP;
};
screen: ImagerPixelMap.PixelMap ~ PixelMapFromTerminal[vt];
target: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Copy[screen.Clip[area]];
paintTrap: PaintTrap ← NEW[PaintTrapRep ← [
watchForChange: watchForChange,
matchedBefore: FALSE,
hit: FALSE,
screen: screen,
target: target
]];
Do: PROC [procName: ROPE] ~ {
Record[SetBreak[procName, PrePaintBreak, paintTrap, FALSE]];
Record[SetBreak[procName, PostPaintBreak, paintTrap, TRUE]];
};
Do["ImagerBitmapDeviceImpl.BitmapMaskRuns"];
Do["ImagerBitmapDeviceImpl.BitmapMaskBoxes"];
Do["ImagerBitmapDeviceImpl.BitmapMaskBits"];
Do["ImagerBitmapDeviceImpl.BitmapMoveBoxes"];
};
Count: FastBreak.FastBreakProc = {
dataRef: REF ~ GetDataRef[data];
WITH dataRef SELECT FROM
refInt: REF INT => refInt^ ← refInt^ + 1;
ENDCASE => NULL;
};
CountDown: FastBreak.FastBreakProc = {
dataRef: REF ~ GetDataRef[data];
WITH dataRef SELECT FROM
refInt: REF INT => {
refInt^ ← refInt^ + 1;
IF refInt^ = 0 THEN useOldBreak ← TRUE;
};
ENDCASE => NULL;
};
Try: PROC RETURNS [LIST OF Break] = {
RETURN [SetBreak["ScreenBreakImpl.Mumble", Count, NEW[INT𡤀], TRUE]]
};
iWasHere: INT ← 0;
Mumble: PROC = {
iWasHere ← iWasHere + 1;
};
ScreenChangeCommand: Commander.CommandProc = {
vt: Terminal.Virtual ~ InterminalBackdoor.terminal;
x, y, w, h: NAT;
[] ← ClearBreaks[];
[x, y, w, h] ← LFBoundingBox.GetArea[! LFBoundingBox.AbortAdjust => ERROR ABORTED];
[] ← SetPaintTrap[vt, [vt.bwHeight-(y+h), x, h, w], TRUE];
};
ScreenMatchCommand: Commander.CommandProc = {
vt: Terminal.Virtual ~ InterminalBackdoor.terminal;
x, y, w, h: NAT;
[] ← ClearBreaks[];
[x, y, w, h] ← LFBoundingBox.GetArea[! LFBoundingBox.AbortAdjust => ERROR ABORTED];
[] ← SetPaintTrap[vt, [vt.bwHeight-(y+h), x, h, w], FALSE];
};
ClearCommand: Commander.CommandProc = {
[] ← ClearBreaks[];
};
Commander.Register["BreakOnScreenChange", ScreenChangeCommand];
Commander.Register["BreakOnScreenMatch", ScreenMatchCommand];
Commander.Register["ClearScreenBreaks", ClearCommand];
END.