NectarineCommand.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Giordano Bruno Beretta, April 11, 1986 7:57:41 pm PST
gbb August 22, 1986 12:57:51 pm PDT
Implements the Nectarine commands for interactive use in ChipNDale. Fuzzless and sweeter than peaches.
DIRECTORY
Atom USING [PutPropOnList],
CD USING [Design, Number, Rect],
CDCommandOps USING [BoundingBox, CallWithResource],
CDEvents USING [EventProc, RegisterEventProc],
CDPanel USING [DefineButton, DefineNewLine],
CDPanelExtras USING [DefineTextEntry, FromDisplayRope],
CDProperties USING [PutDesignProp, RegisterProperty],
CDSequencer USING [Command, ImplementCommand],
CDValue USING [RegisterKey, Store],
CDViewer USING [ViewerList, ViewersOf, VisibleRect],
Commander USING [CommandProc, Handle, Register],
CStitching USING [NewTesselation, Tesselation, FindTile],
Imager USING [metersPerPoint, Rectangle],
IO USING [int, PutF, PutFR, real],
MessageWindow USING [Append, Blink, Clear],
Nectarine USING [communicationsFailure, DoInterpress, invalidPrinter, Print],
Rope USING [ActionType, Equal, Fetch, IsEmpty, Length, Map, ROPE, SkipTo, Substr],
RopeFile USING [Create],
SafeStorage USING [GetCanonicalReferentType, Type],
SweepCollectableStorage USING [EnumerateCollectableStorage, InfoProc],
TEditDocument USING [Selection],
TEditInputOps USING [Break, CallWithLocks],
TerminalIO USING [WriteRope],
TextNode USING [Ref],
TiogaAccess USING [Create, GetInternalProp, Put, TiogaChar, Writer, WriteSelection],
ViewerClasses USING [Viewer];
NectarineCommand: CEDAR PROGRAM
IMPORTS Atom, CDCommandOps, CDEvents, CDPanel, CDPanelExtras, CDProperties, CDSequencer, CDValue, CDViewer, Commander, CStitching, IO, MessageWindow, Nectarine, Rope, RopeFile, SafeStorage, SweepCollectableStorage, TEditInputOps, TerminalIO, TiogaAccess
~ BEGIN
masterKey: ATOM = $Nectarine;
whatKey: ATOM = $NectarineWhat;
whereKey: ATOM = $NectarineWhere;
copiesKey: ATOM = $NectarineCopies;
CSTile: SafeStorage.Type;
ROPE: TYPE ~ Rope.ROPE;
NectarineCommand: PROC [comm: CDSequencer.Command] ~ BEGIN
Called by ChipNDale upon activation of the command.
abort: REF BOOLNEW [BOOLFALSE];
DoIt: PROC [comm: CDSequencer.Command] ~ BEGIN
Protected procedure.
what: ROPE ~ CDPanelExtras.FromDisplayRope [comm.design, whatKey];
where: ROPE ~ CDPanelExtras.FromDisplayRope [comm.design, whereKey];
howMany: INT ← 0;
cropKey, printKey: ATOM;
masterName: ROPENIL; -- NARROW [CDProperties.GetDesignProp [comm.design, masterKey]];
usedField: Imager.Rectangle;
Interpret what.
SELECT TRUE FROM
what.Equal ["Design", FALSE] => cropKey ← $NectarineAll;
what.Equal ["Wysiwyg", FALSE] => cropKey ← $NectarineWysiwyg;
what.Equal ["Selection", FALSE] => cropKey ← $NectarineSel;
ENDCASE => BEGIN
TerminalIO.WriteRope ["Unknown cropping option.\n"]; ERROR ABORTED
END;
Interpret where.
SELECT TRUE FROM
where.Equal ["ColorVersatec", FALSE] => BEGIN
msg: ROPE ~ "Are you sure you did not want to use the printer server 'PeachExpand' (see doc)?";
MessageWindow.Clear [];
MessageWindow.Append [msg]; MessageWindow.Blink [];
TerminalIO.WriteRope [msg]; TerminalIO.WriteRope ["\n"];
printKey ← $NColorVersatec
END;
where.Equal ["Color400", FALSE] => printKey ← $NColor400;
where.Equal ["Raven300", FALSE] => printKey ← $NRaven300;
where.Equal ["Bw400", FALSE] => printKey ← $NBw400;
where.Equal ["Versatec", FALSE] => printKey ← $NVersatec;
where.Equal ["Tioga doc", FALSE] => printKey ← $NPasteInTioga;
where.Equal ["IP only", FALSE] => printKey ← $NmasterOnly;
where.Equal ["PeachExpand", FALSE] => BEGIN
TerminalIO.WriteRope ["I will create an Interpress master, which I will use to produce a PD file. I will then send it to the expansion server to create a bitmap, and from there I will send it to the color Versatec. You will have to delete the temporary files manually.\n"];
printKey ← $NPeachExpand
END;
ENDCASE => {TerminalIO.WriteRope ["Unknown printer.\n"]; ERROR ABORTED};
Interpret how many.
BEGIN
nrRopeRaw: ROPE ~ CDPanelExtras.FromDisplayRope [comm.design, copiesKey];
nrPos: INTEGER ~ nrRopeRaw.SkipTo [0, "0123456789"];
nrRope: ROPE ~ nrRopeRaw.Substr [nrPos, nrRopeRaw.Length[]-nrPos];
IF (NOT nrRope.IsEmpty []) THEN BEGIN-- default: 0
howMany ← (ORD [nrRope.Fetch[0]] - ORD ['0]);
FOR i: INT IN [1 .. nrRopeRaw.Length[]) DO
howMany ← howMany * 10 + (ORD [nrRopeRaw.Fetch[i]] - ORD ['0])
ENDLOOP
END
END; -- Interpret how many
Create an Interpress master if necessary.
IF (masterName.IsEmpty []) THEN BEGIN
cW: CD.Rect; -- ChipNDale window
l: CD.Number ~ comm.design.technology.lambda;
SELECT cropKey FROM
$NectarineAll => cW ← CDCommandOps.BoundingBox [comm.design];
$NectarineSel => cW ← CDCommandOps.BoundingBox [comm.design, TRUE];
$NectarineWysiwyg => BEGIN
viewers: CDViewer.ViewerList = CDViewer.ViewersOf [comm.design];
goodViewer: ViewerClasses.Viewer;
good: INT ← 0;
IF (viewers = NIL) THEN BEGIN
TerminalIO.WriteRope ["You do not see anything of this design !\n"];
ERROR ABORTED
END;
FOR v: CDViewer.ViewerList ← viewers, v.rest WHILE v # NIL DO
IF NOT v.first.iconic THEN {goodViewer ← v.first; good ← good.SUCC}
ENDLOOP;
SELECT good FROM
0 => {TerminalIO.WriteRope ["You do not see anything !\n"]; ERROR ABORTED};
> 1 => TerminalIO.WriteRope ["WARNING: you see more than one viewer. I pick one at random\n"];
ENDCASE => NULL;
cW ← CDViewer.VisibleRect [goodViewer]
END;
ENDCASE => ERROR;
The following is not a hack. In schematics the cells may have a border. On the screen this border is one pixel wide, but with Interpress we have to specify a concrete width in millimetres. We choose to make it ¼ l wide. If the border has a width, it takes some finite amount of space on the paper. It would be natural to use this space inside the cell. However, the designers exploit the fact that on the screen the border has no width and put text flush to the border. In order to preserve such text, Nectarine is forced to print the border outside the cell. This means, that the border can now be outside the field on the medium. This is why here we cheat and increase the window by l on each side.
cW ← [x1: cW.x1 - l, x2: cW.x2 + l, y1: cW.y1 - l, y2: cW.y2 + l];
[masterName, usedField] ← Nectarine.DoInterpress [design: comm.design,
chipNDaleWindow: cW,
clip: (cropKey = $NectarineWysiwyg) OR (cropKey = $NectarineSel),
onlySel: (cropKey = $NectarineSel),
abortFlag: abort];
CDProperties.PutDesignProp [comm.design, masterKey, masterName]
END; -- create Interpress master
Print if asked to do so.
SELECT printKey FROM
$NmasterOnly => NULL;
$NPasteInTioga => Paste [masterName, usedField];
ENDCASE => [] ← Nectarine.Print [masterName, printKey, howMany
! Nectarine.invalidPrinter => ERROR; Nectarine.communicationsFailure => NULL];
TerminalIO.WriteRope ["Done.\n"]
END; -- DoIt
[] ← CDCommandOps.CallWithResource [DoIt, comm, $Nectarine, abort]
END; -- NectarineCommand
Paste: PROC [name: ROPE, bb: Imager.Rectangle] ~ BEGIN
Pastes the Interpress master in file name and with bounding box bb at the current Tioga selection. The appropriate scaling is being implemented in Tioga and in TiogaToInterpress.
I misteri della vita e della morte.
master: ROPE ~ RopeFile.Create [name]; -- the Interpress master desguised as a rope
document: TiogaAccess.Writer ← TiogaAccess.Create []; -- a working area Tioga doc
vanillaChar: TiogaAccess.TiogaChar = [0, 0C, ALL [FALSE], NIL, TRUE, FALSE, 0, NIL];
dummy, ip, caption: TiogaAccess.TiogaChar ← vanillaChar;
space: REAL ~ 8.0 * Imager.metersPerPoint * 1000.0; -- in mm
WriteRope: PROC [r: ROPE, attr: TiogaAccess.TiogaChar] ~ BEGIN
Writes into document the characters in r using the attributes of the sample character attr.
PutChar: Rope.ActionType ~ {attr.char ← c; document.Put [attr]};
[] ← Rope.Map [base: r, action: PutChar]
END; -- WriteRope
PutProp: PROC [char: TiogaAccess.TiogaChar, prop: ATOM, val: ROPE] RETURNS [TiogaAccess.TiogaChar] ~ BEGIN
Safely attaches a property with key prop and value val to the character char.
char.propList ← Atom.PutPropOnList [propList: char.propList, prop: prop, val: TiogaAccess.GetInternalProp [prop, val]];
RETURN [char]
END; -- PutProp
Stuff: PROC [root: TextNode.Ref, tSel:TEditDocument.Selection] ~ BEGIN
Takes the working area Tioga document document and stuffs it into the current selection.
TEditInputOps.Break []; TiogaAccess.WriteSelection [document]
END; -- Stuff
Insert block node containing a CR. Why???
dummy.endOfNode ← TRUE; WriteRope ["\n", dummy];
Insert an artworkFigure node, with a postfix prop for lead and ident, bounds and with Artwork containing the IP master. The node contains a rope which becomes visible when ArtworkInterpress is off.
dummy.endOfNode ← FALSE; dummy.looks['n] ← TRUE;
WriteRope ["[Artwork node; type 'ArtworkInterpress on' to command tool]", dummy];
ip.char ← '\n; ip.endOfNode ← TRUE; ip.deltaLevel ← 1;
ip.format ← $artworkFigure; -- it is an artwork node
ip ← PutProp [ip, $Postfix, IO.PutFR ["%g mm topLeading %g mm topIndent %g mm bottomLeading", IO.real [bb.y+bb.h+space], IO.real [bb.y+bb.h+space], IO.real [-bb.y+space/2.0]]]; -- margin in the document
ip ← PutProp [ip, $Bounds, IO.PutFR ["%g mm xmin %g mm ymin %g mm xmax %g mm ymax", IO.real [bb.x], IO.real [bb.y], IO.real [bb.x+bb.w], IO.real [bb.y+bb.h]]]; -- set the bounding box
ip ← PutProp [ip, $Artwork, "Interpress"]; -- the artwork type is "Interpress"
ip ← PutProp [ip, $Interpress, master]; -- the Interpress master desguised as a rope
ip ← PutProp [ip, $Fit, "TRUE"]; -- fit the figure to the margins of the sibling node
document.Put [ip];
Insert a nested artworkCaption node with a hint rope.
caption.looks['i] ← TRUE; WriteRope ["Insert caption here", caption];
caption.char ← 0C; caption.format ← $artworkCaption; caption.endOfNode ← TRUE;
document.Put [caption];
Take the contents of document and stuff it into the current Tioga selection. If there is no selection, nothing happens.
TEditInputOps.CallWithLocks [Stuff]
END; -- Paste
Registations: PROC [] ~ BEGIN
defaultCrops: LIST OF ROPE ~ LIST ["Design", "Selection", "Wysiwyg"];
defaultPrinters: LIST OF ROPE ~ LIST ["PeachExpand", "Tioga doc", "Raven300", "Bw400", "Versatec", "ColorVersatec", "Color400", "IP only"];
[] ← CDProperties.RegisterProperty [masterKey, masterKey];
CDValue.RegisterKey [key: whatKey, registrationKey: masterKey];
CDValue.RegisterKey [key: whereKey, registrationKey: masterKey];
CDValue.RegisterKey [key: copiesKey, registrationKey: masterKey];
CDValue.Store [key: whatKey, value: defaultCrops];
CDValue.Store [key: whereKey, value: defaultPrinters];
CDValue.Store [key: copiesKey, value: "1"];
CDPanel.DefineButton [name: "Nectarine", border: TRUE, command: $NectarineCmd];
CDPanelExtras.DefineTextEntry [cdValueKey: whatKey, button: "What:", width: 60, editable: FALSE];
CDPanelExtras.DefineTextEntry [cdValueKey: whereKey, button: "Where:", width: 90, editable: FALSE];
CDPanelExtras.DefineTextEntry [cdValueKey: copiesKey, button: "Copies:", width: 30];
CDPanel.DefineNewLine [];
CDSequencer.ImplementCommand [key: $NectarineCmd, proc: NectarineCommand, queue: doQueue];
Commander.Register [key: "NCount", proc: Count, doc: "Counts corner stitching tiles"];
CDEvents.RegisterEventProc [proc: InvalidateInterpress, event: $AfterChange]
END; -- Registrations
InvalidateInterpress: CDEvents.EventProc ~ BEGIN
[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOLFALSE]
Deletes a reference to a master when the design has been edited.
CDProperties.PutDesignProp [design, masterKey, NIL]
END; -- InvalidateInterpress
Count: Commander.CommandProc ~ BEGIN
[cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
PerObject: SweepCollectableStorage.InfoProc ~ BEGIN
[type: SafeStorage.Type, size: INT, object: LONG CARDINAL] RETURNS [continue: BOOLEAN]
IF type = CODE [CStitching.Tesselation] THEN tessCount ← tessCount + 1
ELSE IF type = CSTile THEN tileCount ← tileCount + 1;
RETURN [TRUE]
END; -- PerObject
tessCount: INT ← 0;
tileCount: INT ← 0;
TRUSTED { SweepCollectableStorage.EnumerateCollectableStorage [PerObject] };
cmd.out.PutF ["tesselations = %g\n", IO.int [tessCount]];
cmd.out.PutF ["tiles = %g\n", IO.int [tileCount]]
END; -- Count
CSTile ← SafeStorage.GetCanonicalReferentType [CStitching.NewTesselation[].FindTile[[0,0]]];
Registations [];
TerminalIO.WriteRope ["Nectarine package loaded.\n"]
END.