<<>> <> <> <> <> <> <> <<>> <<>> DIRECTORY Commander, BasicTime, DecomposerRegistry, DecomposerRegistryCodes, ImagerError, InterpressInterpreter, IO, IPAttributes, IPMaster, IPInstructions, IPInterpreter, IPVector, Real, RefTab, Rope; IPAttributesImpl: CEDAR PROGRAM IMPORTS Commander, DecomposerRegistry, BasicTime, IO, IPAttributes, IPInstructions, IPInterpreter, Real, RefTab, Rope EXPORTS IPAttributes = BEGIN ROPE: TYPE = Rope.ROPE; Attribute: TYPE = DecomposerRegistry.Attribute; Value: TYPE = DecomposerRegistry.Value; ValueRep: TYPE = DecomposerRegistry.ValueRep; ValueTag: TYPE = DecomposerRegistry.ValueTag; ValueSeq: TYPE = DecomposerRegistry.ValueSeq; ValueSeqRep: TYPE = DecomposerRegistry.ValueSeqRep; Name: TYPE = IPInstructions.Names; AttrEntry: TYPE = REF AttrEntryRep; AttrEntryRep: TYPE = RECORD [ attr: Attribute, proc: IPToValueProc, names: LIST OF Name <> ]; baseTime: BasicTime.GMT = BasicTime.Pack[[year: 1970, month: January, day: 1, hour: 0, minute: 0, second: 0, zone: 0, dst: no]]; <<>> GetAttributeProc: TYPE = PROC [attr: Attribute, proc: IPToValueProc, names: LIST OF Name]; <> <<>> MapRegisteredAttributes: PROC [proc: GetAttributeProc] = { <> KeyVal: RefTab.EachPairAction = { WITH val SELECT FROM ent: AttrEntry => proc[ent.attr, ent.proc, ent.names]; ENDCASE; }; [] ¬ RefTab.Pairs[attrTable, KeyVal]; -- call KeyVal for every pair in the table }; <<>> IPToValueProc: TYPE = PROC [attr: Attribute, iv: IPVector.Vector, names: LIST OF Name] RETURNS [seq: ValueSeq _ NIL]; <> <<>> RegisterAttr: PROC [attr: Attribute, proc: IPToValueProc, names: LIST OF IPInstructions.Names] = { <> new: AttrEntry = NEW[AttrEntryRep ¬ [attr: attr, proc: proc, names: names]]; [] ¬ RefTab.Store[attrTable, attr, new]; }; GetIPToValue: PROC [attr: Attribute] RETURNS [proc: IPToValueProc] = { <> WITH RefTab.Fetch[attrTable, attr].val SELECT FROM ae: AttrEntry => RETURN [ae.proc]; ENDCASE => RETURN [NIL]; }; <<>> GetProp: PROC [iv: IPVector.Vector, names: LIST OF IPInstructions.Names] RETURNS [found: BOOL ¬ FALSE, value: IPVector.Any] ~ { v: IPVector.Vector ¬ iv; FOR tail: LIST OF IPInstructions.Names ¬ names, tail.rest UNTIL tail = NIL DO nameRope: ROPE ~ IPInstructions.NameRopeFromName[tail.first]; name: IPVector.Any ~ IF Rope.Match["*/*", nameRope] THEN IPInterpreter.VectorFromName[nameRope] ELSE nameRope; [found, value] ¬ IPInterpreter.GetProp[v, name]; IF found AND tail.rest # NIL THEN { v ¬ IPInterpreter.VectorFromAny[value]; }; ENDLOOP; }; GenericCard: IPToValueProc = { <> any: IPVector.Any; found: BOOL ¬ FALSE; [found, any] ¬ GetProp[iv, names]; IF found THEN { seq ¬ NEW[ValueSeqRep[1]]; seq[0] ¬ DecomposerRegistry.MakeCardVal[IPInterpreter.CardinalFromAny[any]]; }; }; GenericString: IPToValueProc = { <> found: BOOL ¬ FALSE; any: IPVector.Any; [found, any] ¬ GetProp[iv, names]; IF found THEN { seq ¬ NEW[ValueSeqRep[1]]; seq[0] ¬ DecomposerRegistry.MakeTextVal[IPInterpreter.RopeFromVector[IPInterpreter.VectorFromAny[any]]]; }; }; <> <<>> debug: IO.STREAM ¬ NIL; IPAttrDebugCommand: Commander.CommandProc = { IF debug = NIL THEN {debug¬cmd.err; msg ¬ "on"} ELSE {debug¬NIL; msg ¬ "off"}; }; Plex: IPToValueProc = { <> <> value: REF ~ GetProp[iv, names].value; WITH value SELECT FROM text: ROPE => { plex: DecomposerRegistryCodes.Plex ¬ unknown; SELECT TRUE FROM Rope.Equal["simplex", text, FALSE] => plex ¬ simplex; Rope.Equal["duplex", text, FALSE] => plex ¬ duplex; Rope.Equal["tumbleDuplex", text, FALSE] => plex ¬ tumble; Rope.Equal["duplexHeadToToe", text, FALSE] => { <> plex ¬ tumble; }; ENDCASE; seq ¬ NEW[ValueSeqRep[1]]; seq[0] ¬ DecomposerRegistry.MakeCardVal[ORD[plex]]; }; ENDCASE; }; Staple: IPToValueProc = { <> <> value: REF ~ GetProp[iv, names].value; WITH value SELECT FROM text: ROPE => { staple: DecomposerRegistryCodes.Staple ¬ unknown; SELECT TRUE FROM Rope.Equal["corner", text, FALSE] => staple ¬ singlePortraitStapling; Rope.Equal["cornerStaple", text, FALSE] => staple ¬ singlePortraitStapling; Rope.Equal["none", text, FALSE] => staple ¬ none; Rope.Equal["finishingNone", text, FALSE] => staple ¬ none; ENDCASE; seq ¬ NEW[ValueSeqRep[1]]; seq[0] ¬ DecomposerRegistry.MakeCardVal[ORD[staple]]; }; ENDCASE; }; ImageShift: IPToValueProc = { <> <> any: IPVector.Any ¬ GetProp[iv, names].value; IF any # NIL THEN { shift: REAL _ IPInterpreter.RealFromAny[any]*1000.0; -- meters to mm seq _ NEW[DecomposerRegistry.ValueSeqRep[1]]; seq[0] _ DecomposerRegistry.MakeIntVal[Real.Round[shift]] }; }; Media: IPToValueProc = { <> OPEN DecomposerRegistry; Any: TYPE ~ IPInterpreter.Any; Vector: TYPE ~ IPInterpreter.Vector; VectorShape: TYPE ~ IPInterpreter.VectorShape; Cardinal: TYPE ~ IPInterpreter.Cardinal; Identifier: TYPE ~ IPInterpreter.Identifier; RealFromAny: PROC [Any] RETURNS [REAL] ~ IPInterpreter.RealFromAny; IdentifierFromAny: PROC [Any] RETURNS [ROPE] ~ IPInterpreter.IdentifierFromAny; VectorFromAny: PROC [Any] RETURNS [Vector] ~ IPInterpreter.VectorFromAny; Shape: PROC [Vector] RETURNS [VectorShape] ~ IPInterpreter.Shape; any: Any ¬ GetProp[iv, names].value; IF any # NIL THEN { milliMetersPerMeter: REAL = 1000.0; defaultXSize: CARD32 = 216; -- see XNSS359106, p. 2-4 defaultYSize: CARD32 = 279; -- see XNSS359106, p. 2-4 defaultMedium: Identifier = ""; defaultColor: Identifier = ""; defaultWeight: CARD32 = 0; <> <> <> mediaVec: Vector ¬ VectorFromAny[any]; <> mediaShape: VectorShape ¬ Shape[mediaVec]; size: CARDINAL = mediaShape.size; lb: Cardinal ¬ mediaShape.lowerBound; ub: Cardinal ¬ mediaShape.lowerBound+size-1; seq ¬ NEW[ValueSeqRep[size]]; <> FOR i: Cardinal IN [lb..ub] DO -- for every mediumDescription next: Any ¬ IPInterpreter.Get[mediaVec, i]; -- get the next mediumDescription nextMedium: Vector ¬ VectorFromAny[next]; -- mediumDescription is a 5 element Vector innerSeq: ValueSeq ¬ NEW[ValueSeqRep[5]]; -- make a 5 element sequence of Values innerVal: Value ¬ NEW[ValueRep.sequence ¬ [sequence[innerSeq]]]; -- make a sequence Value to put innerSeq in seq[i-lb] ¬ innerVal; -- put this sequence value in the RETURN sequence <> <> any ¬ GetProp[nextMedium, LIST[mediumXSize] ].value; innerSeq[0] ¬ MakeCardVal[IF any # NIL THEN Real.Round[RealFromAny[any]*milliMetersPerMeter] ELSE defaultXSize]; any ¬ GetProp[nextMedium, LIST[mediumYSize] ].value; innerSeq[1] ¬ MakeCardVal[IF any # NIL THEN Real.Round[RealFromAny[any]*milliMetersPerMeter] ELSE defaultYSize]; any ¬ GetProp[nextMedium, LIST[mediumName] ].value; innerSeq[2] ¬ MakeTextVal[IF any # NIL THEN IdentifierFromAny[any] ELSE defaultMedium]; any ¬ GetProp[nextMedium, LIST[color] ].value; innerSeq[3] ¬ MakeTextVal[IF any # NIL THEN IdentifierFromAny[any] ELSE defaultColor]; any ¬ GetProp[nextMedium, LIST[weight] ].value; innerSeq[4] ¬ MakeCardVal[IF any # NIL THEN Real.Fix[RealFromAny[any]] ELSE defaultWeight]; ENDLOOP; }; }; PrintVector: PROC [out: IO.STREAM, iv: IPVector.Vector] ~ { OPEN IPInstructions, IPInterpreter; k,v: ROPE; shape: VectorShape ¬ Shape[iv]; lb: Cardinal ¬ shape.lowerBound; ub: Cardinal ¬ shape.lowerBound+shape.size-1; IO.PutF1[out, "[%g: ", IO.card[shape.size] ]; FOR i: Cardinal IN [lb..ub] DO next: Any ¬ Get[iv, i]; nextType: TypeCode ¬ Type[next]; SELECT nextType FROM null => k ¬ "null"; number => { <> n: Number ¬ NumberFromAny[next]; SELECT n.tag FROM zero => k ¬ "zero"; int => k ¬ IO.PutFR1["%g", IO.int[IntegerFromAny[n] ]]; real => k ¬ IO.PutFR1["%g", IO.real[RealFromAny[n] ]]; rational => { nn, nd: INT; nr: NumberRep ~ n­; WITH nr: nr SELECT FROM rational => {nn ¬ nr.n; nd ¬ nr.d;}; ENDCASE; k ¬ IO.PutFR["n: %g, d: %g", IO.int[nn], IO.int[nd] ]; }; ENDCASE => k ¬ "unknown Number type"; }; identifier => k ¬ IdentifierFromAny[next]; vector => { PrintVector[out, VectorFromAny[next] ]; k ¬ NIL; -- prevent redundant printing }; operator => { --print operator.type op: Operator ¬ OperatorFromAny[next]; k ¬ IO.PutFR1["%g", IO.atom[op.class.type] ]; }; transformation => k ¬ "transformation"; color => k ¬ "color"; trajectory => k ¬ "trajectory"; outline => k ¬ "outline"; font =>k ¬ "font"; clipper => k ¬ "clipper"; ENDCASE => k ¬ "unknown"; IF k#NIL THEN IO.PutRope[out, k]; IF i < ub THEN IO.PutRope[out, ", "]; -- avoid comma on last element ENDLOOP; IO.PutRope[out, "]"]; }; PutAttributeValue: PROC [stream: IO.STREAM, value: Value] = { <> WITH value SELECT FROM cardinal: REF ValueRep.cardinal => IO.Put1[stream, [cardinal[cardinal.cardinal]]]; integer: REF ValueRep.integer => IO.Put1[stream, [integer[integer.integer]]]; boolean: REF ValueRep.boolean => IO.Put1[stream, [boolean[boolean.boolean]]]; real: REF ValueRep.real => IO.Put1[stream, [real[real.real]]]; text: REF ValueRep.text => IO.PutRope[stream, text.text]; time: REF ValueRep.time => IO.Put1[stream, [time[time.time]]]; sequence: REF ValueRep.sequence => { IO.PutRope[stream, "["]; FOR i: NAT IN [0..sequence.sequence.len) DO IF i > 0 THEN IO.PutRope[stream, ", "]; PutAttributeValue[stream, sequence.sequence[i]]; ENDLOOP; IO.PutRope[stream, "]"]; }; ENDCASE => IO.Put1[stream, [refAny[value]]]; }; IPAttr: PUBLIC DecomposerRegistry.AttributesProc = { <> dummy: INT ¬ 0; sd: DecomposerRegistry.SequencerData ¬ instance.sequencer; setAttr: DecomposerRegistry.SetAttrProc ¬ sd.procs.setAttr; getAttr: DecomposerRegistry.GetAttrProc ¬ sd.procs.getAttr; master: InterpressInterpreter.Master ¬ IPAttributes.MasterFromInstance[instance]; sk: IPMaster.Skeleton ¬ IPInstructions.GetMasterSkeleton[master: master]; -- new call iv: IPVector.Vector ¬ sk.instructions.instructions; ForAttribute: GetAttributeProc = { <<[attr: Attribute, proc: IPToValueProc, names: LIST OF Name]>> <> FormatNames: PROC [explanation: ROPE] RETURNS [ROPE] = { msg: ROPE ¬ explanation; FOR tail: LIST OF Name ¬ names, tail.rest UNTIL tail = NIL DO msg ¬ msg.Cat[" ", IPInstructions.NameRopeFromName[tail.first]]; ENDLOOP; RETURN [msg] }; IF proc # NIL THEN { ENABLE IPInterpreter.Error => { msg: ROPE = FormatNames[Rope.Concat[explanation, " while processing printing instruction"]]; instance.sequencer.procs.feedback[instance, $PrintingInstructionsError, warning, msg]; IF debug # NIL THEN { s: IO.STREAM = debug; -- sample it to guarantee NIL test. IF s # NIL THEN s.PutRope[msg.Concat["\n"] ! IO.Error => {debug ¬ NIL; CONTINUE}]; }; CONTINUE; }; seq: DecomposerRegistry.ValueSeq ¬ proc[attr, iv, names]; IF seq = NIL THEN RETURN; IF debug # NIL THEN { s: IO.STREAM = debug; ros: IO.STREAM = IO.ROS[]; old: DecomposerRegistry.ValueSeq ¬ NIL; Dump: PROC [seq: DecomposerRegistry.ValueSeq] = { IO.PutF1[ros, "[%g", [atom[attr]]]; FOR i: NAT IN [0..seq.len) DO IO.PutRope[ros, ", "]; PutAttributeValue[ros, seq[i]]; ENDLOOP; IO.PutRope[ros, "]"]; }; Dump[seq]; IF getAttr # NIL THEN old ¬ getAttr[sd, attr ! UNCAUGHT => CONTINUE]; IF old # NIL THEN {IO.PutRope[ros, " was "]; Dump[old] }; IO.PutRope[ros, "\n"]; IF s # NIL THEN s.PutRope[IO.RopeFromROS[ros] ! IO.Error => {debug ¬ NIL; CONTINUE}]; }; setAttr[sd, attr, seq]; -- actually set the attribute! }; }; instance.pages ¬ master.pages; IF sd.flags.debug OR debug # NIL THEN { ros: IO.STREAM = IO.ROS[]; s: IO.STREAM = debug; PrintVector[ros, iv]; { msg: ROPE = IO.RopeFromROS[ros]; IF sd.flags.debug THEN sd.procs.feedback[instance, $PrintVector, comment, msg]; IF s # NIL THEN s.PutRope[msg.Concat["\n"] ! IO.Error => {debug ¬ NIL; CONTINUE}]; }; }; MapRegisteredAttributes[ForAttribute]; }; <> <<>> attrTable: RefTab.Ref = RefTab.Create[mod: 57]; RegisterAttr[$SenderName, GenericString, LIST[STANDARDjobAttributes, jobSender]]; RegisterAttr[$RecipientName, GenericString, LIST[STANDARDjobAttributes, jobRecipient]]; RegisterAttr[$DocumentName, GenericString, LIST[docName]]; RegisterAttr[$DocumentDate, GenericString, LIST[docCreationDate]]; RegisterAttr[$DocumentDate, GenericString, LIST[docCreationDate]]; RegisterAttr[$Priority, GenericCard, LIST[STANDARDjobAttributes, jobPriority]]; RegisterAttr[$Plex, Plex, LIST[plex]]; RegisterAttr[$Staple, Staple, LIST[finishing]]; RegisterAttr[$ImageShiftHorizontal, ImageShift, LIST[xImageShift]]; RegisterAttr[$ImageShiftVertical, ImageShift, LIST[yImageShift]]; RegisterAttr[$AccountInfo, GenericString, LIST[jobAccountName]]; RegisterAttr[$Media, Media, LIST[media]]; RegisterAttr[$DocEndMessage, GenericString, LIST[docEndMessage]]; <> Commander.Register["IPAttrDebug", IPAttrDebugCommand]; <<>> END.