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: REF _ NIL, onExit: BOOL _ TRUE] RETURNS [newBreaks: LIST OF Break] = TRUSTED { ENABLE UNWIND => NULL; exit: BOOLEAN _ FALSE; 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: BOOL _ FALSE; 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_0], 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. †ScreenBreakImpl.mesa Copyright (C) 1985 by Xerox Corporation. All rights reserved. Michael Plass, May 9, 1985 11:38:48 am PDT Κ R˜™Icodešœ>™>J™*J™—šΟk œ˜˜J˜—šœœ˜Jšœ{˜‚šœ˜J˜—šœœœ˜K˜—Kšœœœ ˜šœ œœ˜Kšœœ˜Kšœ˜Kšœ"˜"Kšœœ˜ K˜Kšœ˜Kšœ˜K˜—šœœœ˜K˜—š Οnœœœœœœ˜gKšœ œ˜Kšœ˜Kšœ˜Kšœœ˜š ž œœœœœ˜KKšœ œ˜,Kšœ˜$—šœœ˜Kšœœ^˜zKšœ[˜[Kšœ˜Kšœ˜—K˜ Kšœœœœ˜!K˜&K˜=Kšœf˜fKš œœœœœ˜(Kšœ/˜/Kš œ œœœœ˜!Kšœ9˜9Kšœ˜K˜—šžœœœ œ+œœ œœœ œœ œ˜Kšœœœ˜Kšœœœ˜Kšœ œœ˜.Kšœ5˜5Kšœœ˜#šœ˜)šœœ˜Kšœ@œ˜IKšœ8˜<—Kšœœœ˜—šœ œ˜Kšœ6œ6œ˜„šœ œœ˜šœœ ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ K˜Kšœ˜K˜—Kšœ œ˜Jšœ œ˜#Jšœ˜—Jšœ˜Jšœ˜—Kšœ˜J˜—šž œœœœœœœœ˜LKšœœœ˜š œœœœœ˜6Jšœœ˜Jš œœœœœœ˜AJšœ˜—Kšœœ˜ Kšœ˜J˜—šž œœœœœœ œ˜OKšœœœ˜šœ œ˜Jšœ˜Jšœ7œœ%˜xJšœ˜Jšœ˜—Kšœ˜J˜—Kšœ œœ˜#šœœœ˜Jšœœ˜Jšœœ˜Jšœœ˜ J˜ J˜Jšœ˜J˜—šž œ˜*Kšœ œ˜ šœ œ˜šœœœœ˜#Jšœœ˜4JšœB˜FJšœ˜—Jšœœ˜—Kšœ˜J˜—šžœ˜+Kšœ œ˜ Kšœ œœ˜šœ œ˜šœ˜Jšœœ ˜šœ˜Jšœœ2˜=šœœ˜Jšœ œ˜Jšœ˜—šœ˜Jšœœœ˜*Jšœ˜—Jšœ˜Jšœ˜—Jšœ˜—Jšœœ˜—Kšœ œœ˜%Kšœ˜J˜—šžœœœœ˜^KšœB˜Bšœœœ˜KKšœ˜Kšœ"œ.˜TKšœL˜LKšœ˜—šœ"˜"Kšœ)˜)KšœC˜CKšœ˜—Kšœ˜K˜J˜—š ž œœNœœœœ ˜‡šžœœœœ ˜#šœœ˜Jšœœ˜J˜ Jšœ˜—Jšœ˜—Kšœ;˜;KšœI˜Išœœ˜+Kšœ˜Kšœœ˜Kšœœ˜ Kšœ˜Kšœ˜Kšœ˜—šžœœ œ˜Jšœ4œ˜