503 lines
12 KiB
Plaintext
503 lines
12 KiB
Plaintext
|
|
|||
|
{ Copyright (c) 1985, 88 by Borland International, Inc. }
|
|||
|
|
|||
|
unit MCLIB;
|
|||
|
|
|||
|
interface
|
|||
|
|
|||
|
uses Crt, Dos, MCVars, MCUtil, MCDisply, MCParser;
|
|||
|
|
|||
|
procedure DisplayCell(Col, Row : Word; Highlighting, Updating : Boolean);
|
|||
|
{ Displays the contents of a cell }
|
|||
|
|
|||
|
function SetOFlags(Col, Row : Word; Display : Boolean) : Word;
|
|||
|
{ Sets the overwrite flag on cells starting at (col + 1, row) - returns
|
|||
|
the number of the column after the last column set.
|
|||
|
}
|
|||
|
|
|||
|
procedure ClearOFlags(Col, Row : Word; Display : Boolean);
|
|||
|
{ Clears the overwrite flag on cells starting at (col, row) }
|
|||
|
|
|||
|
procedure UpdateOFlags(Col, Row : Word; Display : Boolean);
|
|||
|
{ Starting in col, moves back to the last TEXT cell and updates all flags }
|
|||
|
|
|||
|
procedure DeleteCell(Col, Row : Word; Display : Boolean);
|
|||
|
{ Deletes a cell }
|
|||
|
|
|||
|
procedure SetLeftCol;
|
|||
|
{ Sets the value of LeftCol based on the value of RightCol }
|
|||
|
|
|||
|
procedure SetRightCol;
|
|||
|
{ Sets the value of rightcol based on the value of leftcol }
|
|||
|
|
|||
|
procedure SetTopRow;
|
|||
|
{ Figures out the value of toprow based on the value of bottomrow }
|
|||
|
|
|||
|
procedure SetBottomRow;
|
|||
|
{ Figures out the value of bottomrow based on the value of toprow }
|
|||
|
|
|||
|
procedure SetLastCol;
|
|||
|
{ Sets the value of lastcol based on the current value }
|
|||
|
|
|||
|
procedure SetLastRow;
|
|||
|
{ Sets the value of lastrow based on the current value }
|
|||
|
|
|||
|
procedure ClearLastCol;
|
|||
|
{ Clears any data left in the last column }
|
|||
|
|
|||
|
procedure DisplayCol(Col : Word; Updating : Boolean);
|
|||
|
{ Displays a column on the screen }
|
|||
|
|
|||
|
procedure DisplayRow(Row : Word; Updating : Boolean);
|
|||
|
{ Displays a row on the screen }
|
|||
|
|
|||
|
procedure DisplayScreen(Updating : Boolean);
|
|||
|
{ Displays the current screen of the spreadsheet }
|
|||
|
|
|||
|
procedure RedrawScreen;
|
|||
|
{ Displays the entire screen }
|
|||
|
|
|||
|
procedure FixFormula(Col, Row, Action, Place : Word);
|
|||
|
{ Modifies a formula when its column or row designations need to change }
|
|||
|
|
|||
|
procedure ChangeAutoCalc(NewMode : Boolean);
|
|||
|
{ Changes and prints the current AutoCalc value on the screen }
|
|||
|
|
|||
|
procedure ChangeFormDisplay(NewMode : Boolean);
|
|||
|
{ Changes and prints the current formula display value on the screen }
|
|||
|
|
|||
|
procedure Recalc;
|
|||
|
{ Recalculates all of the numbers in the speadsheet }
|
|||
|
|
|||
|
procedure Act(S : String);
|
|||
|
{ Acts on a particular input }
|
|||
|
|
|||
|
implementation
|
|||
|
|
|||
|
procedure DisplayCell;
|
|||
|
var
|
|||
|
Color : Word;
|
|||
|
S : IString;
|
|||
|
begin
|
|||
|
if Updating and
|
|||
|
((Cell[Col, Row] = Nil) or (Cell[Col, Row]^.Attrib <> FORMULA)) then
|
|||
|
Exit;
|
|||
|
S := CellString(Col, Row, Color, DOFORMAT);
|
|||
|
if Highlighting then
|
|||
|
begin
|
|||
|
if Color = ERRORCOLOR then
|
|||
|
Color := HIGHLIGHTERRORCOLOR
|
|||
|
else
|
|||
|
Color := HIGHLIGHTCOLOR;
|
|||
|
end;
|
|||
|
SetColor(Color);
|
|||
|
WriteXY(S, ColStart[Succ(Col - LeftCol)], Row - TopRow + 3);
|
|||
|
end; { DisplayCell }
|
|||
|
|
|||
|
function SetOFlags;
|
|||
|
var
|
|||
|
Len : Integer;
|
|||
|
begin
|
|||
|
Len := Length(Cell[Col, Row]^.T) - ColWidth[Col];
|
|||
|
Inc(Col);
|
|||
|
while (Col <= MAXCOLS) and (Len > 0) and (Cell[Col, Row] = nil) do
|
|||
|
begin
|
|||
|
Format[Col, Row] := Format[Col, Row] or OVERWRITE;
|
|||
|
Dec(Len, ColWidth[Col]);
|
|||
|
if Display and (Col >= LeftCol) and (Col <= RightCol) then
|
|||
|
DisplayCell(Col, Row, NOHIGHLIGHT, NOUPDATE);
|
|||
|
Inc(Col);
|
|||
|
end;
|
|||
|
SetOFlags := Col;
|
|||
|
end; { SetOFlags }
|
|||
|
|
|||
|
procedure ClearOFlags;
|
|||
|
begin
|
|||
|
while (Col <= MAXCOLS) and (Format[Col, Row] >= OVERWRITE) and
|
|||
|
(Cell[Col, Row] = nil) do
|
|||
|
begin
|
|||
|
Format[Col, Row] := Format[Col, Row] and (not OVERWRITE);
|
|||
|
if Display and (Col >= LeftCol) and (Col <= RightCol) then
|
|||
|
DisplayCell(Col, Row, NOHIGHLIGHT, NOUPDATE);
|
|||
|
Inc(Col);
|
|||
|
end;
|
|||
|
end; { ClearOFlags }
|
|||
|
|
|||
|
procedure UpdateOFlags;
|
|||
|
var
|
|||
|
Dummy : Word;
|
|||
|
begin
|
|||
|
while (Cell[Col, Row] = nil) and (Col > 1) do
|
|||
|
Dec(Col);
|
|||
|
if (Cell[Col, Row] <> nil) and (Cell[Col, Row]^.Attrib = TXT) and
|
|||
|
(Col >= 1) then
|
|||
|
Dummy := SetOFlags(Col, Row, Display);
|
|||
|
end; { UpdateOFlags }
|
|||
|
|
|||
|
procedure DeleteCell;
|
|||
|
var
|
|||
|
CPtr : CellPtr;
|
|||
|
Size : Word;
|
|||
|
begin
|
|||
|
CPtr := Cell[Col, Row];
|
|||
|
if CPtr = nil then
|
|||
|
Exit;
|
|||
|
case CPtr^.Attrib of
|
|||
|
TXT : begin
|
|||
|
Size := Length(CPtr^.T) + 3;
|
|||
|
ClearOFlags(Succ(Col), Row, Display);
|
|||
|
end;
|
|||
|
VALUE : Size := SizeOf(Real) + 2;
|
|||
|
FORMULA : Size := SizeOf(Real) + Length(CPtr^.Formula) + 3;
|
|||
|
end; { case }
|
|||
|
Format[Col, Row] := Format[Col, Row] and (not OVERWRITE);
|
|||
|
FreeMem(CPtr, Size);
|
|||
|
Cell[Col, Row] := nil;
|
|||
|
if Col = LastCol then
|
|||
|
SetLastCol;
|
|||
|
if Row = LastRow then
|
|||
|
SetLastRow;
|
|||
|
UpdateOFlags(Col, Row, Display);
|
|||
|
Changed := True;
|
|||
|
end; { DeleteCell }
|
|||
|
|
|||
|
procedure SetLeftCol;
|
|||
|
var
|
|||
|
Col : Word;
|
|||
|
Total : Integer;
|
|||
|
begin
|
|||
|
Total := 81;
|
|||
|
Col := 0;
|
|||
|
while (Total > LEFTMARGIN) and (RightCol - Col > 0) do
|
|||
|
begin
|
|||
|
Dec(Total, ColWidth[RightCol - Col]);
|
|||
|
if Total > LEFTMARGIN then
|
|||
|
ColStart[SCREENCOLS - Col] := Total;
|
|||
|
Inc(Col);
|
|||
|
end;
|
|||
|
if Total > LEFTMARGIN then
|
|||
|
Inc(Col);
|
|||
|
Move(ColStart[SCREENCOLS - Col + 2], ColStart, Pred(Col));
|
|||
|
LeftCol := RightCol - Col + 2;
|
|||
|
Total := Pred(ColStart[1] - LEFTMARGIN);
|
|||
|
if Total <> 0 then
|
|||
|
begin
|
|||
|
for Col := LeftCol to RightCol do
|
|||
|
Dec(ColStart[Succ(Col - LeftCol)], Total);
|
|||
|
end;
|
|||
|
PrintCol;
|
|||
|
end; { SetLeftCol }
|
|||
|
|
|||
|
procedure SetRightCol;
|
|||
|
var
|
|||
|
Total, Col : Word;
|
|||
|
begin
|
|||
|
Total := Succ(LEFTMARGIN);
|
|||
|
Col := 1;
|
|||
|
repeat
|
|||
|
begin
|
|||
|
ColStart[Col] := Total;
|
|||
|
Inc(Total, ColWidth[Pred(LeftCol + Col)]);
|
|||
|
Inc(Col);
|
|||
|
end;
|
|||
|
until (Total > 81) or (Pred(LeftCol + Col) > MAXCOLS);
|
|||
|
if Total > 81 then
|
|||
|
Dec(Col);
|
|||
|
RightCol := LeftCol + Col - 2;
|
|||
|
PrintCol;
|
|||
|
end; { SetRightCol }
|
|||
|
|
|||
|
procedure SetTopRow;
|
|||
|
begin
|
|||
|
if BottomRow < ScreenRows then
|
|||
|
BottomRow := ScreenRows;
|
|||
|
TopRow := Succ(BottomRow - ScreenRows);
|
|||
|
PrintRow;
|
|||
|
end; { SetTopRow }
|
|||
|
|
|||
|
procedure SetBottomRow;
|
|||
|
begin
|
|||
|
if TopRow + ScreenRows > Succ(MAXROWS) then
|
|||
|
TopRow := Succ(MAXROWS - ScreenRows);
|
|||
|
BottomRow := Pred(TopRow + ScreenRows);
|
|||
|
PrintRow;
|
|||
|
end; { SetBottomRow }
|
|||
|
|
|||
|
procedure SetLastCol;
|
|||
|
var
|
|||
|
Row, Col : Word;
|
|||
|
begin
|
|||
|
for Col := LastCol downto 1 do
|
|||
|
begin
|
|||
|
for Row := 1 to LastRow do
|
|||
|
begin
|
|||
|
if Cell[Col, Row] <> nil then
|
|||
|
begin
|
|||
|
LastCol := Col;
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
LastCol := 1;
|
|||
|
end; { SetLastCol }
|
|||
|
|
|||
|
procedure SetLastRow;
|
|||
|
var
|
|||
|
Row, Col : Word;
|
|||
|
begin
|
|||
|
for Row := LastRow downto 1 do
|
|||
|
begin
|
|||
|
for Col := 1 to LastCol do
|
|||
|
begin
|
|||
|
if Cell[Col, Row] <> nil then
|
|||
|
begin
|
|||
|
LastRow := Row;
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
LastRow := 1;
|
|||
|
end; { SetLastRow }
|
|||
|
|
|||
|
procedure ClearLastCol;
|
|||
|
var
|
|||
|
Col : Word;
|
|||
|
begin
|
|||
|
Col := ColStart[Succ(RightCol - LeftCol)] + ColWidth[RightCol];
|
|||
|
if (Col < 80) then
|
|||
|
Scroll(UP, 0, Col, 3, 80, ScreenRows + 2, White);
|
|||
|
end; { ClearLastCol }
|
|||
|
|
|||
|
procedure DisplayCol;
|
|||
|
var
|
|||
|
Row : Word;
|
|||
|
begin
|
|||
|
for Row := TopRow to BottomRow do
|
|||
|
DisplayCell(Col, Row, NOHIGHLIGHT, Updating);
|
|||
|
end; { DisplayCol }
|
|||
|
|
|||
|
procedure DisplayRow;
|
|||
|
var
|
|||
|
Col : Word;
|
|||
|
begin
|
|||
|
for Col := LeftCol to RightCol do
|
|||
|
DisplayCell(Col, Row, NOHIGHLIGHT, Updating);
|
|||
|
end; { DisplayRow }
|
|||
|
|
|||
|
procedure DisplayScreen;
|
|||
|
var
|
|||
|
Row : Word;
|
|||
|
begin
|
|||
|
for Row := TopRow to BottomRow do
|
|||
|
DisplayRow(Row, Updating);
|
|||
|
ClearLastCol;
|
|||
|
end; { DisplayScreen }
|
|||
|
|
|||
|
procedure RedrawScreen;
|
|||
|
begin
|
|||
|
CurRow := 1;
|
|||
|
CurCol := 1;
|
|||
|
LeftCol := 1;
|
|||
|
TopRow := 1;
|
|||
|
SetRightCol;
|
|||
|
SetBottomRow;
|
|||
|
GotoXY(1, 1);
|
|||
|
SetColor(MSGMEMORYCOLOR);
|
|||
|
Write(MSGMEMORY);
|
|||
|
GotoXY(29, 1);
|
|||
|
SetColor(PROMPTCOLOR);
|
|||
|
Write(MSGCOMMAND);
|
|||
|
ChangeAutocalc(Autocalc);
|
|||
|
ChangeFormDisplay(FormDisplay);
|
|||
|
PrintFreeMem;
|
|||
|
DisplayScreen(NOUPDATE);
|
|||
|
end; { RedrawScreen }
|
|||
|
|
|||
|
procedure FixFormula;
|
|||
|
var
|
|||
|
FormLen, ColStart, RowStart, CurPos, FCol, FRow : Word;
|
|||
|
CPtr : CellPtr;
|
|||
|
Value : Real;
|
|||
|
S : String[5];
|
|||
|
NewFormula : IString;
|
|||
|
Good : Boolean;
|
|||
|
begin
|
|||
|
CPtr := Cell[Col, Row];
|
|||
|
CurPos := 1;
|
|||
|
NewFormula := CPtr^.Formula;
|
|||
|
while CurPos < Length(NewFormula) do
|
|||
|
begin
|
|||
|
if FormulaStart(NewFormula, CurPos, FCol, FRow, FormLen) then
|
|||
|
begin
|
|||
|
if FCol > 26 then
|
|||
|
begin
|
|||
|
RowStart := CurPos + 2;
|
|||
|
ColStart := RowStart - 2;
|
|||
|
end
|
|||
|
else begin
|
|||
|
RowStart := Succ(CurPos);
|
|||
|
ColStart := Pred(RowStart);
|
|||
|
end;
|
|||
|
case Action of
|
|||
|
COLADD : begin
|
|||
|
if FCol >= Place then
|
|||
|
begin
|
|||
|
if FCol = 26 then
|
|||
|
begin
|
|||
|
if Length(NewFormula) = MAXINPUT then
|
|||
|
begin
|
|||
|
DeleteCell(Col, Row, NOUPDATE);
|
|||
|
Good := AllocText(Col, Row, NewFormula);
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
end;
|
|||
|
S := ColString(FCol);
|
|||
|
Delete(NewFormula, ColStart, Length(S));
|
|||
|
S := ColString(Succ(FCol));
|
|||
|
Insert(S, NewFormula, ColStart);
|
|||
|
end;
|
|||
|
end;
|
|||
|
ROWADD : begin
|
|||
|
if FRow >= Place then
|
|||
|
begin
|
|||
|
if RowWidth(Succ(FRow)) <> RowWidth(FRow) then
|
|||
|
begin
|
|||
|
if Length(NewFormula) = MAXINPUT then
|
|||
|
begin
|
|||
|
DeleteCell(Col, Row, NOUPDATE);
|
|||
|
Good := AllocText(Col, Row, NewFormula);
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
end;
|
|||
|
S := WordToString(FRow, 1);
|
|||
|
Delete(NewFormula, RowStart, Length(S));
|
|||
|
S := WordToString(Succ(FRow), 1);
|
|||
|
Insert(S, NewFormula, RowStart);
|
|||
|
end;
|
|||
|
end;
|
|||
|
COLDEL : begin
|
|||
|
if FCol > Place then
|
|||
|
begin
|
|||
|
S := ColString(FCol);
|
|||
|
Delete(NewFormula, ColStart, Length(S));
|
|||
|
S := ColString(Pred(FCol));
|
|||
|
Insert(S, NewFormula, ColStart);
|
|||
|
end;
|
|||
|
end;
|
|||
|
ROWDEL : begin
|
|||
|
if FRow > Place then
|
|||
|
begin
|
|||
|
S := WordToString(FRow, 1);
|
|||
|
Delete(NewFormula, RowStart, Length(S));
|
|||
|
S := WordToString(Pred(FRow), 1);
|
|||
|
Insert(S, NewFormula, RowStart);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { case }
|
|||
|
Inc(CurPos, FormLen);
|
|||
|
end
|
|||
|
else
|
|||
|
Inc(CurPos);
|
|||
|
end;
|
|||
|
if Length(NewFormula) <> Length(CPtr^.Formula) then
|
|||
|
begin
|
|||
|
Value := CPtr^.FValue;
|
|||
|
DeleteCell(Col, Row, NOUPDATE);
|
|||
|
Good := AllocFormula(Col, Row, NewFormula, Value);
|
|||
|
end
|
|||
|
else
|
|||
|
CPtr^.Formula := NewFormula;
|
|||
|
end; { FixFormula }
|
|||
|
|
|||
|
procedure ChangeAutoCalc;
|
|||
|
var
|
|||
|
S : String[15];
|
|||
|
begin
|
|||
|
if (not AutoCalc) and NewMode then
|
|||
|
Recalc;
|
|||
|
AutoCalc := NewMode;
|
|||
|
if AutoCalc then
|
|||
|
S := MSGAUTOCALC
|
|||
|
else
|
|||
|
S := '';
|
|||
|
SetColor(MSGAUTOCALCCOLOR);
|
|||
|
GotoXY(73, 1);
|
|||
|
Write(S:Length(MSGAUTOCALC));
|
|||
|
end; { ChangeAutoCalc }
|
|||
|
|
|||
|
procedure ChangeFormDisplay;
|
|||
|
var
|
|||
|
S : String[15];
|
|||
|
begin
|
|||
|
FormDisplay := NewMode;
|
|||
|
if FormDisplay then
|
|||
|
S := MSGFORMDISPLAY
|
|||
|
else
|
|||
|
S := '';
|
|||
|
SetColor(MSGFORMDISPLAYCOLOR);
|
|||
|
GotoXY(65, 1);
|
|||
|
Write(S:Length(MSGFORMDISPLAY));
|
|||
|
end; { ChangeFormDisplay }
|
|||
|
|
|||
|
procedure Recalc;
|
|||
|
var
|
|||
|
Col, Row, Attrib : Word;
|
|||
|
begin
|
|||
|
for Col := 1 to LastCol do
|
|||
|
begin
|
|||
|
for Row := 1 to LastRow do
|
|||
|
begin
|
|||
|
if ((Cell[Col, Row] <> nil) and (Cell[Col, Row]^.Attrib = FORMULA)) then
|
|||
|
begin
|
|||
|
Cell[Col, Row]^.FValue := Parse(Cell[Col, Row]^.Formula, Attrib);
|
|||
|
Cell[Col, Row]^.Error := Attrib >= 4;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
DisplayScreen(UPDATE);
|
|||
|
end; { Recalc }
|
|||
|
|
|||
|
procedure Act;
|
|||
|
var
|
|||
|
Attrib, Dummy : Word;
|
|||
|
Allocated : Boolean;
|
|||
|
V : Real;
|
|||
|
begin
|
|||
|
DeleteCell(CurCol, CurRow, UPDATE);
|
|||
|
V := Parse(S, Attrib);
|
|||
|
case (Attrib and 3) of
|
|||
|
TXT : begin
|
|||
|
Allocated := AllocText(CurCol, CurRow, S);
|
|||
|
if Allocated then
|
|||
|
DisplayCell(CurCol, CurRow, NOHIGHLIGHT, NOUPDATE);
|
|||
|
end;
|
|||
|
VALUE : Allocated := AllocValue(CurCol, CurRow, V);
|
|||
|
FORMULA : Allocated := AllocFormula(CurCol, CurRow, UpperCase(S), V);
|
|||
|
end; { case }
|
|||
|
if Allocated then
|
|||
|
begin
|
|||
|
if Attrib >= 4 then
|
|||
|
begin
|
|||
|
Cell[CurCol, CurRow]^.Error := True;
|
|||
|
Dec(Attrib, 4);
|
|||
|
end
|
|||
|
else
|
|||
|
Cell[CurCol, CurRow]^.Error := False;
|
|||
|
Format[CurCol, CurRow] := Format[CurCol, CurRow] and (not OVERWRITE);
|
|||
|
ClearOFlags(Succ(CurCol), CurRow, UPDATE);
|
|||
|
if Attrib = TXT then
|
|||
|
Dummy := SetOFlags(CurCol, CurRow, UPDATE);
|
|||
|
if CurCol > LastCol then
|
|||
|
LastCol := CurCol;
|
|||
|
if CurRow > LastRow then
|
|||
|
LastRow := CurRow;
|
|||
|
if AutoCalc then
|
|||
|
Recalc;
|
|||
|
end
|
|||
|
else
|
|||
|
ErrorMsg(MSGLOMEM);
|
|||
|
PrintFreeMem;
|
|||
|
end; { Act }
|
|||
|
|
|||
|
end.
|
|||
|
|