CDVMain.mesa (part of ChipNDale)
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Ch. Jacobi, June 24, 1983 3:33 pm
last edited by Christian Jacobi, March 12, 1986 6:11:36 pm PST
DIRECTORY
CD,
CDColors,
CDDrawQueue,
CDEvents,
CDExtras,
CDBasics,
CDPanel,
CDProperties,
CDSequencer USING [Command, CommandRec, ExecuteCommand],
CDTipEtc,
CDLayers,
CDValue,
CDVFurtherPainters,
CDVPrivate,
CDViewer,
CDViewerBase,
CDVScale,
Cursors,
InputFocus USING [SetInputFocus],
List,
PrincOps USING [BBTableSpace],
PrincOpsUtils,
Process USING [Detach, Yield],
CedarProcess USING [SetPriority, Priority],
Rope USING [ROPE, Cat],
RuntimeError USING [UNCAUGHT],
SafeStorage USING [ReclaimCollectibleObjects],
TerminalIO,
TIPUser USING [TIPScreenCoords],
UserProfile,
ViewerClasses,
ViewerEvents USING [EventProc, RegisterEventProc],
ViewerOps USING [CreateViewer, RegisterViewerClass, PaintViewer, BlinkIcon, EnumProc, EnumerateViewers],
WindowManager USING [colorDisplayOn];
CDVMain: CEDAR MONITOR
--monitoring rule: aquire the ViewerLock first, the monitor's entry lock only after.
IMPORTS
CedarProcess, CD, CDColors, CDDrawQueue, CDEvents, CDExtras, CDBasics, CDPanel, CDProperties, CDVFurtherPainters, CDVScale, CDSequencer, CDTipEtc, CDLayers, CDValue, CDViewer, CDViewerBase, CDVPrivate, InputFocus, List, PrincOpsUtils, Process, Rope, RuntimeError, SafeStorage, TerminalIO, UserProfile, ViewerEvents, ViewerOps, WindowManager
EXPORTS CDVPrivate
SHARES CDVFurtherPainters, TerminalIO, CDDrawQueue =
BEGIN
greeting: Rope.ROPE = "ChipNDale Version 2.2 for Cedar 6.0 ";
date: Rope.ROPE = "March 12, 1986";
copyRight: Rope.ROPE = "\nCopyright (C) 1984, 1986 by Xerox Corporation. All rights reserved.\n\n";
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
notSupportedColorMode: PUBLIC ERROR = CODE;
allVRefs: PUBLIC LIST OF VRef ← NIL;
catchAny: PUBLIC BOOLTRUE;
catchAnyWhichDeadlock: PUBLIC BOOLTRUE;
putNewViewerOnColor: BOOLTRUE;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viewerClassAtom: ATOM = $ChipNDale;
VRef: TYPE = CDVPrivate.VRef;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
terminalLock: BOOLFALSE;
TerminalLock: PROC [] = {
terminalLock ← TRUE;
viewerClassRec.cursor ← cursorWhileInput
};
TerminalFree: PROC [] ={
terminalLock ← FALSE;
SetCursor[]
};
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- types used for parameters to the viewer paint procedure
--TrackRef: type to force cursor tracking
TrackRef: TYPE = REF TrackRecord;
TrackRecord: TYPE = RECORD [
pos: CD.Position
];
--the Get and Dispose proc's are a hack to reduce the memory allocator's work
track: TrackRef ← NIL;
GetTrackRef: PROC [p: CD.Position] RETURNS [t: TrackRef] = INLINE {
--may be called by viewers NotifyViewer proc only; monitored through viewers NotifyViewer proc
t ← track; track ← NIL;
IF t=NIL THEN t ← NEW[TrackRecord];
t.pos ← p
};
DisposeTrackRef: PROC [t: TrackRef] = INLINE {
track ← t
};
--RepaintRectAreaRef: type to force drawing a rectangular aera
RepaintRectAreaRef: TYPE = REF RepaintRectArea;
RepaintRectArea: TYPE = RECORD[
rect: CD.Rect ← CDBasics.universe,
erase: BOOLFALSE
];
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
tryToPaint: CONDITION;
viewerClassRec: ViewerClasses.ViewerClass ← NEW[ViewerClasses.ViewerClassRec ← [
paint: PaintViewer,
notify: NotifyViewer,
modify: ModifyViewer,
destroy: DestroyViewer,
set: CDViewerBase.SetProc,
get: CDViewerBase.GetProc,
cursor: cursorNoFocus
]];
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
cursoredCDViewer: PUBLIC ViewerClasses.Viewer ← NIL;
inputFocussedViewer: ViewerClasses.Viewer ← NIL;
lastInputFocussedViewer: ViewerClasses.Viewer ← NIL;
cursorWithFocus: Cursors.CursorType = textPointer;
cursorNoFocus: Cursors.CursorType = pointDown;
cursorWhileInput: Cursors.CursorType = questionMark;
SetCursor: PROC [] = INLINE {
viewerClassRec.cursor ←
IF terminalLock THEN cursorWhileInput
ELSE IF cursoredCDViewer=inputFocussedViewer THEN cursorWithFocus
ELSE cursorNoFocus;
};
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LastViewer: PUBLIC PROC [] RETURNS [ViewerClasses.Viewer] =
BEGIN
RETURN [lastInputFocussedViewer]
END;
SetUpAndRedraw: ENTRY PROC[me: VRef] =
--logically inside the viewer's paint proc;
--reset viewer data and then sets up a buffered request for redrawing
BEGIN
ENABLE UNWIND => NULL;
CDDrawQueue.Flush[me.ct];
me.onVC ← FALSE; --erasing viewer automaticaly makes cursor invisible
CDVPrivate.CreateDrawInformation[me];
CDDrawQueue.ChangeClipArea[me.ct, me.dClip];
-- erase to allow also backgrounds of arbitrary patterns or colors
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]];
END;
PaintViewer: ViewerClasses.PaintProc =
--PROC [self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL]
--depending on whatChanged, the call must be protected or need not.
--Never call with modules entry monitor lock set.
BEGIN
ENABLE {
CDVPrivate.notSupportedColorMode => GOTO oops;
RuntimeError.UNCAUGHT =>
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO oops ELSE REJECT;
};
me: VRef = NARROW[self.data];
TrackRefTrack: ENTRY PROC [me: VRef, tr: TrackRef] = INLINE
BEGIN
ENABLE UNWIND => NULL;
IF me.cursorInhibitations=0 THEN {
IF me.onVC THEN me.usedCursor[me]
ELSE {
me.startVC ← me.designRec.startLC;
me.firstHorizontalVC ← me.designRec.firstHLC;
me.designRec.currentLayer ← CDLayers.CurrentLayer[me.actualDesign];
me.defaultWidthVC ← me.designRec.widthLC ←
CDLayers.LayerWidth[me.actualDesign, me.designRec.currentLayer];
me.onVC ← TRUE;
};
--now me.onVC is true
me.usedCursor ← me.designRec.outlineProcLC;
me.stopVC ← tr.pos;
me.usedCursor[me];
};
DisposeTrackRef[tr];
END;
RemoveTrack: ENTRY PROC[me: VRef] = INLINE
BEGIN
ENABLE UNWIND => NULL;
IF me.onVC THEN {
me.usedCursor[me];
me.onVC ← FALSE;
};
END;
--PaintViewer
IF self.destroyed THEN RETURN;
me.viewContext ← context;
WITH whatChanged SELECT FROM
tr: TrackRef => TrackRefTrack[me, tr]; -- called by NotifyViewer
atom: ATOM => {
IF atom=$RemoveTrack THEN RemoveTrack[me]
ELSE CDVFurtherPainters.CallFurther[me, atom]; -- called from anywhere, maybe not protected
};
area: RepaintRectAreaRef => -- protected by ProtectedRepaint
CDVPrivate.RepaintRectAreaInViewer[me, area.rect, area.erase];
ENDCASE => {
IF whatChanged=NIL THEN {
IF me.viewer#self THEN RETURN; --initialization not finished
SetUpAndRedraw[me] -- called from anywhere, maybe not protected
}
ELSE CDVFurtherPainters.CallFurther[me, whatChanged];
}
EXITS oops => NULL;
END;
Flushed: CDVFurtherPainters.FurtherPaintProc =
-- PROC [me: CDVPrivate.VRef, key: REF]
-- logicaly local to viewers paint proc (PaintViewer)
BEGIN
CDDrawQueue.Flush[me.ct];
me.scale ← me.intendedScale;
SetUpAndRedraw[me];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
--local--
EnableCursoring: ENTRY PROC[me: VRef] =
--logically local to ProtectedRepaint
--is outside to make callable from catch-phrase and initialization
INLINE BEGIN
ENABLE {
UNWIND => NULL;
RuntimeError.UNCAUGHT => {
BROADCAST tryToPaint;
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO oops ELSE REJECT
};
};
me.cursorInhibitations ← me.cursorInhibitations-1;
BROADCAST tryToPaint
EXITS oops => NULL;
END;
ProtectedRepaint: PROC[me: VRef, whatChanged: REF ANY] =
--does:
--remove cursor and disables any cursoring process
--let only one client come through
BEGIN
ENABLE RuntimeError.UNCAUGHT => {
EnableCursoring[me];
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO oops ELSE REJECT
};
DisableCursoring: ENTRY PROC[me: VRef] RETURNS [mustRemoveCursor: BOOL] =
--and enters protected region.
INLINE BEGIN
ENABLE {
UNWIND => NULL;
RuntimeError.UNCAUGHT => {BROADCAST tryToPaint; REJECT};
};
me.cursorInhibitations ← me.cursorInhibitations+1;
WHILE me.cursorInhibitations>1 DO
me.cursorInhibitations ← me.cursorInhibitations-1;
WAIT tryToPaint;
me.cursorInhibitations ← me.cursorInhibitations+1;
ENDLOOP;
mustRemoveCursor ← me.onVC;
END;
--ProtectedRepaint
IF DisableCursoring[me].mustRemoveCursor THEN RemoveCursor[me];
ViewerOps.PaintViewer[me.viewer, client, FALSE, whatChanged];
EnableCursoring[me];
EXITS oops => NULL;
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
ViewerProcess: PROC[me: VRef] =
BEGIN
comm: REF CDDrawQueue.Request = NEW[CDDrawQueue.Request];
bBTableSpace1, bBTableSpace2, bBTableSpace3: PrincOps.BBTableSpace;
--me.fooBBptr is a short pointer! (hardware) therefore must be local to some procedure space.
IF me.running THEN ERROR;
TRUSTED {
me.pBBptr ← PrincOpsUtils.AlignedBBTable[@bBTableSpace1];
me.oBBptr ← PrincOpsUtils.AlignedBBTable[@bBTableSpace2];
me.xBBptr ← PrincOpsUtils.AlignedBBTable[@bBTableSpace3];
};
me.running ← TRUE;
DO
comm^ ← CDDrawQueue.FetchCommand[me.ct];
SELECT comm.key FROM
$redraw => {
paintArea: RepaintRectAreaRef = NEW[RepaintRectArea←[comm.rect, TRUE]];
ProtectedRepaint[me, paintArea];
};
$draw => {
paintArea: RepaintRectAreaRef = NEW[RepaintRectArea←[comm.rect, FALSE]];
ProtectedRepaint[me, paintArea];
};
CDDrawQueue.queueEmpty => {
ProtectedRepaint[me, $Temporaries];
CedarProcess.SetPriority[CedarProcess.Priority[background]];
--do the garbage collection now, when not to much else is to do,
--and also all the allocations of the drawing can be freed
SafeStorage.ReclaimCollectibleObjects[suspendMe: FALSE];
};
CDDrawQueue.finishedForEver => EXIT;
ENDCASE => ProtectedRepaint[me, comm];
ENDLOOP;
TerminalIO.WriteRope["Viewer destroyed\n"];
me.running ← FALSE;
me.ct ← NIL;
me.actualDesign ← NIL;
me.designRec ← NIL;
me.deviceDrawRef ← NIL;
me.painterList ← NIL;
me.properties ← NIL;
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
SlowDown: PROC [v: ViewerClasses.Viewer] =
BEGIN
IF v#NIL THEN WITH v.data SELECT FROM
me: VRef => {
--order important
me.hurryUp ← FALSE;
me.slowDown ← TRUE;
me.check ← TRUE;
me.deviceDrawRef.checkPriority ← TRUE;
};
ENDCASE => NULL;
END;
SpeedUp: PROC [v: ViewerClasses.Viewer] =
BEGIN
IF v#NIL THEN WITH v.data SELECT FROM
me: VRef => {
--order important
me.slowDown ← FALSE;
me.hurryUp ← TRUE;
me.check ← TRUE;
me.deviceDrawRef.checkPriority ← TRUE;
};
ENDCASE => NULL;
END;
RemoveCursor: PROC [me: VRef] =
--removes visible cursor, if there is
--monitores inside viewerpaintproc
INLINE BEGIN
IF me.onVC THEN
ViewerOps.PaintViewer[me.viewer, client, FALSE, $RemoveTrack];
END;
ModifyViewer: ViewerClasses.ModifyProc = -- PROC [self: Viewer, change: ModifyAction]
BEGIN ENABLE UNWIND => NULL;
SELECT change FROM
set, pop => lastInputFocussedViewer ← inputFocussedViewer ← self;
kill, push => inputFocussedViewer ← NIL;
ENDCASE => NULL;
SetCursor[];
END;
NotifyViewer: ViewerClasses.NotifyProc =
-- PROC [self: Viewer, input: LIST OF REF ANY]
-- ENTRY ommitted since sequential already by viewer package
BEGIN
ENABLE RuntimeError.UNCAUGHT =>
IF CDVPrivate.catchAnyWhichDeadlock THEN GOTO oops ELSE REJECT;
me: VRef = NARROW[self.data];
mouse: CD.Position ← [0, 0]; --initialize, there are crazy tiptables.
LogicalTrack: PROC [me: VRef, pos: CD.Position] = INLINE
--makes cursor logically available
BEGIN
IF NOT me.designRec.startLCValid THEN {
me.designRec.startLC ← pos;
me.designRec.startLCValid ← TRUE;
}
END;
LogicalTrackOff: PROC [me: VRef, pos: CD.Position] = INLINE
--makes cursor logically unavailable
BEGIN
me.designRec.stopLC ← pos;
me.designRec.startLCValid ← FALSE;
END;
Track: PROC [me: VRef] = INLINE
--uses intermediate layer variable mouse
BEGIN
VisibleTrack: PROC [me: VRef, pos: CD.Position] = INLINE
--makes cursor visible
BEGIN
ViewerOps.PaintViewer[me.viewer, client, FALSE, GetTrackRef[pos] ];
END;
--Track
pos: CD.Position = CDVScale.ViewerToDesignPosition[me.scale, mouse];
LogicalTrack[me, pos];
IF me.cursorInhibitations=0 THEN VisibleTrack[me, pos];
END;
StopTrack: PROC [me: VRef] =
--uses intermediate layer variable mouse
BEGIN
pos: CD.Position = CDVScale.ViewerToDesignPosition[me.scale, mouse];
me.hurryUp ← TRUE;
LogicalTrackOff[me, pos];
RemoveCursor[me];
CDVPrivate.SetCursorMode[me, NIL];
END;
--NotifyViewer
IF self#cursoredCDViewer THEN {
tem: ViewerClasses.Viewer = cursoredCDViewer;
IF me.deviceDrawRef=NIL THEN {
--silly Cedar Viewer package allows calls of notify before
--the first call to the paint procedure happened;
--but in ChipNDale, some initializations happens in paintprocedure only.
--luckily at that time cursoredCDViewer#self; so here is the only
--place to check.
RETURN
};
IF tem#NIL AND tem.data#NIL THEN RemoveCursor[NARROW[tem.data, VRef]];
cursoredCDViewer ← self;
SetCursor[];
};
WHILE input#NIL DO
WITH input.first SELECT FROM
atom: ATOM => {
IF atom=$Track THEN Track[me]
ELSE IF atom=$StopTrack THEN StopTrack[me]
ELSE IF terminalLock THEN {
IF atom#$UseCursor THEN ViewerOps.BlinkIcon[viewer: self, millisecondsPerBlink: 100];
RETURN;
}
ELSE {
IF self#inputFocussedViewer THEN {
SlowDown[inputFocussedViewer];
InputFocus.SetInputFocus[self];
SpeedUp[self];
IF atom=$CloseReSelectOnlyP THEN RETURN;
};
IF atom=$UseCursor THEN { --command involving 2 atoms
RemoveCursor[me];
input ← input.rest; IF input=NIL THEN RETURN;
CDVPrivate.SetCursorMode[me, input.first]
}
ELSE { -- all other (standard) commands
StopTrack[me];
TRUSTED {Process.Detach[
FORK CDSequencer.ExecuteCommand[
design: me.actualDesign,
comm: NEW[CDSequencer.CommandRec ← CDSequencer.CommandRec[
design: me.actualDesign,
a: atom,
pos: me.designRec.stopLC,
sPos: me.designRec.startLC,
l: me.designRec.currentLayer,
ref: me,
n: me.defaultWidthVC,
b: me.designRec.firstHLC
]]
]
]};
};
};
};
coords: TIPUser.TIPScreenCoords => {
-- range test,
-- [some crazy tiptables use coords without having had a mouse action first]
mouse.x ← MIN[MAX[coords.mouseX, 0], me.viewer.cw-1];
mouse.y ← MIN[MAX[coords.mouseY, 0], me.viewer.ch-1];
};
ENDCASE => NULL;
input ← input.rest
ENDLOOP;
EXITS oops => NULL;
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Caption: PROC [design: CD.Design] RETURNS [Rope.ROPE] =
BEGIN
IF design=NIL THEN RETURN["nil design"]
ELSE RETURN [Rope.Cat[
(IF design.name#NIL THEN design.name ELSE "no name"),
" (",
design.technology.name,
") cell: ",
CDExtras.PushedCellName[design]
]]
END;
CDEventHappened: CDEvents.EventProc =
-- PROC [event: REF, design: CD.Design, x: REF]
-- repaint captions and sometimes the contents
BEGIN
name: Rope.ROPE = Caption[design];
FOR l: CDViewer.ViewerList ← CDViewer.ViewersOf[design], l.rest WHILE l#NIL DO
me: VRef = NARROW[l.first.data];
l.first.name ← name;
ViewerOps.PaintViewer[l.first, caption];
IF event=$AfterPop OR event=$AfterPush THEN {
--redraw everything, because
--  after pop: cell change may have propagated
--  after push: background features must be redrawn greyish
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]]
}
ENDLOOP;
END;
CreateViewer: PUBLIC PROC[design: CD.Design] RETURNS [ViewerClasses.Viewer]=
BEGIN
bb: CD.Rect = CDExtras.BoundingBox[design];
me: VRef = New[design];
TRUSTED {Process.Detach[FORK ViewerProcess[me]]};
[] ← CDPanel.CreatePanel[design];
--must wait until me.fooBBLT is initialized by ViewerProcess
WHILE NOT me.running DO Process.Yield[] ENDLOOP;
me.viewer ← ViewerOps.CreateViewer[
flavor: viewerClassAtom,
info: [
name: Caption[design], 
scrollable: FALSE,
icon: CDTipEtc.GetIcon[design],
iconic: FALSE,
column: ColumnForNewViewer[],
tipTable: CDTipEtc.GetTipTable[design],
data: me
],
paint: FALSE --important: me.viewer is initialized only after return
paint: TRUE --sorry, must check elsewhere for this case, otherwise viewerpackage blusters
];
me.dClip ← CDVScale.GetClipRecord[me.intendedScale, me.viewer.cw, me.viewer.ch];
IF CDBasics.NonEmpty[bb] THEN {
--but redraw does not yet come through... (clip area empty!)
CDViewer.ShowAndScale[me.viewer, bb];
CDDrawQueue.Flush[me.ct]; --I don't trust me
me.scale ← me.intendedScale;
me.dClip ← CDVScale.GetClipRecord[me.intendedScale, me.viewer.cw, me.viewer.ch];
};
CDDrawQueue.Flush[me.ct]; --I don't trust me
CDDrawQueue.ChangeClipArea[me.ct, me.dClip];
ViewerOps.PaintViewer[me.viewer, all];
EnableCursoring[me];
RETURN [me.viewer]
END;
ColumnForNewViewer: PROC [] RETURNS [col: ViewerClasses.Column←left] =
--selects colordisplay if it is on and free
BEGIN
colorDisplayEmpty: BOOLTRUE;
CheckColorScreen: ViewerOps.EnumProc = {-- PROC [v: Viewer] RETURNS [BOOL ← TRUE]
IF v.column=color AND ~v.iconic AND ~v.offDeskTop THEN
RETURN [colorDisplayEmpty ← FALSE]
};
IF WindowManager.colorDisplayOn AND putNewViewerOnColor THEN {
ViewerOps.EnumerateViewers[CheckColorScreen];
IF colorDisplayEmpty THEN col ← color
}
END;
DestroyViewer: ViewerClasses.DestroyProc =
BEGIN
Destroy[NARROW[self.data]];
self.data ← NIL;
END;
ViewerCloseEvent: ViewerEvents.EventProc =
-- PROC [viewer: Viewer, event: ViewerEvent, before: BOOL] RETURNS [abort: BOOLFALSE]
BEGIN
me: VRef ~ NARROW[viewer.data];
IF event=close THEN CDDrawQueue.ChangeClipArea[me.ct, CDBasics.empty];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
New: PUBLIC ENTRY PROC [design: CD.Design] RETURNS [me: VRef] =
BEGIN
ENABLE UNWIND => NULL;
NewScale: PROC [design: CD.Design] RETURNS [CDVScale.ScaleRec] =
BEGIN
scale: INT = CDValue.FetchInt[boundTo: design, key: $CDxInitScale, propagation: global, ifNotFound: 6];
grid: INT = CDValue.FetchInt[boundTo: design, key: $CDxInitGrid, propagation: global, ifNotFound: design.technology.lambda];
RETURN [ CDVScale.MakeScale[
nscale: MIN[MAX[scale, 0], CDVScale.scaleNum-1],
grid: MIN[MAX[grid, 0], 512],
off: [0, 0]
]];
END;
InitDesignRec: PROC [me: VRef] =
BEGIN
FOR l: LIST OF VRef ← allVRefs, l.rest WHILE l#NIL DO
IF me.actualDesign=l.first.actualDesign THEN { me.designRec ← l.first.designRec; RETURN };
ENDLOOP;
me.designRec ← NEW[CDVPrivate.VPrivatePerDesign];
CDVPrivate.SetCursorMode[me, NIL];
END;
--New
b: REF BOOL = NEW[BOOLFALSE];
me ← NEW[CDVPrivate.VRec←[
actualDesign: design,
ct: CDDrawQueue.Create[design, b, CDBasics.empty],
scale: NewScale[design],
dClip: CDBasics.empty,
intendedScale: NewScale[design],
stoprequest: b,
environment: CDProperties.GetPropFromDesign[design, $CDxDrawEnvironment]#$FALSE,
symbolics: CDProperties.GetPropFromDesign[design, $CDxDrawSymbolics]#$FALSE,
b4: CDProperties.GetPropFromDesign[design, $CDxSkipBorder]#$FALSE,
personalColors: CDColors.globalColors,
cursorInhibitations: 1, --disabled, not yet ready
properties: CD.InitPropRef[]
]];
InitDesignRec[me];
allVRefs ← CONS[me, allVRefs];
END;
Destroy: PUBLIC ENTRY PROC [me: VRef] =
TRUSTED BEGIN ENABLE UNWIND => NULL;
allVRefs ← LOOPHOLE[List.DRemove[ref: me, list: LOOPHOLE[allVRefs]]];
IF me#NIL THEN CDDrawQueue.Destroy[me.ct];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
NoteProfileChange: UserProfile.ProfileChangedProc =
-- PROC [reason: ProfileChangeReason]
BEGIN
catchAny ← UserProfile.Boolean["ChipNDale.CatchLowLevelErrors", TRUE];
catchAnyWhichDeadlock ← catchAny OR UserProfile.Boolean["ChipNDale.CatchErrorsWhichCauseDeadlock", TRUE];
putNewViewerOnColor ← UserProfile.Boolean["ChipNDale.FirstViewerOnColor", TRUE];
END;
UserProfile.CallWhenProfileChanges[NoteProfileChange];
TerminalIO.AddLock[TerminalLock, TerminalFree];
CDVFurtherPainters.InstallFurtherPaint[keyValue: $changeScale, proc: Flushed];
CDVFurtherPainters.InstallFurtherPaint[keyValue: $flushed, proc: Flushed];
CDEvents.RegisterEventProc[$ResetDesign, CDEventHappened];
CDEvents.RegisterEventProc[$RenameDesign, CDEventHappened];
CDEvents.RegisterEventProc[$AfterPush, CDEventHappened];
CDEvents.RegisterEventProc[$AfterPop, CDEventHappened];
ViewerOps.RegisterViewerClass[viewerClassAtom, viewerClassRec];
[] ← ViewerEvents.RegisterEventProc[proc: ViewerCloseEvent, event: close, filter: viewerClassAtom, before: TRUE];
TerminalIO.WriteRopes[greeting, date, copyRight];
END.