-- PageListImpl.mesa -- last edit July 22, 1984 2:01:25 pm PDT Sturgis DIRECTORY ButtonCells USING[CreateBCell, ReLabelBCell], Convert USING[RopeFromCard], HCells USING[AppendHCellArrayInGroup, ConnectHCellArrayInGroup, CreateHCellArrayModeledAfter, CreateSummaryHCellArray, InsertHCellArrayInGroup, ReadCellText], IO USING[atom, char, Close, CR, FF, GetChar, GetRefAny, STREAM, int, Put, RIS, rope, RopeFromROS, ROS], NewCalcGlobal USING[Displayer, Document, DocumentProcs, CheckForDirtyDataInPage, ConnectInstalledItemArrays, ConnectLoadedItemArrays, CountOpenSlotsInPage, CreatePageDisplayer, DestroyPageDisplayer, GetHCellArrayAtSlot, InstallHCellArrayAtAnOpenSlot, GenerateSummaryArrays, LoadPageDisplayer, NoteNewPageMode, NoteNewPageName, NoteNewPageNumber, PageDisplayer, PageMode, RepaintOpenPage, SavePageDisplayer, ShowPageDisplayer, VerifyPageDisplayer], Rope USING[Cat, ROPE], StructureNodes USING[Action, AddColumnAt, AddRowAt, BadFormatLoadFile, CreateDisplayArray, DACell, DeleteRowAt, DisplayArray, GetContextDA, GetElementAt, PrePaintPass, SetElementAt, StructureNode, StructureNodeBody, StructureNodeProcs], ViewerClasses USING[Viewer]; PageListImpl: PROGRAM IMPORTS ButtonCells, Convert, HCells, IO, NewCalcGlobal, Rope, StructureNodes EXPORTS NewCalcGlobal = BEGIN OPEN IO, NewCalcGlobal, ViewerClasses; PageList: TYPE = REF PageListBody; PageListBody: TYPE = RECORD[ document: Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer, sn: StructureNodes.StructureNode ← NIL, -- refers to this list itself da: StructureNodes.DisplayArray ← NIL, -- this and next item refer to the associated Display Array daSn: StructureNodes.StructureNode ← NIL, nPages: CARDINAL ← 0 ]; PageCellInfo: TYPE = REF PageCellInfoBody; PageCellInfoBody: TYPE = RECORD[ pageNumberBCell: StructureNodes.StructureNode, pageTitleBCell: StructureNodes.StructureNode, pageModeBCell: StructureNodes.StructureNode, mode: PageMode, displayer: PageDisplayer ]; TextForPageMode: ARRAY PageMode OF Rope.ROPE = [" ", "item", "summary"]; PageListStructureNodeProcs: REF StructureNodes.StructureNodeProcs ← NEW[StructureNodes.StructureNodeProcs ← [PageListCheckForDirtyData, PageListPreShow, PageListShowLine, PageListPrePrePaint, PageListPrePaint, PageListPaint, PageListUnPaint, PageListNoteEnclosingCell, PageListNoteCoordinates, SavePageList, ActPageList, SubstituteInPageList, AbandonPageList, VerifyPageList]]; CreatePageList: PUBLIC PROCEDURE[document: Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer] RETURNS[StructureNodes.StructureNode] = BEGIN pgs: PageList ← NEW[PageListBody ← [ document: document, displayer: displayer, vParent: vParent ]]; pgs.sn ← NEW[StructureNodes.StructureNodeBody ← [pgs, PageListStructureNodeProcs]]; [pgs.daSn, pgs.da] ← StructureNodes.CreateDisplayArray[pgs.sn]; StructureNodes.AddColumnAt[pgs.da, 1]; StructureNodes.AddColumnAt[pgs.da, 2]; StructureNodes.AddColumnAt[pgs.da, 3]; InstallPGSPageAt[pgs, 1, 1, CreatePageDisplayer[document, 1, "", individual], "foo", individual]; RETURN[pgs.sn]; END; LoadPageList: PUBLIC PROCEDURE[document: Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer, from: IO.STREAM, version: CARDINAL] RETURNS[StructureNodes.StructureNode] = BEGIN badChar: CHARACTER; case: ATOM; pgs: PageList ← NEW[PageListBody ← [ document: document, displayer: displayer, vParent: vParent ]]; prevSummaryPage: PageDisplayer ← NIL; pgs.sn ← NEW[StructureNodes.StructureNodeBody ← [pgs, PageListStructureNodeProcs]]; [pgs.daSn, pgs.da] ← StructureNodes.CreateDisplayArray[pgs.sn]; StructureNodes.AddColumnAt[pgs.da, 1]; StructureNodes.AddColumnAt[pgs.da, 2]; StructureNodes.AddColumnAt[pgs.da, 3]; DO WHILE (badChar ← IO.GetChar[from]) = ' DO ENDLOOP; -- spin over blanks IF badChar # '( THEN StructureNodes.BadFormatLoadFile; case ← NARROW[from.GetRefAny[]]; SELECT case FROM $NamedPage, $NamedItemPage, $NamedSummaryPage => BEGIN displayer: PageDisplayer; pageName: Rope.ROPE ← HCells.ReadCellText[from]; pageMode: PageMode ← SELECT case FROM $NamedPage => individual, $NamedItemPage => groupItem, $NamedSummaryPage => groupSummary, ENDCASE => ERROR; IF (badChar ← IO.GetChar[from]) # '( THEN StructureNodes.BadFormatLoadFile; IF NARROW[from.GetRefAny[], ATOM] # $ColumnOfRows THEN StructureNodes.BadFormatLoadFile; displayer ← LoadPageDisplayer[document, pgs.nPages+1, pageName, pageMode, from, version]; IF (badChar ← IO.GetChar[from]) # ') THEN StructureNodes.BadFormatLoadFile; InstallPGSPageAt[pgs, pgs.nPages+1, pgs.nPages, displayer, pageName, pageMode]; IF case = $NamedItemPage THEN BEGIN ConnectOneItemArray: PROCEDURE[itemHcaSn: StructureNodes.StructureNode, itemKey: LONG CARDINAL, atRow: CARDINAL] = BEGIN SeeOneSummaryArray: PROCEDURE[summaryHcaSn: StructureNodes.StructureNode, summaryKey: LONG CARDINAL] RETURNS[continue: BOOLEAN] = BEGIN IF summaryKey = itemKey THEN BEGIN HCells.ConnectHCellArrayInGroup[itemHcaSn, summaryHcaSn, atRow]; RETURN[FALSE]; END ELSE RETURN[TRUE]; END; GenerateSummaryArrays[prevSummaryPage, SeeOneSummaryArray]; END; ConnectLoadedItemArrays[displayer, ConnectOneItemArray]; END; SELECT case FROM $NamedSummaryPage => prevSummaryPage ← displayer; $NamedItemPage => NULL; ENDCASE => prevSummaryPage ← NIL; END; $Page => BEGIN -- pre named page format displayer: PageDisplayer; pageName: Rope.ROPE ← Rope.Cat["page ", Convert.RopeFromCard[pgs.nPages+1]]; IF (badChar ← IO.GetChar[from]) # '( THEN StructureNodes.BadFormatLoadFile; IF NARROW[from.GetRefAny[], ATOM] # $ColumnOfRows THEN StructureNodes.BadFormatLoadFile; displayer ← LoadPageDisplayer[document, pgs.nPages+1, pageName, individual, from, version]; IF (badChar ← IO.GetChar[from]) # ') THEN StructureNodes.BadFormatLoadFile; InstallPGSPageAt[pgs, pgs.nPages+1, pgs.nPages, displayer, pageName, individual]; END; $ColumnOfRows => BEGIN -- pre multi page format displayer: PageDisplayer; pageName: Rope.ROPE ← Rope.Cat["page ", Convert.RopeFromCard[pgs.nPages+1]]; IF pgs.nPages # 0 THEN StructureNodes.BadFormatLoadFile; displayer ← LoadPageDisplayer[document, 1, pageName, individual, from, version]; InstallPGSPageAt[pgs, pgs.nPages+1, pgs.nPages, displayer, pageName, individual]; END; $End => EXIT; ENDCASE => StructureNodes.BadFormatLoadFile; IF (badChar ← IO.GetChar[from]) # ') THEN StructureNodes.BadFormatLoadFile; ENDLOOP; RETURN[pgs.sn]; END; ShowPageList: PUBLIC PROCEDURE[info: StructureNodes.StructureNode, out: IO.STREAM] = BEGIN pgs: PageList ← NARROW[info.ref]; FOR J: CARDINAL IN [1..pgs.nPages] DO info: REF ANY; pgcj: PageCellInfo; Put[out, rope["page "], int[J]]; Put[out, char[IO.CR], char[IO.CR]]; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgcj ← NARROW[info]; ShowPageDisplayer[pgcj.displayer, out]; IF J # pgs.nPages THEN Put[out, char[IO.CR], char[IO.FF]]; ENDLOOP; END; CheckForDirtyDataInPages: PUBLIC PROCEDURE[info: StructureNodes.StructureNode] = BEGIN pgs: PageList ← NARROW[info.ref]; FOR J: CARDINAL IN [1..pgs.nPages] DO info: REF ANY; pgcj: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgcj ← NARROW[info]; CheckForDirtyDataInPage[pgcj.displayer]; ENDLOOP; END; -- page list, display node interface PageListCheckForDirtyData: PROCEDURE[node: StructureNodes.StructureNode] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.CheckForDirtyData[pgs.daSn]; END; PageListPreShow: PROCEDURE[node: StructureNodes.StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] = BEGIN pgs: PageList ← NARROW[node.ref]; [lead, height, space, L, A, B, R, W] ← pgs.daSn.procs.PreShow[pgs.daSn]; END; PageListShowLine: PROCEDURE[node: StructureNodes.StructureNode, L, R, W: INTEGER, lineX: INTEGER, to: STREAM] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.ShowLine[pgs.daSn, L, R, W, lineX, to]; END; PageListPrePrePaint: PROCEDURE[node: StructureNodes.StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] = BEGIN pgs: PageList ← NARROW[node.ref]; [lead, height, space, L, A, B, R, W] ← pgs.daSn.procs.PrePrePaint[pgs.daSn]; END; PageListPrePaint: PROCEDURE[node: StructureNodes.StructureNode, y, x, L, R, W: INTEGER, pass: StructureNodes.PrePaintPass] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.PrePaint[pgs.daSn, y, x, L, R, W, pass]; END; PageListPaint: PROCEDURE[node: StructureNodes.StructureNode, dirtyOnly: BOOLEAN] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.Paint[pgs.daSn, dirtyOnly]; END; PageListUnPaint: PROCEDURE[node: StructureNodes.StructureNode] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.UnPaint[pgs.daSn]; END; PageListNoteEnclosingCell: PROCEDURE[node: StructureNodes.StructureNode, dac: StructureNodes.DACell] = BEGIN pgs: PageList ← NARROW[node.ref]; pgs.daSn.procs.NoteEnclosingCell[pgs.daSn, dac]; END; PageListNoteCoordinates: PROCEDURE[node: StructureNodes.StructureNode, da: StructureNodes.DisplayArray, I, J: CARDINAL] = BEGIN END; -- page list, logical node interface SavePageList: PUBLIC PROCEDURE[info: StructureNodes.StructureNode, to: IO.STREAM] = BEGIN pgs: PageList ← NARROW[info.ref]; FOR J: CARDINAL IN [1..pgs.nPages] DO info: REF ANY; pgcj: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgcj ← NARROW[info]; Put[to, char['(], atom[SELECT pgcj.mode FROM individual => $NamedPage, groupItem => $NamedItemPage, groupSummary => $NamedSummaryPage, ENDCASE => ERROR]]; SavePageDisplayer[pgcj.displayer, to]; Put[to, char[')]]; ENDLOOP; END; SubstituteInPageList: PROCEDURE[info: StructureNodes.StructureNode, newText, oldText: Rope.ROPE] = BEGIN ERROR END; AbandonPageList: PUBLIC PROCEDURE[info: StructureNodes.StructureNode] = BEGIN pgs: PageList ← NARROW[info.ref]; WHILE pgs.nPages # 0 DO RemovePGSPageAt[pgs, pgs.nPages] ENDLOOP; END; ActPageList: PROCEDURE[info: StructureNodes.StructureNode, I, J: CARDINAL, action: StructureNodes.Action, p1, p2: REF ANY] RETURNS[StructureNodes.StructureNode, CARDINAL, CARDINAL] = BEGIN pgs: PageList ← NARROW[info.ref]; SELECT action FROM InsertPage => InstallPGSPageAt[pgs, J, J, NIL, pgs.document.procs.getControlRope[pgs.document, newPageId], GetPGSPageModeFromModel[pgs, J, J]]; AppendPage => InstallPGSPageAt[pgs, J+1, J, NIL, pgs.document.procs.getControlRope[pgs.document, newPageId], GetPGSPageModeFromModel[pgs, J+1, J]]; DeletePage => RemovePGSPageAt[pgs, J]; SetPageId => SetPGSPageId[pgs, J, pgs.document.procs.getControlRope[pgs.document, newPageId]]; MakeSummaryPage => MakeSummaryPGSPageAt[pgs, J]; CreateSummaryHCellArray => CreateArrayGroup[pgs, J]; ENDCASE => BEGIN cSn: StructureNodes.StructureNode; cI, cJ: CARDINAL; [cSn, cI, cJ] ← StructureNodes.GetContextDA[pgs.da]; RETURN[cSn, cI, cJ]; END; RETURN[NIL, 0, 0]; END; VerifyPageList: PROCEDURE[info: StructureNodes.StructureNode] = BEGIN pgs: PageList ← NARROW[info.ref]; -- for now, we just verify the internal structure of each page, but not the list as a whole FOR J: CARDINAL IN [1..pgs.nPages] DO pgc: PageCellInfo ← NARROW[ StructureNodes.GetElementAt[pgs.da, 1, J].info]; VerifyPageDisplayer[pgc.displayer, pgc.mode]; ENDLOOP; END; -- page list support procedures -- remark: there is a crock here. If the displayer argument is NIL, then we know we are not doing a load, therefore an append or insert. If an itemPage is involved then we connect up the assorted arrays. However, if it is a load (displayer argument # NIL), then the caller will do the connections. This should be re-arranged so that the connections are done at the same logical level in both cases. Also, the NIL argument test is not a clean way to make the decision. InstallPGSPageAt: PROCEDURE[pgs: PageList, J: CARDINAL, modelJ: CARDINAL, displayer: PageDisplayer, pageName: Rope.ROPE, mode: PageMode] = BEGIN numberText: Rope.ROPE ← Rope.Cat["page ", Convert.RopeFromCard[J]]; numBCell: StructureNodes.StructureNode; titleBCell: StructureNodes.StructureNode; modeBCell: StructureNodes.StructureNode; pgc: PageCellInfo; [numBCell] ← ButtonCells.CreateBCell[pgs.document, pgs.displayer, pgs.vParent, numberText, "page 99", PageNumberProc, pgs, TRUE]; [titleBCell] ← ButtonCells.CreateBCell[pgs.document, pgs.displayer, pgs.vParent, pageName, "a long title]", PageTitleProc, pgs, TRUE]; [modeBCell] ← ButtonCells.CreateBCell[pgs.document, pgs.displayer, pgs.vParent, TextForPageMode[mode], "a long title]", PageModeProc, pgs, TRUE]; IF displayer = NIL THEN SELECT mode FROM individual => displayer ← CreatePageDisplayer[pgs.document, J, " ", individual]; groupItem => BEGIN modelPageInfo: PageCellInfo ← IF modelJ > pgs.nPages OR modelJ = 0 THEN NIL ELSE NARROW[StructureNodes.GetElementAt[pgs.da, 1, modelJ].info]; modelOutS: IO.STREAM ← IO.ROS[]; modelRope: Rope.ROPE; modelInS: IO.STREAM; pageName: Rope.ROPE; badChar: CHARACTER; ConnectOneItemArray: PROCEDURE[itemHcaSn: StructureNodes.StructureNode, row, col: CARDINAL] = BEGIN relativeToHcaSn: StructureNodes.StructureNode ← GetHCellArrayAtSlot[modelPageInfo.displayer, row, col]; SELECT TRUE FROM J = modelJ => HCells.InsertHCellArrayInGroup[itemHcaSn, relativeToHcaSn]; J = modelJ+1 => HCells.AppendHCellArrayInGroup[itemHcaSn, relativeToHcaSn]; ENDCASE => ERROR; END; SavePageDisplayer[modelPageInfo.displayer , modelOutS]; modelRope ← IO.RopeFromROS[modelOutS]; modelInS ← IO.RIS[modelRope]; -- must skip over some stuff that represents an inconsistencey between SavePageDisplayer and LoadPageDisplayer pageName ← HCells.ReadCellText[modelInS]; IF (badChar ← IO.GetChar[modelInS]) # '( THEN ERROR; IF NARROW[modelInS.GetRefAny[], ATOM] # $ColumnOfRows THEN ERROR; -- now we can proceed displayer ← LoadPageDisplayer[pgs.document, J, " ", mode, modelInS, 0]; ConnectInstalledItemArrays[displayer, ConnectOneItemArray]; modelInS.Close[]; END; groupSummary => ERROR; ENDCASE => ERROR; pgc ← NEW[PageCellInfoBody ← [numBCell, titleBCell, modeBCell, mode, displayer]]; pgs.nPages ← pgs.nPages + 1; StructureNodes.AddRowAt[pgs.da, J]; StructureNodes.SetElementAt[pgs.da, 1, J, numBCell, pgc]; -- holds page number text, and info StructureNodes.SetElementAt[pgs.da, 2, J, titleBCell, NIL]; -- holds page title texto StructureNodes.SetElementAt[pgs.da, 3, J, modeBCell, NIL]; -- holds mode text FOR JJ: CARDINAL IN (J..pgs.nPages] DO info: REF ANY; pgcjj: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, JJ]; pgcjj ← NARROW[info]; ButtonCells.ReLabelBCell[pgcjj.pageNumberBCell, Rope.Cat["page ", Convert.RopeFromCard[JJ]]]; NoteNewPageNumber[pgcjj.displayer, JJ]; ENDLOOP; IF pageName # NIL THEN SetPGSPageId[pgs, J, pageName]; END; GetPGSPageModeFromModel: PROCEDURE[pgs: PageList, J, modelJ: CARDINAL] RETURNS[PageMode] = BEGIN modelPageInfo: PageCellInfo ← IF modelJ > pgs.nPages OR modelJ = 0 THEN NIL ELSE NARROW[StructureNodes.GetElementAt[pgs.da, 1, modelJ].info]; RETURN[ IF modelPageInfo = NIL THEN individual ELSE SELECT modelPageInfo.mode FROM individual => individual, groupItem => IF J = pgs.nPages+1 THEN individual ELSE groupItem, groupSummary => IF modelJ = J THEN individual ELSE groupItem, ENDCASE => ERROR]; END; RemovePGSPageAt: PROCEDURE[pgs: PageList, J: CARDINAL] = BEGIN info: REF ANY; pgc: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgc ← NARROW[info]; IF J # pgs.nPages AND pgc.mode = groupSummary THEN BEGIN nextPgc: PageCellInfo ← NARROW[StructureNodes.GetElementAt[pgs.da, 1, J+1].info]; IF nextPgc.mode = groupItem THEN RETURN; END; pgs.nPages ← pgs.nPages - 1; StructureNodes.DeleteRowAt[pgs.da, J]; pgc.displayer ← DestroyPageDisplayer[pgc.displayer]; FOR JJ: CARDINAL IN [J..pgs.nPages] DO infojj: REF ANY; pgcjj: PageCellInfo; [info: infojj] ← StructureNodes.GetElementAt[pgs.da, 1, JJ]; pgcjj ← NARROW[infojj]; ButtonCells.ReLabelBCell[pgcjj.pageNumberBCell, Rope.Cat["page ", Convert.RopeFromCard[JJ]]]; NoteNewPageNumber[pgcjj.displayer, JJ]; ENDLOOP; END; SetPGSPageId: PROCEDURE[pgs: PageList, J: CARDINAL, newName: Rope.ROPE] = BEGIN info: REF ANY; pgc: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgc ← NARROW[info]; ButtonCells.ReLabelBCell[pgc.pageTitleBCell, newName]; NoteNewPageName[pgc.displayer, newName]; END; MakeSummaryPGSPageAt: PROCEDURE[pgs: PageList, J: CARDINAL] = BEGIN info: REF ANY; pgc: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgc ← NARROW[info]; IF pgc.mode = individual THEN BEGIN pgc.mode ← groupSummary; ButtonCells.ReLabelBCell[pgc.pageModeBCell, TextForPageMode[groupSummary]]; NoteNewPageMode[pgc.displayer, groupSummary]; END; END; CreateArrayGroup: PROCEDURE[pgs: PageList, J: CARDINAL] = BEGIN info: REF ANY; pgc: PageCellInfo; highJ: CARDINAL ← pgs.nPages; -- tentative slotCount: CARDINAL; previousHcaSn: StructureNodes.StructureNode ← NIL; didIt: BOOLEAN ← FALSE; CreateTheSummaryArray: PROCEDURE[displayer: NewCalcGlobal.Displayer, vParent: ViewerClasses.Viewer, pageName: Rope.ROPE, rowNumber, colNumber: CARDINAL] RETURNS[StructureNodes.StructureNode] = BEGIN newHcaSn: StructureNodes.StructureNode ← HCells.CreateSummaryHCellArray[pgs.document, displayer, vParent, pageName]; previousHcaSn ← newHcaSn; didIt ← TRUE; RETURN[newHcaSn]; END; CreateAnItemArray: PROCEDURE[displayer: NewCalcGlobal.Displayer, vParent: ViewerClasses.Viewer, pageName: Rope.ROPE, rowNumber, colNumber: CARDINAL] RETURNS[StructureNodes.StructureNode] = BEGIN newHcaSn: StructureNodes.StructureNode ← HCells.CreateHCellArrayModeledAfter[previousHcaSn, pgs.document, displayer, vParent, pageName]; HCells.AppendHCellArrayInGroup[newHcaSn, previousHcaSn]; previousHcaSn ← newHcaSn; didIt ← TRUE; RETURN[newHcaSn]; END; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, J]; pgc ← NARROW[info]; IF pgc.mode # groupSummary THEN RETURN; FOR JJ: CARDINAL IN (J..pgs.nPages] DO jjPgc: PageCellInfo ← NARROW[StructureNodes.GetElementAt[pgs.da, 1, JJ].info]; IF jjPgc.mode # groupItem THEN {highJ ← JJ-1; EXIT}; ENDLOOP; FOR JJ: CARDINAL IN [J..highJ] DO jjPgc: PageCellInfo ← NARROW[StructureNodes.GetElementAt[pgs.da, 1, JJ].info]; IF (slotCount ← CountOpenSlotsInPage[jjPgc.displayer]) # 1 THEN RETURN; ENDLOOP; InstallHCellArrayAtAnOpenSlot[pgc.displayer, CreateTheSummaryArray]; IF NOT didIt THEN ERROR; FOR JJ: CARDINAL IN (J..highJ] DO jjPgc: PageCellInfo ← NARROW[StructureNodes.GetElementAt[pgs.da, 1, JJ].info]; didIt ← FALSE; InstallHCellArrayAtAnOpenSlot[jjPgc.displayer, CreateAnItemArray]; IF NOT didIt THEN ERROR; ENDLOOP; END; PageNumberProc: PROCEDURE[info: REF ANY] = -- runs when the page number is clicked BEGIN END; PageTitleProc: PROCEDURE[info: REF ANY] = -- runs when the page title is clicked BEGIN END; PageModeProc: PROCEDURE[info: REF ANY] = -- runs when the page mode is clicked BEGIN END; RepaintAllOpenPages: PUBLIC PROCEDURE[info: StructureNodes.StructureNode] = BEGIN pgs: PageList; IF info = NIL THEN RETURN; -- probably during initialization of a displayer pgs ← NARROW[info.ref]; FOR JJ: CARDINAL IN [1..pgs.nPages] DO info: REF ANY; pgcjj: PageCellInfo; [info: info] ← StructureNodes.GetElementAt[pgs.da, 1, JJ]; pgcjj ← NARROW[info]; RepaintOpenPage[pgcjj.displayer]; ENDLOOP; END; END.. -- July 20, 1984 8:00:03 am PDT: Sturgis, PageListImpl split from NewCalcImpl