-- GCellToolImpl.mesa
-- last edit July 10, 1984 9:42:03 pm PDT
DIRECTORY
Commander USING[CommandProc, Register],
EasyTool USING[DefineItemsProc, DefineTool, ItemHandle],
Expressions USING[ParseExpression, ParseIdentifier, SyntaxError],
GCell USING[GCellItemDescriptor, GCellItemJustification, GCellItemMode, GCellItemRowColSumMode, GCellItemValueMode, GetGCellContents, GetItemSelection, SetGCellContents],
MessageWindow USING[Append, Blink],
NewCalcGlobal USING[Document],
Rope USING[Equal, ROPE],
StructureNodes USING[StructureNode];
GCellToolImpl: MONITOR IMPORTS Commander, GCell, EasyTool, Expressions, MessageWindow, Rope EXPORTS GCell =
BEGIN
ToolInstance: TYPE = REF ToolBody;
ToolBody: TYPE = RECORD [
document: NewCalcGlobal.Document,
itemDescriptors: ItemSequence,
nActiveItems: REF CARDINAL
];
ItemSequence: TYPE = REF ItemSequenceBody;
ItemSequenceBody: TYPE = RECORD[SEQUENCE maxNItems: CARDINAL OF ItemDisplay];
ItemDisplay: TYPE = REF ItemDisplayBody;
ItemDisplayBody: TYPE = RECORD[
tool: ToolInstance,
j: CARDINAL,
active: BOOLEAN,
mode: GCell.GCellItemMode, modeText: REF Rope.ROPE,
justification: GCell.GCellItemJustification, justificationText: REF Rope.ROPE,
rowSumMode: GCell.GCellItemRowColSumMode, rowSumModeText: REF Rope.ROPE,
colSumMode: GCell.GCellItemRowColSumMode, colSumModeText: REF Rope.ROPE,
valueMode: GCell.GCellItemValueMode, valueModeText: REF Rope.ROPE,
idText: REF Rope.ROPE,
textText: REF Rope.ROPE,
zeroValTextText: REF Rope.ROPE
];
ModeTextSize: Rope.ROPE ← "showValue";
JustificationTextSize: Rope.ROPE ← "rightDecimal";
rowSumModeTextSize: Rope.ROPE ← "noEffect";
colSumModeTextSize: Rope.ROPE ← "noEffect";
valueModeTextSize: Rope.ROPE ← "expression";
IdTextSize: Rope.ROPE ← "lots of text, ver long rope etc more space";
TextTextSize: Rope.ROPE ← "lots of text, ver long rope etc more space";
ZVTextSize: Rope.ROPE ← "lots of text, ver long rope etc more space";
-- build an instance of the tool
MakeAGCellToolInstance: PUBLIC ENTRY PROCEDURE[document: NewCalcGlobal.Document] =
BEGIN
NItems: CARDINAL = 20;
sequence: ItemSequence ← NEW[ItemSequenceBody[NItems]];
instance: ToolInstance ← NEW[ToolBody ← [document, sequence, NEW[CARDINAL ←0]]];
DefineDisplayItems: EasyTool.DefineItemsProc =
BEGIN
colDescList: LIST OF EasyTool.ItemHandle ← NIL;
lastOnColDescList: LIST OF EasyTool.ItemHandle;
AppendToColumnList: PROCEDURE[item: EasyTool.ItemHandle] =
BEGIN
new: LIST OF EasyTool.ItemHandle ← LIST[item];
IF colDescList = NIL THEN colDescList ← lastOnColDescList ← new
ELSE {lastOnColDescList.rest ← new; lastOnColDescList ← new};
END;
AppendToColumnList[defineRow[LIST[
defineButton["Get a cell", GetACell],
defineFiller[5, 5],
defineButton["Set a cell", SetACell],
defineFiller[5, 5],
defineItem[ , "nItems", , instance.nActiveItems]]]];
AppendToColumnList[defineFiller[1, 10]];
FOR J: CARDINAL IN [0..NItems) DO
AppendToColumnList[defineFiller[1, 10]];
AppendToColumnList[defineRow[LIST[
defineButton["I", InsertItem, sequence[J]],
defineButton["D", DeleteItem, sequence[J]],
defineFiller[15, 1],
defineButton["M", StepItemMode, sequence[J]],
defineItem[ , "m", , sequence[J].modeText, ModeTextSize, TRUE],
defineFiller[15, 1],
defineButton["J", StepItemJustification, sequence[J]],
defineItem[ , "j", , sequence[J].justificationText, JustificationTextSize, TRUE],
defineButton["RSM", StepItemRowSumMode, sequence[J]],
defineItem[ , "rsm", , sequence[J].rowSumModeText, rowSumModeTextSize, TRUE],
defineButton["CSM", StepItemColSumMode, sequence[J]],
defineItem[ , "csm", , sequence[J].colSumModeText, colSumModeTextSize, TRUE],
defineButton["VM", StepItemValueMode, sequence[J]],
defineItem[ , "vm", , sequence[J].valueModeText, valueModeTextSize, TRUE]]]];
AppendToColumnList[defineRow[LIST[
defineFiller[15, 1],
defineItem[ , "id", , sequence[J].idText, IdTextSize, TRUE]]]];
AppendToColumnList[defineRow[LIST[
defineFiller[15, 1],
defineItem[ , "exp", , sequence[J].textText, TextTextSize, TRUE]]]];
AppendToColumnList[defineRow[LIST[
defineFiller[15, 1],
defineItem[ , "zvt", , sequence[J].zeroValTextText, ZVTextSize, TRUE]]]];
ENDLOOP;
RETURN[defineColumn[colDescList]];
END;
FOR J: CARDINAL IN [0..NItems) DO
sequence[J] ← NEW[ItemDisplayBody ← [instance, J, FALSE, showText, NEW[Rope.ROPE ← " "], left, NEW[Rope.ROPE ← " "], addVal, NEW[Rope.ROPE ← " "], addVal, NEW[Rope.ROPE ← " "], expression, NEW[Rope.ROPE ← " "], NEW[Rope.ROPE ← " "], NEW[Rope.ROPE ← " "], NEW[Rope.ROPE ← " "]]];
ENDLOOP;
[] ← EasyTool.DefineTool["Cell Tool", instance, DefineDisplayItems];
END;
-- global actions
GetACell: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
tool: ToolInstance ← NARROW[data];
gcSn: StructureNodes.StructureNode;
ReceiveTheItems: PROCEDURE[nItems: CARDINAL, getOneItem: PROCEDURE RETURNS[GCell.GCellItemDescriptor]] =
BEGIN
FOR J: CARDINAL IN [0..nItems) DO
desc: GCell.GCellItemDescriptor← getOneItem[];
tool.itemDescriptors[J].active ← TRUE;
tool.itemDescriptors[J].mode ← desc.mode;
ShowItemMode[tool.itemDescriptors[J]];
tool.itemDescriptors[J].justification ← desc.justification;
ShowItemJustification[tool.itemDescriptors[J]];
tool.itemDescriptors[J].rowSumMode ← desc.rowSumMode;
ShowItemRowSumMode[tool.itemDescriptors[J]];
tool.itemDescriptors[J].colSumMode ← desc.colSumMode;
ShowItemColSumMode[tool.itemDescriptors[J]];
tool.itemDescriptors[J].valueMode ← desc.valueMode;
ShowItemValueMode[tool.itemDescriptors[J]];
tool.itemDescriptors[J].idText↑ ← desc.id;
tool.itemDescriptors[J].textText↑ ← desc.text;
tool.itemDescriptors[J].zeroValTextText↑ ← desc.zeroValText;
tool.nActiveItems↑ ← nItems;
ENDLOOP;
END;
FOR J: CARDINAL IN [0..tool.itemDescriptors.maxNItems) DO
NilAnItem[tool.itemDescriptors[J]]
ENDLOOP;
tool.nActiveItems↑ ← 0;
[ , gcSn, ] ← GCell.GetItemSelection[]; -- really a call on NewCalcImpl
IF gcSn = NIL THEN RETURN;
GCell.GetGCellContents[gcSn, ReceiveTheItems, TRUE];
END;
SetACell: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
tool: ToolInstance ← NARROW[data];
gcSn: StructureNodes.StructureNode;
j: CARDINAL ← 0;
SendOneItem: PROCEDURE RETURNS[GCell.GCellItemDescriptor] =
BEGIN
desc: GCell.GCellItemDescriptor ← [
mode: tool.itemDescriptors[j].mode,
justification: tool.itemDescriptors[j].justification,
rowSumMode: tool.itemDescriptors[j].rowSumMode,
colSumMode: tool.itemDescriptors[j].colSumMode,
valueMode: tool.itemDescriptors[j].valueMode,
id: tool.itemDescriptors[j].idText↑,
text: tool.itemDescriptors[j].textText↑,
zeroValText:tool.itemDescriptors[j].zeroValTextText↑
];
j ← j + 1;
RETURN[desc];
END;
BEGIN -- allow for abort exit
FOR J: CARDINAL IN [0..tool.nActiveItems↑) DO -- make sure there will be no "hidden" parse errors
SELECT tool.itemDescriptors[J].mode FROM
showText => NULL;
showId, showExp, showValue, noShow =>
BEGIN
IF tool.itemDescriptors[J].mode # showId
AND NOT tool.itemDescriptors[J].idText↑ = NIL
AND NOT Rope.Equal[tool.itemDescriptors[J].idText↑, ""]
AND NOT Rope.Equal[tool.itemDescriptors[J].idText↑, " "]
THEN [] ← Expressions.ParseIdentifier[tool.itemDescriptors[J].idText↑
! Expressions.SyntaxError =>
BEGIN
MessageWindow.Append[
message: "syntax error in identifier, text is ", clearFirst: TRUE];
MessageWindow.Append[
message: tool.itemDescriptors[J].idText↑, clearFirst: FALSE];
MessageWindow.Blink[];
GOTO abort;
END];
[] ← Expressions.ParseExpression[tool.itemDescriptors[J].textText↑
! Expressions.SyntaxError =>
BEGIN
MessageWindow.Append[
message: "syntax error in expression, text is ", clearFirst: TRUE];
MessageWindow.Append[
message: tool.itemDescriptors[J].textText↑, clearFirst: FALSE];
MessageWindow.Blink[];
GOTO abort;
END];
END;
ENDCASE => ERROR;
ENDLOOP;
[ , gcSn, ] ← GCell.GetItemSelection[]; -- really a call on NewCalcImpl
IF gcSn = NIL THEN RETURN;
j ← 0;
GCell.SetGCellContents[gcSn, tool.nActiveItems↑, SendOneItem, TRUE];
EXITS
abort => NULL;
END
END;
-- item button procs
InsertItem: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
itemJ: CARDINAL ← item.j;
IF item.j > 0 AND NOT item.tool.itemDescriptors[item.j-1].active THEN RETURN;
IF item.tool.nActiveItems↑ = item.tool.itemDescriptors.maxNItems THEN RETURN;
FOR J: CARDINAL DECREASING IN [itemJ..item.tool.nActiveItems↑] DO
item.tool.itemDescriptors[J+1].mode ← item.tool.itemDescriptors[J].mode;
item.tool.itemDescriptors[J+1].modeText↑ ← item.tool.itemDescriptors[J].modeText↑;
item.tool.itemDescriptors[J+1].justification ← item.tool.itemDescriptors[J].justification;
item.tool.itemDescriptors[J+1].justificationText↑ ← item.tool.itemDescriptors[J].justificationText↑;
item.tool.itemDescriptors[J+1].idText↑ ← item.tool.itemDescriptors[J].idText↑;
item.tool.itemDescriptors[J+1].textText↑ ← item.tool.itemDescriptors[J].textText↑;
item.tool.itemDescriptors[J+1].zeroValTextText↑ ← item.tool.itemDescriptors[J].zeroValTextText↑;
ENDLOOP;
item.tool.nActiveItems↑ ← item.tool.nActiveItems↑ + 1;
item.active ← TRUE;
item.mode ← showText;
item.justification ← right;
item.idText↑ ← " ";
item.textText↑ ← " ";
item.zeroValTextText↑ ← " ";
ShowItemMode[item];
ShowItemJustification[item];
END;
DeleteItem: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
itemJ: CARDINAL ← item.j;
IF NOT item.active THEN RETURN;
FOR J: CARDINAL IN [itemJ..item.tool.nActiveItems↑) DO
item.tool.itemDescriptors[J].mode ← item.tool.itemDescriptors[J+1].mode;
item.tool.itemDescriptors[J].modeText↑ ← item.tool.itemDescriptors[J+1].modeText↑;
item.tool.itemDescriptors[J].justification ← item.tool.itemDescriptors[J+1].justification;
item.tool.itemDescriptors[J].justificationText↑ ← item.tool.itemDescriptors[J+1].justificationText↑;
item.tool.itemDescriptors[J].idText↑ ← item.tool.itemDescriptors[J+1].idText↑;
item.tool.itemDescriptors[J].textText↑ ← item.tool.itemDescriptors[J+1].textText↑;
item.tool.itemDescriptors[J].zeroValTextText↑ ← item.tool.itemDescriptors[J+1].zeroValTextText↑;
ENDLOOP;
NilAnItem[item.tool.itemDescriptors[item.tool.nActiveItems↑]];
item.tool.nActiveItems↑ ← item.tool.nActiveItems↑-1;
END;
StepItemMode: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
IF NOT item.active THEN RETURN;
item.mode ← SELECT item.mode FROM
showText => showId,
showId => showExp,
showExp => showValue,
showValue => noShow,
noShow => showText,
ENDCASE => ERROR;
ShowItemMode[item];
END;
ShowItemMode: PROCEDURE[item: ItemDisplay] =
BEGIN
IF NOT item.active THEN RETURN;
item.modeText↑ ← SELECT item.mode FROM
showText => "showText",
showId => "showId",
showExp => "showExp",
showValue => "showValue",
noShow => "noShow",
ENDCASE => ERROR;
END;
StepItemJustification: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
IF NOT item.active THEN RETURN;
item.justification ← SELECT item.justification FROM
left => leftDecimal,
leftDecimal => centered,
centered => rightDecimal,
rightDecimal => right,
right => left,
ENDCASE => ERROR;
ShowItemJustification[item];
END;
ShowItemJustification: PROCEDURE[item: ItemDisplay] =
BEGIN
IF NOT item.active THEN RETURN;
item.justificationText↑ ← SELECT item.justification FROM
left => "left",
leftDecimal => "leftDecimal",
centered => "centered",
rightDecimal => "rightDecimal",
right => "right",
ENDCASE => ERROR;
END;
StepItemRowSumMode: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
IF NOT item.active THEN RETURN;
item.rowSumMode ← SELECT item.rowSumMode FROM
addVal => subVal,
subVal => setZero,
setZero => noEffect,
noEffect => addVal,
ENDCASE => ERROR;
ShowItemRowSumMode[item];
END;
ShowItemRowSumMode: PROCEDURE[item: ItemDisplay] =
BEGIN
IF NOT item.active THEN RETURN;
item.rowSumModeText↑ ← SELECT item.rowSumMode FROM
addVal => "addVal",
subVal => "subVal",
setZero => "setZero",
noEffect => "noEffect",
ENDCASE => ERROR;
END;
StepItemColSumMode: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
IF NOT item.active THEN RETURN;
item.colSumMode ← SELECT item.colSumMode FROM
addVal => subVal,
subVal => setZero,
setZero => noEffect,
noEffect => addVal,
ENDCASE => ERROR;
ShowItemColSumMode[item];
END;
ShowItemColSumMode: PROCEDURE[item: ItemDisplay] =
BEGIN
IF NOT item.active THEN RETURN;
item.colSumModeText↑ ← SELECT item.colSumMode FROM
addVal => "addVal",
subVal => "subVal",
setZero => "setZero",
noEffect => "noEffect",
ENDCASE => ERROR;
END;
StepItemValueMode: ENTRY PROCEDURE[data: REF ANY] =
BEGIN
item: ItemDisplay ← NARROW[data];
IF NOT item.active THEN RETURN;
item.valueMode ← SELECT item.valueMode FROM
rowSum => colSum,
colSum => expression,
expression => rowSum,
ENDCASE => ERROR;
ShowItemValueMode[item];
END;
ShowItemValueMode: PROCEDURE[item: ItemDisplay] =
BEGIN
IF NOT item.active THEN RETURN;
item.valueModeText↑ ← SELECT item.valueMode FROM
rowSum => "rowSum",
colSum => "colSum",
expression => "expression",
ENDCASE => ERROR;
END;
NilAnItem: PROCEDURE[item: ItemDisplay] =
BEGIN
item.active ← FALSE;
item.modeText↑ ← " ";
item.justificationText↑ ← " ";
item.idText↑ ← " ";
item.textText↑ ← " ";
item.zeroValTextText↑ ← " ";
END;
-- main code
TestGCellTool: Commander.CommandProc = TRUSTED
{MakeAGCellToolInstance[NIL]};
Commander.Register[key: "TestGCellTool", proc: TestGCellTool, doc: ""];
END..
-- October 5, 1982 5:35 pm: Sturgis, started GCellToolImpl.mesa
-- RTE: October 6, 1982 4:08 pm: used same nil rope ref for all rope refs.
-- RTE: October 6, 1982 4:29 pm: display had bad shape, not enough room for needed text, so changed form.
-- RTE: October 6, 1982 4:34 pm: now there is not text to edit in the text fileds, so replace initial NIL rope with non null rope.
remark: October 6, 1982 4:39 pm: well, it displays, and one can change the entries, but BOY, is it not esthetic. Also it has some techinical problems in the way it deals with commands delivered beyond the active area. BUT, I will live with it.
-- RTEs (3): October 7, 1982 2:47 pm: main commands appeared in each item, sending a cell sent only the first item, and nilanitem always nilled the item following the last active item, rather than the parameter item.
-- RTE: October 8, 1982 3:23 pm: add code to catch a syntax error before text is sent to a cell. A syntax error in the cell for an an item which is not displayed leads to a mesa ERROR.
-- RTE: October 8, 1982 4:45 pm: do not check for syntax error on showText mode items.
-- change: October 11, 1982 3:18 pm: SetAGCellProc changed slightly.
-- change: October 14, 1982 5:15 pm: GetSelection had changed slightly.
-- change: October 16, 1982 3:42 pm: make into a monitor, set "entry" TRUE on calls to Get and Set GCellContents.
-- RTE: October 21, 1982 2:45 pm: too many procs set as entry.
-- RTE: October 21, 1982 2:53 pm: in getacell and setacell, test for tool.global = NIL is unjustified.
-- October 22, 1982 1:42 pm: add rowSumMode, colSumMode, valueMode.
-- RTE: October 23, 1982 12:18 pm: did not correctly label noew mode fields.
-- RTE: October 23, 1982 3:43 pm: it is now ok to permit some identifiers which are NIL, or length 0, or a single blank.
-- change: November 14, 1982 1:59 pm: convert to new selection logic.
-- change: November 14, 1982 2:52 pm: add setZero to row and col sum modes.
-- February 27, 1983 3:57 pm: replace display node, logical node etc with structurenode. In particular, GCell.GCell is replaced with StructureNode. Took about 5 minutes.
-- change: June 22, 1984 4:28:33 pm PDT: convert to 5.2