-- GCellArrayImpl.mesa -- Last Edited by: Sturgis, March 8, 1983 12:46 pm DIRECTORY IO USING[char, GetInt, STREAM, int, Put], Dependencies USING[Action, DeactivateAction, DefineAction], Expressions USING[IdTable, IdTableSet, MakeIdTable], GCell USING[CreateGCell, DoColSum, DoRowSum, GCellItemDescriptor, GetGCellContents, LoadGCell, NoteArraySelection, NoteSummers, SelectionDirection, SetAGCellArrayProc, SetAGCellProc, SetGCellContents, SetGCellIdInfo, StandardGCells, StepSelection], NewCalcGlobal USING[Displayer, Document], Rope USING[ROPE], StructureNodes USING[Action, AddColumnAt, AddRowAt, ColHandle, CreateDisplayArray, DACell, DeleteColumnAt, DeleteRowAt, DisplayArray, GetColNumber, GetColInfoAt, GetContextDA, GetElementAt, GetRowInfoAt, GetRowNumber, PrePaintPass, RowHandle, SetColInfoAt, SetElementAt, SetRowInfoAt, StructureNode, StructureNodeBody, StructureNodeProcs], ViewerClasses USING[Viewer]; GCellArrayImpl: PROGRAM IMPORTS Dependencies, Expressions, GCell, IO, StructureNodes EXPORTS GCell = BEGIN OPEN Expressions, GCell, IO, NewCalcGlobal, StructureNodes, ViewerClasses; GCellArray: TYPE = REF GCellArrayBody; GCellArrayBody: PUBLIC TYPE = RECORD[ da: DisplayArray, -- this and next item refer to the associated Display Array daSn: StructureNode, nRows, nColumns: CARDINAL, document: NewCalcGlobal.Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer]; SlotInfo: TYPE = REF SlotInfoBody; SlotInfoBody: TYPE = RECORD[ ids: IdTable ]; StructureNodeProcs: REF StructureNodes.StructureNodeProcs ← NEW[StructureNodes.StructureNodeProcs ← [GCellArrayCheckForDirtyData, GCellArrayPreShow, GCellArrayShowLine, GCellArrayPrePrePaint, GCellArrayPrePaint, GCellArrayPaint, GCellArrayUnPaint, GCellArrayNoteEnclosingCell, GCellArrayNoteCoordinates, SaveGCellArray, ActGCellArray, SubstituteInGCellArray, AbandonGCellArray, VerifyGCellArray]]; -- public procedures for GCellArray (matrix) interface LoadGCellArray: PUBLIC PROCEDURE[document: NewCalcGlobal.Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer, from: IO.STREAM, version: CARDINAL] RETURNS[StructureNode] = BEGIN gca: GCellArray ← NEW[GCellArrayBody ← [NIL, NIL, 0, 0, document, displayer, vParent]]; nRows, nColumns: CARDINAL; gcaSn: StructureNode ← NEW[StructureNodeBody ← [gca, StructureNodeProcs]]; [gca.daSn, gca.da] ← CreateDisplayArray[gcaSn]; nRows ← GetInt[from]; nColumns ← GetInt[from]; FOR I: CARDINAL IN [1..nColumns] DO [] ← BasicInstallColumnAt[gca, I] ENDLOOP; FOR J: CARDINAL IN [1..nRows] DO [] ← BasicInstallRowAt[gca, J] ENDLOOP; FOR I: CARDINAL IN [1..gca.nColumns] DO colInfo: ColInfo ← NARROW[GetColInfoAt[gca.da, I]]; FOR J: CARDINAL IN [1..gca.nRows] DO rowInfo: RowInfo ← NARROW[GetRowInfoAt[gca.da, J]]; LoadOneSlot[gcaSn, gca, I, J, rowInfo.rowSummer, colInfo.colSummer, from, version]; ENDLOOP; ENDLOOP; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO ResetSlotIdInfo[gcaSn, gca, I, J]; ENDLOOP; ENDLOOP; RETURN[gcaSn] END; CreateGCellArray: PUBLIC PROCEDURE[document: NewCalcGlobal.Document, displayer: NewCalcGlobal.Displayer, vParent: Viewer] RETURNS[StructureNode] = BEGIN gca: GCellArray ← NEW[GCellArrayBody ← [NIL, NIL, 0, 0, document, displayer, vParent]]; col1Summer, col2Summer, col3Summer, row1Summer, row2Summer, row3Summer: Dependencies.Action; gcaSn: StructureNode ← NEW[StructureNodeBody ← [gca, StructureNodeProcs]]; [gca.daSn, gca.da] ← CreateDisplayArray[gcaSn]; col1Summer ← BasicInstallColumnAt[gca, 1]; col2Summer ← BasicInstallColumnAt[gca, 2]; col3Summer ← BasicInstallColumnAt[gca, 3]; row1Summer ← BasicInstallRowAt[gca, 1]; row2Summer ← BasicInstallRowAt[gca, 2]; row3Summer ← BasicInstallRowAt[gca, 3]; -- prepare title column PrepareTitleCellOfColumn[gcaSn, gca, 1, 1, row1Summer, col1Summer, "title"]; PrepareTitleCellOfRow[gcaSn, gca, 1, 2, row2Summer, col1Summer, "title"]; PrepareTitleCellOfRow[gcaSn, gca, 1, 3, row3Summer, col1Summer, "total"]; -- prepare 1 data column PrepareTitleCellOfColumn[gcaSn, gca, 2, 1, row1Summer, col2Summer, "title"]; PrepareAssignmentCell[gcaSn, gca, 2, 2, row2Summer, col2Summer]; PrepareColumnSumCell[gcaSn, gca, 2, 3, row3Summer, col2Summer]; -- prepare 1 total column PrepareTitleCellOfColumn[gcaSn, gca, 3, 1, row1Summer, col3Summer, "total"]; PrepareRowSumCell[gcaSn, gca, 3, 2, row2Summer, col3Summer]; PrepareColumnSumCell[gcaSn, gca, 3, 3, row3Summer, col3Summer]; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO ResetSlotIdInfo[gcaSn, gca, I, J]; ENDLOOP; ENDLOOP; RETURN[gcaSn] END; GetGCellArrayShape: PUBLIC PROCEDURE[node: StructureNode] RETURNS[nRows, nColumns: CARDINAL] = BEGIN gca: GCellArray ← NARROW[node.ref]; RETURN[gca.nRows, gca.nColumns] END; SetGCellArrayRow: PUBLIC PROCEDURE[gcaSn: StructureNode, nColumns: CARDINAL, J: CARDINAL, GetOneCell: PROCEDURE[SetAGCellProc], entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; SGCAR: PROCEDURE = BEGIN IF nColumns # gca.nColumns THEN FOR I: CARDINAL IN [1..nColumns] DO DummySetAGCell: SetAGCellProc = {NULL}; GetOneCell[DummySetAGCell] ENDLOOP ELSE BEGIN FOR I: CARDINAL IN [1..nColumns] DO RealSetAGCell: SetAGCellProc = {SetOneArrayGCell[gcaSn, gca, I, J, nItems, getOneItem]}; GetOneCell[RealSetAGCell] ENDLOOP; FOR I: CARDINAL IN [1..nColumns] DO IF J > 1 THEN ResetSlotIdInfo[gcaSn, gca, I, J-1]; ResetSlotIdInfo[gcaSn, gca, I, J]; IF J < gca.nRows THEN ResetSlotIdInfo[gcaSn, gca, I, J+1]; ENDLOOP; END; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, SGCAR] ELSE SGCAR[]; END; SetGCellArrayColumn: PUBLIC PROCEDURE[gcaSn: StructureNode, I: CARDINAL, nRows: CARDINAL, GetOneCell: PROCEDURE[SetAGCellProc], entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; SGCAC: PROCEDURE = BEGIN IF nRows # gca.nRows THEN FOR J: CARDINAL IN [1..nRows] DO DummySetAGCell: SetAGCellProc = {NULL}; GetOneCell[DummySetAGCell] ENDLOOP ELSE BEGIN FOR J: CARDINAL IN [1..nRows] DO RealSetAGCell: SetAGCellProc = {SetOneArrayGCell[gcaSn, gca, I, J, nItems, getOneItem]}; GetOneCell[RealSetAGCell] ENDLOOP; FOR J: CARDINAL IN [1..nRows] DO IF I > 1 THEN ResetSlotIdInfo[gcaSn, gca, I-1, J]; ResetSlotIdInfo[gcaSn, gca, I, J]; IF I < gca.nColumns THEN ResetSlotIdInfo[gcaSn, gca, I+1, J]; ENDLOOP; END; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, SGCAC] ELSE SGCAC[]; END; SetGCellArray: PUBLIC PROCEDURE[gcaSn: StructureNode, nColumns, nRows: CARDINAL, GetOneCell: PROCEDURE[SetAGCellProc], entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; SGCA: PROCEDURE = BEGIN AbandonGCellArray[gcaSn]; FOR I: CARDINAL IN [1..nColumns] DO [] ← BasicInstallColumnAt[gca, I] ENDLOOP; FOR J: CARDINAL IN [1..nRows] DO [] ← BasicInstallRowAt[gca, J] ENDLOOP; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO SetTheCell: SetAGCellProc = {SetOneArrayGCell[gcaSn, gca, I, J, nItems, getOneItem]}; GetOneCell[SetTheCell]; ENDLOOP; ENDLOOP; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO ResetSlotIdInfo[gcaSn, gca, I, J]; ENDLOOP; ENDLOOP; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, SGCA] ELSE SGCA[]; END; GetGCellArrayRow: PUBLIC PROCEDURE[gcaSn: StructureNode, J: CARDINAL, send: SetAGCellArrayProc, entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; GGCAR: PROCEDURE= BEGIN I: CARDINAL ← 0; SendOneCell: PROCEDURE[sendIt: SetAGCellProc] = {GetOneArrayGCell[gca, I←I+1, J, sendIt]}; IF J > 0 AND J <= gca.nRows THEN send[gca.nColumns, 1, SendOneCell] ELSE send[0, 0, SendOneCell]; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, GGCAR] ELSE GGCAR[]; END; GetGCellArrayColumn: PUBLIC PROCEDURE[gcaSn: StructureNode, I: CARDINAL, send: SetAGCellArrayProc, entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; GGCAC: PROCEDURE= BEGIN J: CARDINAL ← 0; SendOneCell: PROCEDURE[sendIt: SetAGCellProc] = {GetOneArrayGCell[gca, I, J←J+1, sendIt]}; IF I > 0 AND I <= gca.nColumns THEN send[1, gca.nRows, SendOneCell] ELSE send[0, 0, SendOneCell]; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, GGCAC] ELSE GGCAC[]; END; GetIdTableSet: PUBLIC PROCEDURE[gcaSn: StructureNode, I, J: CARDINAL, callBack: PROCEDURE[IdTableSet]] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; ConstructIdTables[gca, I, J, callBack]; END; GetGCellArray: PUBLIC PROCEDURE[gcaSn: StructureNode, send: SetAGCellArrayProc, entry: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[gcaSn.ref]; GGCA: PROCEDURE= BEGIN I: CARDINAL ← 1; J: CARDINAL ← 1; GetOneCell: PROCEDURE[sendIt: SetAGCellProc] = BEGIN GetOneArrayGCell[gca, I, J, sendIt]; J ← J + 1; IF J > gca.nRows THEN {J ← 1; I ← I + 1}; END; send[gca.nColumns, gca.nRows, GetOneCell]; END; IF entry THEN gca.document.procs.executeInMonitor[gca.document, GGCA] ELSE GGCA[]; END; -- procedures for display node interface GCellArrayCheckForDirtyData: PROCEDURE[node: StructureNode] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.CheckForDirtyData[gca.daSn]; END; GCellArrayPreShow: PROCEDURE[node: StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] = BEGIN gca: GCellArray ← NARROW[node.ref]; [lead, height, space, L, A, B, R, W] ← gca.daSn.procs.PreShow[gca.daSn]; END; GCellArrayShowLine: PROCEDURE[node: StructureNode, L, R, W: INTEGER, lineX: INTEGER, to: STREAM] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.ShowLine[gca.daSn, L, R, W, lineX, to]; END; GCellArrayPrePrePaint: PROCEDURE[node: StructureNode] RETURNS[lead, height: INTEGER, space, L, A, B, R, W: INTEGER] = BEGIN gca: GCellArray ← NARROW[node.ref]; [lead, height, space, L, A, B, R, W] ← gca.daSn.procs.PrePrePaint[gca.daSn]; END; GCellArrayPrePaint: PROCEDURE[node: StructureNode, y, x, L, R, W: INTEGER, pass: PrePaintPass] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.PrePaint[gca.daSn, y, x, L, R, W, pass]; END; GCellArrayPaint: PROCEDURE[node: StructureNode, dirtyOnly: BOOLEAN] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.Paint[gca.daSn, dirtyOnly]; END; GCellArrayUnPaint: PROCEDURE[node: StructureNode] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.UnPaint[gca.daSn]; END; GCellArrayNoteEnclosingCell: PROCEDURE[node: StructureNode, dac: DACell] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.NoteEnclosingCell[gca.daSn, dac]; END; GCellArrayNoteCoordinates: PROCEDURE[node: StructureNode, da: DisplayArray, I, J: CARDINAL] = BEGIN gca: GCellArray ← NARROW[node.ref]; gca.daSn.procs.NoteCoordinates[gca.daSn, da, I, J]; END; -- procedures for logical node interface SaveGCellArray: PROCEDURE[info: StructureNode, to: IO.STREAM] = BEGIN gca: GCellArray ← NARROW[info.ref]; Put[to, char[' ], int[gca.nRows], char[' ]]; Put[to, int[gca.nColumns]]; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO SaveOneSlot[gca, I, J, to]; ENDLOOP; ENDLOOP; END; SubstituteInGCellArray: PROCEDURE[info: StructureNode, newText, oldText: Rope.ROPE] = BEGIN gca: GCellArray ← NARROW[info.ref]; SubstituteInWholeArray[gca, newText, oldText]; END; AbandonGCellArray: PROCEDURE[info: StructureNode] = BEGIN gca: GCellArray ← NARROW[info.ref]; WHILE gca.nColumns # 0 DO RemoveColumnAt[info, gca, gca.nColumns] ENDLOOP; WHILE gca.nRows # 0 DO RemoveRowAt[info, gca, gca.nRows] ENDLOOP; END; ActGCellArray: PROCEDURE[info: StructureNode, I, J: CARDINAL, action: StructureNodes.Action, p1, p2: REF ANY] RETURNS[StructureNode, CARDINAL, CARDINAL] = BEGIN gca: GCellArray ← NARROW[info.ref]; SELECT action FROM InsertColumn => {InstallColumnAt[info, gca, I, I+1]; [] ← MoveSelectionTo[gca, I, J, first]}; AppendColumn => {InstallColumnAt[info, gca, I+1, I]; [] ← MoveSelectionTo[gca, I, J, first]}; DeleteColumn => {RemoveColumnAt[info, gca, I]; IF I <= gca.nColumns THEN [] ← MoveSelectionTo[gca, I, J, first]}; InsertRow => {InstallRowAt[info, gca, J, J+1]; [] ← MoveSelectionTo[gca, I, J, first]}; AppendRow => {InstallRowAt[info, gca, J+1, J]; [] ← MoveSelectionTo[gca, I, J, first]}; DeleteRow => {RemoveRowAt[info, gca, J]; IF J <= gca.nRows THEN [] ← MoveSelectionTo[gca, I, J, first]}; MoveSelectionToNext => MoveSelectionToNext[gca, I, J]; MoveSelectionToPrevious => MoveSelectionToPrevious[gca, I, J]; SubstituteInArray => SubstituteInWholeArray[gca, p1, p2]; SubstituteInRow => SubstituteInRow[gca, J, p1, p2]; SubstituteInColumn => SubstituteInColumn[gca, I, p1, p2]; NoteArraySelection => NoteArraySelection[gca.displayer, info, I, J]; ENDCASE => BEGIN cSn: StructureNode; cI, cJ: CARDINAL; [cSn, cI, cJ] ← GetContextDA[gca.da]; RETURN[cSn, cI, cJ]; END; RETURN[NIL, 0, 0]; END; VerifyGCellArray: PROCEDURE[info: StructureNode] = BEGIN gca: GCellArray ← NARROW[info.ref]; FOR I: CARDINAL IN [1..gca.nColumns] DO FOR J: CARDINAL IN [1..gca.nRows] DO sn: StructureNode; [sn: sn] ← StructureNodes.GetElementAt[gca.da, I, J]; sn.procs.Verify[sn]; ENDLOOP; ENDLOOP; END; -- column and row activity InstallColumnAt: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I: CARDINAL, copyFrom: CARDINAL] = BEGIN colSummer: Dependencies.Action ← BasicInstallColumnAt[gca, I]; FOR J: CARDINAL IN [1..gca.nRows] DO rowInfo: RowInfo ← NARROW[GetRowInfoAt[gca.da, J]]; PrepareGCellFromNeighbor[gcaSn, gca, I, J, rowInfo.rowSummer, colSummer, copyFrom, J]; ENDLOOP; FOR J: CARDINAL IN [1..gca.nRows] DO IF I > 1 THEN ResetSlotIdInfo[gcaSn, gca, I-1, J]; ResetSlotIdInfo[gcaSn, gca, I, J]; IF I < gca.nColumns THEN ResetSlotIdInfo[gcaSn, gca, I+1, J]; ENDLOOP; END; BasicInstallColumnAt: PROCEDURE[gca: GCellArray, I: CARDINAL] RETURNS[colSummer: Dependencies.Action] = BEGIN colInfo: ColInfo ← NEW[ColInfoBody ← [gca]]; gca.nColumns ← gca.nColumns+1; StructureNodes.AddColumnAt[gca.da, I]; colInfo.colHandle ← SetColInfoAt[gca.da, I, colInfo]; colSummer ← colInfo.colSummer ← Dependencies.DefineAction[gca.document.dSet, ColumnSummer, colInfo]; FOR J: CARDINAL IN [1..gca.nRows] DO BasicInstallSlot[gca, I, J]; ENDLOOP; END; RemoveColumnAt: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I: CARDINAL] = BEGIN colInfo: ColInfo ← NARROW[GetColInfoAt[gca.da, I]]; Dependencies.DeactivateAction[colInfo.colSummer]; StructureNodes.DeleteColumnAt[gca.da, I]; gca.nColumns ← gca.nColumns-1; FOR J: CARDINAL IN [1..gca.nRows] DO IF I > 1 THEN ResetSlotIdInfo[gcaSn, gca, I-1, J]; IF I <= gca.nColumns THEN ResetSlotIdInfo[gcaSn, gca, I, J]; ENDLOOP; END; InstallRowAt: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, J: CARDINAL, copyFrom: CARDINAL] = BEGIN rowSummer: Dependencies.Action ← BasicInstallRowAt[gca, J]; FOR I: CARDINAL IN [1..gca.nColumns] DO colInfo: ColInfo ← NARROW[GetColInfoAt[gca.da, I]]; PrepareGCellFromNeighbor[gcaSn, gca, I, J, rowSummer, colInfo.colSummer, I, copyFrom]; ENDLOOP; FOR I: CARDINAL IN [1..gca.nColumns] DO IF J > 1 THEN ResetSlotIdInfo[gcaSn, gca, I, J-1]; ResetSlotIdInfo[gcaSn, gca, I, J]; IF J < gca.nRows THEN ResetSlotIdInfo[gcaSn, gca, I, J+1]; ENDLOOP; END; BasicInstallRowAt: PROCEDURE[gca: GCellArray, J: CARDINAL] RETURNS[rowSummer: Dependencies.Action] = BEGIN rowInfo: RowInfo ← NEW[RowInfoBody ← [gca]]; gca.nRows ← gca.nRows+1; StructureNodes.AddRowAt[gca.da, J]; rowInfo.rowHandle ← SetRowInfoAt[gca.da, J, rowInfo]; rowSummer ←rowInfo.rowSummer ← Dependencies.DefineAction[gca.document.dSet, RowSummer, rowInfo]; FOR I: CARDINAL IN [1..gca.nColumns] DO BasicInstallSlot[gca, I, J]; ENDLOOP; END; RemoveRowAt: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, J: CARDINAL] = BEGIN rowInfo: RowInfo ← NARROW[GetRowInfoAt[gca.da, J]]; Dependencies.DeactivateAction[rowInfo.rowSummer]; StructureNodes.DeleteRowAt[gca.da, J]; gca.nRows ← gca.nRows-1; FOR I: CARDINAL IN [1..gca.nColumns] DO IF J > 1 THEN ResetSlotIdInfo[gcaSn, gca, I, J-1]; IF J <= gca.nRows THEN ResetSlotIdInfo[gcaSn, gca, I, J]; ENDLOOP END; -- slot operations BasicInstallSlot: PROCEDURE[gca: GCellArray, I, J: CARDINAL] = BEGIN si: SlotInfo ← NEW[SlotInfoBody ← [MakeIdTable[]]]; StructureNodes.SetElementAt[gca.da, I, J, NIL, si]; END; SaveOneSlot: PROCEDURE[gca: GCellArray, I, J: CARDINAL, to: IO.STREAM] = BEGIN sn: StructureNodes.StructureNode; [sn: sn] ← StructureNodes.GetElementAt[gca.da, I, J]; Put[to, char[' ]]; sn.procs.Save[sn, to]; END; -- MUST ALLOW FOR POSSIBILITY OF GCellArray HERE LoadOneSlot: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action, from: IO.STREAM, version: CARDINAL] = BEGIN info: REF ANY; si: SlotInfo; gcSn: StructureNodes.StructureNode; [info: info] ← StructureNodes.GetElementAt[gca.da, I, J]; si ← NARROW[info]; gcSn ← LoadGCell[gca.document, gca.displayer, gcaSn, gca.vParent, from, version]; StructureNodes.SetElementAt[gca.da, I, J, gcSn, si]; NoteSummers[gcSn, rowSummer, colSummer]; END; PrepareNullCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, null]}; SetOneArrayGCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, nItems: CARDINAL, getOneItem: PROCEDURE RETURNS[GCellItemDescriptor]] = BEGIN info: REF ANY; si: SlotInfo; gcSn: StructureNode; colInfo: ColInfo ← NARROW[GetColInfoAt[gca.da, I]]; rowInfo: RowInfo ← NARROW[GetRowInfoAt[gca.da, J]]; [info: info] ← StructureNodes.GetElementAt[gca.da, I, J]; si ← NARROW[info]; gcSn ← CreateGCell[gca.document, gca.displayer, gcaSn, gca.vParent, null]; StructureNodes.SetElementAt[gca.da, I, J, gcSn, si]; SetGCellContents[gcSn, nItems, getOneItem]; NoteSummers[gcSn, rowInfo.rowSummer, colInfo.colSummer]; END; GetOneArrayGCell: PROCEDURE[gca: GCellArray, I, J: CARDINAL, sendIt: SetAGCellProc] = BEGIN info: REF ANY; si: SlotInfo; gcSn: StructureNode; [sn: gcSn, info: info] ← StructureNodes.GetElementAt[gca.da, I, J]; si ← NARROW[info]; GetGCellContents[gcSn, sendIt]; --J ← J + 1; --IF J > gca.nRows THEN {J ← 1; I ← I + 1}; END; PrepareGCellFromNeighbor: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action, fromI: CARDINAL, fromJ: CARDINAL] = BEGIN info: REF ANY; si: SlotInfo; gcSn: StructureNode; neighborRA: REF ANY; neighbor: SlotInfo; neighborGcSn: StructureNode; ShipInfo: SetAGCellProc = {SetGCellContents[gcSn, nItems, getOneItem]}; [sn: gcSn, info: info] ← StructureNodes.GetElementAt[gca.da, I, J]; si ← NARROW[info]; [sn: neighborGcSn, info: neighborRA] ← StructureNodes.GetElementAt[gca.da, fromI, fromJ]; neighbor ← NARROW[neighborRA]; gcSn ← CreateGCell[gca.document, gca.displayer, gcaSn, gca.vParent, null]; StructureNodes.SetElementAt[gca.da, I, J, gcSn, si]; GetGCellContents[neighborGcSn, ShipInfo]; NoteSummers[gcSn, rowSummer, colSummer]; END; ResetSlotIdInfo: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL] = BEGIN idTables: IdTableSet; ReceiveIdTables: PROCEDURE[ids: IdTableSet] = {idTables ← ids}; ConstructIdTables[gca, I, J, ReceiveIdTables]; SetGCellIdInfo[StructureNodes.GetElementAt[gca.da, I, J].sn, idTables]; END; ConstructIdTables: PROCEDURE[gca: GCellArray, I, J: CARDINAL, callBack: PROCEDURE[IdTableSet]] = BEGIN siRa: REF ANY; si: SlotInfo; nRA: REF ANY; nSI: SlotInfo; n: IdTable; eRA: REF ANY; eSI: SlotInfo; e: IdTable; sRA: REF ANY; sSI: SlotInfo; s: IdTable; wRA: REF ANY; wSI: SlotInfo; w: IdTable; IF J > 1 THEN BEGIN [info: nRA] ← StructureNodes.GetElementAt[gca.da, I, J-1]; nSI ← NARROW[nRA]; n ← nSI.ids; END ELSE n ← NIL; IF I < gca.nColumns THEN BEGIN [info: eRA] ← StructureNodes.GetElementAt[gca.da, I+1, J]; eSI ← NARROW[eRA]; e ← eSI.ids; END ELSE e ← NIL; IF J < gca.nRows THEN BEGIN [info: sRA] ← StructureNodes.GetElementAt[gca.da, I, J+1]; sSI ← NARROW[sRA]; s ← sSI.ids; END ELSE s ← NIL; IF I > 1 THEN BEGIN [info: wRA] ← StructureNodes.GetElementAt[gca.da, I-1, J]; wSI ← NARROW[wRA]; w ← wSI.ids; END ELSE w ← NIL; [sn: , info: siRa] ← GetElementAt[gca.da, I, J]; si ← NARROW[siRa]; callBack[[si.ids, n, e, s, w, NIL, gca.document.ids]]; END; PrepareTitleCellOfRow: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action, title: Rope.ROPE] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, rowTitle]}; PrepareTitleCellOfColumn: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action, title: Rope.ROPE] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, colTitle]}; PrepareColumnSumCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, colSum]}; PrepareRowSumCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, rowSum]}; PrepareAssignmentCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer, colSummer: Dependencies.Action] = {PrepareGCell[gcaSn, gca, I, J, rowSummer, colSummer, assignment]}; PrepareGCell: PROCEDURE[gcaSn: StructureNode, gca: GCellArray, I, J: CARDINAL, rowSummer: Dependencies.Action, colSummer: Dependencies.Action, type: StandardGCells] = BEGIN info: REF ANY; si: SlotInfo; gcSn: StructureNode; [sn: gcSn, info: info] ← StructureNodes.GetElementAt[gca.da, I, J]; si ← NARROW[info]; IF gcSn # NIL THEN ERROR; -- February 27, 1983 3:07 pm: expect NIL here, else have to abandon the cell??? gcSn ← CreateGCell[gca.document, gca.displayer, gcaSn, gca.vParent, type]; NoteSummers[gcSn, rowSummer, colSummer]; StructureNodes.SetElementAt[gca.da, I, J, gcSn, si]; END; MoveSelectionToNext: PROCEDURE[gca: GCellArray, I, J: CARDINAL] = BEGIN WHILE TRUE DO IF I # gca.nColumns THEN I ← I+1 ELSE IF J # gca.nRows THEN {I ← 1; J ← J + 1} ELSE RETURN; IF MoveSelectionTo[gca, I, J, first] THEN RETURN; ENDLOOP; END; MoveSelectionToPrevious: PROCEDURE[gca: GCellArray, I, J: CARDINAL] = BEGIN WHILE TRUE DO IF I # 1 THEN I ← I - 1 ELSE IF J # 1 THEN {I ← gca.nColumns; J ← J - 1} ELSE RETURN; IF MoveSelectionTo[gca, I, J, last] THEN RETURN; ENDLOOP; END; MoveSelectionTo: PROCEDURE[gca: GCellArray, I, J: CARDINAL, position: SelectionDirection] RETURNS[BOOLEAN] = BEGIN gcSn: StructureNode; [sn: gcSn] ← StructureNodes.GetElementAt[gca.da, I, J]; RETURN[StepSelection[gcSn, 0, position]]; END; SubstituteInWholeArray: PROCEDURE[gca: GCellArray, p1, p2: REF ANY] = BEGIN FOR I: CARDINAL IN [1..gca.nColumns] DO SubstituteInColumn[gca, I, p1, p2]; ENDLOOP; END; SubstituteInRow: PROCEDURE[gca: GCellArray, J: CARDINAL, p1, p2: REF ANY] = BEGIN newText: Rope.ROPE ← NARROW[p1]; oldText: Rope.ROPE ← NARROW[p2]; FOR I: CARDINAL IN [1..gca.nColumns] DO gcSn: StructureNode; [sn: gcSn] ← StructureNodes.GetElementAt[gca.da, I, J]; gcSn.procs.Substitute[gcSn, newText, oldText]; ENDLOOP; END; SubstituteInColumn: PROCEDURE[gca: GCellArray, I: CARDINAL, p1, p2: REF ANY] = BEGIN newText: Rope.ROPE ← NARROW[p1]; oldText: Rope.ROPE ← NARROW[p2]; FOR J: CARDINAL IN [1..gca.nRows] DO gcSn: StructureNode; [sn: gcSn] ← StructureNodes.GetElementAt[gca.da, I, J]; gcSn.procs.Substitute[gcSn, newText, oldText]; ENDLOOP; END; -- row and column summers RowInfo: TYPE = REF RowInfoBody; RowInfoBody: TYPE = RECORD[ gca: GCellArray, rowHandle: RowHandle ← NIL, rowSummer: Dependencies.Action ← NIL ]; ColInfo: TYPE = REF ColInfoBody; ColInfoBody: TYPE = RECORD[ gca: GCellArray, colHandle: ColHandle ← NIL, colSummer: Dependencies.Action ← NIL ]; RowSummer: PROCEDURE[action: Dependencies.Action, info: REF ANY] = BEGIN rowInfo: RowInfo ← NARROW[info]; sum: REAL ← 0; J: CARDINAL ← GetRowNumber[rowInfo.rowHandle]; FOR I: CARDINAL IN [1..rowInfo.gca.nColumns] DO gcSn: StructureNode; [sn: gcSn] ← StructureNodes.GetElementAt[rowInfo.gca.da, I, J]; sum ← DoRowSum[gcSn, sum]; ENDLOOP; END; ColumnSummer: PROCEDURE[action: Dependencies.Action, info: REF ANY] = BEGIN colInfo: ColInfo ← NARROW[info]; sum: REAL ← 0; I: CARDINAL ← GetColNumber[colInfo.colHandle]; FOR J: CARDINAL IN [1..colInfo.gca.nRows] DO gcSn: StructureNode; [sn: gcSn] ← StructureNodes.GetElementAt[colInfo.gca.da, I, J]; sum ← DoColSum[gcSn, sum]; ENDLOOP; END; -- debugging routines END.. -- September 21, 1982 6:58 pm: Sturgis, started GCMatrixImpl.mesa, edit from AdditiveMatrixImpl -- RTE: October 1, 1982 2:49 pm: BasicInstallRow installed nRows slots, rather than nColumns slots. -- RTE: October 1, 1982 2:57 pm: REsetSlotIdInfo subracted 1 in a case where it should have added 1. -- RTE: October 1, 1982 3:05 pm: CreateGCellArray prepared column 2 twice, rather than also column 3. --BTE: October 2, 1982 3:09 pm: change verify loop to use ln.procs.Verify, rather than a VerifyGCell procedure that does not exist. -- change: October 3, 1982 1:00 pm: modify selection mechanism so that when an action fales, Act returns enclosing context, after obtaining it from the associated DisplayArray. -- RTE: October 3, 1982 1:38 pm: old AdditiveMatrixCode (from which this was edited) would not allow appending to early rows or columns, as they were special. Now no row or column is special, so remove the tests. -- RTE: October 3, 1982 1:49 pm: PrepareGCellFromNeighbor did not use the neighbor as the source, but rather the cell that was being prepared. -- RTE: October 3, 1982 2:34 pm: load failed because gca.nRows was non zero, when in fact there were no rows yet. So an inapropriate attempt was made to install a slot. RTE: October 3, 1982 3:22 pm: imperfect fix, the loop callin basic install used counts from gca.nRows for example. but these are 0. -- RTE: October 10, 1982 12:56 pm: ResetSlotIdInfo was not including global ids from global. -- change: October 11, 1982 2:47 pm: export to GCell, also export SetGCellArray and GetGCellArray. -- change: October 14, 1982 5:05 pm: displayer now arrives at laod and creation time, and additional params passed to gcells. RTE: October 14, 1982 6:18 pm: GetGCellArray was running row and column indices from 0 rather than 1. RTE: October 14, 1982 6:30 pm: forgot to construct a new GCell before trying to set its contents. October 16, 1982 3:39 pm: conditional entry into global monitor in GetGCellArray and SetGCellArray. -- October 22, 1982 2:34 pm: add row and column summers. -- RTE: October 23, 1982 1:55 pm: col and row sums not appearing in appended columns and rows. DUe to current coding of GCellImpl, must call NoteSummers AFTER creating the cell and setting its contents. -- change: October 26, 1982 2:31 pm: put a title cell in upper left hand cell of an array. -- change: October 26, 1982 5:16 pm: install move selection machinary. -- change: October 26, 1982 6:21 pm: add code to retain selection in appropriate column and row after deletio or insertion. -- change: November 2, 1982 4:28 pm: add 2 ref any params to ActGCellArray. -- change: November 2, 1982 5:09 pm: add SubstituteInRow and Column actions. -- chnage: November 3, 1982 3:43 pm: add SubstituteInArray action, and as a logical node proc. -- change: November 14, 1982 1:15 pm: add Get/Set Row/Column -- change: November 14, 1982 3:03 pm: add NoteArraySelection, so as to handle new selection logic. -- BTE: November 14, 1982 3:49 pm: add GetGCellArrayShape. -- February 27, 1983 1:56 pm: convert from logical and display nodes to a single node, structure node. idea is to reduce to one the pointers to an entity, also remove the back poitners to the node. February 27, 1983 3:16 pm: Took about 1.2 hours. Discovered that I have to store info as well as gcSn at each crosspoint, so as to hold the id table. This forced a change to StructureNode displayArray calls. This requires work on ColumnOfRows. -- February 28, 1983 2:20 pm: add dummy NoteCoordinates procedure. -- March 4, 1983 11:38 am: add provision to compute IdTableSets on the fly. -- March 4, 1983 1:14 pm: owing to unsafe large return record, convert COnstructeIdTableSet to using a call back procedure to deliver the result. ALso convert to passing gcaSn through more procedures. -- RTE: March 4, 1983 1:39 pm: ResetSlotIdInfo passed gcaSn rather than gcSn to the GCell routine. -- March 8, 1983 11:40 am: add UnPaint. -- RTE: March 8, 1983 12:44 pm: did not propogate NoteCoordinates to associated da cell.