DIRECTORY FS, Convert, FileNames, GGBasicTypes, GGError, GGModelTypes, GGParseIn, GGUtility, Imager, ImagerTransformation, Interpress, IO, IPMaster, Real, Rope, ViewerClasses; GGUtilityImpl: CEDAR PROGRAM IMPORTS Convert, FileNames, GGError, GGParseIn, FS, Imager, Interpress, IO, IPMaster, Real, Rope EXPORTS GGUtility = BEGIN ROPE: TYPE = Rope.ROPE; BitVector: TYPE = GGBasicTypes.BitVector; FeatureData: TYPE = GGModelTypes.FeatureData; Outline: TYPE = GGModelTypes.Outline; Sequence: TYPE = GGModelTypes.Sequence; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; Traj: TYPE = GGModelTypes.Traj; Viewer: TYPE = ViewerClasses.Viewer; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; EntityNotFound: PUBLIC SIGNAL = CODE; StartFeatureDataList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF FeatureData] = { ptr _ entityList _ NIL; }; AddFeatureData: PUBLIC PROC [entity: FeatureData, entityList, ptr: LIST OF FeatureData] RETURNS [newList, newPtr: LIST OF FeatureData] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; DeleteSequenceFromList: PUBLIC PROC [seq: Sequence, seqList: LIST OF Sequence] RETURNS [smallerList: LIST OF Sequence] = { beforeEnt, ent, afterEnt: LIST OF Sequence; notFound: BOOL _ FALSE; [beforeEnt, ent, afterEnt] _ FindSequenceAndNeighbors[seq, seqList]; IF notFound THEN RETURN[seqList]; IF beforeEnt = NIL THEN smallerList _ afterEnt ELSE { beforeEnt.rest _ afterEnt; smallerList _ seqList; }; }; -- end of DeleteSequenceFromList FindSequenceAndNeighbors: PROC [entity: Sequence, entityList: LIST OF Sequence] RETURNS [beforeEnt, ent, afterEnt: LIST OF Sequence] = { lastE: LIST OF Sequence _ NIL; eList: LIST OF Sequence _ entityList; IF eList = NIL THEN ERROR EntityNotFound; UNTIL eList = NIL DO IF eList.first = entity THEN { beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN}; lastE _ eList; eList _ eList.rest; ENDLOOP; SIGNAL Problem[msg: "sequence not found."]; }; AppendSequenceList: PUBLIC PROC [list1, list2: LIST OF Sequence] RETURNS [result: LIST OF Sequence] = { pos: LIST OF Sequence; newCell: LIST OF Sequence; IF list1 = NIL THEN RETURN[list2]; result _ CONS[list1.first, NIL]; pos _ result; FOR l: LIST OF Sequence _ list1.rest, l.rest UNTIL l = NIL DO newCell _ CONS[l.first, NIL]; pos.rest _ newCell; pos _ newCell; ENDLOOP; pos.rest _ list2; }; -- end of AppendSequenceList StartSequenceList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF Sequence] = { ptr _ entityList _ NIL; }; AddSequence: PUBLIC PROC [entity: Sequence, entityList, ptr: LIST OF Sequence] RETURNS [newList, newPtr: LIST OF Sequence] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; StartList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF REF ANY] = { ptr _ entityList _ NIL; }; AddEntity: PUBLIC PROC [entity: REF ANY, entityList, ptr: LIST OF REF ANY] RETURNS [newList, newPtr: LIST OF REF ANY] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AppendNATs: PUBLIC PROC [list1, list2: LIST OF NAT] RETURNS [result: LIST OF NAT] = { pos: LIST OF NAT; newCell: LIST OF NAT; IF list1 = NIL THEN RETURN[list2]; result _ CONS[list1.first, NIL]; pos _ result; FOR l: LIST OF NAT _ list1.rest, l.rest UNTIL l = NIL DO newCell _ CONS[l.first, NIL]; pos.rest _ newCell; pos _ newCell; ENDLOOP; pos.rest _ list2; }; StartNATList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF NAT] = { ptr _ entityList _ NIL; }; StartTrajList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF Traj] = { ptr _ entityList _ NIL; }; StartSDList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF SliceDescriptor] = { ptr _ entityList _ NIL; }; StartOutlineList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF Outline] = { ptr _ entityList _ NIL; }; StartSliceList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF Slice] = { ptr _ entityList _ NIL; }; AddOutline: PUBLIC PROC [entity: Outline, entityList, ptr: LIST OF Outline] RETURNS [newList, newPtr: LIST OF Outline] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AddSlice: PUBLIC PROC [entity: Slice, entityList, ptr: LIST OF Slice] RETURNS [newList, newPtr: LIST OF Slice] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AddNAT: PUBLIC PROC [entity: NAT, entityList, ptr: LIST OF NAT] RETURNS [newList, newPtr: LIST OF NAT] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AddTraj: PUBLIC PROC [entity: Traj, entityList, ptr: LIST OF Traj] RETURNS [newList, newPtr: LIST OF Traj] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AddSD: PUBLIC PROC [entity: SliceDescriptor, entityList, ptr: LIST OF SliceDescriptor] RETURNS [newList, newPtr: LIST OF SliceDescriptor] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; BreakIntervalMOD: PUBLIC PROC [start, end, mod: NAT] RETURNS [s1, e1, s2, e2: INT] = { IF start >= mod OR end >= mod THEN ERROR; IF start <= end THEN RETURN[start, end, -1, -1]; RETURN[0, end, start, mod-1]; }; BreakIntervalMODLen: PUBLIC PROC [start, len, mod: NAT] RETURNS [s1, len1, s2, len2: INT] = { IF start >= mod OR len > mod + 1 THEN ERROR; IF start + len -1 < mod THEN RETURN[start, len, -1, -1]; RETURN[0, start+len-mod, start, mod-start]; }; InMODRegion: PUBLIC PROC [test: NAT, start, end, mod: NAT] RETURNS [BOOL] = { IF start = end THEN RETURN [test = start]; IF start < end THEN RETURN [test IN [start..end]]; RETURN [test IN [start..mod) OR test IN [0..end]]; }; AllFalse: PUBLIC PROC [bitvec: BitVector] RETURNS [BOOL] = { FOR i: NAT IN [0..bitvec.len) DO IF bitvec[i] = TRUE THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; AllTrue: PUBLIC PROC [bitvec: BitVector] RETURNS [BOOL] = { FOR i: NAT IN [0..bitvec.len) DO IF bitvec[i] = FALSE THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; GetInterpressFileName: PUBLIC PROC [ipName: Rope.ROPE, currentWDir: Rope.ROPE, feedback: Viewer] RETURNS [fullName: Rope.ROPE _ NIL, success: BOOL _ TRUE] = { cp: FS.ComponentPositions; IF Rope.Length[ipName]=0 OR Rope.Equal[ipName, ""] THEN { GGError.AppendHerald[feedback, "Select an Interpress file name", oneLiner]; GGError.Blink[feedback]; RETURN[NIL, FALSE]; }; [fullName, cp, ] _ FS.ExpandName[ipName, currentWDir ! FS.Error => { GGError.Append[feedback, "... FS Error during name expansion", oneLiner]; GGError.Blink[feedback]; success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; IF Rope.Equal[Rope.Substr[fullName, cp.ext.start, cp.ext.length], "gargoyle", FALSE] THEN { GGError.Append[feedback, " .gargoyle extension for IP files not allowed", oneLiner]; GGError.Blink[feedback]; success _ FALSE; RETURN; }; IF cp.ext.length=0 THEN fullName _ Rope.Concat[fullName, ".IP"]; }; OpenInterpressOrComplain: PUBLIC PROC [feedback: Viewer, fullName: Rope.ROPE] RETURNS [ipMaster: Interpress.Master, success: BOOL] = { success _ TRUE; ipMaster _ Interpress.Open[fileName: fullName, log: NIL ! FS.Error => { GGError.Append[feedback, error.explanation, oneLiner]; GOTO Quit; }; IPMaster.Error => { --ErrorDesc: TYPE = RECORD[code: ATOM, explanation: ROPE] GGError.Append[feedback, Rope.Cat[error.explanation, " for ", fullName], oneLiner]; GOTO Quit; }; Imager.Error => { --ErrorDesc: TYPE = RECORD [code: ATOM, explanation: ROPE] GGError.Append[feedback, Rope.Cat[error.explanation, " for ", fullName], oneLiner]; GOTO Quit; }; IO.Error, IO.EndOfStream => { GGError.Append[feedback, Rope.Cat["IO Stream Error for ", fullName], oneLiner]; GOTO Quit; }; ]; IF ipMaster.pages=0 THEN { GGError.Append[feedback, Rope.Concat["Zero pages in ", fullName], oneLiner]; GOTO Quit; }; EXITS Quit => { GGError.Blink[feedback]; success _ FALSE; }; }; GetGargoyleFileName: PUBLIC PROC [ggName: Rope.ROPE, currentWDir: Rope.ROPE, feedback: Viewer, emergency: BOOL _ FALSE] RETURNS [fullName: Rope.ROPE _ NIL, success: BOOL _ TRUE, versionSpecified: BOOL _ FALSE] = { cp: FS.ComponentPositions; versionSpecified _ Rope.SkipTo[s: ggName, skip: "!"]#Rope.Length[ggName]; IF Rope.Length[ggName]=0 OR Rope.Equal[ggName, ""] THEN { IF NOT emergency THEN { GGError.PutF[feedback, oneLiner, "No filename specified"]; GGError.Blink[feedback]; }; RETURN[NIL, FALSE]; }; [fullName, cp, ] _ FS.ExpandName[ggName, currentWDir ! FS.Error => { success _ FALSE; IF NOT emergency THEN { GGError.PutF[feedback, oneLiner, "FS Error during name expansion of %g", [rope[ggName]]]; GGError.Blink[feedback]; }; CONTINUE; } ]; IF success AND (Rope.Equal[s1: Rope.Substr[base: fullName, start: cp.ext.start, len: cp.ext.length], s2: "IP", case: FALSE] OR Rope.Equal[s1: Rope.Substr[base: fullName, start: cp.ext.start, len: cp.ext.length], s2: "interpress", case: FALSE]) THEN { IF NOT emergency THEN { GGError.Append[feedback, " Interpress extension for Gargoyle files not allowed", oneLiner]; GGError.Blink[feedback]; }; success _ FALSE; }; IF success AND cp.ext.length=0 THEN fullName _ Rope.Concat[fullName, ".gargoyle"]; }; ParseFontData: PUBLIC PROC [inStream: IO.STREAM, prefixP, familyP, faceP, transformP, sizeP: BOOL _ FALSE] RETURNS [fail: BOOL, prefix, family, face: Rope.ROPE, transform: ImagerTransformation.Transformation, size: REAL _ 0.0] = { ENABLE IO.Error, IO.EndOfStream, Convert.Error, GGParseIn.SyntaxError => { fail _ TRUE; CONTINUE; }; ReadWord: PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { WordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED { SELECT char FROM IO.TAB => RETURN [break]; IO.CR =>RETURN [break]; IO.SP => RETURN [break]; ', => RETURN [break]; '] => RETURN [break]; ') => RETURN [break]; ENDCASE => RETURN [other]; }; [word, ----] _ IO.GetTokenRope[f, WordBreakProc !IO.EndOfStream => {word _ NIL; CONTINUE}]; }; nameStream: IO.STREAM ; fail _ FALSE; IF prefixP THEN prefix _ IO.GetTokenRope[inStream, IO.IDProc].token; -- "xerox/myfonts/" nameStream _ IO.RIS[IO.GetTokenRope[inStream, IO.IDProc].token]; -- "fontOne-BI" IF familyP THEN family _ IO.GetTokenRope[nameStream, IO.TokenProc].token; -- "fontOne" IF faceP THEN face _ ReadWord[nameStream]; -- "-BI" (or SP) IF transformP THEN transform _ GGParseIn.ReadFactoredTransformation[inStream]; IF sizeP THEN size _ Convert.RealFromRope[IO.GetTokenRope[inStream, IO.IDProc].token]; -- "12" }; ParseLiteralFontData: PUBLIC PROC [inStream: IO.STREAM, nameP, transformP, sizeP: BOOL _ FALSE] RETURNS [fail: BOOL, fontName: Rope.ROPE, transform: ImagerTransformation.Transformation, size: REAL _ 0.0] = { ENABLE IO.Error, IO.EndOfStream, Convert.Error, GGParseIn.SyntaxError => { fail _ TRUE; CONTINUE; }; fail _ FALSE; IF nameP THEN fontName _ IO.GetTokenRope[inStream, IO.IDProc].token; -- "xerox/myfonts/Helvetica-bir" IF transformP THEN transform _ GGParseIn.ReadFactoredTransformation[inStream]; IF sizeP THEN size _ Convert.RealFromRope[IO.GetTokenRope[inStream, IO.IDProc].token]; -- "12" }; FontDataFromUserData: PUBLIC PROC [prefix, family, face: Rope.ROPE, size: REAL, preferredSize: REAL] RETURNS [fontName: Rope.ROPE, fontSize: REAL _ 1.0, fontPreferredSize: REAL, problem: Rope.ROPE] = { pressPrefix: Rope.ROPE _ "xerox/pressfonts/"; printPrefix: Rope.ROPE _ "xerox/xc1-2-2/"; screenPrefix: Rope.ROPE _ "xerox/tiogafonts/"; cmrFamily: Rope.ROPE _ "CMR"; faceRope: Rope.ROPE; SELECT TRUE FROM Rope.Equal[prefix, pressPrefix, FALSE] => { faceRope _ SELECT TRUE FROM Rope.Equal[face, "-B", FALSE] => "-brr", Rope.Equal[face, "-I", FALSE] => "-mir", Rope.Equal[face, "-BI", FALSE] => "-bir", Rope.Equal[face, "-IB", FALSE] => "-bir", ENDCASE => IF Rope.Equal[Rope.Substr[base: family, start: 0, len: 3], cmrFamily, FALSE] THEN "" ELSE "-mrr"; }; Rope.Equal[prefix, printPrefix, FALSE] => { faceRope _ SELECT TRUE FROM Rope.Equal[face, "-B", FALSE] => "-bold", Rope.Equal[face, "-I", FALSE] => "-italic", Rope.Equal[face, "-BI", FALSE] => "-bold-italic", Rope.Equal[face, "-IB", FALSE] => "-bold-italic", ENDCASE => ""; }; Rope.Equal[prefix, screenPrefix, FALSE] => { IF Real.Float[Real.Fix[preferredSize]] # preferredSize THEN RETURN[NIL, size, preferredSize, "Preferred size must be an integer."]; faceRope _ SELECT TRUE FROM Rope.Equal[face, "-B", FALSE] => "B", Rope.Equal[face, "-I", FALSE] => "I", Rope.Equal[face, "-BI", FALSE] => "BI", Rope.Equal[face, "-IB", FALSE] => "BI", ENDCASE => ""; faceRope _ Rope.Concat[Convert.RopeFromInt[from: Real.Fix[preferredSize], showRadix: FALSE], faceRope]; }; ENDCASE => RETURN[Rope.Cat[prefix, family, face], size, preferredSize, NIL]; -- may not be the right thing to do RETURN[Rope.Cat[prefix, family, faceRope], size, preferredSize, NIL]; }; UserDataFromFontData: PUBLIC PROC [fontName: Rope.ROPE, fontSize: REAL _ 0.0, fontPreferredSize: REAL _ 0.0] RETURNS [prefix, family, face: Rope.ROPE, size: REAL _ -1.0, preferredSize: REAL _ -1.0, problem: Rope.ROPE] = { isBold, isItalic: BOOL _ FALSE; familyFace: Rope.ROPE; pressPrefix: Rope.ROPE _ "xerox/pressfonts/"; printPrefix: Rope.ROPE _ "xerox/xc1-2-2/"; screenPrefix: Rope.ROPE _ "xerox/tiogafonts/"; cmrFamily: Rope.ROPE _ "CMR"; dashBold: Rope.ROPE _ "-bold"; dashItalic: Rope.ROPE _ "-italic"; prefix _ FileNames.Directory[fontName]; -- xerox/foofonts/ SELECT TRUE FROM Rope.Equal[prefix, pressPrefix, FALSE] => { familyFace _ FileNames.GetShortName[fontName]; -- Helvetica-bir or CMR family _ Head[familyFace, '-]; -- Helvetica face _ FileNames.Tail[fontName, '-]; -- -bir face _ SELECT TRUE FROM Rope.Equal[face, "bir", FALSE] => "-BI", Rope.Equal[face, "brr", FALSE] => "-B", Rope.Equal[face, "mir", FALSE] => "-I", Rope.Equal[face, "mrr", FALSE] => "", ENDCASE => ""; -- maybe should be ERROR ?? RETURN[prefix, family, face, 1.0, 1.0, NIL]; -- actual size is in client transform, not known here }; Rope.Equal[prefix, printPrefix, FALSE] => { familyFace _ FileNames.GetShortName[fontName]; -- Modern-bold-italic family _ Head[familyFace, '-]; -- Modern isBold _ Rope.Find[familyFace, dashBold, 0, FALSE]#-1; -- has -bold isItalic _ Rope.Find[familyFace, dashItalic, 0, FALSE]#-1; -- has -italic face _ SELECT TRUE FROM isBold AND isItalic => "-BI", isBold => "-B", isItalic => "-I", ENDCASE => ""; RETURN[prefix, family, face, 1.0, 1.0, NIL]; -- actual size is in client transform, not known here }; Rope.Equal[prefix, screenPrefix, FALSE] => { DigitProc: IO.BreakProc = { SELECT char FROM IO.TAB, IO.CR, IO.SP => RETURN [break]; '0, '1, '2, '3, '4, '5, '6, '7, '8, '9 => RETURN [break]; ENDCASE => RETURN [other]; }; AlphaProc: IO.BreakProc = { SELECT char FROM IO.TAB, IO.CR, IO.SP => RETURN [break]; IN ['a .. 'z], IN ['A .. 'Z] => RETURN [break]; ENDCASE => RETURN [other]; }; endOfName: BOOL; nameStream: IO.STREAM _ IO.RIS[(familyFace _ FileNames.GetShortName[fontName])]; -- Tioga10BI or TERMINAL family _ IO.GetTokenRope[nameStream, DigitProc].token; -- get the leading alpha characters preferredSize _ Convert.RealFromRope[IO.GetTokenRope[nameStream, AlphaProc ! IO.EndOfStream, IO.Error, Convert.Error => {endOfName _ TRUE; CONTINUE;};].token]; -- get any digit characters face _ GGParseIn.ReadBlankAndWord[nameStream]; face _ IF face=NIL THEN "" ELSE Rope.Concat["-", face]; RETURN[prefix, family, face, 1.0, preferredSize, NIL]; }; ENDCASE => RETURN[NIL, NIL, NIL, 0.0, 0.0, "Unknown font"]; }; Head: PROC [s: ROPE, char: CHAR] RETURNS [ROPE] = { pos: INT _ s.Length[] - 1; IF pos < 0 THEN RETURN[NIL]; DO IF s.Fetch[pos] = char THEN RETURN[s.Substr[0, pos]]; pos _ pos - 1; IF pos < 0 THEN RETURN[s]; ENDLOOP; }; END. êGGUtilityImpl.mesa Last edited by Bier on January 30, 1987 8:33:49 pm PST. Contents: General Purpose routines for use by Gargoyle. Pier, February 3, 1987 2:16:44 pm PST Templates for List Operations Destructive Delete DeleteTypeFromList: PUBLIC PROC [entity: Type, entityList: LIST OF Type] RETURNS [smallerList: LIST OF Type] = { beforeEnt, ent, afterEnt: LIST OF Type; notFound: BOOL _ FALSE; [beforeEnt, ent, afterEnt] _ FindTypeAndNeighbors[entity, entityList]; IF notFound THEN RETURN[entityList]; IF beforeEnt = NIL THEN smallerList _ afterEnt ELSE { beforeEnt.rest _ afterEnt; smallerList _ entityList; }; }; -- end of DeleteTypeFromList FindTypeAndNeighbors: PROC [entity: Type, entityList: LIST OF Type] RETURNS [beforeEnt, ent, afterEnt: LIST OF Type] = { lastE: LIST OF Type _ NIL; eList: LIST OF Type _ entityList; IF eList = NIL THEN SIGNAL Problem[msg: "msg"]; UNTIL eList = NIL DO IF eList.first = entity THEN { beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN}; lastE _ eList; eList _ eList.rest; ENDLOOP; SIGNAL Problem[msg: "msg"]; }; Operations on LIST OF FeatureData Operations on LIST OF Sequence Non-destructive (copies the first list). Operations on LIST OF REF ANY Two Finger List Constructor Operations on Assorted LIST Types Non-destructive (copies the first list). Two Finger List Construction StartTypeList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF Type] = { ptr _ entityList _ NIL; }; AddType: PUBLIC PROC [entity: Type, entityList, ptr: LIST OF Type] RETURNS [newList, newPtr: LIST OF Type] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; Modular Arithmetic Example: BreakIntervalMODLen[6, 4, 7] => [0, 3, 6, 1]. BreakIntervalMODLen[2, 5, 7] => [2, 5, -1, -1]. BreakIntervalMODLen[6, 8, 7] => [0, 7, 6, 1]. -- repeats 6 twice Operations on Bit Vectors File Names Font Parsing Used to read in a rope which is data. This routine has the hairy specific knowledge of the formats of font names. So far: prefix face fontName suffix xerox/xc1-2-2/ -B -bold xerox/xc1-2-2/ -I -italic xerox/xc1-2-2/ -BI -bold-italic xerox/xc1-2-2/ -IB -bold-italic xerox/xc1-2-2/ none none xerox/pressfonts/ -B -brr xerox/pressfonts/ -I -mir xerox/pressfonts/ -BI -bir xerox/pressfonts/ -IB -bir xerox/pressfonts/ none -mrr (unless CMR font) xerox/tiogafonts/ -B Fix[size]B xerox/tiogafonts/ -I Fix[size]I xerox/tiogafonts/ -BI Fix[size]BI xerox/tiogafonts/ -IB Fix[size]BI xerox/tiogafonts/ none Fix[size] DOESN'T DO CMR YET Head returns the part of a rope before the last instance of char. Head returns the entire rope if char is not found �ʘIcode™Kšœ3Ïkœ™7šÏnœ0™8Kšœ%™%—š� ˜ Kš�œ{�œ&˜¥—K˜šž œ�œ�˜Kš�œ)�œ�œ˜`Kš�œ �˜—˜Kš�œ�œ�œ˜Kšœ �œ˜)Kšœ �œ˜-Kšœ �œ˜%Kšœ �œ˜'Kšœ�œ˜!Kšœ�œ ˜5Kšœ�œ˜Kšœ�œ˜$—K˜Kš žœ�œ�œ �œ�œ˜/Kšžœ�œ�œ�œ˜%K˜Kšœ™™K™—KšÏb™šŸœžœ�œ�œ�œ�œ �œ�œ�œ ™xKšœ�œ�œ™)Kšœ �œ�œ™KšœH™HKš�œ �œ�œ ™$Kš�œ �œ�œ™.š�œ™Kšœ™Kšœ™K™—KšœÏc™!—šœ ž œ�œ�œ�œ �œ�œ�œ ™€Kšœ�œ�œ �œ™Kšœ�œ�œ™$Kš�œ �œ�œ�œ™1š�œ �œ�™Kš�œ�œ™Kšœ7�œ™?Kšœ™Kšœ™—Kš�œ™Kš�œ™Kšœ™—K™K˜Kšœ�œ�œ ™!K™š žœ�œ�œ�œ�œ�œ˜WKšœ�œ˜K˜K˜—šžœ�œ�œ(�œ�œ�œ�œ�œ˜Šš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜K˜—Kšœ�œ�œ ™K˜šžœ�œ�œ�œ�œ �œ�œ�œ˜zKšœ�œ�œ ˜+Kšœ �œ�œ˜KšœD˜DKš�œ �œ�œ ˜!Kš�œ �œ�œ˜.š�œ˜Kšœ˜Kšœ˜K˜—Kšœ  ˜#K˜—šžœ�œ �œ�œ �œ�œ�œ˜ˆKšœ�œ�œ �œ˜Kšœ�œ�œ˜%Kš�œ �œ�œ�œ˜)š�œ �œ�˜Kš�œ�œ˜Kšœ7�œ˜?Kšœ˜Kšœ˜—Kš�œ˜Kš�œ%˜+Kšœ˜—šžœ�œ�œ�œ�œ �œ �œ�œ˜gKšœ�œ�œ ˜Kšœ �œ�œ ˜K™(Kš�œ �œ�œ�œ˜"Kšœ �œ�œ˜ Kšœ ˜ š �œ�œ�œ�œ�œ�˜=Kšœ �œ �œ˜Kšœ˜Kšœ˜—Kš�œ˜Kšœ˜Kšœ ˜K˜—š žœ�œ�œ�œ�œ�œ˜QKšœ�œ˜K˜K˜—šž œ�œ�œ%�œ�œ �œ�œ�œ˜~š�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜—K˜Kšœ�œ�œ�œ�™K™KšŸ™šž œ�œ�œ�œ�œ�œ�œ�œ˜HKšœ�œ˜K˜K˜—šž œ�œ�œ �œ�œ�œ�œ�œ�œ�œ�œ�œ�œ�œ˜yš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜K˜—K™Kšœ�œ™!K™šž œ�œ�œ�œ�œ�œ�œ �œ�œ�œ˜UKšœ�œ�œ�œ˜Kšœ �œ�œ�œ˜K™(Kš�œ �œ�œ�œ˜"Kšœ �œ�œ˜ Kšœ ˜ š �œ�œ�œ�œ�œ�œ�˜8Kšœ �œ �œ˜Kšœ˜Kšœ˜—Kš�œ˜Kšœ˜Kšœ˜K˜—K˜šž œ�œ�œ�œ�œ�œ�œ˜GKšœ�œ˜K˜K˜—š ž œ�œ�œ�œ�œ�œ ˜IKšœ�œ˜K˜—š ž œ�œ�œ�œ�œ�œ˜RKšœ�œ˜K˜—š žœ�œ�œ�œ�œ�œ ˜OKšœ�œ˜K˜K˜—š žœ�œ�œ�œ�œ�œ ˜KKšœ�œ˜K˜—K™KšŸ™š œ žœ�œ�œ�œ�œ�œ ™MKšœ�œ™K™—šœ �œ�œ#�œ�œ �œ�œ�œ ™vš�œ�œ�œ™Kš �œ�œ�œ�œ�œ™#Kšœ�œ �œ™%Kš�œ™K™—š�œ™Kšœ™Kšœ �œ �œ™Kšœ™K™—K™—K˜šž œ�œ�œ$�œ�œ �œ�œ�œ ˜zš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜K˜—šžœ�œ�œ"�œ�œ�œ�œ�œ ˜rš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜—šžœ�œ�œ �œ�œ�œ�œ�œ�œ�œ�œ˜jš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜K˜—šžœ�œ�œ!�œ�œ�œ�œ�œ ˜nš�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜—šžœ�œ�œ,�œ�œ�œ�œ�œ˜�š�œ�œ�œ˜Kš �œ�œ�œ�œ�œ˜#Kšœ�œ �œ˜%Kš�œ˜K˜—š�œ˜Kšœ˜Kšœ �œ �œ˜Kšœ˜K˜—K˜—K˜Kšœ™K™š žœ�œ�œ�œ�œ�œ˜VKš�œ�œ �œ�œ˜)Kš�œ�œ�œ˜0Kš�œ˜K˜K˜—š žœ�œ�œ�œ�œ�œ˜]Kšžœ/™6Kšœ/™/Kšœ. ™@Kš�œ�œ�œ�œ˜,Kš�œ�œ�œ˜8Kš�œ%˜+K˜K˜—šž œ�œ�œ�œ�œ�œ�œ˜NKš�œ �œ�œ˜*Kš�œ �œ�œ�œ˜2Kš�œ�œ�œ�œ ˜2Kšœ˜—K˜Kšœ™K™š žœ�œ�œ�œ�œ˜<š�œ�œ�œ�˜ Jš �œ �œ�œ�œ�œ˜'—Jš�œ˜Jš�œ�œ˜ K˜K˜—š žœ�œ�œ�œ�œ˜;š�œ�œ�œ�˜ Jš �œ �œ�œ�œ�œ˜(—Jš�œ˜Jš�œ�œ˜ K˜K˜—K˜K™ K™šžœ�œ�œ�œ�œ�œ�œ�œ �œ�œ˜žKšœ�œ˜š�œ�œ�œ˜9KšœK˜KKšœ˜Kš�œ�œ�œ˜K˜—šœ�œ"�œ ˜DKšœI˜IKšœ˜Kšœ �œ˜Kš�œ˜ K˜Kšœ˜—Kš�œ�œ �œ�œ˜š�œL�œ˜Tš�œ˜KšœU˜UKšœ˜Kšœ �œ�œ˜K˜——Kš�œ�œ)˜@K˜K˜—š žœ�œ�œ#�œ�œ(�œ˜†Kšœ �œ˜šœ4�œ˜9š�œ ˜ Kšœ6˜6Kš�œ˜ Kšœ˜—šœ 9˜MKšœS˜SKš�œ˜ Kšœ˜—šœ :˜LKšœS˜SKš�œ˜ Kšœ˜—š�œ�œ˜KšœO˜OKš�œ˜ Kšœ˜—Kšœ˜—š�œ�œ˜KšœL˜LKš�œ˜ Kšœ˜—š�˜šœ ˜ Kšœ˜Kšœ �œ˜K˜——K˜K˜K˜—šžœ�œ�œ�œ�œ�œ�œ�œ�œ�œ �œ�œ�œ�œ˜ÕKšœ�œ˜KšœI˜Iš�œ�œ�œ˜9•StartOfExpansionÒ[gargoyleData: REF ANY, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]š�œ�œ �œ˜Kšœ:˜:Kšœ˜K˜—Kš�œ�œ�œ˜Kšœ˜—šœ�œ"�œ ˜DKšœ �œ˜–Ò[gargoyleData: REF ANY, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]š�œ�œ �œ˜KšœY˜YKšœ˜K˜—Kš�œ˜ K˜Kšœ˜—–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]š �œ �œg�œ�œn�œ�œ˜úš�œ�œ �œ˜Kšœ\˜\Kšœ˜K˜—Kšœ �œ˜K˜—Kš�œ �œ�œ/˜RK˜K˜—K™ šž œ�œ�œ �œ�œ.�œ�œ�œ�œ�œ8�œ ˜æš�œ�œ�œ7˜JKšœ�œ˜ Kš�œ˜ Kšœ˜—procš žœ�œ�œ�œ�œ �œ˜;Lšœ%™%šž œ�œ�œ�œ�œ�œ�œ˜Hš�œ�˜Lš�œ�œ�œ ˜Lš�œ�œ�œ ˜Lš�œ�œ�œ ˜Lšœ�œ ˜Lšœ�œ ˜Lšœ�œ ˜Lš�œ�œ ˜—Lšœ˜—šœ œ�œ˜/Lšœ�œ�œ�œ˜+—Lšœ˜L˜—Kšœ �œ�œ˜Kšœ�œ˜ Kš �œ �œ �œ�œ ˜XKš œ �œ�œ�œ�œ ˜PKš �œ �œ �œ�œ  ˜VKš�œ�œ ˜;K– [f: STREAM]š�œ �œ<˜NK– [r: ROPE]š �œ�œ�œ�œ ˜^Jšœ˜J˜—šžœ�œ�œ �œ�œ�œ�œ�œ�œ�œ8�œ ˜Ïš�œ�œ�œ7˜JKšœ�œ˜ Kš�œ˜ Kšœ˜—Kšœ�œ˜ Kš �œ�œ �œ�œ  ˜eK– [f: STREAM]š�œ �œ<˜NK– [r: ROPE]š �œ�œ�œ�œ ˜^Jšœ˜J˜—šžœ�œ�œ�œ�œ�œ�œ�œ �œ�œ�œ˜ÉšœK™KKšœ%™%Kšœ™Kšœ™Kšœ�œ ™ Kšœ�œ ™ Kšœ™K™Kšœ™Kšœ™Kšœ�œ™Kšœ�œ™Kšœ%�œ™.K™Kšœ ™ Kšœ ™ Kšœ�œ �™"Kšœ�œ �™"Kšœ!™!K™—Kšœ�œ˜-Kšœ�œ˜*Kšœ�œ˜.Kšœ�œ ˜Kšœ�œ˜š�œ�œ�˜šœ �œ˜+šœ �œ�œ�˜Kšœ�œ ˜(Kšœ�œ ˜(Kšœ�œ ˜)Kšœ�œ ˜)K–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]š �œ�œD�œ�œ�œ˜l—Kšœ˜—šœ �œ˜+šœ �œ�œ�˜Kšœ�œ ˜)Kšœ�œ˜+Kšœ�œ˜1Kšœ�œ˜1Kš�œ˜—K˜Kšœ˜—šœ!�œ˜,Kš�œ5�œ�œ�œ=˜ƒšœ �œ�œ�˜Kšœ�œ ˜%Kšœ�œ ˜%Kšœ�œ ˜'Kšœ�œ ˜'Kš�œ˜—K–L[from: REAL, precision: Convert.RealPrecision _ 7, useE: BOOL _ FALSE]šœU�œ ˜gKšœ˜—Kš�œ�œ6�œ #˜p—Kš�œ:�œ˜EKšœ˜K˜—šžœ�œ�œ�œ �œ�œ�œ�œ�œ�œ�œ˜ÝKšœ�œ�œ˜Kšœ�œ˜Kšœ�œ˜-Kšœ�œ˜*Kšœ�œ˜.Kšœ�œ ˜Kšœ�œ ˜Kšœ�œ ˜"K˜K–[path: ROPE]šœ) ˜;š�œ�œ�˜šœ �œ˜+Kšœ/ ˜FKšœ  ˜+Kšœ% ˜,šœ�œ�œ�˜Kšœ�œ ˜(Kšœ�œ ˜'Kšœ�œ ˜'Kšœ�œ˜%Kš�œ ˜*KšÐbkŸ¡Ÿ¡Ÿ¡™—Kš�œ!�œ 5˜bK˜—šœ �œ˜+Kšœ/ ˜DKšœ  ˜(Kšœ,�œ  ˜CKšœ0�œ ˜Išœ�œ�œ�˜Kšœ�œ˜Kšœ˜Kšœ˜Kš�œ˜—Kš�œ!�œ 5˜bK˜—šœ!�œ˜,šž œ�œ˜š�œ�˜Lš�œ�œ�œ�œ�œ�œ�œ ˜'Lšœ*�œ ˜9Lš�œ�œ ˜—K˜—šž œ�œ˜š�œ�˜Lš�œ�œ�œ�œ�œ�œ�œ ˜'Lš�œ �œ�œ ˜/Lš�œ�œ ˜—K˜—Kšœ �œ˜Kš œ �œ�œ�œ�œ3 ˜iKšœ �œ, #˜ZKš œ%�œ&�œ�œ&�œ�œ  ˜»Kšœ.˜.Kš œ�œ�œ�œ�œ˜7Kš�œ+�œ˜6K˜—Kš �œ�œ�œ�œ�œ˜;—K˜K˜—š žœ�œ�œ�œ�œ�œ˜3K™AK™1Kšœ�œ˜Kš�œ �œ�œ�œ˜š�˜Kš�œ�œ�œ˜5K˜Kš�œ �œ�œ˜Kš�œ˜—K˜—K˜Kš�œ˜—…—?Þhä