DIRECTORY ColorizeViewPoint, ColorizeViewPointBackdoor, ColorizeViewPointSweep, Convert, FS, IO, IPMaster, IPScan, Process, Profiles, Real, Rope, RopeFile, Vector2; ColorizeViewPointImplA: CEDAR PROGRAM IMPORTS ColorizeViewPointBackdoor, ColorizeViewPointSweep, Convert, FS, IO, IPMaster, IPScan, Process, Profiles, Real, Rope, RopeFile EXPORTS ColorizeViewPoint, ColorizeViewPointBackdoor ~ BEGIN OPEN ColorizeViewPoint, ColorizeViewPointBackdoor; Profile: TYPE ~ Profiles.Profile; VEC: TYPE ~ Vector2.VEC; ASSERTION: TYPE ~ BOOL [TRUE..TRUE]; Warning: PUBLIC SIGNAL [class: ATOM, explanation: ROPE] ~ CODE; Error: PUBLIC ERROR [class: ATOM, explanation: ROPE] ~ CODE; Do: PUBLIC PROC [fromFile, toFile: ROPE, palette: Profiles.Profile, checkSystemSetting: CheckSystemSettingProc] ~ { fromIP: ROPE ~ RopeFile.Create[name: fromFile]; toIP: ROPE ~ DoRope[fromIP: fromIP, palette: palette, checkSystemSetting: checkSystemSetting]; out: IO.STREAM ~ FS.StreamOpen[fileName: toFile, accessOptions: create]; out.PutRope[toIP]; out.Close; }; DoRope: PUBLIC PROC [fromIP: ROPE, palette: Profiles.Profile, checkSystemSetting: CheckSystemSettingProc] RETURNS [toIP: ROPE] ~ { If: PROC [option: ROPE] RETURNS [BOOL] ~ { Default: PROC RETURNS [BOOL] ~ { FOR each: LIST OF SettingData _ settings, each.rest UNTIL each=NIL DO IF Rope.Equal[s1: each.first.setting.key, s2: option, case: FALSE] THEN RETURN [each.first.setting.default]; ENDLOOP; ERROR; --System error! }; RETURN [Profiles.Boolean[profile: palette, key: option, default: checkSystemSetting[key: option, default: Default[]]]]; }; enable: BOOL; header, ipToColorize: ROPE; [header: header, ip: ipToColorize] _ IPRopeFromRope[fromIP]; SELECT TRUE FROM Rope.Match["Interpress/Xerox/1.*", header] => enable _ If["Colorize1"]; Rope.Match["Interpress/Xerox/2.*", header] => enable _ If["Colorize2"]; Rope.Match["Interpress/Xerox/3.0", header] => enable _ If["Colorize3"]; ENDCASE => ERROR Error[$UnknownIPVersion, IO.PutFR[format: "Unknown encoding of Interpress: [%g]", v1: [rope[header]]]]; IF enable THEN { --Enable any colorization paletteSlices: LIST OF Profiles.Slice _ palette.GetProfileSlices; --a profile is defined with "file slices" and "rope slices" clientFileSlices: LIST OF Profiles.Slice ~ GetProfileFileSlices[paletteSlices]; --default profile from client clientRopeSlice: ROPE ~ CleanupUserCommands[RopeFromProfileRopeSlices[paletteSlices], palette]; --custom commands from the client finalIP: ROPE _ NIL; --final output from Concat of each colorized piece of doc useIP2: BOOL _ TRUE; --set false almost always (for color colorizations, use 3.0 header). But "colorizations" done with certain palettes (like "BW" or some "Grey") should get a 2.2 header to be printable on widest range of printers, not just color printers. stillToColorize: ROPE _ DoPrePass[ipToColorize]; --if more than one CustomColorsPage, each chunk of document is ruled by its CustomColorsPage; stillToColorize is the rest of document. DoPrePass does any necessary operations before colorization. DO customColorsFound: BOOL _ FALSE; documentRopeSlice: ROPE _ NIL;--custom cmds from document's current CustomColorsPage curPalette: Profiles.Profile _ palette; --stores the current palette for each doc section IF If["FindCustomCommands"] THEN [ipToColorize: ipToColorize, documentRopeSlice: documentRopeSlice, stillToColorize: stillToColorize] _ ObtainEmbeddedProfile[stillToColorize]; IF ipToColorize.Equal[""] THEN {IF stillToColorize=NIL THEN EXIT ELSE LOOP}; documentRopeSlice _ CleanupUserCommands[documentRopeSlice, palette]; IF customColorsFound _ (clientRopeSlice#NIL OR documentRopeSlice#NIL) THEN curPalette _ Profiles.CreateFromSlices[slices: JoinLists[clientFileSlices, LIST[[rope[documentRopeSlice.Concat[clientRopeSlice]]]]], keepFresh: FALSE];--the order documentRopeSlice before clientRopeSlice is important: Profiles.mesa layers later slices over earlier; this is a decision that clientRopeSlice (the incoming rope slices) take precedence over the document custom color commands (documentRopeSlice), so that a printer msg or a commandtool cmd may, for example, temporarily suspend the document-embedded specs IF customColorsFound OR ~ If["ColorizeOnlyIfCustomColors"] THEN { mapData: MapData ~ GetMappings[curPalette]; FOR each: LIST OF SettingData _ settings, each.rest UNTIL each=NIL DO Process.CheckForAbort[]; IF each.first.colorization#NIL THEN { ENABLE Error => { --Map Error to Warning, and abandon colorization SIGNAL Warning[class, IO.PutFR[format: "%g in colorization %g, which has been abandoned", v1: [rope[explanation]], v2: [rope[each.first.setting.key]]]]; GOTO AbandonColorization; }; IF If[each.first.setting.key] THEN ipToColorize _ each.first.colorization[ip: ipToColorize, palette: curPalette, checkSystemSetting: checkSystemSetting, mapData: mapData]; EXITS AbandonColorization => NULL; }; ENDLOOP; }; finalIP _ finalIP.Concat[ipToColorize]; useIP2 _ MIN[useIP2, Profiles.Boolean[profile: curPalette, key: "IP2", default: FALSE]];--if each section of the doc allows an IP2 header, then useIP2, otherwise IP3 IF stillToColorize=NIL THEN EXIT; ENDLOOP; header _ IF useIP2 THEN "Interpress/Xerox/2.2 " ELSE "Interpress/Xerox/3.0 "; RETURN [Rope.Concat[header, finalIP]]; --the colorized ip }; RETURN [fromIP]; --the uncolorized ip if enable FALSE }; SettingData: TYPE ~ RECORD [setting: Setting, colorization: Colorization _ NIL]; settings: LIST OF SettingData _ NIL; InstallNewColorization: PUBLIC PROC [colorization: PROC [ip: ROPE, palette: Profiles.Profile, checkSystemSetting: CheckSystemSettingProc, mapData: MapData] RETURNS [newIP: ROPE], setting: Setting] ~ { new: LIST OF SettingData ~ LIST[[setting, colorization]]; IF settings=NIL THEN { settings _ new; RETURN; }; FOR each: LIST OF SettingData _ settings, each.rest DO IF each.rest=NIL THEN { each.rest _ new; EXIT; }; ENDLOOP; }; InstallStandardSettings: PROC ~ { InstallNewColorization[colorization: NIL, setting: ["ColorizeOnlyIfCustomColors", "Colorization will occur only if custom color pages are found in the document or if custom color instructions are passed in (eg, thru printer message)", FALSE]]; InstallNewColorization[colorization: NIL, setting: ["FindCustomCommands", "Search interpress master for colorization profile pages", TRUE]]; InstallNewColorization[colorization: NIL, setting: ["Colorize3", "Enable colorization of Interpress 3.0 masters", FALSE]]; InstallNewColorization[colorization: NIL, setting: ["Colorize2", "Enable colorization of Interpress 2.x masters", TRUE]]; InstallNewColorization[colorization: NIL, setting: ["Colorize1", "Enable colorization of Interpress 1.x masters", TRUE]]; }; ExaminesTheseSettings: PUBLIC PROC RETURNS [list: LIST OF Setting _ NIL] ~ { FOR each: LIST OF SettingData _ settings, each.rest UNTIL each=NIL DO list _ CONS[each.first.setting, list]; ENDLOOP; }; DoPrePass: PROC [ip: ROPE] RETURNS [newIP: ROPE] ~ {--setup before colorization PerOp: IPScan.ScanProc ~ { IF max=newIP.Length THEN RETURN; --protects bounds fault at last endBody IF Rope.Equal[s1: newIP.Substr[start: max, len: 2], s2: "\240j"--{ (beginBody)--] THEN newIP _ newIP.Replace[start: max, len: 2, with: "\240j\017\241\241\250" --{ 1 SETGRAY--] --explicitly insert initial default color setting (1 SetGray) at beginning of each page; page beginning found by endBody immed. followed by beginBody }; newIP _ ip; IPScan.ScanRope[ip: newIP, ops: LIST[endBody], seqs: NIL, action: PerOp]; }; IPRopeFromName: PUBLIC PROC [xeroxName: ROPE] RETURNS [header, ip: ROPE] ~ { [header: header, ip: ip] _ IPScan.IPRopeFromName[xeroxName: xeroxName]; }; IPRopeFromRope: PUBLIC PROC [xeroxRope: ROPE] RETURNS [header, ip: ROPE] ~ { pos: INT ~ Rope.Find[s1: xeroxRope, s2: " "]; RETURN [ header: xeroxRope.Substr[len: pos], ip: xeroxRope.Substr[start: pos+1] ]; }; IPFragmentForColorSetting: PUBLIC PROC [def: LIST OF ROPE, palette: Profiles.Profile] RETURNS [frag: REF] ~ { frag _ IPFragmentForColorDefinition[def: def, palette: palette]; IF frag=NIL THEN RETURN; WITH frag SELECT FROM frag: ROPE => RETURN [frag.Concat["\017\255\223" --13 (color) ISET--]]; frag: REF SampledColorIPFragments => { RETURN [NEW[SampledColorIPFragments _ [ beforeTransform: frag.beforeTransform, afterTransform: frag.afterTransform.Concat["\017\255\223" --13 (color) ISET-- ], sweepAngleMod360: frag.sweepAngleMod360, removeDefiningObject: frag.removeDefiningObject ]]]; }; ENDCASE => ERROR; --System error! }; IPFragmentForColorDefinition: PUBLIC PROC [def: LIST OF ROPE, palette: Profiles.Profile] RETURNS [frag: REF] ~ { SELECT TRUE FROM def=NIL OR def.first=NIL => RETURN [NIL]; Rope.Equal[s1: def.first.Substr[0,5], s2: "Sweep", case: FALSE] => {--Sweeps iSize: NAT; beforeTransform, afterTransform: ROPE; sweepAngleMod360: [0..360) _ 0; removeDefiningObject: BOOL _ FALSE; sweepAngle: ROPE _ def.first.Substr[start: 5]; --eg, Sweep15 => sweepAngle="15" dummyHead: LIST OF ROPE _ LIST[NIL]; --mechanism to add elements to end of a list tail: LIST OF ROPE _ dummyHead; FOR each: LIST OF ROPE _ def, each.rest UNTIL each=NIL DO IF Rope.Match[pattern: "Remove*", object: each.first, case: FALSE] THEN removeDefiningObject _ TRUE ELSE tail _ (tail.rest _ LIST[each.first]); --keep all tokens but "Remove*" ENDLOOP; def _ dummyHead.rest; IF ~sweepAngle.Equal[""] THEN { realSweep: REAL _ Convert.RealFromRope[sweepAngle ! Convert.Error => GOTO Oops]; temp: INTEGER _ ColorizeViewPointBackdoor.AltRound[realSweep] MOD 360; sweepAngleMod360 _ IF temp<0 THEN temp+360 ELSE temp; EXITS Oops => SIGNAL Warning[$MalformedPaletteEntry, IO.PutFR[format: "Need a number following \"Sweep\" , eg Sweep15, but found \"Sweep%g\". Sweep angle being set to 0.", v1: [rope[sweepAngle]] ]]; }; def _ def.rest; [iSize, beforeTransform] _ ColorizeViewPointSweep.ConstructSweepPixelArray[def: def, palette: palette]; afterTransform _ Rope.Cat["\240\240\017\244\222\240\245" --MAKET 4 IGET CONCAT--, BuildColorOperator[i: iSize, scaleFactor: 255 ! Error => { SIGNAL Warning[class: class, explanation: explanation]; GOTO Barf }], "\241\253" --MAKESAMPLEDCOLOR--]; frag _ NEW[SampledColorIPFragments _ [ beforeTransform: beforeTransform, afterTransform: afterTransform, sweepAngleMod360: sweepAngleMod360, removeDefiningObject: removeDefiningObject ]]; SetProfileBoolean[profile: palette, key: "IP2", val: FALSE]; --InterPress 2.0 can't do sweeps }; Rope.Equal[s1: def.first, s2: "IPFrag", case: FALSE] => {--Pre-defined IP fragment follows IF def.rest#NIL THEN RETURN [def.rest.first]; }; ENDCASE => { --Constant scaleFactor: NAT ~ 1000; scaledVector: ROPE; vectorSize: NAT; [scaledVector, vectorSize] _ BuildScaledVector[def, scaleFactor ! Convert.Error => { SIGNAL Warning[$MalformedPaletteEntry, "Non-number found in following color definition:"]; GOTO Barf }]; IF vectorSize=1 THEN { fragStream: IO.STREAM ~ IO.ROS[]; IPMaster.PutReal[stream: fragStream, val: Convert.RealFromRope[r: def.first]]; IPMaster.PutOp[stream: fragStream, op: makegray]; frag _ IO.RopeFromROS[self: fragStream]; } ELSE frag _ scaledVector.Cat[BuildColorOperator[i: vectorSize, scaleFactor: scaleFactor ! Error => { SIGNAL Warning[class: class, explanation: explanation]; GOTO Barf }], "\240\347" --DO--]; }; EXITS Barf => IF def=NIL OR def.first=NIL THEN RETURN [NIL] ELSE { colorEntry: ROPE _ NIL; FOR each: LIST OF ROPE _ def, each.rest UNTIL each=NIL DO colorEntry _ colorEntry.Cat[each.first, " "]; ENDLOOP; SIGNAL Warning[$MalformedPaletteEntry, IO.PutFR[format: "Problem color definition: \"%g\". Objects with that entry will not be colorized.", v1: [rope[colorEntry]] ]]; RETURN [NIL]; }; }; BuildScaledVector: PROC [list: LIST OF ROPE, scaleFactor: NAT] RETURNS [vec: ROPE _ NIL, size: NAT _ 0] ~ { vecStream: IO.STREAM ~ IO.ROS[]; FOR each: LIST OF ROPE _ list, each.rest UNTIL each=NIL DO int: INT; real: REAL; real _ MIN[1, MAX[0, Convert.RealFromRope[r: each.first]]]; int _ ColorizeViewPointBackdoor.AltRound[real * scaleFactor]; IPMaster.PutInt[stream: vecStream, n: int]; size _ size+1; ENDLOOP; IPMaster.PutShortNumber[stream: vecStream, n: size]; IPMaster.PutOp[stream: vecStream, op: makevec]; vec _ IO.RopeFromROS[self: vecStream]; }; BuildColorOperator: PROC [i, scaleFactor: NAT] RETURNS [ip: ROPE] ~ { ip _ Rope.Cat[BuildColorOperatorScaleInfo[i, scaleFactor], BuildColorModelOperatorFinder[i], "\240\347" --DO--]; }; BuildColorOperatorScaleInfo: PROC [i, scaleFactor: NAT] RETURNS [ip: ROPE] ~ { out: IO.STREAM ~ IO.ROS[]; IPMaster.PutShortNumber[stream: out, n: scaleFactor]; SELECT i FROM 1 => ip _ Rope.Cat["\017\240", out.RopeFromROS, "\017\240\017\243\241\033"]; -- 0 scaleFactor 0 3 MAKEVEC. This creates a GrayLinear which maps to SETGRAY (white=0, black=scaleFactor). The second 0 defaults an optional LookUpTable for the gray values to NIL 3, 4 => ip _ out.RopeFromROS.Cat["\017\241\241\033"]; -- scaleFactor 1 MAKEVEC ENDCASE => ERROR Error[$MalformedPaletteEntry, IO.PutFR[format: "The following color definition has %g numbers (only 1, 3, or 4 allowed):", v1: [cardinal[i]] ]]; }; BuildColorModelOperatorFinder: PROC [i: NAT] RETURNS [ip: ROPE] ~ { SELECT i FROM 1 => ip _ "\305\005Xerox\305\012GrayLinear\017\242\241\033\241\246"; -- Xerox GrayLinear 2 MAKEVEC FINDCOLORMODELOPERATOR 3 => ip _ "\305\005Xerox\305\bResearch\305\tRGBLinear\017\243\241\033\241\246"; -- Xerox Research RGBLinear 3 MAKEVEC FINDCOLORMODELOPERATOR 4 => ip _ "\305\005Xerox\305\bResearch\305\004CMYK\017\243\241\033\241\246"; -- Xerox Research CMYK 3 MAKEVEC FINDCOLORMODELOPERATOR ENDCASE => NULL; }; RopeFromProfileRopeSlices: PROC [sliceList: LIST OF Profiles.Slice] RETURNS [sliceRope: ROPE _ NIL] ~ { --Turns a list of Profiles.Slice.rope into a single rope with a space between each slice FOR each: LIST OF Profiles.Slice _ sliceList, each.rest UNTIL each=NIL DO WITH each.first SELECT FROM ropeSlice: Profiles.Slice.rope => sliceRope _ sliceRope.Cat[ropeSlice.text, " "]; ENDCASE => NULL; ENDLOOP; }; GetProfileFileSlices: PROC [allSlices: LIST OF Profiles.Slice] RETURNS [fileSlices: LIST OF Profiles.Slice] ~ { RETURN [ IF allSlices=NIL THEN NIL ELSE WITH allSlices.first SELECT FROM fileSlice: Profiles.Slice.file => CONS[fileSlice, GetProfileFileSlices[allSlices.rest]], ENDCASE => GetProfileFileSlices[allSlices.rest] ]; }; JoinLists: PROC [start: LIST OF Profiles.Slice, addAtEnd: LIST OF Profiles.Slice] RETURNS [joined: LIST OF Profiles.Slice] ~ {RETURN [IF start=NIL THEN addAtEnd ELSE CONS[start.first, JoinLists[start.rest, addAtEnd]]]}; embeddedProfilePassword: ROPE ~ "CustomColor"; --actually "CustomColor*" will match keepPassword: ROPE ~ "Keep"; --use embedded profile but don't delete it from ip master endPassword: ROPE ~ "EndCustom"; --use to end CustomColor commands before page end ObtainEmbeddedProfile: PROC [oldIp: ROPE] RETURNS [ipToColorize, documentRopeSlice, stillToColorize: ROPE _ NIL] ~ { PerOp: IPScan.ScanProc = { FoundKeep: PROC [] RETURNS [BOOL] ~ { --searches for uncommented keepPassword seq: ROPE _ oldIp.Substr[start: min+2, len: max-min-2]; commentPos: INT _ MIN[seq.Index[s2: "--"], seq.Index[s2: "<<"], seq.Index[s2: "\377\041\076\076\377\000" --extended char set dbldash--]]; RETURN [seq.Index[s2: keepPassword, case: FALSE] < commentPos]; }; IF punt THEN RETURN; SELECT op FROM beginBody => { IF bodyNest=0 THEN { bodyStart _ min; enabled _ enabledKeep _ FALSE; }; bodyNest _ bodyNest+1; }; endBody => { IF (bodyNest _ bodyNest-1)=0 THEN SELECT TRUE FROM enabled, enabledKeep, everEnabled => {--CustomColors found; abort scan, colorize, then go on ipToColorize _ ipToColorize.Concat[oldIp.Substr[start: flushFrom, len: IF enabled THEN bodyStart-flushFrom ELSE --include CCPage-- max-flushFrom]]; IF oldIp.Substr[start: max].Equal["\240g"--END--] THEN ipToColorize _ ipToColorize.Concat["\240g"] ELSE stillToColorize _ oldIp.Substr[start: max]; quit _ TRUE; --will cause early abort of IPScan profileAddition.PutChar['\n]; }; ENDCASE => NULL; -- just keep going }; nil => { --short sequenceString; actual sequence starts at min+2 IF oldIp.Fetch[index: min]#'\301 -- short sequenceString-- THEN ERROR; --System error! SELECT TRUE FROM enabled OR enabledKeep => { IF lookForKeep AND FoundKeep[] THEN {enabledKeep _ TRUE; enabled _ FALSE} --if is used, ("CustomColors (Keep)") VP uses SETXY for tabs and we catch SETXYs as newline; so lookForKeep allows us to check one more line for the keepPassword before it is reset to FALSE ELSE SELECT TRUE FROM endPassword.Run[s2: oldIp, pos2: min+2, case: FALSE]=endPasswordLength --"EndCustom*"-- AND (enabled OR enabledKeep) => { ipToColorize _ ipToColorize.Concat[oldIp.Substr[start: flushFrom, len: IF enabled THEN passStart-flushFrom ELSE --include CC section-- max+1-flushFrom]]; enabled _ enabledKeep _ FALSE; --collect no more CC cmds flushFrom _ max+1 --get past SHOW-- }; ENDCASE => { --this line is a custom color command profileAddition.PutRope[oldIp.Substr[start: min+2, len: max-min-2]]; profileAddition.PutRope["\377\000" --\377\000 ensures this is char set 0 since a hyphen sometimes changes the char set--]; }; lookForKeep _ FALSE; }; embeddedProfilePassword.Run[s2: oldIp, pos2: min+2, case: FALSE]=embeddedProfilePasswordLength --"CustomColor*"-- => { enabled _ lookForKeep _ ~(enabledKeep _ FoundKeep[]); everEnabled _ TRUE; passStart _ min; }; ENDCASE => NULL; }; setxy => IF enabled OR enabledKeep THEN {--sameY=tab(add space); diffY=newLine(\n) testY: INT _ ExtractY[oldIp.Substr[start: min, len: max-min]]; IF curY=testY THEN profileAddition.PutRope[" "] ELSE { prevY _ curY; curY _ testY; IF DifLineSpace[] THEN profileAddition.PutRope["\f"] ELSE profileAddition.PutRope["\n"]; --obscure problem. ViewPoint uses SETXY to do a newLine & also to spill a long line over. This is a hint to whether this is a completely newLine farther down on the page, like a footer, or a spill over (same y offset as used on prev line). }; }; setxyrel, setyrel => IF enabled OR enabledKeep THEN { testY: INT _ IF op=setxyrel THEN ExtractY[oldIp.Substr[start: min, len: max-min]] ELSE ExtractY[setxyFrag: oldIp.Substr[start: min, len: max-min], noX: TRUE]; IF testY=0 --same line-- THEN profileAddition.PutRope[" "] ELSE { --diff line prevY _ curY; curY _ curY+testY; IF DifLineSpace[] THEN profileAddition.PutRope["\f"] ELSE profileAddition.PutRope["\n"]; }; }; ENDCASE => ERROR; --System error! }; DifLineSpace: PROC [] RETURNS [diff: BOOL]~ { curJump: INT _ ABS[curY-prevY]; diff _ prevJump#0 AND (curJump>prevJump+10); --10 is fudge allowed for line spacing prevJump _ IF diff THEN 0 ELSE curJump; --every time there's a big jump, start over }; embeddedProfilePasswordLength: INT ~ embeddedProfilePassword.Size; endPasswordLength: INT ~ endPassword.Size; lookForKeep: BOOL _ FALSE; --TRUE => found enabled, see if (Keep) on next line enabled: BOOL _ FALSE; --TRUE => have found the password on this page enabledKeep: BOOL _ FALSE; --TRUE => have found the keep password on this page everEnabled: BOOL _ FALSE; --TRUE => at least one page had profile entries bodyNest: INT _ 0; flushFrom, bodyStart, passStart: INT _ 0; curY, prevY: INT _ 0; --used to distinguish Tab SETXYs from \n SETXYs; used as vague hint to detect a big jump on page like a footer prevJump: INT _ 0; --tracks the y-diff in the prev. line profileAddition: IO.STREAM ~ IO.ROS[]; IPScan.ScanRope[ip: oldIp, ops: LIST[beginBody, endBody, setxy, setxyrel, setyrel], seqs: LIST[sequenceString], action: PerOp]; IF everEnabled THEN RETURN [ipToColorize: ipToColorize, documentRopeSlice: profileAddition.RopeFromROS, stillToColorize: stillToColorize] ELSE RETURN [ipToColorize: oldIp, documentRopeSlice: NIL, stillToColorize: NIL]; }; ExtractY: PROC [setxyFrag: ROPE, noX: BOOL _ FALSE] RETURNS [y: INT _ 0] ~ { startY: NAT _ IF noX THEN 0 ELSE 2; --2 is normal start of y in setxyFrag, if x encoded as short number IF ~noX THEN SELECT setxyFrag.Fetch[0] --start of x-- FROM <= '\177 --using 2 byte short number encoding for x-- => NULL; --startY correct '\302 --using multi-byte seqInteger encoding for x, # bytes found in next byte-- => startY _ startY + ORD[setxyFrag.Fetch[1]]; ENDCASE => ERROR; --system error; unknown encoding SELECT setxyFrag.Fetch[startY] --start of y-- FROM <= '\177 --using 2 byte short number encoding for y, biased by 4000-- => y _ IPMaster.IntFromSequenceData[text: Rope.ToRefText[setxyFrag], start: startY, len: 2]; '\302 --using multi-byte seqInteger encoding for y, # bytes found in next byte-- => { bytes: NAT _ ORD[setxyFrag.Fetch[startY _ startY+1]]; --#bytes in y IF bytes>4 THEN ERROR; --system error; would overflow INT boundaries y _ IPMaster.IntFromSequenceData[text: Rope.ToRefText[setxyFrag], start: startY+1, len: bytes]; }; ENDCASE => ERROR; --system error; unknown encoding }; InstallStandardSettings[]; RegisterKeywords[keywordsList: LIST["Sweep", "Remove"]]; --Reserved colorizing keywords. These can be a pattern (ie, Sweep45 will be found as a keyword). END. bColorizeViewPointImplA.mesa Copyright Ó 1988, 1989, 1990 by Xerox Corporation. All rights reserved. Eric Nickell, May 22, 1989 4:09:31 pm PDT Bob Coleman, September 6, 1990 12:14:03 pm PDT Dave Rumph, January 23, 1990 1:11:41 pm PST Errors class describes the general type of error (e.g., $MalformedPaletteEntry) explanation is a user-readable ROPE describing the problem In general, clients should RESUME Warning. Standard Colorization 1. Get & clean the next CustomColorsPage in the document, if any 2. If either a CustomColorsPage or commands from the client, construct a new palette which includes them 3. Using the new palette, perform all requested colorizations If["ColorizeOnlyIfCustomColors"] => that colorization should only take place for documents where an embedded palette or printer messages are found. 4. Finally, output the new colorized ip with the correct header We just add this stuff as a setting which happens to have an associated colorization New [colorization, setting] pairs are added to the end of the list. Note: The first colorizations installed are the first to be performed! [min: INT, max: INT, op: IPMaster.Op _ nil, seq: IPScan.Seq _ nil, num: INTEGER _ 0, punt: BOOL _ FALSE] RETURNS [quit: BOOL _ FALSE] Utilities We do it this way because MOD's behavior wrt negative arguments is not well defined, and therefore not portable. eg, ip _ scaleInformation colorModelOperator DO Embedded Palettes (Custom Colors) embeddedProfilePassword: ROPE ~ "UseThisPageAsColorizerProfileEntries"; [min: INT, max: INT, op: IPMaster.Op _ nil, seq: IPScan.Seq _ nil, num: INTEGER _ 0, punt: BOOL _ FALSE] RETURNS [quit: BOOL _ FALSE] y _ ORD[setxyFrag.Fetch[startY]]*256 + ORD[setxyFrag.Fetch[startY+1]] - 4000; FOR i: NAT IN [1..bytes] DO y _ y+ORD[setxyFrag.Fetch[startY+i]]*Real.Round[RealFns.Power[base: 256.0, exponent: bytes-i]]; ENDLOOP; Initialization Êž˜™Icode™HK™)K™.K™+K™—šÏk ˜ Kšœ.˜.Kšœ!œœE˜lK˜—K˜KšÐlnœ ˜%Kšœ=œœ;˜…Kšœ-˜4Kšœ˜šœ.˜2K˜Kšœ œ˜!Kšœœ œ˜K˜Kš œœœœœ˜$—subtitle™Kš Ïnœœœ œœœ˜?š Ÿœœœ œœœ˜[s1: ROPE, s2: ROPE, pos1: INT _ 0, case: BOOL _ TRUE]šœœ%˜-šœ˜K˜#K˜"Kšœ˜—K˜K˜—šŸœœœœœœœœ˜mKšœ@˜@Kšœœœœ˜šœœ˜Kš œœœ¡ ¥¡œ˜Gšœœ˜&šœœ˜'K˜&Kšœ:¡ ¥¡œ˜PKšœ(˜(Kšœ/˜/Kšœ˜—Kšœ˜—Kšœœ¡˜!—Kšœ˜K˜—šŸœœœœœœœœ˜pšœœ˜Kš œœœ œœœ˜)šœ9œ¡˜LKšœœ˜ Kšœ!˜&Kšœ˜Kšœœ˜#Kšœ œ¡ ˜OKš œ œœœœœ¡,˜QKšœœœœ ˜š œœœœœœ˜9Kšœ:œœ˜cKšœœ¡˜KKšœ˜ —K˜šœœ˜Kšœ œ6œ˜PKšœœ1œ˜Fšœœœ œ˜5K™p—Kšœ œ!œ˜ÇK˜—K˜Kšœg˜gKšœ9¡¥¡¥¡¥¡Ïsœ;œ3œ¦œ ¡¥¡œ˜õšœœ˜&Kšœ"˜"Kšœ˜Kšœ#˜#Kšœ*˜*Kšœ˜—Kšœ5œ¡ ˜]K˜—šœ.œ¡!˜ZKšœ œœœ˜-K˜—šœ¡ ˜Kšœ œ˜Kšœœ˜Kšœ œ˜šœT˜TKšœVœ ˜i—šœ œ˜K–ldStream: STREAM _ NIL]š œ œœœœ˜!K– [r: ROPE]˜NK–%[stream: STREAM, op: IPMaster.Op]˜1K–&[self: STREAM, close: BOOL _ TRUE]šœœ˜(Kšœ˜—šœT˜XKš œ œ3œ¡¥¡œ˜g—Kšœ˜——šœ ˜Kšœœœ œœœœ˜-šœ˜Kšœ œœ˜š œœœœœœ˜9Kšœ-˜-Kšœ˜—Kšœ!œ~˜§Kšœœ˜ K˜——K˜K˜—šŸœœœœœœœœœœ ˜kK–ldStream: STREAM _ NIL]š œ œœœœ˜ š œœœœœœ˜:Kšœœ˜ Kšœœ˜ Kšœœœ*˜;Kšœ-œ ˜=K–[stream: STREAM, n: INT]˜+K˜Kšœ˜—K–-[stream: STREAM, n: IPMaster.ShortNumber]˜4K–%[stream: STREAM, op: IPMaster.Op]˜/K–&[self: STREAM, close: BOOL _ TRUE]šœœ˜&K˜K˜—š Ÿœœœœœ˜EKšœh¡¥¡œ˜pKšœ ¦œ¦™0K˜K˜—š Ÿœœœœœ˜NKš œœœœœ˜K˜5šœ˜ KšœM¡¥¡˜ƒKšœ6¡¥˜NKšœœœp˜¡—K˜K˜—š Ÿœœœœœ˜Cšœ˜ KšœE¡¥¡¥˜yKšœP¡¥¡¥˜ŒKšœM¡¥¡¥˜„Kšœœ˜—K˜K˜—šŸœœ œœœ œœ¡X˜Àš œœœ'œœ˜Išœ œ˜KšœQ˜QKšœœ˜—Kšœ˜—K˜K˜—šŸœœ œœœœœœ˜xKšœ œœ˜šœœœ˜%Kšœ"œ2˜XKšœ+˜2—Kšœ˜—K™šŸ œœ œœœœœ œœœœœœ œœ1˜ÛK˜—K˜—™!Kšœœ,™IKšœœ¡$˜SKšœœ ¡9˜WKšœ œ¡1˜Sš Ÿœœ œœ4œœ˜t–l -- [min: INT, max: INT, op: IPMaster.Op _ nil, seq: IPScan.Seq _ nil, num: INTEGER _ 0, punt: BOOL _ FALSE]šŸœ˜Kš¤…™…š Ÿ œœœœ¡'˜MKšœœ/˜8Kšœ œœT¡œ˜‰Kšœ$œ˜?K˜—Kšœœœ˜šœ˜šœ˜šœ œ˜Kšœ˜Kšœœ˜Kšœ˜—K˜Kšœ˜—šœ ˜ š œœœœ˜3šœ&¡6˜\Kš œGœ œœ¡œ˜•Kš œ'¡¤¡œœ-œ,˜“Kšœœ¡"˜/Kšœ˜Kšœ˜—Kšœœ¡˜$—Kšœ˜—šœ ¡7˜@K– [base: ROPE, index: INT _ 0]š œ¡œœœ¡˜Všœœ˜šœœ˜Kš œ œ œœ œ¡Ê˜”šœœœ˜š œ.œ¡œœ œ˜yKš œGœ œœ¡œ˜™Kšœœ¡˜8Kšœ¡˜#Kšœ˜—šœ¡&˜2KšœD˜DKšœ#¡Uœ˜zK˜——Kšœœ˜Kšœ˜—šœ:œ ¡œ˜vKšœ5˜5Kšœœ˜K˜K˜—Kšœœ˜—Kšœ˜—šœ œ œ œ¡)˜RKšœœ4˜>Kšœ œ˜/šœ˜Kšœ ˜ Kšœ ˜ Kšœœœ ¡ó˜ÌK˜—K˜—šœœ œ œ˜5Kš œœœ œ2œBœ˜žKšœ ¡ œœ˜:šœ¡ ˜Kšœ ˜ Kšœ˜Kšœœœ˜XK˜—K˜—Kšœœ¡˜!—K˜—šŸ œœœœ˜-Kšœ œœ ˜Kšœœ¡&˜SKšœ œœœ ¡+˜SK˜—Kšœœ ˜BKšœœ˜*Kšœ œœ¡3˜NKšœ œœ¡.˜FKšœ œœ¡3˜NKšœ œœ¡/˜JKšœ œ˜Kšœ!œ˜)Kšœ œ¡n˜„Kšœ œ¡%˜8Kš œœœœœ˜&Kšœ œ6œ!˜Kšœ œœo˜‰Kšœœ*œœ˜PK˜K˜—šŸœœ œœœœœ ˜LKš œœœœœ¡C˜gš œœœ¡œ˜:Kšœ ¡,œœ¡˜OKšœ¡Jœœ˜~Kšœœ¡ ˜2—šœ¡œ˜2šœ ¡<œ˜IKšœœ œ#™MK–A[text: REF READONLY TEXT, start: NAT _ 0, len: NAT _ 32767]šœY˜Y—šœ¡Jœ˜UKšœœœ&¡ ˜CKšœ œœ¡-˜Dšœœœ ™K– [base: REAL, exponent: REAL]šœœV™_Kšœ™—Kšœ_˜_K˜—Kšœœ¡ ˜2—K˜——™Kšœ˜K˜Kšœœ¡a˜›Kš¡˜K˜—Kš˜K˜—…—QÒtÒ