<> <> <> <> DIRECTORY Rope, TSTypes, TSGlue, TSFont, TSGraphic; TSObject: CEDAR DEFINITIONS IMPORTS TSTypes, Rope = BEGIN ROPE: TYPE = Rope.ROPE; GlueRec: TYPE = TSGlue.Glue; Dimn: TYPE = TSTypes.Dimn; Direction: TYPE = TSTypes.Direction; Dimensions: TYPE = TSTypes.Dimensions; ParameterName: TYPE = {baselineskip, lineskip, lineskipstretch, lineskipshrink, lineskiplimit}; ItemList: TYPE = REF ItemListRec; ListReader: TYPE = REF ListReaderRec; ListWriter: TYPE = REF ListWriterRec; Next: PROCEDURE [self: ListReader]; End: PROCEDURE [self: ListReader] RETURNS [BOOLEAN] = INLINE { RETURN[self.itemList.tagList.first[self.tagOffset] = end] }; CreateItemList: PROCEDURE [ producer: ProducerProc, writerData: REF ANY _ NIL ] RETURNS [new: ItemList]; SingletonList: PROCEDURE [item: REF ANY] RETURNS [new: ItemList]; Copy: PROCEDURE [self: ItemList] RETURNS [new: ItemList]; Concat: PROCEDURE [a, b: TSObject.ItemList]; -- concatenates b onto the end of a. CreateReader: PROCEDURE [list: ItemList] RETURNS [reader: ListReader]; CopyReader: PROCEDURE [reader: ListReader] RETURNS [copy: ListReader]; DestroyReader: PROCEDURE [reader: ListReader]; -- O.K. to never destroy a reader, but don't destroy one twice! Expand: PROCEDURE [self: ListReader] RETURNS [explicitList: LIST OF REF ANY _ NIL]; ItemListFromExplicitList: PROCEDURE [explicitList: LIST OF REF ANY _ NIL] RETURNS [new: ItemList]; -- the explicit list should be immutable. CurrentTag: PROCEDURE [self: ListReader] RETURNS [Tag] = INLINE {RETURN[self.itemList.tagList.first[self.tagOffset]]}; CurrentChar: PROCEDURE [self: ListReader] RETURNS [CHAR] = INLINE {RETURN[self.baseRope.Fetch[self.ropeOffset]]}; CurrentItem: PROCEDURE [self: ListReader] RETURNS [REF ANY] = INLINE {RETURN[self.itemList.exceptionList.first]}; ItemListRec: TYPE = RECORD [ listWriter: ListWriter, tagList: LIST OF TagRec, exceptionList: LIST OF REF ANY, successor: ItemList _ NIL ]; ListReaderRec: TYPE = RECORD [ itemList: ItemListRec, baseRope: ROPE _ NIL, ropeOffset: INT _ 0, currentFont: TSFont.Ref _ NIL, tagOffset: NAT _ 0, parameter: ARRAY ParameterType OF Dimn, listParameter: ARRAY ListParameterType OF LIST OF REF ANY ]; ListWriterRec: TYPE = RECORD [ producer: ProducerProc, tagList: LIST OF TagRec _ NIL, tagOffset: NAT _ 0, exceptionList: LIST OF REF ANY _ NIL, currentFont: TSFont.Ref _ NIL, baseRope: ROPE _ NIL, ropeOffset: INT _ 0, parameter: ARRAY ParameterType OF Dimn, writerData: REF ANY _ NIL ]; tagRecSize: NAT = 100; TagRec: TYPE = PACKED ARRAY [0..tagRecSize) OF Tag; Tag: TYPE = { char, -- get next character from the rope, using current font space, -- normal space, in current font hyphen, -- discretionary hyphen in current font leading, -- calculated inter-line leading exception, -- refer to the exception list for the next item end, -- the end of the list <> ignore, -- ignore the next character in the rope produce -- call the producer proc to extend the list }; <> Box: TYPE = REF BoxRec; Leader: TYPE = REF LeaderRec; Glue: TYPE = REF TSGlue.Glue; Kern: TYPE = REF Dimn; Penalty: TYPE = REF PenaltyRec; Kerf: TYPE = REF KerfRec; Parameter: TYPE = REF ParameterRec; ListParameter: TYPE = REF ListParameterRec; MarkList: TYPE = REF MarkListItem; <> Font: TYPE = TSFont.Ref; <> RopeOffset: TYPE = REF RopeOffsetRec; ProducerProc: TYPE = PROCEDURE [listWriter: ListWriter]; ProduceItem: PROCEDURE [self: ListWriter, item: REF ANY] = INLINE { self.exceptionList.rest _ qZone.LIST[item]; self.exceptionList _ self.exceptionList.rest; self.tagList.first[self.tagOffset] _ exception; self.tagOffset _ self.tagOffset + 1; IF self.tagOffset >= tagRecSize THEN Extend[self]; }; ProduceParameter: PROCEDURE [self: ListWriter, parameterType: ParameterType, parameterValue: Dimn]; ProduceFromRope: PROCEDURE [self: ListWriter, font: Font, rope: ROPE, offset: INT, tag: Tag] = INLINE { IF font # self.currentFont THEN { self.ProduceItem[font]; self.currentFont _ font; }; IF rope # self.baseRope THEN { self.ProduceItem[rope]; self.baseRope _ rope; self.ropeOffset _ 0; }; SELECT offset-self.ropeOffset FROM 0 => {}; 1 => {self.ProduceTag[ignore]; self.ropeOffset _ self.ropeOffset + 1}; 2 => {self.ProduceTag[ignore]; self.ProduceTag[ignore]; self.ropeOffset _ self.ropeOffset + 2}; ENDCASE => { self.ProduceItem[qZone.NEW[RopeOffsetRec _ [offset]]]; self.ropeOffset _ offset; }; self.ProduceTag[tag]; self.ropeOffset _ self.ropeOffset + 1; }; ProduceHyphen: PROCEDURE [self: ListWriter, font: Font] = INLINE { IF font # self.currentFont THEN { self.ProduceItem[font]; self.currentFont _ font; }; self.ProduceTag[hyphen]; }; ProduceLeading: PROCEDURE [self: ListWriter] = INLINE { self.ProduceTag[leading]; }; ProduceEnd: PROCEDURE [self: ListWriter] = INLINE { self.ProduceTag[end]; self.producer _ NIL; self.tagList _ NIL; self.exceptionList _ NIL; self.currentFont _ NIL; self.baseRope _ NIL; self.writerData _ NIL; }; BoxType: TYPE = {empty, char, list, rule, graphic}; BoxRec: TYPE = RECORD [ extent: Dimensions, body: SELECT type: BoxType FROM empty => [], char => [font: TSFont.Ref, c: CHAR], list => [direction: Direction, items: ItemList, glueset: TSGlue.GlueSet], rule => [], graphic => [graphicObject: TSGraphic.Object], ENDCASE]; LeaderRec: TYPE = RECORD [ minExtent: Dimensions, stretchDirection: Direction, flexibility: Glue, graphicObject: TSGraphic.Object ]; PenaltyRec: TYPE = RECORD [ penalty: TSTypes.Penalty ]; KerfRec: TYPE = RECORD [ penalty: TSTypes.Penalty, prebreak, join, postbreak: LIST OF REF ANY ]; ParameterType: TYPE = {minbaseline, mingaps, shift, hue, saturation, brightness, strikeoutThickness, strikeoutBottom, underlineThickness, underlineBottom}; ParameterRec: TYPE = RECORD [ parameterType: ParameterType, parameter: Dimn ]; ListParameterType: TYPE = {lineskip, columnskip, leftfill, rightfill}; ListParameterRec: TYPE = RECORD [ listParameterType: ListParameterType, listParameter: LIST OF REF ANY ]; MarkListItem: TYPE = RECORD [ link: REF MarkListItem, markKind: ATOM, -- Derived from the "mark" property on nodes; argument to .getmark and .getfirstmark in the page builder routine. markValue: Box ]; RopeOffsetRec: TYPE = RECORD [ ropeOffset: INT ]; ProduceTag: PRIVATE PROCEDURE [self: ListWriter, tag: Tag] = INLINE { self.tagList.first[self.tagOffset] _ tag; self.tagOffset _ self.tagOffset + 1; IF self.tagOffset >= tagRecSize THEN Extend[self]; }; MakeGlue: PROCEDURE [space, plus, minus: Dimn _ TSTypes.zeroDimn] RETURNS [p: REF ANY]; -- makes glue or, if possible, a kern MakeKerf: PUBLIC PROCEDURE [prebreak, join, postbreak: LIST OF REF ANY _ NIL, penalty: TSTypes.Penalty _ 0] RETURNS [p: TSObject.Kerf]; fillGlue: READONLY REF ANY; filGlue: READONLY REF ANY; bigGlue: READONLY REF ANY; Extend: PRIVATE PROCEDURE [self: ListWriter]; pZone: ZONE; qZone: ZONE; END. Michael Plass, September 1, 1982 9:02 pm: Added qZone, changed tagRecSize from 12 to 100. Michael Plass, November 2, 1982 10:19 am. CEDARized. Michael Plass, November 12, 1982 9:21 am. Added pZone, undeline & strikeout parameters. Michael Plass, May 12, 1983 4:22 pm. Added MarkList, MarkListItem.