CDVCommands.mesa (part of ChipNDale)
Copyright © 1983, 1985, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, June 29, 1983 4:44 pm
Last Edited by: Christian Jacobi, September 3, 1986 10:32:35 am PDT
DIRECTORY
CD,
CDBasics,
CDDrawQueue,
CDCells,
CDCommandOps,
CDEnvironment,
CDEvents,
CDInstances,
CDOps,
CDPanel,
CDProperties,
CDSequencer,
CDValue,
CDViewer,
CDViewerInternals,
CDVPrivate,
CDVScale,
IO,
PopUpSelection,
Process,
Rope,
TerminalIO,
UserProfile,
ViewerClasses USING [Viewer],
ViewerOps USING [PaintViewer, GetViewer, SetViewer, OpenIcon, BlinkIcon];
CDVCommands: CEDAR PROGRAM
IMPORTS CDBasics, CDCommandOps, CDDrawQueue, CDCells, CDEnvironment, CDEvents, CDInstances, CDOps, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer, CDVScale, IO, PopUpSelection, Process, Rope, TerminalIO, UserProfile, ViewerOps
EXPORTS CDViewerInternals =
BEGIN
VRef: TYPE = CDVPrivate.VRef;
--Utilities and public
DoWithVRef: PROC [comm: CDSequencer.Command, proc: PROC[vRef: VRef]] = {
v: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF v=NIL THEN TerminalIO.WriteRope["failed: no viewer\n"]
ELSE WITH v.data SELECT FROM
vRef: VRef => IF ~vRef.viewer.destroyed THEN proc[vRef];
ENDCASE => NULL;
};
AddCR: PROC [r: Rope.ROPE] RETURNS [Rope.ROPE] = {
--if r does not already has a CR
ml: INT ← Rope.Length[r];
IF Rope.Fetch[r, ml-1]#'\n THEN RETURN[Rope.Concat[r, "\n"]];
RETURN [r];
};
MsgAndVRef: PROC [comm: CDSequencer.Command, msg: Rope.ROPE] RETURNS [vRef: VRef←NIL] = {
v: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
TerminalIO.WriteRope[AddCR[msg]];
IF v=NIL THEN TerminalIO.WriteRope[" failed: no viewer\n"]
ELSE WITH v.data SELECT FROM
vr: VRef =>
IF ~vr.viewer.destroyed THEN vRef ← vr
ELSE TerminalIO.WriteRope[" failed: viewer destroyed\n"];
ENDCASE => TerminalIO.WriteRope[" failed: no ChipNDale viewer\n"];
};
Repaint: PROC [v: REF] = {
WITH v SELECT FROM
vRef: VRef => {
CDDrawQueue.Flush[vRef.ct];
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]];
};
viewer: ViewerClasses.Viewer => Repaint[viewer.data];
comm: CDSequencer.Command => Repaint[comm.ref];
ENDCASE => NULL;
};
SaveScale: PUBLIC PROC [viewer: ViewerClasses.Viewer] = {
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => CDProperties.PutProp[vRef.properties, $CDxSavedScale, NEW[CDVScale.ScaleRec ← vRef.scale]];
ENDCASE => NULL;
};
RestoreScale: PUBLIC PROC [viewer: ViewerClasses.Viewer] = {
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => {
GetScale: PROC [key: ATOM] RETURNS [CDVScale.ScaleRec] = {
WITH CDProperties.GetProp[vRef.properties, key] SELECT FROM
sr: REF CDVScale.ScaleRec => RETURN [sr^];
ENDCASE => RETURN [CDVScale.MakeScale[]];
};
scale: CDVScale.ScaleRec ← GetScale[$CDxSavedScale];
CDDrawQueue.Flush[vRef.ct];
--NO SaveScale[viewer]; it is better to have one fixed point
IF vRef.scale.off=scale.off AND vRef.scale.nscale=scale.nscale THEN
scale ← GetScale[$CDxSecondaryScale];
CDProperties.PutProp[vRef.properties, $CDxSecondaryScale, NEW[CDVScale.ScaleRec ← vRef.scale]];
vRef.intendedScale ← CDVScale.MakeScale[off: scale.off, nscale: scale.nscale, grid: vRef.scale.grid];
Repaint[vRef];
};
ENDCASE => NULL;
};
WriteLnScale: PROC [v: REF] = {
WITH v SELECT FROM
vRef: VRef => TerminalIO.WriteF1[" (scale: %g)\n", IO.int[vRef.scale.nscale]];
viewer: ViewerClasses.Viewer => WriteLnScale[viewer.data];
comm: CDSequencer.Command => WriteLnScale[comm.ref];
ENDCASE => TerminalIO.WriteLn[];
};
ChangeScale: PROC [vRef: VRef, newScale: INT] = {
newScale ← MIN[MAX[0, newScale], CDVScale.scaleNum-1];
IF vRef.scale.nscale = newScale THEN
TerminalIO.WriteRope["no scale change"]
ELSE {
oldDesignCenterOffset, newDesignCenterOffset: CD.Position;
viewerCenterOffset: CD.Position ← [vRef.viewer.cw/2, vRef.viewer.ch/2];
off: CD.Position ← vRef.scale.off;
dscale: CDVScale.ScaleRec;
CDDrawQueue.Flush[vRef.ct];
TerminalIO.WriteRope["change scale"];
dscale ← CDVScale.MakeScale[nscale: vRef.scale.nscale, grid: vRef.scale.grid];
oldDesignCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
dscale ← CDVScale.MakeScale[nscale: newScale, grid: vRef.scale.grid];
newDesignCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
off ← CDBasics.SubPoints[
CDBasics.AddPoints[off, oldDesignCenterOffset],
newDesignCenterOffset
];
dscale ← CDVScale.MakeScale[off: off, nscale: newScale, grid: vRef.scale.grid];
vRef.intendedScale ← dscale;
Repaint[vRef];
};
WriteLnScale[vRef.viewer];
};
ScaleUp: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
i: INT ← vRef.scale.nscale;
i ← IF i>0 THEN i-1 ELSE 0;
ChangeScale[vRef, i];
};
DoWithVRef[comm, Do]
};
ScaleDown: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {ChangeScale[vRef, vRef.scale.nscale+1]};
DoWithVRef[comm, Do]
};
MoveScreen: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
off: CD.Position;
CDDrawQueue.Flush[vRef.ct];
off.x ← vRef.scale.off.x-(comm.pos.x-comm.sPos.x);
off.y ← vRef.scale.off.y-(comm.pos.y-comm.sPos.y);
vRef.intendedScale ← CDVScale.MakeScale[off: off,nscale: vRef.scale.nscale,grid: vRef.scale.grid];
Repaint[vRef];
};
TerminalIO.WriteRope["move window\n"];
DoWithVRef[comm, Do]
};
GetViewerInt: PROC [viewer: ViewerClasses.Viewer, at: ATOM] RETURNS [i: INT ← -1] = {
WITH ViewerOps.GetViewer[viewer, at] SELECT FROM
ri: REF INT => i ← ri^;
ENDCASE => NULL;
};
GridInfoComm: PROC [comm: CDSequencer.Command] = {
GridRope: PROC [v: ViewerClasses.Viewer] RETURNS [r: Rope.ROPE] = {
r ← CDCommandOps.LambdaRope[GetViewerInt[viewer, $Grid], lambda]
};
g: INT ← -1;
lambda: INT ← comm.design.technology.lambda;
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer=NIL THEN TerminalIO.WriteRope["no viewer\n"]
ELSE {
TerminalIO.WriteF1["set grid (currently %g)\n", [rope[GridRope[viewer]]]];
SELECT PopUpSelection.Request[
choice: LIST["1", " 2", " 4", " 8", "16", "1/2", "default", "type lambda", "type int"],
header: "grid",
headerDoc: "distance used for snapping the cursor"] FROM
1 => g ← lambda;
2 => g ← 2*lambda;
3 => g ← 4*lambda;
4 => g ← 8*lambda;
5 => g ← 16*lambda;
6 => g ← lambda/2;
7 => g ← CDValue.FetchInt[boundTo: CDViewer.DesignOf[viewer], key: $CDxInitGrid, propagation: global];
8 => g ← MIN[INT[2600/lambda], TerminalIO.RequestInt["grid: "]]*lambda;
9 => g ← MIN[INT[2600], TerminalIO.RequestInt["grid: "]];
ENDCASE => g ← -1;
IF g>0 AND g<=2600 THEN {
ViewerOps.SetViewer[viewer: viewer, data: NEW[INT←g], op: $Grid];
TerminalIO.WriteF1[" grid set to %g \n", IO.rope[CDCommandOps.LambdaRope[g, lambda]]];
}
ELSE TerminalIO.WriteRope[" failed \n"];
};
};
SetSimplificationComm: PROC[comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
n: INT;
CDDrawQueue.Flush[vRef.ct];
n ← PopUpSelection.Request[
choice: LIST["very simplified", "simplified", "standard", "detailed", "very detailed", "show all"],
header: "viewer simplification treshold",
headerDoc: "the viewer simplification treshold is multiplied with the cell simplification treshold"
];
SELECT n FROM
1 => vRef.suppressFactorForCells ← 0.4;
2 => vRef.suppressFactorForCells ← 0.7;
3 => vRef.suppressFactorForCells ← 1;
4 => vRef.suppressFactorForCells ← 1.6;
5 => vRef.suppressFactorForCells ← 2.6;
6 => vRef.suppressFactorForCells ← 0;
ENDCASE => RETURN;
Repaint[vRef]
};
TerminalIO.WriteRope["set viewer simplification threshold\n"];
DoWithVRef[comm, Do]
};
TicksInfoComm: PROC[comm: CDSequencer.Command] = {
ticks, n: INT ← -2;
lambda: INT ← comm.design.technology.lambda;
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer=NIL THEN TerminalIO.WriteRope["no viewer\n"]
ELSE {
ticks ← GetViewerInt[viewer, $Ticks];
TerminalIO.WriteF1["input tick (currently%g)\n", IO.rope[CDCommandOps.LambdaRope[ticks, lambda]]];
n ← PopUpSelection.Request[
choice: LIST["off", " 4", " 8", " 16", " 32", "type", "type int"],
header: "Ticks",
headerDoc: "dots to help positioning; number for spacing of dots"
];
ticks ← -2;
SELECT n FROM
1 => ticks ← 0;
2 => ticks ← 4*lambda;
3 => ticks ← 8*lambda;
4 => ticks ← 16*lambda;
5 => ticks ← 32*lambda;
6 => {
n: INT ← TerminalIO.RequestInt["ticks: "];
IF n>=0 AND n<=LAST[INTEGER]/lambda-1 THEN ticks ← n*lambda
};
7 => {
n: INT ← TerminalIO.RequestInt["ticks (int): "];
IF n>=0 AND n<=LAST[INTEGER]-1 THEN ticks ← n
};
ENDCASE => NULL;
ViewerOps.SetViewer[viewer: viewer, data: NEW[INT←ticks], op: $Ticks];
IF ticks<-1 THEN TerminalIO.WriteRope[" failed\n"]
ELSE IF ticks<=0 THEN TerminalIO.WriteRope[" ticks off\n"]
ELSE TerminalIO.WriteF1[" ticks set to %g \n", IO.rope[CDCommandOps.LambdaRope[ticks, lambda]]]
};
};
InstanceNames: PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm];
TerminalIO.WriteRope["display instance names\n"];
IF v#NIL THEN
ViewerOps.PaintViewer[v, client, FALSE, $DrawInstanceNames]
};
SignalNames: PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
TerminalIO.WriteRope["display signal names\n"];
IF v#NIL THEN
ViewerOps.PaintViewer[v, client, FALSE, $DrawSignalNames]
};
GetOppositViewer: PROC [comm: CDSequencer.Command] RETURNS [ViewerClasses.Viewer] = {
--gets viewer on different screen if possible,
--else different viewer, if possible...
vl: CDViewer.ViewerList = CDViewer.ViewersOf[comm.design];
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
onColor: BOOL = (viewer=NIL OR viewer.column=color);
FOR l: CDViewer.ViewerList ← vl, l.rest WHILE l#NIL DO
IF ~l.first.iconic THEN
IF (l.first.column=color)#onColor THEN RETURN [l.first];
ENDLOOP;
FOR l: CDViewer.ViewerList ← vl, l.rest WHILE l#NIL DO
IF ~l.first.iconic THEN
IF l.first.column#viewer.column THEN RETURN [l.first];
ENDLOOP;
FOR l: CDViewer.ViewerList ← vl, l.rest WHILE l#NIL DO
IF ~l.first.iconic THEN
IF l.first#viewer THEN RETURN [l.first];
ENDLOOP;
RETURN [viewer];
};
ShowRectX: PROC [comm: CDSequencer.Command] = {
SmallScale: PROC [comm: CDSequencer.Command] RETURNS [BOOL] = {
min: CD.Number = 30;
RETURN [min>ABS[comm.pos.x-comm.sPos.x] AND min>ABS[comm.pos.y-comm.sPos.y]]
};
viewer: ViewerClasses.Viewer ~ GetOppositViewer[comm];
TerminalIO.WriteRope["position a viewer\n"];
IF viewer#NIL THEN
IF SmallScale[comm] THEN CDViewer.ShowPosition[viewer: viewer, pos: comm.sPos]
ELSE CDViewer.ShowAndScale[viewer: viewer, rect: CDBasics.ToRect[comm.pos, comm.sPos]];
};
RestoreViewComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.WriteRope["restore previous scale\n"];
RestoreScale[CDViewer.GetViewer[comm]];
};
ShowRect: PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm];
TerminalIO.WriteRope["scale viewer"];
SaveScale[viewer];
IF comm.pos=comm.sPos THEN CDViewer.ShowPosition[viewer, comm.pos]
ELSE CDViewer.ShowAndScale[viewer, CDBasics.ToRect[comm.pos, comm.sPos]];
WriteLnScale[viewer];
};
ResetScaleComm: PROC [comm: CDSequencer.Command] = {
ResetScaleAll: PROC [viewer: ViewerClasses.Viewer] = {
b: CD.Rect;
TerminalIO.WriteRope["reset scale (view all)"];
b ← CDCommandOps.BoundingBox[CDViewer.DesignOf[viewer]];
IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b];
WriteLnScale[viewer];
};
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer#NIL THEN {
SaveScale[viewer];
ResetScaleAll[viewer];
};
};
ResetScaleToSelectedComm: PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
TerminalIO.WriteRope["reset scale to selection"];
IF viewer#NIL THEN {
b: CD.Rect ← CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: TRUE];
IF CDBasics.NonEmpty[b] THEN {
SaveScale[viewer];
CDViewer.ShowAndScale[viewer: viewer, rect: b];
WriteLnScale[viewer];
RETURN;
};
};
TerminalIO.WriteRope[" no selection\n"];
};
ResetScaleToPushedComm: PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
IF viewer#NIL THEN {
b: CD.Rect;
SaveScale[viewer];
TerminalIO.WriteRope["reset scale (to view all of pushed cell)"];
b ← CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: FALSE];
IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b];
WriteLnScale[viewer];
};
};
ShowViewers: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$ShowViewers, CDBasics.universe]];
};
TerminalIO.WriteRope["show viewers\n"];
DoWithVRef[comm, Do]
};
SplitViewer: PROC [comm: CDSequencer.Command] = {
TerminalIO.WriteRope["split viewer\n"];
[] ← CDViewer.CreateViewer[comm.design]
};
SetCellSimplification: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
scale: CDVScale.ScaleRec ← vRef.scale;
FOR l: CD.InstanceList ← CDOps.InstList[comm.design], l.rest WHILE l#NIL DO
IF l.first.selected AND CDCells.IsCell[l.first.ob] THEN {
simplifyOn: CD.Number ← CDVScale.DesignToViewerScalar[scale, l.first.ob.size.y];
CDCells.SetSimplificationTreshhold[l.first.ob, simplifyOn, TRUE];
CDOps.RedrawInstance[comm.design, l.first];
};
ENDLOOP;
};
TerminalIO.WriteRope["put visibility threshold to current scale\n"];
DoWithVRef[comm, Do]
};
EnforcePanel: PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer;
TerminalIO.WriteRope["enforce a control panel\n"];
v ← CDPanel.CreatePanel[comm.design];
IF v#NIL THEN {
IF v.iconic THEN ViewerOps.OpenIcon[v]
ELSE ViewerOps.BlinkIcon[v, 1, 1, 200]
};
};
DrawEnvComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw environment of pushed cells"];
IF vRef#NIL THEN {
vRef.environment ← TRUE;
CDProperties.PutProp[comm.design, $CDxDrawEnvironment, NIL];
Repaint[vRef];
};
};
DontDrawEnvComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw environment of pushed cells"];
IF vRef#NIL THEN {
vRef.environment ← FALSE;
CDProperties.PutProp[comm.design, $CDxDrawEnvironment, $FALSE];
Repaint[vRef];
};
};
DrawSymbolicsComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw symbolic objects"];
IF vRef#NIL THEN {
vRef.symbolics ← TRUE;
CDProperties.PutProp[comm.design, $CDxDrawSymbolics, NIL];
Repaint[vRef];
};
};
DontDrawSymbolicsComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw symbolic objects"];
IF vRef#NIL THEN {
vRef.symbolics ← FALSE;
CDProperties.PutProp[comm.design, $CDxDrawSymbolics, $FALSE];
Repaint[vRef];
};
};
DrawBordersComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw with borders"];
IF vRef#NIL THEN {
vRef.borders ← TRUE;
CDProperties.PutProp[comm.design, $CDxSkipBorder, $FALSE];
Repaint[vRef];
};
};
DontDrawBordersComm: PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw borders"];
IF vRef#NIL THEN {
vRef.borders ← FALSE;
CDProperties.PutProp[comm.design, $CDxSkipBorder, NIL];
Repaint[vRef];
};
};
SetNewVersion: PROC [design: CD.Design, new: BOOLTRUE] = {
IF design#NIL THEN
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf[design], vl.rest WHILE vl#NIL DO
IF vl.first.newVersion#new THEN {
vl.first.newVersion ← new;
ViewerOps.PaintViewer[vl.first, caption]
};
ENDLOOP
};
SetNewEvent: CDEvents.EventProc = {
TRUSTED {Process.Detach[FORK SetNewVersion[design, TRUE]]};
};
AfterOutputEvent: CDEvents.EventProc = {
TRUSTED {Process.Detach[FORK SetNewVersion[design, FALSE]]};
};
NoteProfileChange: UserProfile.ProfileChangedProc = {
IF reason=edit THEN {
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf[NIL], vl.rest WHILE vl#NIL DO
d: CD.Design ← CDViewer.DesignOf[vl.first];
IF d#NIL THEN vl.first.tipTable ← CDEnvironment.GetTipTable[d];
ENDLOOP
};
};
UserProfile.CallWhenProfileChanges[NoteProfileChange];
CDPanel.DefineButton[tech: NIL, name: " new view ", proc: SplitViewer, queue: dontQueue, topLine: TRUE];
CDSequencer.ImplementCommand[$ScaleLessDetail, ScaleDown,, dontQueue];
CDSequencer.ImplementCommand[$ScaleMoreDetail, ScaleUp,, dontQueue];
CDSequencer.ImplementCommand[$MoveScreen, MoveScreen,, dontQueue];
CDSequencer.ImplementCommand[$DisplayNames, SignalNames,, doQueue];
CDSequencer.ImplementCommand[$DisplayInstanceNames, InstanceNames,, doQueue];
CDSequencer.ImplementCommand[$ShowRectX, ShowRectX,, dontQueue];
CDSequencer.ImplementCommand[$ShowRect, ShowRect,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleAll, ResetScaleComm,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleTop, ResetScaleToPushedComm,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleSel, ResetScaleToSelectedComm,, dontQueue];
CDSequencer.ImplementCommand[$DisplayViewers, ShowViewers,, doQueue];
CDSequencer.ImplementCommand[$SplitViewer, SplitViewer,, dontQueue];
CDSequencer.ImplementCommand[$GridInfo, GridInfoComm,, dontQueue];
CDSequencer.ImplementCommand[$TicksInfo, TicksInfoComm,, doQueue];
CDSequencer.ImplementCommand[$SetSimplification, SetSimplificationComm,, dontQueue];
CDSequencer.ImplementCommand[$RestoreScale, RestoreViewComm,, dontQueue];
CDSequencer.ImplementCommand[$SetCellSimplification, SetCellSimplification];
CDSequencer.ImplementCommand[$EnforcePanel, EnforcePanel,, doQueue];
CDSequencer.ImplementCommand[$ViewEnv, DrawEnvComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNEnv, DontDrawEnvComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewSym, DrawSymbolicsComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNSym, DontDrawSymbolicsComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewBord, DrawBordersComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNBord, DontDrawBordersComm,, dontQueue];
CDEvents.RegisterEventProc[event: $AfterOutput, proc: AfterOutputEvent];
CDEvents.RegisterEventProc[event: $SetEdited, proc: SetNewEvent];
END.