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 = { 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. b IPAttributesImpl.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Kenneth A. Pier, February 3, 1992 3:53 pm PST Russ Atkinson (RRA) May 3, 1992 11:32 am PDT Michael Plass, June 1, 1993 3:02 pm PDT This module implements a procedure that can be called from registered Interpress decomposers. It is used to translate IP printing instructions found in the IP skeleton into attributes that the downstream decomposer understands. As the decomposer evolves so must this module; in particular, the attributes it registers with itself must track those registered by the AttributeTranslation module. This is a list of Name to deal with things like jobName, which is nested underneath standard/jobAttributes - in this case we would want names to be LIST[STANDARDjobAttributes, jobName] For use with MapRegisteredAttributes The proc is called once for each registered attribute. There is one proc of this type for each DecomposerRegistry ValueSeq to be derived from the Interpress instructions vector iv for use in the subsequent call to setAttr. DecomposerRegistry Values may be mapped one-to-one to Interpress instructions vector values, but usually are not. When an IPToValueProc is called, it creates a seq and fills in the fields from values that it finds in the instructions vector. Registers an IPToValueProc for this attribute. The IPToValueProc that has been registered for this attribute is returned. attr is a cardinal-valued attribute attr is a string-valued attribute These IPToValueProcs know how to build a value sequence of the right shape for their particular attribute Interpess PLEX is "simplex", "duplex", or "tumbleDuplex". Values are Identifiers. Decomposer Plex is an enumeration. This is non-standard, but it is what GlobalView expects to be able to say. Interpess staple is "none" or "corner". Values are Identifiers. Possible Vector of Identifiers not implemented here. Interpress has xImageShift and yImageShift in ICS coordinates, which I assume are meters. DecomposerRegistry wants dimensions in units of milliMeters mediaType is [xSize: CARD32, ySize: CARD32, formType: ROPE, color: ROPE, weight: CARD32] defaultMedium: Identifier = "defaultMedium"; defaultColor: Identifier = "white"; defaultWeight: CARD32 = 75; Vector of mediumDescription Vectors make a new RETURN sequence with one sequence Value for each mediumDescription look for up to 5 elements in the mediumDescription vector fill in the inner sequence with corresponding mediaType field values decode each kind of number and print it Used for debug. Does this replicate some code somewhere???? AttributesProc: TYPE = PROC [instance: InstanceData]; [attr: Attribute, proc: IPToValueProc, names: LIST OF Name] this is where all the work of deriving and setting attributes is done The following attributes correspond to those registered with the AttributeTranslation module and must track that module as attributes evolve. The attributes registered here are not ALL of the attributes registered with the AttributeTranslation module, but only the ones for which it makes sense to derive values from the IP skeleton instructions. RegisterAttr[$, ]; Κb•NewlineDelimiter –(cedarcode) style™code™Kšœ Οeœ1™Kšœžœžœ˜9Kšœžœžœ!˜>šœ žœ˜$Kšžœ˜šžœžœžœž˜+Kšžœžœžœ˜'K˜0Kšžœ˜—Kšžœ˜K˜—Kšžœžœ˜,—Kšœ˜K˜—šŸœžœ&˜4Kšœžœžœ™5Kšœžœ˜K˜:K˜;K˜;K˜QKšœJ  ˜UK˜4šŸ œ˜"K™;K™Eš Ÿ œžœžœžœžœ˜8Kšœžœ˜š žœžœžœžœžœž˜=K˜@Kšžœ˜—Kšžœ˜ K˜—šžœžœžœ˜šžœ˜KšœžœS˜\K˜Všžœ žœžœ˜Kšœžœžœ  #˜9Kš žœžœžœžœžœžœ˜RK˜—Kšžœ˜ K˜—K˜9Kšžœžœžœžœ˜šžœ žœžœ˜Kšœžœžœ ˜Kš œžœžœžœžœ˜Kšœ#žœ˜'šŸœžœ'˜1Kšžœ!˜#šžœžœžœž˜Kšžœ˜K˜Kšžœ˜—Kšžœ˜Kšœ˜—K˜ Kš žœ žœžœžœžœ˜EKšžœžœžœžœ$˜9Kšžœ˜Kšžœžœžœ žœžœžœžœ˜UK˜—Kšœ ˜6K˜—K˜—K˜šžœžœžœ˜'Kš œžœžœžœžœ˜Kšœžœžœ ˜K˜˜Kšœžœžœ˜ Kšžœžœ9˜OKš žœžœžœžœžœžœ˜RKšœ˜—K˜—K˜&K˜K˜——™ΫK™—˜/K˜—Kšœ)žœ’ œ‘˜QKšœ,žœ’ œ‘˜WKšœ+žœ’œ‘˜:Kšœ+žœ’œ‘˜BKšœ+žœ’œ‘˜BKšœ%žœ’ œ‘˜OKšœžœ’œ‘˜&Kšœžœ’ œ‘˜/Kšœ0žœ’ œ‘˜CKšœ.žœ’ œ‘˜AKšœ*žœ’œ‘˜@Kšœžœ’œ‘˜)Kšœ,žœ’ œ‘˜AKšœ‘œ‘™˜6K™—Kšžœ˜K˜K˜—…—/Iή