<> <> <> <> <> DIRECTORY Ascii, Atom, LooksReader, NodeProps, NodeStyle, NodeStyleOps, Rope, RopeReader, TextLooks, TextNode, TSTranslate, TSTranslatePrivate, TSArtwork, TSFont, TSGraphic, TSGlue, TSObject, TSOps, TSTypes, TextEdit; TSTranslateImpl: CEDAR PROGRAM IMPORTS Atom, LooksReader, NodeProps, NodeStyleOps, Rope, RopeReader, TextNode, TSTranslatePrivate, TSArtwork, TSFont, TSGraphic, TSObject, TSOps, TSTypes, TextEdit EXPORTS TSTranslate = BEGIN OPEN TSTypes, TSTranslatePrivate; FontNotFound: PUBLIC SIGNAL [fontName: Rope.ROPE, location: INT] RETURNS [substitute: Rope.ROPE] = CODE; ROPE: TYPE = Rope.ROPE; underAndStrikeThickess: REAL _ 0.4; underlineDrop: REAL _ -3.0; strikeoutRise: REAL _ 3.0; TreeToVlist: PUBLIC PROCEDURE [t: TextNode.Ref, progressProc: TSTranslate.ProgressProc _ NIL] RETURNS [galley: TSObject.ItemList, style: NodeStyle.Ref] = TRUSTED BEGIN state: State _ NewState[]; <> state.level _ IF TextNode.Level[t] = 0 THEN 0 ELSE -1; state.currentNode _ t; state.remainingLength _ 0; state.progressProc _ progressProc; state.totalChars _ state.charsToGo _ TextNode.LocNumber[TextNode.LastLocWithin[t], 0]; galley _ TSObject.CreateItemList[ProduceFromBranch, state]; style _ state.nodeStyle; NodeStyleOps.ApplyAll[style, t, print]; IF NodeProps.GetProp[t, $Yum] # NIL THEN state.totalChars _ state.charsToGo _ 1; END; ProduceFromBranch: TSObject.ProducerProc = TRUSTED { state: State _ NARROW[listWriter.writerData]; ProduceEndOfDocument: PROCEDURE = TRUSTED { listWriter.ProduceItem[TSObject.fillGlue]; listWriter.ProduceEnd[]; IF state.progressProc # NIL THEN state.progressProc[100]; }; IF state.remainingLength = 0 THEN { DO IF state.level < 0 THEN <> state.level _ 0 ELSE { <> deltaLevel: INTEGER; [state.currentNode, deltaLevel] _ TextNode.Forward[state.currentNode]; state.level _ state.level + deltaLevel; IF state.progressProc # NIL THEN -- update progress as we advance nodes state.progressProc[100*(state.totalChars-state.charsToGo)/(state.totalChars+0.01)]; IF state.level <= 0 THEN { ProduceEndOfDocument[]; RETURN }; }; IF NOT IsAMarkNode[state.currentNode] THEN EXIT; -- the current node content should be formatted ProduceMarkBranch[listWriter, state]; SkipOverBranch[state]; IF state.level <= 0 THEN { ProduceEndOfDocument[]; RETURN }; ENDLOOP; InitializeStateForNewNode[listWriter, state]; }; IF IsAnArtworkNode[state.currentNode] THEN { ProduceArtworkBranch[listWriter, state]; SkipOverBranch[state]; IF state.level <= 0 THEN ProduceEndOfDocument[]; RETURN } ELSE ProduceFromTextNode[listWriter, state]; }; ProduceFromTextNode: PROCEDURE [listWriter: TSObject.ListWriter, state: State] = TRUSTED { OPEN state^; r: TSObject.ListReader; hlist: TSObject.ItemList _ TSObject.CreateItemList[producer: NIL]; hlistWriter: TSObject.ListWriter _ hlist.listWriter; hasCharProps: BOOL ~ currentNode.hascharprops; oldCharPostfix: REF _ NIL; hlist.listWriter _ NIL; IF leftFillParameter # NIL THEN hlistWriter.ProduceItem[leftFillParameter]; IF rightFillParameter # NIL THEN hlistWriter.ProduceItem[rightFillParameter]; IF leftFillParameter # NIL THEN FOR p: LIST OF REF ANY _ leftFillParameter.listParameter, p.rest UNTIL p=NIL DO hlistWriter.ProduceItem[p.first]; ENDLOOP; IF firstIndentItem # NIL THEN {hlistWriter.ProduceItem[firstIndentItem]; firstIndentItem _ NIL}; oldLooks _ TextLooks.allLooks; -- to force apply on first char UNTIL remainingLength = 0 DO ropeIndex: INT _ ropeReader.GetIndex[]; CharPostfixChange: PROC RETURNS [changed: BOOL] ~ CHECKED { charPostfix: REF ~ TextEdit.GetCharProp[currentNode, ropeIndex, $Postfix]; changed _ oldCharPostfix # charPostfix; oldCharPostfix _ charPostfix; }; char: CHAR _ RopeReader.Get[ropeReader]; looks: TextLooks.Looks _ LooksReader.Get[looksReader]; charPostfix: REF _ NIL; charsToGo _ charsToGo-1; remainingLength _ remainingLength - 1; IF looks # oldLooks OR underlining#None OR strikeout#None OR (hasCharProps AND CharPostfixChange[]) THEN { under, strike: Dimn _ zeroDimn; GetNewLooks[hlistWriter, state, looks ! TSFont.FontNotFound => TRUSTED {substituteName _ SIGNAL FontNotFound[name, state.totalChars-state.charsToGo]}]; SELECT underlining FROM None => {}; LettersAndDigits => IF char IN ['A..'Z] OR char IN ['a..'z] OR char IN ['0..'9] THEN under _ Pt[underAndStrikeThickess]; Visible => IF char IN (' ..'~] THEN under _ Pt[underAndStrikeThickess]; All => under _ Pt[underAndStrikeThickess]; ENDCASE => ERROR; SELECT strikeout FROM None => {}; LettersAndDigits => IF char IN ['A..'Z] OR char IN ['a..'z] OR char IN ['0..'9] THEN strike _ Pt[underAndStrikeThickess]; Visible => IF char IN (' ..'~] THEN strike _ Pt[underAndStrikeThickess]; All => strike _ Pt[underAndStrikeThickess]; ENDCASE => ERROR; hlistWriter.ProduceParameter[underlineThickness, under]; hlistWriter.ProduceParameter[strikeoutThickness, strike]; IF under#zeroDimn THEN hlistWriter.ProduceParameter[underlineBottom, Pt[underlineDrop]]; IF strike#zeroDimn THEN hlistWriter.ProduceParameter[strikeoutBottom, Pt[strikeoutRise]]; }; SELECT char FROM Ascii.CR => EXIT; Ascii.TAB => { hlistWriter.ProduceEnd[]; hlist _ Tabify[hlist, state]; hlistWriter _ hlist.listWriter; hlist.listWriter _ NIL; }; Ascii.SP => hlistWriter.ProduceFromRope[curfont, rope, ropeIndex, space]; ENDCASE => hlistWriter.ProduceFromRope[curfont, rope, ropeIndex, char]; ENDLOOP; IF progressProc#NIL THEN progressProc[100*(totalChars-charsToGo)/(totalChars+0.01)]; FOR p: LIST OF REF ANY _ endFill, p.rest UNTIL p=NIL DO hlistWriter.ProduceItem[p.first]; ENDLOOP; hlistWriter.ProduceEnd[]; r _ TSOps.BreakUp[hlist, right, galleyWidth].CreateReader[]; UNTIL r.End[] DO IF r.CurrentTag[] = exception THEN listWriter.ProduceItem[r.CurrentItem[]] ELSE ERROR; r.Next[]; ENDLOOP; r.DestroyReader[]; ProduceBottomLeadingStretchAndShrink[listWriter, state]; }; IsAnArtworkNode: PROC [node: TextNode.Ref] RETURNS [BOOLEAN] ~ { recursingOnThisArtwork: BOOLEAN _ NodeProps.GetProp[node, $TSetterProcessingArtwork] # NIL; IF recursingOnThisArtwork THEN RETURN [FALSE] ELSE RETURN [NOT Rope.IsEmpty[NARROW[NodeProps.GetProp[node, $ArtworkClass]]]]; }; ProduceArtworkBranch: PROCEDURE [listWriter: TSObject.ListWriter, state: State] = TRUSTED { artworkClass: ROPE _ NARROW[NodeProps.GetProp[state.currentNode, $ArtworkClass]]; box: TSObject.Box; <> NodeProps.PutProp[state.currentNode, $TSetterProcessingArtwork, $ArtworkClass]; box _ BoxFromArtworkBranch[state, artworkClass]; <<>> <> NodeProps.RemProp[state.currentNode, $TSetterProcessingArtwork]; { <> r: TSObject.ListReader; hlist: TSObject.ItemList _ TSObject.CreateItemList[producer: NIL]; hlistWriter: TSObject.ListWriter _ hlist.listWriter; hlist.listWriter _ NIL; IF state.leftFillParameter # NIL THEN hlistWriter.ProduceItem[state.leftFillParameter]; IF state.rightFillParameter # NIL THEN hlistWriter.ProduceItem[state.rightFillParameter]; IF state.leftFillParameter # NIL THEN FOR p: LIST OF REF ANY _ state.leftFillParameter.listParameter, p.rest UNTIL p=NIL DO hlistWriter.ProduceItem[p.first]; ENDLOOP; IF state.firstIndentItem # NIL THEN { hlistWriter.ProduceItem[state.firstIndentItem]; state.firstIndentItem _ NIL}; hlistWriter.ProduceItem[box]; -- we do all this for this box FOR p: LIST OF REF ANY _ state.endFill, p.rest UNTIL p=NIL DO hlistWriter.ProduceItem[p.first]; ENDLOOP; hlistWriter.ProduceEnd[]; r _ TSOps.BreakUp[hlist, right, state.galleyWidth].CreateReader[]; UNTIL r.End[] DO IF r.CurrentTag[] = exception THEN listWriter.ProduceItem[r.CurrentItem[]] ELSE ERROR; r.Next[]; ENDLOOP; r.DestroyReader[]; ProduceBottomLeadingStretchAndShrink[listWriter, state]; }; }; BoxFromArtworkBranch: PROCEDURE [state: State, artworkClass: ROPE] RETURNS [box: TSObject.Box] = TRUSTED { objectFromBranch: TSArtwork.ObjectFromBranchProc ~ TSArtwork.Lookup[artworkClass]; object: TSGraphic.Object ~ objectFromBranch[state.currentNode]; extent: Dimensions ~ object.Layout[ maxX: state.galleyWidth, maxY: RealDimn[11, in], suggestedX: state.galleyWidth ]; box _ NEW[graphic TSObject.BoxRec _ [extent, graphic [object]]]; }; IsAMarkNode: PROC [node: TextNode.Ref] RETURNS [BOOLEAN] ~ { recursingOnThisMark: BOOLEAN _ NodeProps.GetProp[node, $TSetterProcessingMark] # NIL; IF recursingOnThisMark THEN RETURN [FALSE] ELSE RETURN [NOT Rope.IsEmpty[NARROW[NodeProps.GetProp[node, $Mark]]]]; }; ProduceMarkBranch: PROCEDURE [listWriter: TSObject.ListWriter, state: State] = TRUSTED { contents: TSObject.ItemList; box: TSObject.Box; mark: ROPE _ NARROW[NodeProps.GetProp[state.currentNode, $Mark]]; newMark: TSObject.MarkList _ NEW[TSObject.MarkListItem]; <> NodeProps.PutProp[state.currentNode, $TSetterProcessingMark, $Mark]; contents _ TreeToVlist[state.currentNode].galley; box _ TSOps.GetSlimBoxFrom[contents]; newMark.link _ NIL; newMark.markKind _ Atom.MakeAtom[mark]; newMark.markValue _ box; listWriter.ProduceItem[newMark]; <> NodeProps.RemProp[state.currentNode, $TSetterProcessingMark]; }; SkipOverBranch: PROCEDURE [state: State] = { continuationNode: TextNode.Ref _ TextNode.LastWithin[state.currentNode]; state.charsToGo _ state.totalChars- TextNode.LocNumber[TextNode.LastLocWithin[state.currentNode], 0]; state.remainingLength _ 0; state.level _ state.level + TextNode.Level[continuationNode] - TextNode.Level[state.currentNode]; state.currentNode _ continuationNode; }; END. Michael Plass, June 28, 1982 8:56 am. Renamed from TPTranslateImpl. Michael Plass, July 15, 1982 11:20 am. Fixed it so CRs do not cause firstIndent on the next line. Michael Plass, September 15, 1982 10:54 am. Changed Rope.SP, etc, to refer to Ascii. Michael Plass, November 12, 1982 10:53 am. Added underline and strikeout. Michael Plass, November 17, 1982 9:13 am. Changed TreeToVlist to return style. Michael Plass, November 17, 1982 12:09 pm. Added FontNotFound. Michael Plass, December 8, 1982 3:38 pm. Took account of layout proc change. Rick Beach, May 18, 1983 8:26 am. Added marks to ProduceFromBranch., Rick <> <> <> <> < procedures that took a listWriter and updated the current state.>> <> <> <> <> <> <<>> <> <> <<>> <> <> <<>> <> <> <<>> <<>> <> <> <> <<>> <<>> <<>> <<>>