-- 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.