MODULE DTPData; (** AUTHOR "PL"; PURPOSE "Data Model for simple DTP Editor"; *) IMPORT Files, XML, WMGraphics, Strings, WMWindowManager; (* , DTPFrame; *) CONST TYPE MetaInformation* = OBJECT VAR author*, documentName*, documentTitle* : Strings.String; END MetaInformation; StyleObject* = OBJECT VAR name*: ARRAY 64 OF CHAR; (* unique style name *) END StyleObject; ParagraphStyleObject* = OBJECT(StyleObject) VAR alignment* : LONGINT; (* 0 = left, 1 = center, 2 = right, 3 = justified *) spaceBefore* : REAL; (* space before paragraph [mm] *) spaceAfter* : REAL; (* space after paragrapg [mm] *) leftIndent* : REAL; (* left Indent [mm] *) rightIndent* : REAL; (* right Indent [mm] *) firstIndent* : REAL; (* first Line Indent [mm] *) charStyle* : CharacterStyleObject; PROCEDURE Clone*(): ParagraphStyleObject; VAR newPSO: ParagraphStyleObject; BEGIN NEW(newPSO); newPSO.name := name; newPSO.alignment := alignment; newPSO.spaceBefore := spaceBefore; newPSO.spaceAfter := spaceAfter; newPSO.firstIndent := firstIndent; newPSO.leftIndent := leftIndent; newPSO.rightIndent := rightIndent; newPSO.charStyle := charStyle; RETURN newPSO; END Clone; END ParagraphStyleObject; CharacterStyleObject* = OBJECT(StyleObject) VAR family* : ARRAY 32 OF CHAR; (* font family *) style* : SET; (* font style; 0 = bold, 1 = italic *) size* : REAL; (* font size [pt]; 1pt == 1/72inch == 0,3527777778mm *) leading* : REAL; (* baseline distance [pt] - usually 120% of font size *) baselineShift* : REAL; (* baseline shift up/down [pt] *) tracking* : REAL; (* character spacing [pt] *) kerning* : REAL; (* NOT USED - needs appropriate Fonts *) scaleHorizontal* : REAL; (* horizontal character scale *) scaleVertical* : REAL; (* vertical character scale *) color* : LONGINT; (* character color *) bgColor* : LONGINT; (* character background color *) PROCEDURE Clone*(): CharacterStyleObject; VAR newCSO: CharacterStyleObject; BEGIN NEW(newCSO); newCSO.name := name; newCSO.family := family; newCSO.style := style; newCSO.size := size; newCSO.leading := leading; newCSO.baselineShift := baselineShift; newCSO.color := color; newCSO.bgColor := bgColor; newCSO.tracking := tracking; newCSO.kerning := kerning; newCSO.scaleHorizontal := scaleHorizontal; newCSO.scaleVertical := scaleVertical; RETURN newCSO; END Clone; END CharacterStyleObject; GraphicStyleObject* = OBJECT(StyleObject) VAR (* NOT IMPLEMENTED ;-) do it yourself *) END GraphicStyleObject; CustomStyleObject* = OBJECT(StyleObject) VAR (* NOT IMPLEMENTED ;-) do it yourself *) END CustomStyleObject; PStyles* = POINTER TO ARRAY OF ParagraphStyleObject; CStyles* = POINTER TO ARRAY OF CharacterStyleObject; GStyles* = POINTER TO ARRAY OF GraphicStyleObject; CustomStyles* = POINTER TO ARRAY OF CustomStyleObject; (* root for the data - all units in [mm] *) Document* = OBJECT VAR pageWidth, pageHeight : REAL; marginTop, marginBottom, marginLeft, marginRight : REAL; facingPages : BOOLEAN; meta : MetaInformation; objectCounter*: LONGINT; copyCounter*: LONGINT; nofPStyles*: LONGINT; pStyles* : PStyles; nofCStyles*: LONGINT; cStyles* : CStyles; nofGStyles*: LONGINT; gStyles* : GStyles; nofCustomStyles*: LONGINT; customStyles* : CustomStyles; defaultParagraphStyle* : ParagraphStyleObject; defaultCharacterStyle* : CharacterStyleObject; defaultGraphicStyle* : GraphicStyleObject; defaultCustomStyle* : CustomStyleObject; pages* : ContentPages; mpages* : MasterPages; contents* : Contents; nofContents* : LONGINT; frames* : Frames; (* dollyFrame* : FrameObject; *) dollyGuide* : GuideObject; currentPage*, firstPage*, lastPage* : PageObject; pageNumber*, nofPages* : LONGINT; currentMPage*, firstMPage*, lastMPage* : MasterPageObject; mpageNumber*, nofMPages* : LONGINT; PROCEDURE &New*(width, height, margintop,marginbottom, marginleft, marginright : REAL; facingpages : BOOLEAN); VAR BEGIN pageWidth := width; pageHeight := height; marginTop := margintop; marginBottom := marginbottom; marginLeft := marginleft; marginRight := marginright; facingPages := facingpages; currentPage := NIL; firstPage := NIL; lastPage := NIL; pageNumber := 0; nofPages := 0; currentMPage := NIL; firstMPage := NIL; lastMPage := NIL; mpageNumber := 0; nofMPages := 0; (* dollyFrame := NIL; *) dollyGuide := NIL; objectCounter := 0; copyCounter := 0; NEW(pStyles, 4); nofPStyles := 0; NEW(cStyles, 4); nofCStyles := 0; NEW(gStyles, 4); nofGStyles := 0; NEW(customStyles, 4); nofCustomStyles := 0; AddDefaultStyles; NEW(contents, 4); nofContents := 0; END New; PROCEDURE AddDefaultStyles; VAR newPStyle: ParagraphStyleObject; newCStyle: CharacterStyleObject; BEGIN NEW(newCStyle); newCStyle.name := "defaultCharacterStyle"; newCStyle.family := "Oberon"; newCStyle.style := {}; newCStyle.size := 16; newCStyle.leading := 19; newCStyle.baselineShift := 0; newCStyle.tracking := 0; newCStyle.kerning := 0; newCStyle.scaleHorizontal := 100; newCStyle.scaleVertical := 100; newCStyle.color := 0000000FFH; newCStyle.bgColor := LONGINT(0FFFFFF00H); NEW(newPStyle); newPStyle.name := "defaultParagraphStyle"; newPStyle.alignment := 0; (* Left Align *) newPStyle.spaceBefore := 0; newPStyle.spaceAfter := 0; newPStyle.leftIndent := 0; newPStyle.rightIndent := 0; newPStyle.firstIndent := 0; newPStyle.charStyle := newCStyle; defaultCharacterStyle := newCStyle; defaultParagraphStyle := newPStyle; AddStyle(newCStyle); AddStyle(newPStyle); END AddDefaultStyles; PROCEDURE AddStyle*(style: StyleObject); VAR newPStyles: PStyles; newCStyles: CStyles; newGStyles: GStyles; newCustomStyles: CustomStyles; pStyle: ParagraphStyleObject; cStyle: CharacterStyleObject; i : LONGINT; BEGIN IF (style IS ParagraphStyleObject) THEN pStyle := GetParagraphStyleByName(style.name); IF (pStyle = NIL) THEN (* no style with that name - create one *) INC(nofPStyles); IF nofPStyles > LEN(pStyles) THEN NEW(newPStyles, LEN(pStyles) * 2); FOR i := 0 TO LEN(pStyles)-1 DO newPStyles[i] := pStyles[i]; END; pStyles := newPStyles; END; pStyles[nofPStyles-1] := style(ParagraphStyleObject); ELSE (* style with that name already exists - update *) pStyle.alignment := style(ParagraphStyleObject).alignment; pStyle.firstIndent := style(ParagraphStyleObject).firstIndent; pStyle.leftIndent := style(ParagraphStyleObject).leftIndent; pStyle.rightIndent := style(ParagraphStyleObject).rightIndent; pStyle.spaceBefore := style(ParagraphStyleObject).spaceBefore; pStyle.spaceAfter := style(ParagraphStyleObject).spaceAfter; pStyle.charStyle := style(ParagraphStyleObject).charStyle; END; ELSIF (style IS CharacterStyleObject) THEN cStyle := GetCharacterStyleByName(style.name); IF (cStyle = NIL) THEN (* no style with that name - create one *) INC(nofCStyles); IF nofCStyles > LEN(cStyles) THEN NEW(newCStyles, LEN(cStyles) * 2); FOR i := 0 TO LEN(cStyles)-1 DO newCStyles[i] := cStyles[i]; END; cStyles := newCStyles; END; cStyles[nofCStyles-1] := style(CharacterStyleObject); ELSE (* style with that name already exists - update *) COPY(style(CharacterStyleObject).family, cStyle.family); cStyle.size := style(CharacterStyleObject).size; cStyle.style := style(CharacterStyleObject).style; cStyle.leading := style(CharacterStyleObject).leading; cStyle.baselineShift := style(CharacterStyleObject).baselineShift; cStyle.color := style(CharacterStyleObject).color; cStyle.bgColor := style(CharacterStyleObject).bgColor; cStyle.tracking := style(CharacterStyleObject).tracking; cStyle.kerning := style(CharacterStyleObject).kerning; cStyle.scaleHorizontal := style(CharacterStyleObject).scaleHorizontal; cStyle.scaleVertical := style(CharacterStyleObject).scaleVertical; END; ELSIF (style IS GraphicStyleObject) THEN INC(nofGStyles); IF nofGStyles > LEN(gStyles) THEN NEW(newGStyles, LEN(gStyles) * 2); FOR i := 0 TO LEN(gStyles)-1 DO newGStyles[i] := gStyles[i]; END; gStyles := newGStyles; END; gStyles[nofGStyles-1] := style(GraphicStyleObject); ELSIF (style IS CustomStyleObject) THEN INC(nofCustomStyles); IF nofCustomStyles > LEN(customStyles) THEN NEW(newCustomStyles, LEN(customStyles) * 2); FOR i := 0 TO LEN(customStyles)-1 DO newCustomStyles[i] := customStyles[i]; END; customStyles := newCustomStyles; END; customStyles[nofCustomStyles-1] := style(CustomStyleObject); ELSE END; END AddStyle; PROCEDURE RemoveStyle*(style: StyleObject); VAR i : LONGINT; BEGIN IF (style IS ParagraphStyleObject) THEN IF (style(ParagraphStyleObject).name # "defaultParagraphStyle") THEN i := 0; WHILE (i < nofPStyles) & (pStyles[i] # style(ParagraphStyleObject)) DO INC(i) END; IF i < nofPStyles THEN WHILE (i < nofPStyles-1) DO pStyles[i] := pStyles[i+1]; INC(i); END; DEC(nofPStyles); pStyles[nofPStyles] := NIL; END; END; ELSIF (style IS CharacterStyleObject) THEN IF (style(CharacterStyleObject).name # "defaultCharacterStyle") THEN i := 0; WHILE (i < nofCStyles) & (cStyles[i] # style(CharacterStyleObject)) DO INC(i) END; IF i < nofCStyles THEN WHILE (i < nofCStyles-1) DO cStyles[i] := cStyles[i+1]; INC(i); END; DEC(nofCStyles); cStyles[nofCStyles] := NIL; END; END; ELSIF (style IS GraphicStyleObject) THEN IF (style(GraphicStyleObject) # defaultGraphicStyle) THEN i := 0; WHILE (i < nofGStyles) & (gStyles[i] # style(GraphicStyleObject)) DO INC(i) END; IF i < nofGStyles THEN WHILE (i < nofGStyles-1) DO gStyles[i] := gStyles[i+1]; INC(i); END; DEC(nofGStyles); gStyles[nofGStyles] := NIL; END; END; ELSIF (style IS CustomStyleObject) THEN IF (style(CustomStyleObject) # defaultCustomStyle) THEN i := 0; WHILE (i < nofCustomStyles) & (customStyles[i] # style(CustomStyleObject)) DO INC(i) END; IF i < nofCustomStyles THEN WHILE (i < nofCustomStyles-1) DO customStyles[i] := customStyles[i+1]; INC(i); END; DEC(nofCustomStyles); customStyles[nofCustomStyles] := NIL; END; END; ELSE END; END RemoveStyle; PROCEDURE GetCharacterStyleByName*(name: ARRAY OF CHAR): CharacterStyleObject; VAR styleObject: CharacterStyleObject; i : LONGINT; found : BOOLEAN; match: Strings.String; BEGIN styleObject := NIL; i := 0; found := FALSE; WHILE ((i < nofCStyles) & ~found) DO match := Strings.NewString(cStyles[i].name); IF Strings.Match(match^, name) THEN styleObject := cStyles[i]; found := TRUE; END; INC(i); END; RETURN styleObject; END GetCharacterStyleByName; PROCEDURE GetParagraphStyleByName*(name: ARRAY OF CHAR): ParagraphStyleObject; VAR styleObject: ParagraphStyleObject; i : LONGINT; found : BOOLEAN; match: Strings.String; BEGIN styleObject := NIL; i := 0; found := FALSE; WHILE ((i < nofPStyles) & ~found) DO match := Strings.NewString(pStyles[i].name); IF Strings.Match(match^, name) THEN styleObject := pStyles[i]; found := TRUE; END; INC(i); END; RETURN styleObject; END GetParagraphStyleByName; PROCEDURE AddContent*(content: ContentObject); VAR newContents: Contents; i : LONGINT; BEGIN INC(nofContents); (* INC(objectCounter); *) IF nofContents > LEN(contents) THEN NEW(newContents, LEN(contents) * 2); FOR i := 0 TO LEN(contents)-1 DO newContents[i] := contents[i]; END; contents := newContents; END; contents[nofContents-1] := content; END AddContent; PROCEDURE RemoveContent*(content: ContentObject); VAR i : LONGINT; BEGIN i := 0; WHILE (i < nofContents) & (contents[i] # content) DO INC(i) END; IF i < nofContents THEN WHILE (i < nofContents-1) DO contents[i] := contents[i+1]; INC(i); END; DEC(nofContents); contents[nofContents] := NIL; END; END RemoveContent; PROCEDURE GetContentByName*(name: ARRAY OF CHAR): ContentObject; VAR contentObject: ContentObject; i : LONGINT; found : BOOLEAN; match: Strings.String; BEGIN contentObject := NIL; i := 0; found := FALSE; WHILE ((i < nofContents) & ~found) DO match := contents[i].contentName; IF Strings.Match(match^, name) THEN contentObject := contents[i]; found := TRUE; END; INC(i); END; RETURN contentObject; END GetContentByName; PROCEDURE FixContents*; (* loop over all contents and fix the links *) VAR contentObject: ContentObject; i : LONGINT; BEGIN i := 0; WHILE (i < nofContents) DO contentObject := contents[i]; contentObject.FixLinks; INC(i); END; END FixContents; PROCEDURE FixName*(name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR); VAR counterString : ARRAY 64 OF CHAR; BEGIN COPY(name, result); Strings.Append(result, "c"); Strings.IntToStr(copyCounter, counterString); Strings.Append(result, counterString); INC(copyCounter); WHILE (GetContentByName(result) # NIL) DO Strings.IntToStr(copyCounter, counterString); Strings.Append(result, counterString); INC(copyCounter); END; END FixName; PROCEDURE AddPage*(after : BOOLEAN); VAR newpage : PageObject; BEGIN NEW(newpage); IF lastPage = NIL THEN (* document was empty *) firstPage := newpage; lastPage := newpage; INC(pageNumber); ELSE (* there were already pages *) IF after THEN (* add after current page *) newpage.next := currentPage.next; currentPage.next := newpage; newpage.prev := currentPage; IF newpage.next = NIL THEN (* current was last page *) lastPage := newpage; ELSE newpage.next.prev := newpage; (* current was not last page *) END; INC(pageNumber); ELSE (* add before current page *) newpage.prev := currentPage.prev; currentPage.prev := newpage; newpage.next := currentPage; IF newpage.prev = NIL THEN (* current was first page *) firstPage := newpage; ELSE newpage.prev.next := newpage; (* current was not first page *) END; END; END; currentPage := newpage; (* change current page *) INC(nofPages); currentPage.SetOwner(SELF); (* UpdatePageNumber; *) END AddPage; PROCEDURE DeletePage*; VAR BEGIN IF currentPage.prev # NIL THEN (* not first *) IF currentPage.next # NIL THEN (* not last *) currentPage.prev.next := currentPage.next; currentPage.next.prev := currentPage.prev; currentPage := currentPage.next; IF currentPage.prev = NIL THEN firstPage := currentPage; END; IF currentPage.next = NIL THEN lastPage := currentPage; END; DEC(nofPages); ELSE (* last *) currentPage.prev.next := currentPage.next; currentPage := currentPage.prev; IF currentPage.prev = NIL THEN firstPage := currentPage; END; lastPage := currentPage; DEC(nofPages); DEC(pageNumber); END; ELSE (* first *) IF currentPage.next # NIL THEN (* you can only delete if more than 1 page left *) currentPage.next.prev := currentPage.prev; currentPage := currentPage.next; firstPage := currentPage; IF currentPage.next = NIL THEN lastPage := currentPage; END; DEC(nofPages); END; END; (* UpdatePageNumber; *) END DeletePage; PROCEDURE NextPage*; BEGIN IF currentPage.next # NIL THEN currentPage := currentPage.next; INC(pageNumber); END; (* UpdatePageNumber; *) END NextPage; PROCEDURE PrevPage*; BEGIN IF currentPage.prev # NIL THEN currentPage := currentPage.prev; DEC(pageNumber); END; (* UpdatePageNumber; *) END PrevPage; PROCEDURE FirstPage*; BEGIN currentPage := firstPage; pageNumber := 1; (* UpdatePageNumber; *) END FirstPage; PROCEDURE LastPage*; BEGIN currentPage := lastPage; pageNumber := nofPages; (* UpdatePageNumber; *) END LastPage; PROCEDURE AddMasterPage*(after: BOOLEAN); VAR newpage : MasterPageObject; BEGIN NEW(newpage); IF lastMPage = NIL THEN (* document was empty *) firstMPage := newpage; lastMPage := newpage; INC(mpageNumber); ELSE (* there were already pages *) IF after THEN (* add after current page *) newpage.next := currentMPage.next; currentMPage.next := newpage; newpage.prev := currentMPage; IF newpage.next = NIL THEN (* current was last page *) lastMPage := newpage; ELSE newpage.next.prev := newpage; (* current was not last page *) END; INC(mpageNumber); ELSE (* add before current page *) newpage.prev := currentMPage.prev; currentMPage.prev := newpage; newpage.next := currentMPage; IF newpage.prev = NIL THEN (* current was first page *) firstMPage := newpage; ELSE newpage.prev.next := newpage; (* current was not first page *) END; END; END; currentMPage := newpage; (* change current page *) INC(nofMPages); currentMPage.SetOwner(SELF); END AddMasterPage; PROCEDURE DeleteMasterPage*; BEGIN IF currentMPage.prev # NIL THEN (* not first *) IF currentMPage.next # NIL THEN (* not last *) currentMPage.prev.next := currentMPage.next; currentMPage.next.prev := currentMPage.prev; currentMPage := currentMPage.next; IF currentMPage.prev = NIL THEN firstMPage := currentMPage; END; IF currentMPage.next = NIL THEN lastMPage := currentMPage; END; DEC(nofMPages); ELSE (* last *) currentMPage.prev.next := currentMPage.next; currentMPage := currentMPage.prev; IF currentMPage.prev = NIL THEN firstMPage := currentMPage; END; lastMPage := currentMPage; DEC(nofMPages); DEC(mpageNumber); END; ELSE (* first *) IF currentMPage.next # NIL THEN (* you can only delete if more than 1 page left *) currentMPage.next.prev := currentMPage.prev; currentMPage := currentMPage.next; firstMPage := currentMPage; IF currentMPage.next = NIL THEN lastMPage := currentMPage; END; DEC(nofMPages); END; END; END DeleteMasterPage; PROCEDURE NextMasterPage*; BEGIN IF currentMPage.next # NIL THEN currentMPage := currentMPage.next; INC(mpageNumber); END; END NextMasterPage; PROCEDURE PrevMasterPage*; BEGIN IF currentMPage.prev # NIL THEN currentMPage := currentMPage.prev; DEC(mpageNumber); END; END PrevMasterPage; PROCEDURE FirstMasterPage*; BEGIN currentMPage := firstMPage; mpageNumber := 1; END FirstMasterPage; PROCEDURE LastMasterPage*; BEGIN currentMPage := lastMPage; mpageNumber := nofMPages; END LastMasterPage; PROCEDURE SetPageWidth*(pagewidth : REAL); BEGIN pageWidth := pagewidth; END SetPageWidth; PROCEDURE GetPageWidth*(): REAL; BEGIN RETURN pageWidth END GetPageWidth; PROCEDURE SetPageHeight*(pageheight : REAL); BEGIN pageHeight := pageheight; END SetPageHeight; PROCEDURE GetPageHeight*(): REAL; BEGIN RETURN pageHeight END GetPageHeight; PROCEDURE SetMargins*(top, bottom, left, right : REAL); BEGIN marginTop := top; marginBottom := bottom; marginLeft := left; marginRight := right; END SetMargins; PROCEDURE GetMarginTop*(): REAL; BEGIN RETURN marginTop END GetMarginTop; PROCEDURE GetMarginBottom*() : REAL; BEGIN RETURN marginBottom END GetMarginBottom; PROCEDURE GetMarginLeft*(): REAL; BEGIN RETURN marginLeft END GetMarginLeft; PROCEDURE GetMarginRight*(): REAL; BEGIN RETURN marginRight END GetMarginRight; PROCEDURE SetFacingPages*(fpages : BOOLEAN); BEGIN facingPages := fpages; END SetFacingPages; PROCEDURE GetFacingPages*(): BOOLEAN; BEGIN RETURN facingPages END GetFacingPages; PROCEDURE GetCurrentPage*(): PageObject; BEGIN RETURN currentPage; END GetCurrentPage; PROCEDURE GetFirstPage*(): PageObject; BEGIN RETURN firstPage; END GetFirstPage; PROCEDURE GetLastPage*(): PageObject; BEGIN RETURN lastPage; END GetLastPage; PROCEDURE GetCurrentMasterPage*(): MasterPageObject; BEGIN RETURN currentMPage; END GetCurrentMasterPage; PROCEDURE GetFirstMasterPage*(): MasterPageObject; BEGIN RETURN firstMPage; END GetFirstMasterPage; PROCEDURE GetLastMasterPage*(): MasterPageObject; BEGIN RETURN lastMPage; END GetLastMasterPage; PROCEDURE GetMasterByName*(name: Strings.String): MasterPageObject; VAR page, result: MasterPageObject; match: Strings.String; BEGIN result := NIL; IF name # NIL THEN page := GetFirstMasterPage(); WHILE page # NIL DO match := page.GetName(); (* KernelLog.String(match^); *) IF (match # NIL) & Strings.Match(match^, name^) THEN result := page; END; page := page.next; END; END; RETURN result; END GetMasterByName; PROCEDURE GetCurrentPageNumber*(): LONGINT; BEGIN RETURN pageNumber; END GetCurrentPageNumber; PROCEDURE GetCurrentMasterPageNumber*(): LONGINT; BEGIN RETURN mpageNumber; END GetCurrentMasterPageNumber; END Document; PageObject* = OBJECT VAR ownerDocument* : Document; masterpage* : MasterPageObject; next*, prev* : PageObject; firstFrame*, lastFrame*, currentFrame* : FrameObject; firstGuide*, lastGuide*, currentGuide* : GuideObject; PROCEDURE SetOwner*(doc: Document); BEGIN ownerDocument := doc; END SetOwner; PROCEDURE &New*; VAR BEGIN firstFrame := NIL; lastFrame := NIL; currentFrame := NIL; firstGuide := NIL; lastGuide := NIL; currentGuide := NIL; next := NIL; prev := NIL; masterpage := NIL; END New; PROCEDURE SetMasterPage*(master: MasterPageObject); BEGIN masterpage := master; END SetMasterPage; PROCEDURE GetMasterPage*(): MasterPageObject; BEGIN RETURN masterpage; END GetMasterPage; PROCEDURE AddFrame*(x, y, w, h : REAL); VAR newframe : FrameObject; BEGIN (* new Frames are added at last position (top) *) NEW(newframe); newframe.SetExtent(x,y,w,h); IF lastFrame = NIL THEN (* First frame added *) firstFrame := newframe; lastFrame := newframe; ELSE (* not first frame added *) newframe.prev := lastFrame; lastFrame.next := newframe; lastFrame := newframe; END; currentFrame := newframe; (* change current frame *) END AddFrame; PROCEDURE InsertFrame*(frame: FrameObject); (* insert the given frame at front *) VAR name : Strings.String; content: ContentObject; temp: ARRAY 64 OF CHAR; BEGIN (* check if name of given frame is in use, add content to list *) name := frame.GetName(); content := ownerDocument.GetContentByName(name^); IF content # NIL THEN ownerDocument.FixName(name^, temp); name := Strings.NewString(temp); frame.SetName(name); content := frame.GetContent(); content.contentName := name; ELSE content := frame.GetContent(); END; ownerDocument.AddContent(content); (* insert frame in page *) IF lastFrame = NIL THEN (* First frame added *) firstFrame := frame; lastFrame := frame; ELSE (* not first frame added *) frame.prev := lastFrame; lastFrame.next := frame; lastFrame := frame; END; currentFrame := frame; (* change current frame *) END InsertFrame; PROCEDURE DeleteFrame*; VAR name: Strings.String; content: ContentObject; BEGIN IF currentFrame # NIL THEN (* remove content first *) name := currentFrame.GetName(); content := ownerDocument.GetContentByName(name^); IF content # NIL THEN ownerDocument.RemoveContent(content); END; (* remove frame *) IF (currentFrame.prev = NIL) & (currentFrame.next = NIL) THEN (* only this frame left *) currentFrame := NIL; firstFrame := NIL; lastFrame := NIL; ELSIF currentFrame.prev = NIL THEN (* frame at back *) currentFrame.next.prev := currentFrame.prev; currentFrame := currentFrame.next; firstFrame := currentFrame; ELSIF currentFrame.next = NIL THEN (* frame at front *) currentFrame.prev.next := currentFrame.next; currentFrame := currentFrame.prev; lastFrame := currentFrame; ELSE (* frame in between *) currentFrame.prev.next := currentFrame.next; currentFrame.next.prev := currentFrame.prev; currentFrame := currentFrame.prev; END; END; END DeleteFrame; PROCEDURE NextFrame*; BEGIN IF (currentFrame # NIL) & (currentFrame.next # NIL) THEN currentFrame := currentFrame.next; END; END NextFrame; PROCEDURE PrevFrame*; BEGIN IF (currentFrame # NIL) & (currentFrame.prev # NIL) THEN currentFrame := currentFrame.prev; END END PrevFrame; PROCEDURE AddGuide*(position : REAL; horizontal : BOOLEAN); VAR newguide : GuideObject; BEGIN NEW(newguide, position, horizontal); IF lastGuide = NIL THEN (* first Guide added *) firstGuide := newguide; lastGuide := newguide; ELSE (* guides are added on top *) newguide.prev := lastGuide; lastGuide.next := newguide; lastGuide := newguide; END; currentGuide := newguide; (* change Guide *) END AddGuide; PROCEDURE DeleteGuide*; BEGIN IF currentGuide # NIL THEN IF (currentGuide.prev = NIL) & (currentGuide.next = NIL) THEN (* one and only guide *) firstGuide := NIL; lastGuide := NIL; currentGuide := NIL; ELSIF (currentGuide.prev = NIL) THEN (* first guide *) currentGuide.next.prev := currentGuide.prev; firstGuide := currentGuide.next; currentGuide := currentGuide.next; ELSIF (currentGuide.next = NIL) THEN (* last guide *) currentGuide.prev.next := currentGuide.next; lastGuide := currentGuide.prev; currentGuide := currentGuide.prev; ELSE (* between guide *) currentGuide.prev.next := currentGuide.next; currentGuide.next.prev := currentGuide.prev; END; END; END DeleteGuide; PROCEDURE Move2Front*; BEGIN IF currentFrame # NIL THEN IF (currentFrame.prev = NIL) & (currentFrame.next = NIL) THEN (* one and only frame *) firstFrame := currentFrame; ELSIF (currentFrame.next = NIL) THEN (* last frame *) (* do nothing *) ELSIF (currentFrame.prev = NIL) THEN (* first frame *) currentFrame.next.prev := currentFrame.prev; firstFrame := currentFrame.next; lastFrame.next := currentFrame; currentFrame.prev := lastFrame; currentFrame.next := NIL; ELSE (* between *) currentFrame.prev.next := currentFrame.next; currentFrame.next.prev := currentFrame.prev; lastFrame.next := currentFrame; currentFrame.prev := lastFrame; currentFrame.next := NIL; END; lastFrame := currentFrame; END; END Move2Front; PROCEDURE Move2Back*; VAR BEGIN IF currentFrame # NIL THEN IF (currentFrame.prev = NIL) & (currentFrame.next = NIL) THEN (* one and only frame *) lastFrame := currentFrame; ELSIF (currentFrame.next = NIL) THEN (* last frame *) currentFrame.prev.next := currentFrame.next; lastFrame := currentFrame.prev; firstFrame.prev := currentFrame; currentFrame.prev := NIL; currentFrame.next := firstFrame; ELSIF (currentFrame.prev = NIL) THEN (* first frame *) (* do nothing *) ELSE (* between *) currentFrame.prev.next := currentFrame.next; currentFrame.next.prev := currentFrame.prev; firstFrame.prev := currentFrame; currentFrame.prev := NIL; currentFrame.next := firstFrame; END; firstFrame := currentFrame; END; END Move2Back; PROCEDURE Move2FrontStep*; VAR BEGIN IF currentFrame # NIL THEN IF (currentFrame.prev = NIL) & (currentFrame.next = NIL) THEN firstFrame := currentFrame; lastFrame := currentFrame; ELSIF (currentFrame.prev = NIL) THEN (* first frame *) IF currentFrame.next.next = NIL THEN (* only 2 frames - swap *) currentFrame.prev := currentFrame.next; lastFrame.next := currentFrame; lastFrame.prev := NIL; currentFrame.next := NIL; firstFrame := lastFrame; lastFrame := currentFrame; ELSE (* more than 2 frames *) currentFrame.prev := currentFrame.next; currentFrame.next.next.prev := currentFrame; currentFrame.next := currentFrame.next.next; currentFrame.prev.next := currentFrame; firstFrame := currentFrame.prev; firstFrame.prev := NIL; END; ELSIF (currentFrame.next = NIL) THEN (* last frame *) (* do nothing *) ELSE (* between *) IF currentFrame.next.next = NIL THEN (* 2nd last frame *) currentFrame.prev.next := currentFrame.next; currentFrame.next.prev := currentFrame.prev; currentFrame.prev := currentFrame.next; currentFrame.next.next := currentFrame; currentFrame.next := NIL; lastFrame := currentFrame; ELSE (* "deep" between *) currentFrame.prev.next := currentFrame.next; currentFrame.next.prev := currentFrame.prev; currentFrame.prev := currentFrame.prev.next; currentFrame.next := currentFrame.prev.next; currentFrame.prev.next.prev := currentFrame; currentFrame.prev.next := currentFrame; END; END; END; END Move2FrontStep; PROCEDURE Move2BackStep*; BEGIN IF currentFrame # NIL THEN IF (currentFrame.prev = NIL) & (currentFrame.next = NIL) THEN firstFrame := currentFrame; lastFrame := currentFrame; ELSIF (currentFrame.prev = NIL) THEN (* first frame *) (* do nothing *) ELSIF (currentFrame.next = NIL) THEN (* last frame *) IF currentFrame.prev.prev = NIL THEN (* only 2 frames - swap *) currentFrame.next := currentFrame.prev; firstFrame.prev := currentFrame; firstFrame.next := NIL; currentFrame.prev := NIL; lastFrame := firstFrame; firstFrame := currentFrame; ELSE (* more than 2 frames *) currentFrame.next := currentFrame.prev; currentFrame.prev.prev.next := currentFrame; currentFrame.prev := currentFrame.prev.prev; currentFrame.next.prev := currentFrame; lastFrame := currentFrame.next; lastFrame.next := NIL; END; ELSE (* between *) IF currentFrame.prev.prev = NIL THEN (* 2nd first frame *) currentFrame.next.prev := currentFrame.prev; currentFrame.prev.next := currentFrame.next; currentFrame.next := currentFrame.prev; currentFrame.prev.prev := currentFrame; currentFrame.prev := NIL; firstFrame := currentFrame; ELSE (* "deep" between *) currentFrame.next.prev := currentFrame.prev; currentFrame.prev.next := currentFrame.next; currentFrame.next := currentFrame.next.prev; currentFrame.prev := currentFrame.next.prev; currentFrame.next.prev.next := currentFrame; currentFrame.next.prev := currentFrame; END; END; END; END Move2BackStep; PROCEDURE SetCurrentFrame*(frame : FrameObject); BEGIN currentFrame := frame; END SetCurrentFrame; PROCEDURE GetCurrentFrame*(): FrameObject; BEGIN RETURN currentFrame; END GetCurrentFrame; PROCEDURE GetFirstFrame*(): FrameObject; BEGIN RETURN firstFrame; END GetFirstFrame; PROCEDURE GetLastFrame*(): FrameObject; BEGIN RETURN lastFrame; END GetLastFrame; PROCEDURE GetCurrentGuide*(): GuideObject; BEGIN RETURN currentGuide; END GetCurrentGuide; PROCEDURE GetFirstGuide*(): GuideObject; BEGIN RETURN firstGuide; END GetFirstGuide; PROCEDURE GetLastGuide*(): GuideObject; BEGIN RETURN lastGuide; END GetLastGuide; END PageObject; MasterPageObject* = OBJECT(PageObject) VAR mpageName* : Strings.String; next*, prev* : MasterPageObject; PROCEDURE &New*; BEGIN New^; mpageName := Strings.NewString("Master"); END New; PROCEDURE SetName*(name: Strings.String); BEGIN mpageName := name; END SetName; PROCEDURE GetName*(): Strings.String; BEGIN RETURN mpageName; END GetName; END MasterPageObject; GuideObject* = OBJECT VAR horizontal : BOOLEAN; position : REAL; prev*, next* : GuideObject; PROCEDURE &New*(posi : REAL; horiz : BOOLEAN); BEGIN position := posi; horizontal := horiz; prev := NIL; next := NIL; END New; PROCEDURE SetHorizontal*(isHorizontal : BOOLEAN); BEGIN horizontal := isHorizontal; END SetHorizontal; PROCEDURE GetHorizontal*() : BOOLEAN; BEGIN RETURN horizontal; END GetHorizontal; PROCEDURE SetPosition*(posi : REAL); BEGIN position := posi; END SetPosition; PROCEDURE GetPosition*() : REAL; BEGIN RETURN position; END GetPosition; PROCEDURE Clone*(): GuideObject; VAR newguide: GuideObject; BEGIN NEW(newguide, GetPosition(), GetHorizontal()); RETURN newguide; END Clone; END GuideObject; FrameObject* = OBJECT VAR frameName : Strings.String; frameType : Strings.String; x, y, w, h : REAL; style : StyleObject; content : ContentObject; (* DTPFrame.ContentObject; *) textwrapON : BOOLEAN; twrapTop, twrapBottom, twrapLeft, twrapRight : REAL; next*, prev* : FrameObject; PROCEDURE &New*; BEGIN textwrapON := FALSE; twrapTop := 0; twrapBottom := 0; twrapLeft := 0; twrapRight := 0; next := NIL; prev := NIL; frameName := Strings.NewString("newframe"); style := NIL; content := NIL; END New; PROCEDURE SetName*(name : Strings.String); VAR BEGIN frameName := name; END SetName; PROCEDURE GetName*() : Strings.String ; VAR BEGIN RETURN frameName END GetName; PROCEDURE SetType*(type : Strings.String); BEGIN frameType := type; END SetType; PROCEDURE GetType*() : Strings.String; VAR BEGIN RETURN frameType; END GetType; PROCEDURE FixExtent*; VAR cx, cy, cw, ch: REAL; BEGIN cx := x; cy := y; cw := w; ch := h; x := MIN(cx, cx+cw); y := MIN(cy, cy+ch); w := MAX(cx, cx+cw)-MIN(cx, cx+cw); h := MAX(cy, cy+ch)-MIN(cy, cy+ch); END FixExtent; PROCEDURE SetExtent*(x, y, w, h: REAL); BEGIN SELF.x := x; SELF.y := y; SELF.w := w; SELF.h := h; END SetExtent; PROCEDURE SetSize*( w, h : REAL); VAR BEGIN SELF.w := w; SELF.h := h; END SetSize; PROCEDURE SetPosition*(x, y: REAL); BEGIN SELF.x := x; SELF.y := y; END SetPosition; PROCEDURE GetX*(): REAL; VAR BEGIN RETURN x; END GetX; PROCEDURE GetY*(): REAL; VAR BEGIN RETURN y; END GetY; PROCEDURE GetWidth*(): REAL; VAR BEGIN RETURN w; END GetWidth; PROCEDURE GetHeight*(): REAL; VAR BEGIN RETURN h; END GetHeight; PROCEDURE SetStyle*(style : StyleObject); BEGIN SELF.style := style; END SetStyle; PROCEDURE GetStyle*() : StyleObject; BEGIN RETURN style END GetStyle; PROCEDURE SetContent*(content : ContentObject); (* DTPFrame.ContentObject; *) BEGIN SELF.content := content; END SetContent; PROCEDURE GetContent*() : ContentObject; (* DTPFrame.ContentObject; *) BEGIN RETURN content END GetContent; PROCEDURE SetWrap*(wrap : BOOLEAN); BEGIN textwrapON := wrap; END SetWrap; PROCEDURE GetWrap*() : BOOLEAN; BEGIN RETURN textwrapON; END GetWrap; PROCEDURE SetWrapSize*(t, b, l, r : REAL); BEGIN twrapTop := t; twrapBottom := b; twrapLeft := l; twrapRight := r; END SetWrapSize; PROCEDURE GetWrapTop*(): REAL; BEGIN RETURN twrapTop END GetWrapTop; PROCEDURE GetWrapBottom*(): REAL; BEGIN RETURN twrapBottom END GetWrapBottom; PROCEDURE GetWrapLeft*(): REAL; BEGIN RETURN twrapLeft END GetWrapLeft; PROCEDURE GetWrapRight*(): REAL; BEGIN RETURN twrapRight END GetWrapRight; PROCEDURE Clone*(): FrameObject; VAR newframe: FrameObject; newcontent: ContentObject; (* DTPFrame.ContentObject; *) BEGIN NEW(newframe); newframe.SetName(GetName()); (* maybe change name to avoid conflicts *) newframe.SetType(GetType()); newframe.SetExtent(GetX(), GetY(), GetWidth(), GetHeight()); newframe.SetStyle(GetStyle()); newcontent := GetContent(); newframe.SetContent(newcontent.Clone()); newframe.SetWrap(GetWrap()); newframe.SetWrapSize(GetWrapTop(), GetWrapBottom(), GetWrapLeft(), GetWrapRight()); newframe.prev := NIL; newframe.next := NIL; RETURN newframe; END Clone; END FrameObject; ContentObject* = OBJECT VAR contentName* : Strings.String; redrawProc* : PROCEDURE {DELEGATE}; updatePropsPosition*: PROCEDURE {DELEGATE} (x, y: LONGINT); contentWidth*, contentHeight*: LONGINT; zoomFactor* : REAL; ownerDoc*: Document; hasFocus- : BOOLEAN; running- : BOOLEAN; PROCEDURE &New*; BEGIN hasFocus := FALSE; running := FALSE; END New; PROCEDURE Clone*(): ContentObject; VAR newObj: ContentObject; BEGIN NEW(newObj); newObj.contentName := Strings.NewString(contentName^); newObj.redrawProc := redrawProc; newObj.updatePropsPosition := updatePropsPosition; newObj.contentWidth := contentWidth; newObj.contentHeight := contentHeight; newObj.zoomFactor := zoomFactor; newObj.ownerDoc := ownerDoc; RETURN newObj; END Clone; PROCEDURE Draw*(canvas : WMGraphics.Canvas; x, y, w, h : LONGINT; zoomFactor: REAL; quality, preview: BOOLEAN); VAR color: LONGINT; BEGIN color := LONGINT(0FF0000FFH); canvas.Line(x, y, x+w, y+h, color, WMGraphics.ModeCopy); canvas.Line(x+w, y, x, y+h, color, WMGraphics.ModeCopy); END Draw; PROCEDURE Redraw*; BEGIN IF redrawProc # NIL THEN redrawProc; ELSE (* KernelLog.String("redraw = NIL");KernelLog.Ln; *) END; END Redraw; PROCEDURE UpdatePosition*(x, y: LONGINT); BEGIN updatePropsPosition(x, y); END UpdatePosition; PROCEDURE SetSize*(w, h: LONGINT); BEGIN contentWidth := w; contentHeight := h; END SetSize; PROCEDURE Resize*(zoomF: REAL); BEGIN zoomFactor := zoomF; END Resize; PROCEDURE Show*(x, y: LONGINT); END Show; PROCEDURE Hide*; END Hide; PROCEDURE Close*; END Close; PROCEDURE SetFocus*(focus: BOOLEAN); BEGIN hasFocus := focus; END SetFocus; PROCEDURE FocusLost*; BEGIN hasFocus := FALSE; END FocusLost; PROCEDURE FocusReceived*; BEGIN hasFocus := TRUE; END FocusReceived; PROCEDURE GetPluginPointer*(): WMWindowManager.PointerInfo; VAR manager : WMWindowManager.WindowManager; BEGIN manager := WMWindowManager.GetDefaultManager(); RETURN manager.pointerStandard; END GetPluginPointer; PROCEDURE PointerDown*(x, y: LONGINT; keys: SET); END PointerDown; PROCEDURE PointerMove*(x, y: LONGINT; keys: SET); END PointerMove; PROCEDURE PointerUp*(x, y: LONGINT; keys: SET); END PointerUp; PROCEDURE PointerLeave*; END PointerLeave; PROCEDURE IsHit*(x, y: LONGINT): BOOLEAN; BEGIN RETURN TRUE; END IsHit; PROCEDURE KeyEvent*(ucs: LONGINT; flags: SET; VAR keyCode: LONGINT); END KeyEvent; PROCEDURE Start*; BEGIN running := TRUE; END Start; PROCEDURE Stop*; BEGIN running := FALSE; END Stop; PROCEDURE OnPageEnter*; END OnPageEnter; PROCEDURE OnPageLeave*; END OnPageLeave; PROCEDURE OnCreate*; END OnCreate; PROCEDURE OnDelete*; END OnDelete; PROCEDURE Load*(elem: XML.Element); END Load; PROCEDURE FixLinks*; END FixLinks; PROCEDURE Store*(VAR w: Files.Writer); BEGIN w.String(''); w.Ln; END Store; END ContentObject; ContentFactory* = PROCEDURE() : ContentObject; ContentPages* = POINTER TO ARRAY OF PageObject; MasterPages* = POINTER TO ARRAY OF MasterPageObject; Frames* = POINTER TO ARRAY OF FrameObject; Contents* = POINTER TO ARRAY OF ContentObject; (* ------------------------------------- *) VAR dollyFrame*: FrameObject; PROCEDURE NewObject*(): ContentObject; VAR newObject: ContentObject; BEGIN NEW(newObject); RETURN newObject; END NewObject; END DTPData.