1366 lines
32 KiB
Plaintext
1366 lines
32 KiB
Plaintext
|
|
|||
|
{ Copyright (c) 1989 by Borland International, Inc. }
|
|||
|
|
|||
|
unit TCRun;
|
|||
|
{ Turbo Pascal 5.5 object-oriented example run module.
|
|||
|
This unit is used by TCALC.PAS.
|
|||
|
See TCALC.DOC for an more information about this example.
|
|||
|
}
|
|||
|
|
|||
|
{$N+,S-}
|
|||
|
|
|||
|
interface
|
|||
|
|
|||
|
uses Crt, Dos, TCUtil, TCLStr, TCScreen, TCHash, TCCell, TCCellSp, TCSheet,
|
|||
|
TCInput, TCParser, TCMenu;
|
|||
|
|
|||
|
const
|
|||
|
FreeListItems = 1000;
|
|||
|
MenuHeapSpace = 1000;
|
|||
|
MaxSpreadsheets = (MinScreenRows - EmptyRowsAtTop - EmptyRowsAtBottom) div
|
|||
|
4;
|
|||
|
LegalJustification = ['L', 'C', 'R'];
|
|||
|
HelpLine = 'F2\Save\F3\Load\F7\Formula\F8\AutoCalc\F9\Recalc\F10\Menu\Ins\Block\Alt-X\Exit';
|
|||
|
TitleString = 'TurboCalc - Turbo Pascal Demo Program';
|
|||
|
MainMenuString = 'Spreadsheet, Block, Column, Row, Format, Goto, Edit, Options, Quit';
|
|||
|
SpreadsheetMenuString = 'Load, Save, Zap, Write, Open, Close, Next, Print';
|
|||
|
OpenMenuString = 'Load, New';
|
|||
|
BlockMenuString = 'Copy, Delete, Format, Restore default format';
|
|||
|
ColumnMenuString = 'Insert, Delete, Width';
|
|||
|
RowMenuString = 'Insert, Delete';
|
|||
|
UtilityMenuString1 = 'Screen lines, Recalc, Formula display, Autocalc';
|
|||
|
UtilityMenuString2 = 'Recalc, Formula display, Autocalc';
|
|||
|
PromptFileLoad = 'File to load';
|
|||
|
PromptGotoCell = 'Go to cell';
|
|||
|
PromptCopyCell = 'Copy to cell';
|
|||
|
PromptColLiteral = 'Copy formula columns literally';
|
|||
|
PromptRowLiteral = 'Copy formula rows literally';
|
|||
|
PromptCopySpreadsheet = 'Copy to spreadsheet number (0 = current)';
|
|||
|
PromptFormatPlaces = 'Number of decimal places';
|
|||
|
PromptFormatJustification = 'Justification - (L)eft, (C)enter, (R)ight';
|
|||
|
PromptFormatDollar = 'Dollar format';
|
|||
|
PromptFormatCommas = 'Put commas in numbers';
|
|||
|
ErrFreeList = 'The free list is full';
|
|||
|
MsgBlockCopy = 'Copying block';
|
|||
|
|
|||
|
type
|
|||
|
ProgramObject = object
|
|||
|
SSData, CurrSS : SpreadsheetPtr;
|
|||
|
TotalSheets : Byte;
|
|||
|
CellInput : InputField;
|
|||
|
MainMenu : Menu;
|
|||
|
SpreadsheetMenu : Menu;
|
|||
|
OpenMenu : Menu;
|
|||
|
BlockMenu : Menu;
|
|||
|
ColumnMenu : Menu;
|
|||
|
RowMenu : Menu;
|
|||
|
UtilityMenu : Menu;
|
|||
|
Stop : Boolean;
|
|||
|
constructor Init;
|
|||
|
destructor Done;
|
|||
|
procedure GetCommands;
|
|||
|
procedure SetDisplayAreas;
|
|||
|
procedure DisplayAll;
|
|||
|
function AddSheet(Name : PathStr) : Boolean;
|
|||
|
procedure DeleteSheet;
|
|||
|
end;
|
|||
|
|
|||
|
var
|
|||
|
Vars : ProgramObject;
|
|||
|
|
|||
|
procedure Run;
|
|||
|
|
|||
|
implementation
|
|||
|
|
|||
|
const
|
|||
|
RedrawYes = True;
|
|||
|
RedrawNo = False;
|
|||
|
|
|||
|
{$F+}
|
|||
|
|
|||
|
function RunHeapError(Size : Word) : Integer;
|
|||
|
{ Prints an error if the heap runs out of memory }
|
|||
|
begin
|
|||
|
Scr.PrintError(ErrNoMemory);
|
|||
|
RunHeapError := 1;
|
|||
|
end; { RunHeapError }
|
|||
|
|
|||
|
{$F-}
|
|||
|
|
|||
|
procedure InitMenus; forward;
|
|||
|
|
|||
|
constructor ProgramObject.Init;
|
|||
|
{ Sets up the program }
|
|||
|
var
|
|||
|
Counter : Word;
|
|||
|
Good : Boolean;
|
|||
|
begin { ProgramObject.Init }
|
|||
|
if MaxAvail < MenuHeapSpace then
|
|||
|
Abort(ErrNoMemory);
|
|||
|
InitMenus;
|
|||
|
TotalSheets := 0;
|
|||
|
SSData := nil;
|
|||
|
CurrSS := nil;
|
|||
|
Stop := False;
|
|||
|
if ParamCount = 0 then { Load spreadsheets named on command line }
|
|||
|
begin
|
|||
|
if not AddSheet('') then
|
|||
|
Abort(ErrNoMemory);
|
|||
|
end
|
|||
|
else begin
|
|||
|
Counter := 1;
|
|||
|
repeat
|
|||
|
Good := AddSheet(ParamStr(Counter));
|
|||
|
Inc(Counter);
|
|||
|
until (not Good) or (Counter > Min(ParamCount, MaxSpreadsheets));
|
|||
|
end;
|
|||
|
SetDisplayAreas;
|
|||
|
DisplayAll;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end; { with }
|
|||
|
end; { ProgramObject.Init }
|
|||
|
|
|||
|
destructor ProgramObject.Done;
|
|||
|
{ Releases all memory used by the program }
|
|||
|
begin
|
|||
|
CurrSS^.MakeNotCurrent;
|
|||
|
while SSData <> nil do
|
|||
|
begin
|
|||
|
CurrSS := SSData;
|
|||
|
SSData := SSData^.Next;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
CheckForSave;
|
|||
|
MakeNotCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
Dispose(CurrSS, Done);
|
|||
|
end; { with }
|
|||
|
end;
|
|||
|
MainMenu.Done;
|
|||
|
SpreadsheetMenu.Done;
|
|||
|
OpenMenu.Done;
|
|||
|
BlockMenu.Done;
|
|||
|
ColumnMenu.Done;
|
|||
|
RowMenu.Done;
|
|||
|
UtilityMenu.Done;
|
|||
|
end; { ProgramObject.Done }
|
|||
|
|
|||
|
function GetFormat(var Format : Byte) : Boolean;
|
|||
|
{ Reads a format value from the keyboard }
|
|||
|
var
|
|||
|
Places : Byte;
|
|||
|
J : Justification;
|
|||
|
ESCPressed, Good, Dollar, Commas : Boolean;
|
|||
|
Ch : Char;
|
|||
|
begin
|
|||
|
GetFormat := False;
|
|||
|
Dollar := GetYesNo(PromptFormatDollar, ESCPressed);
|
|||
|
if ESCPressed then
|
|||
|
Exit;
|
|||
|
if Dollar then
|
|||
|
begin
|
|||
|
Places := 2;
|
|||
|
J := JRight;
|
|||
|
end
|
|||
|
else begin
|
|||
|
Places := GetNumber(PromptFormatPlaces, 0,
|
|||
|
Vars.CurrSS^.MaxDecimalPlaces, Good);
|
|||
|
if not Good then
|
|||
|
Exit;
|
|||
|
Ch := GetLegalChar(PromptFormatJustification, LegalJustification,
|
|||
|
ESCPressed);
|
|||
|
if ESCPressed then
|
|||
|
Exit;
|
|||
|
case Ch of
|
|||
|
'L' : J := JLeft;
|
|||
|
'C' : J := JCenter;
|
|||
|
'R' : J := JRight;
|
|||
|
end; { case }
|
|||
|
end;
|
|||
|
Commas := GetYesNo(PromptFormatCommas, ESCPressed);
|
|||
|
if ESCPressed then
|
|||
|
Exit;
|
|||
|
Format := Places + (Ord(J) shl 4) + (Ord(Dollar) shl 6) +
|
|||
|
(Ord(Commas) shl 7);
|
|||
|
GetFormat := True;
|
|||
|
end; { GetFormat }
|
|||
|
|
|||
|
procedure EditInput(Ch : Word; Editing : Boolean);
|
|||
|
{ Edits the data on the input line }
|
|||
|
var
|
|||
|
Good, FirstEdit, Deleted : Boolean;
|
|||
|
P : CellPos;
|
|||
|
begin
|
|||
|
with Vars, CurrSS^ do
|
|||
|
begin
|
|||
|
if not CellInput.Init(1, 0, -1, 0, NotUpper) then
|
|||
|
Exit;
|
|||
|
with CellInput.InputData^ do
|
|||
|
begin
|
|||
|
if Editing then
|
|||
|
begin
|
|||
|
Good := True;
|
|||
|
CellHash.Search(CurrPos)^.EditString(MaxDecimalPlaces,
|
|||
|
CellInput.InputData)
|
|||
|
end
|
|||
|
else
|
|||
|
Good := FromString(Chr(Ch));
|
|||
|
if not Good then
|
|||
|
begin
|
|||
|
CellInput.Done;
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
FirstEdit := True;
|
|||
|
Parser.Init(@CellHash, CellInput.InputData, MaxCols, MaxRows);
|
|||
|
repeat
|
|||
|
if FirstEdit then
|
|||
|
CellInput.Edit(0)
|
|||
|
else
|
|||
|
CellInput.Edit(Parser.Position);
|
|||
|
if Length > 0 then
|
|||
|
begin
|
|||
|
Parser.Parse;
|
|||
|
if Parser.TokenError = 0 then
|
|||
|
begin
|
|||
|
DeleteCell(CurrPos, Deleted);
|
|||
|
Good := AddCell(Parser.CType, CurrPos, Parser.ParseError,
|
|||
|
Parser.ParseValue, CellInput.InputData);
|
|||
|
end;
|
|||
|
end;
|
|||
|
FirstEdit := False;
|
|||
|
until (Length = 0) or (Parser.TokenError = 0);
|
|||
|
if Length > 0 then
|
|||
|
begin
|
|||
|
SetChanged(WasChanged);
|
|||
|
if AutoCalc then
|
|||
|
Update(DisplayYes);
|
|||
|
P := CurrPos;
|
|||
|
for P.Col := CurrPos.Col to ScreenBlock.Stop.Col do
|
|||
|
DisplayCell(P);
|
|||
|
end;
|
|||
|
CellInput.InputArea.Clear;
|
|||
|
end; { with }
|
|||
|
CellInput.Done;
|
|||
|
DisplayMemory;
|
|||
|
end; { with }
|
|||
|
end; { EditInput }
|
|||
|
|
|||
|
procedure OpenSpreadsheet(Name : String);
|
|||
|
{ Opens a new spreadsheet }
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
if not AddSheet(Name) then
|
|||
|
Exit;
|
|||
|
SetDisplayAreas;
|
|||
|
DisplayAll;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end; { with }
|
|||
|
end; { with }
|
|||
|
end; { OpenSpreadsheet }
|
|||
|
|
|||
|
procedure ClearCurrBlock;
|
|||
|
{ Turns off the block and redisplays the cells in it }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if BlockOn then
|
|||
|
begin
|
|||
|
BlockOn := False;
|
|||
|
DisplayBlock(CurrBlock);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { ClearCurrBlock }
|
|||
|
|
|||
|
{$F+}
|
|||
|
|
|||
|
procedure ReplaceSpreadsheet;
|
|||
|
{ Load a spreadsheet over the current one }
|
|||
|
var
|
|||
|
S : PathStr;
|
|||
|
ESCPressed : Boolean;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
S := ReadString(PromptFileLoad, Pred(SizeOf(PathStr)), ESCPressed);
|
|||
|
if S = '' then
|
|||
|
Exit;
|
|||
|
CheckForSave;
|
|||
|
Done;
|
|||
|
if FromFile(S) then
|
|||
|
begin
|
|||
|
SetChanged(NotChanged);
|
|||
|
SetScreenColStart(1);
|
|||
|
SetScreenRowStart(1);
|
|||
|
Display;
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { ReplaceSpreadsheet }
|
|||
|
|
|||
|
procedure NameSaveSpreadsheet;
|
|||
|
{ Save a spreadsheet to a file other that its default }
|
|||
|
var
|
|||
|
St : PathStr;
|
|||
|
ESCPressed : Boolean;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
St := ReadString(PromptFileSave, Pred(SizeOf(PathStr)), ESCPressed);
|
|||
|
if St = '' then
|
|||
|
Exit;
|
|||
|
if FileExists(St) then
|
|||
|
begin
|
|||
|
if not GetYesNo(PromptOverwriteFile, ESCPressed) then
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
ToFile(St);
|
|||
|
DisplayFileName;
|
|||
|
end; { with }
|
|||
|
end; { NameSaveSpreadsheet }
|
|||
|
|
|||
|
procedure SaveCurrSpreadsheet;
|
|||
|
{ Save a spreadsheet to its default file }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if FileName = '' then
|
|||
|
NameSaveSpreadsheet
|
|||
|
else
|
|||
|
ToFile(FileName);
|
|||
|
end; { with }
|
|||
|
end; { SaveCurrSpreadsheet }
|
|||
|
|
|||
|
procedure ZapSpreadsheet;
|
|||
|
{ Clear the current spreadsheet from memory }
|
|||
|
var
|
|||
|
S : PathStr;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
CheckForSave;
|
|||
|
S := FileName;
|
|||
|
Done;
|
|||
|
Init(0, DefaultMaxCols, DefaultMaxRows, DefaultMaxDecimalPlaces,
|
|||
|
DefaultDefaultDecimalPlaces, DefaultDefaultColWidth);
|
|||
|
MakeCurrent;
|
|||
|
FileName := S;
|
|||
|
SetScreenColStart(1);
|
|||
|
SetScreenRowStart(1);
|
|||
|
Display;
|
|||
|
end; { with }
|
|||
|
end; { ZapSpreadsheet }
|
|||
|
|
|||
|
procedure CloseSpreadsheet;
|
|||
|
{ Delete a spreadsheet, closing the window that it is in }
|
|||
|
begin
|
|||
|
with Vars, CurrSS^ do
|
|||
|
begin
|
|||
|
if TotalSheets = 1 then
|
|||
|
Exit;
|
|||
|
DeleteSheet;
|
|||
|
end; { with }
|
|||
|
end; { CloseSpreadsheet }
|
|||
|
|
|||
|
procedure NextSpreadsheet;
|
|||
|
{ Move to the next spreadsheet }
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
if TotalSheets = 1 then
|
|||
|
Exit;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeNotCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end; { with }
|
|||
|
CurrSS := CurrSS^.Next;
|
|||
|
if CurrSS = nil then
|
|||
|
CurrSS := SSData;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end; { with }
|
|||
|
end; { with }
|
|||
|
end; { NextSpreadsheet }
|
|||
|
|
|||
|
procedure NewSpreadsheet;
|
|||
|
{ Create a new spreadsheet, opening a window for it and loading it }
|
|||
|
var
|
|||
|
S : PathStr;
|
|||
|
ESCPressed : Boolean;
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
if TotalSheets >= MaxSpreadsheets then
|
|||
|
Exit;
|
|||
|
S := ReadString(PromptFileLoad, Pred(SizeOf(PathStr)), ESCPressed);
|
|||
|
if S = '' then
|
|||
|
Exit;
|
|||
|
OpenSpreadsheet(S);
|
|||
|
end; { with }
|
|||
|
end; { NewSpreadsheet }
|
|||
|
|
|||
|
procedure NewBlankSpreadsheet;
|
|||
|
{ Create a new blank spreadsheet, opening a window for it }
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
if TotalSheets >= MaxSpreadsheets then
|
|||
|
Exit;
|
|||
|
OpenSpreadsheet('');
|
|||
|
end; { with }
|
|||
|
end; { NewBlankSpreadsheet }
|
|||
|
|
|||
|
procedure PrintSpreadsheet;
|
|||
|
{ Print a spreadsheet to a file or a printer }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.Print;
|
|||
|
end; { PrintSpreadsheet }
|
|||
|
|
|||
|
procedure CopyBlock;
|
|||
|
{ Copy a block of cells from one spreadsheet to the same or a different
|
|||
|
spreadsheet }
|
|||
|
var
|
|||
|
P, N, C : CellPos;
|
|||
|
Good, ESCPressed, ColLit, RowLit, AnyChanged, Deleted : Boolean;
|
|||
|
CP : CellPtr;
|
|||
|
L : LStringPtr;
|
|||
|
CopyTo : SpreadsheetPtr;
|
|||
|
CopySheet : Byte;
|
|||
|
Counter : Word;
|
|||
|
begin
|
|||
|
with Vars, CurrSS^, CurrBlock do
|
|||
|
begin
|
|||
|
if not BlockOn then
|
|||
|
Exit;
|
|||
|
if TotalSheets > 1 then
|
|||
|
CopySheet := GetNumber(PromptCopySpreadsheet, 0, TotalSheets, Good)
|
|||
|
else
|
|||
|
CopySheet := 1;
|
|||
|
if not Good then
|
|||
|
Exit;
|
|||
|
if not GetCellPos(PromptCopyCell, MaxCols, MaxRows, ColSpace,
|
|||
|
RowNumberSpace, P) then
|
|||
|
Exit;
|
|||
|
ColLit := GetYesNo(PromptColLiteral, ESCPressed);
|
|||
|
if ESCPressed then
|
|||
|
Exit;
|
|||
|
RowLit := GetYesNo(PromptRowLiteral, ESCPressed);
|
|||
|
if ESCPressed then
|
|||
|
Exit;
|
|||
|
Scr.PrintMessage(MsgBlockCopy);
|
|||
|
if CopySheet = 0 then
|
|||
|
CopyTo := CurrSS
|
|||
|
else begin
|
|||
|
CopyTo := SSData;
|
|||
|
for Counter := 2 to CopySheet do
|
|||
|
CopyTo := CopyTo^.Next;
|
|||
|
end;
|
|||
|
AnyChanged := False;
|
|||
|
C.Row := P.Row;
|
|||
|
N.Row := Start.Row;
|
|||
|
L := New(LStringPtr, Init);
|
|||
|
Good := L <> nil;
|
|||
|
while Good and (N.Row <= Stop.Row) do
|
|||
|
begin
|
|||
|
C.Col := P.Col;
|
|||
|
N.Col := Start.Col;
|
|||
|
while Good and (N.Col <= Stop.Col) do
|
|||
|
begin
|
|||
|
if (Longint(P.Col) + N.Col - Start.Col <= MaxCols) and
|
|||
|
(Longint(P.Row) + N.Row - Start.Row <= MaxRows) then
|
|||
|
begin
|
|||
|
CopyTo^.DeleteCell(C, Deleted);
|
|||
|
if Deleted then
|
|||
|
AnyChanged := True;
|
|||
|
CP := CellHash.Search(N);
|
|||
|
if CP <> Empty then
|
|||
|
begin
|
|||
|
AnyChanged := True;
|
|||
|
with CP^ do
|
|||
|
Good := CopyTo^.AddCell(CellType, C, HasError, CurrValue,
|
|||
|
CopyString(ColLit, RowLit,
|
|||
|
Longint(C.Col) - N.Col, L));
|
|||
|
if Good and ((not ColLit) or (not RowLit)) then
|
|||
|
begin
|
|||
|
CP := CopyTo^.CellHash.Search(C);
|
|||
|
if CP^.ShouldUpdate then
|
|||
|
begin
|
|||
|
if not ColLit then
|
|||
|
FixFormulaCol(CP, Longint(C.Col) - N.Col, MaxCols,
|
|||
|
MaxRows);
|
|||
|
if not RowLit then
|
|||
|
FixFormulaRow(CP, Longint(C.Row) - N.Row, MaxCols,
|
|||
|
MaxRows);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
Inc(C.Col);
|
|||
|
Inc(N.Col);
|
|||
|
end;
|
|||
|
Inc(C.Row);
|
|||
|
Inc(N.Row);
|
|||
|
end;
|
|||
|
if AnyChanged then
|
|||
|
begin
|
|||
|
if CopySheet = 0 then
|
|||
|
BlockOn := False;
|
|||
|
with CopyTo^ do
|
|||
|
begin
|
|||
|
SetLastPos(LastPos);
|
|||
|
SetChanged(WasChanged);
|
|||
|
if AutoCalc then
|
|||
|
Update(DisplayNo);
|
|||
|
DisplayAllCells;
|
|||
|
DisplayMemory;
|
|||
|
end; { with }
|
|||
|
if CopySheet <> 0 then
|
|||
|
ClearCurrBlock;
|
|||
|
end
|
|||
|
else
|
|||
|
ClearCurrBlock;
|
|||
|
Scr.ClearMessage;
|
|||
|
end; { with }
|
|||
|
if L <> nil then
|
|||
|
Dispose(L, Done);
|
|||
|
end; { CopyBlock }
|
|||
|
|
|||
|
procedure DeleteBlock;
|
|||
|
{ Delete a block of cells }
|
|||
|
var
|
|||
|
Deleted : Boolean;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^, CurrBlock do
|
|||
|
begin
|
|||
|
if not BlockOn then
|
|||
|
Exit;
|
|||
|
DeleteBlock(CurrBlock, Deleted);
|
|||
|
if Deleted then
|
|||
|
begin
|
|||
|
BlockOn := False;
|
|||
|
SetLastPos(LastPos);
|
|||
|
SetChanged(WasChanged);
|
|||
|
if AutoCalc then
|
|||
|
Update(DisplayNo);
|
|||
|
DisplayMemory;
|
|||
|
DisplayAllCells;
|
|||
|
end
|
|||
|
else
|
|||
|
ClearCurrBlock;
|
|||
|
end; { with }
|
|||
|
end; { DeleteBlock }
|
|||
|
|
|||
|
procedure FormatBlock;
|
|||
|
{ Format a block of cells }
|
|||
|
var
|
|||
|
Format : Byte;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if not BlockOn then
|
|||
|
Exit;
|
|||
|
if not GetFormat(Format) then
|
|||
|
Exit;
|
|||
|
with CurrBlock do
|
|||
|
begin
|
|||
|
if not FormatHash.Add(Start, Stop, Format) then
|
|||
|
Exit;
|
|||
|
SetChanged(WasChanged);
|
|||
|
DisplayAllCells;
|
|||
|
DisplayMemory;
|
|||
|
end; { with }
|
|||
|
end; { with }
|
|||
|
end; { FormatBlock }
|
|||
|
|
|||
|
procedure FormatDefault;
|
|||
|
{ Change the format of a block of cells to the default }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if not BlockOn then
|
|||
|
Exit;
|
|||
|
with CurrBlock do
|
|||
|
begin
|
|||
|
if not FormatHash.Delete(Start, Stop) then
|
|||
|
Exit;
|
|||
|
SetChanged(WasChanged);
|
|||
|
DisplayAllCells;
|
|||
|
DisplayMemory;
|
|||
|
end; { with }
|
|||
|
end; { with }
|
|||
|
end; { FormatDefault }
|
|||
|
|
|||
|
procedure ColInsert;
|
|||
|
{ Insert a column into the spreadsheet }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.InsertColumn;
|
|||
|
end; { ColInsert }
|
|||
|
|
|||
|
procedure ColDelete;
|
|||
|
{ Delete a column from the spreadsheet }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.DeleteColumn;
|
|||
|
end; { ColDelete }
|
|||
|
|
|||
|
procedure ChangeColWidth;
|
|||
|
{ Change the width of a column }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.ChangeWidth;
|
|||
|
end; { ChangeColWidth }
|
|||
|
|
|||
|
procedure RowInsert;
|
|||
|
{ Insert a row into the spreadsheet }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.InsertRow;
|
|||
|
end; { RowInsert }
|
|||
|
|
|||
|
procedure RowDelete;
|
|||
|
{ Delete a row from the spreadsheet }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.DeleteRow;
|
|||
|
end; { RowDelete }
|
|||
|
|
|||
|
procedure ToggleMaxLines;
|
|||
|
{ Toggle 43/50-line mode }
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
Scr.ToggleMaxLinesMode;
|
|||
|
SetCursor(NoCursor);
|
|||
|
SetDisplayAreas;
|
|||
|
DisplayAll;
|
|||
|
end; { with }
|
|||
|
end; { ToggleMaxLines }
|
|||
|
|
|||
|
procedure Recalc;
|
|||
|
{ Recalculate all of the cells }
|
|||
|
begin
|
|||
|
Vars.CurrSS^.Update(DisplayYes);
|
|||
|
end; { Recalc }
|
|||
|
|
|||
|
procedure ToggleFormulas;
|
|||
|
{ Toggle formula display on and off }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
ToggleFormulaDisplay;
|
|||
|
end; { ToggleFormulas }
|
|||
|
|
|||
|
procedure ToggleAutoCalc;
|
|||
|
{ Toggle AutoCalc on and off }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if AutoCalc then
|
|||
|
begin
|
|||
|
AutoCalc := False;
|
|||
|
DisplayInfo;
|
|||
|
end
|
|||
|
else begin
|
|||
|
AutoCalc := True;
|
|||
|
DisplayInfo;
|
|||
|
Update(DisplayYes);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { ToggleAutoCalc }
|
|||
|
|
|||
|
procedure FormatCell;
|
|||
|
{ Format a single cell }
|
|||
|
var
|
|||
|
Format : Byte;
|
|||
|
P : CellPos;
|
|||
|
CP : CellPtr;
|
|||
|
Good : Boolean;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if not GetFormat(Format) then
|
|||
|
Exit;
|
|||
|
if not FormatHash.Add(CurrPos, CurrPos, Format) then
|
|||
|
Exit;
|
|||
|
CP := CellHash.Search(CurrPos);
|
|||
|
SetChanged(WasChanged);
|
|||
|
OverwriteHash.Delete(CurrPos);
|
|||
|
if CP <> Empty then
|
|||
|
Good := OverwriteHash.Add(CP, CP^.Overwritten(CellHash, FormatHash,
|
|||
|
WidthHash, LastPos, MaxCols, GetColWidth,
|
|||
|
DisplayFormulas));
|
|||
|
P := CurrPos;
|
|||
|
for P.Col := CurrPos.Col to ScreenBlock.Stop.Col do
|
|||
|
DisplayCell(P);
|
|||
|
DisplayMemory;
|
|||
|
end; { with }
|
|||
|
end; { FormatCell }
|
|||
|
|
|||
|
procedure GotoCell;
|
|||
|
{ Go to a selected cell }
|
|||
|
var
|
|||
|
P, OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if not GetCellPos(PromptGotoCell, MaxCols, MaxRows, ColSpace,
|
|||
|
RowNumberSpace, P) then
|
|||
|
Exit;
|
|||
|
if not ScreenBlock.CellInBlock(P) then
|
|||
|
begin
|
|||
|
CurrPos := P;
|
|||
|
SetScreenColStart(CurrPos.Col);
|
|||
|
SetScreenRowStart(CurrPos.Row);
|
|||
|
Display;
|
|||
|
end
|
|||
|
else begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos := P;
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { GotoCell }
|
|||
|
|
|||
|
procedure EditCell;
|
|||
|
{ Edit the current cell }
|
|||
|
begin
|
|||
|
EditInput(0, EditYes);
|
|||
|
end; { EditCell }
|
|||
|
|
|||
|
procedure Quit;
|
|||
|
{ Exit from the program }
|
|||
|
begin
|
|||
|
Vars.Stop := True;
|
|||
|
end; { Quit }
|
|||
|
|
|||
|
{$F-}
|
|||
|
|
|||
|
procedure ExtendCurrBlock(Redraw : Boolean);
|
|||
|
{ Extend the current block and redraw any cells that are affected }
|
|||
|
var
|
|||
|
OldBlock : Block;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if BlockOn then
|
|||
|
begin
|
|||
|
Move(CurrBlock, OldBlock, SizeOf(CurrBlock));
|
|||
|
if CurrBlock.ExtendTo(CurrPos) then
|
|||
|
begin
|
|||
|
if Redraw then
|
|||
|
DisplayBlockDiff(OldBlock, CurrBlock);
|
|||
|
end
|
|||
|
else
|
|||
|
ClearCurrBlock;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { ExtendCurrBlock }
|
|||
|
|
|||
|
procedure ToggleCurrBlock;
|
|||
|
{ Turn the block on and off }
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if not BlockOn then
|
|||
|
begin
|
|||
|
BlockOn := True;
|
|||
|
CurrBlock.Init(CurrPos);
|
|||
|
end
|
|||
|
else
|
|||
|
ClearCurrBlock;
|
|||
|
end; { with }
|
|||
|
end; { ToggleCurrBlock }
|
|||
|
|
|||
|
procedure RemoveCell;
|
|||
|
{ Delete a cell }
|
|||
|
var
|
|||
|
P : CellPos;
|
|||
|
Deleted : Boolean;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
DeleteCell(CurrPos, Deleted);
|
|||
|
if Deleted then
|
|||
|
begin
|
|||
|
SetLastPos(CurrPos);
|
|||
|
SetChanged(WasChanged);
|
|||
|
if AutoCalc then
|
|||
|
Update(DisplayYes);
|
|||
|
P.Row := CurrPos.Row;
|
|||
|
for P.Col := CurrPos.Col to ScreenBlock.Stop.Col do
|
|||
|
DisplayCell(P);
|
|||
|
DisplayMemory;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { RemoveCell }
|
|||
|
|
|||
|
procedure MoveHome;
|
|||
|
{ Move to the home position (1, 1) }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos.Col := 1;
|
|||
|
CurrPos.Row := 1;
|
|||
|
if not ScreenBlock.CellInBlock(CurrPos) then
|
|||
|
begin
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
SetScreenColStart(1);
|
|||
|
SetScreenRowStart(1);
|
|||
|
SetBlankArea;
|
|||
|
Display;
|
|||
|
end
|
|||
|
else begin
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveHome }
|
|||
|
|
|||
|
procedure MoveEnd;
|
|||
|
{ Move to the last position used }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos := LastPos;
|
|||
|
if not ScreenBlock.CellInBlock(CurrPos) then
|
|||
|
begin
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
SetScreenColStop(CurrPos.Col);
|
|||
|
SetScreenRowStop(CurrPos.Row);
|
|||
|
SetBlankArea;
|
|||
|
Display;
|
|||
|
end
|
|||
|
else begin
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveEnd }
|
|||
|
|
|||
|
procedure MoveUp;
|
|||
|
{ Move up a row }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Row > 1 then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
Dec(CurrPos.Row);
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
if CurrPos.Row < ScreenBlock.Start.Row then
|
|||
|
begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
SetScreenRowStart(CurrPos.Row);
|
|||
|
DisplayRows;
|
|||
|
DisplayArea.Scroll(Down, 1);
|
|||
|
DisplayRow(CurrPos.Row);
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveUp }
|
|||
|
|
|||
|
procedure MoveDown;
|
|||
|
{ Move down a row }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Row < MaxRows then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
Inc(CurrPos.Row);
|
|||
|
if CurrPos.Row > ScreenBlock.Stop.Row then
|
|||
|
begin
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
DisplayCell(OldPos);
|
|||
|
SetScreenRowStop(CurrPos.Row);
|
|||
|
DisplayRows;
|
|||
|
DisplayArea.Scroll(Up, 1);
|
|||
|
DisplayRow(CurrPos.Row);
|
|||
|
end
|
|||
|
else begin
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveDown }
|
|||
|
|
|||
|
procedure MovePgUp;
|
|||
|
{ Move up a page }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Row > 1 then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos.Row := Max(1, Longint(CurrPos.Row) - TotalRows);
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
if CurrPos.Row < ScreenBlock.Start.Row then
|
|||
|
begin
|
|||
|
SetScreenRowStart(CurrPos.Row);
|
|||
|
DisplayRows;
|
|||
|
DisplayAllCells;
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MovePgUp }
|
|||
|
|
|||
|
procedure MovePgDn;
|
|||
|
{ Move down a page }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Row < MaxRows then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos.Row := Min(MaxRows, Longint(CurrPos.Row) + TotalRows);
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
if CurrPos.Row > ScreenBlock.Start.Row then
|
|||
|
begin
|
|||
|
SetScreenRowStart(CurrPos.Row);
|
|||
|
DisplayRows;
|
|||
|
DisplayAllCells;
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MovePgDn }
|
|||
|
|
|||
|
procedure MoveLeft;
|
|||
|
{ Move left a column }
|
|||
|
var
|
|||
|
C : Word;
|
|||
|
OldPos : CellPos;
|
|||
|
OldSCol : Word;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Col > 1 then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
Dec(CurrPos.Col);
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
if CurrPos.Col < ScreenBlock.Start.Col then
|
|||
|
begin
|
|||
|
OldSCol := ScreenBlock.Start.Col;
|
|||
|
C := GetColStart(1);
|
|||
|
DisplayCell(OldPos);
|
|||
|
SetScreenColStart(CurrPos.Col);
|
|||
|
SetBlankArea;
|
|||
|
DisplayCols;
|
|||
|
DisplayArea.Scroll(Right,
|
|||
|
GetColStart(OldSCol - ScreenBlock.Start.Col) - GetColStart(0));
|
|||
|
if not NoBlankArea then
|
|||
|
BlankArea.Clear;
|
|||
|
for C := ScreenBlock.Start.Col to CurrPos.Col do
|
|||
|
DisplayCol(C);
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveLeft }
|
|||
|
|
|||
|
procedure MoveRight;
|
|||
|
{ Move right a column }
|
|||
|
var
|
|||
|
C : Word;
|
|||
|
OldPos : CellPos;
|
|||
|
SaveColStart : array[0..79] of Byte;
|
|||
|
OldSCol : Word;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Col < MaxCols then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
Inc(CurrPos.Col);
|
|||
|
if CurrPos.Col > ScreenBlock.Stop.Col then
|
|||
|
begin
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
for C := 0 to Pred(MaxScreenCols) do
|
|||
|
SaveColStart[C] := GetColStart(C);
|
|||
|
OldSCol := ScreenBlock.Start.Col;
|
|||
|
DisplayCell(OldPos);
|
|||
|
C := ColWidth(ScreenBlock.Start.Col);
|
|||
|
SetScreenColStop(CurrPos.Col);
|
|||
|
SetBlankArea;
|
|||
|
DisplayCols;
|
|||
|
DisplayArea.Scroll(Left,
|
|||
|
SaveColStart[ScreenBlock.Start.Col - OldSCol] - ColStart^[0]);
|
|||
|
if not NoBlankArea then
|
|||
|
BlankArea.Clear;
|
|||
|
for C := CurrPos.Col to ScreenBlock.Stop.Col do
|
|||
|
DisplayCol(C);
|
|||
|
end
|
|||
|
else begin
|
|||
|
ExtendCurrBlock(RedrawYes);
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MoveRight }
|
|||
|
|
|||
|
procedure MovePgLeft;
|
|||
|
{ Move left a page }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Col > 1 then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos.Col := Max(1, Pred(ScreenBlock.Start.Col));
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
if CurrPos.Col < ScreenBlock.Start.Col then
|
|||
|
begin
|
|||
|
SetScreenColStop(CurrPos.Col);
|
|||
|
SetBlankArea;
|
|||
|
DisplayCols;
|
|||
|
if not NoBlankArea then
|
|||
|
BlankArea.Clear;
|
|||
|
DisplayAllCells;
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MovePgLeft }
|
|||
|
|
|||
|
procedure MovePgRight;
|
|||
|
{ Move right a page }
|
|||
|
var
|
|||
|
OldPos : CellPos;
|
|||
|
begin
|
|||
|
with Vars.CurrSS^ do
|
|||
|
begin
|
|||
|
if CurrPos.Col < MaxCols then
|
|||
|
begin
|
|||
|
OldPos := CurrPos;
|
|||
|
CurrPos.Col := Min(MaxCols, Succ(ScreenBlock.Stop.Col));
|
|||
|
ExtendCurrBlock(RedrawNo);
|
|||
|
if CurrPos.Col > ScreenBlock.Start.Col then
|
|||
|
begin
|
|||
|
SetScreenColStart(CurrPos.Col);
|
|||
|
SetBlankArea;
|
|||
|
DisplayCols;
|
|||
|
if not NoBlankArea then
|
|||
|
BlankArea.Clear;
|
|||
|
DisplayAllCells;
|
|||
|
end
|
|||
|
else begin
|
|||
|
DisplayCell(OldPos);
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end; { with }
|
|||
|
end; { MovePgRight }
|
|||
|
|
|||
|
procedure HandleInput(Ch : Word);
|
|||
|
{ Process the initial input from the keyboard }
|
|||
|
begin
|
|||
|
EditInput(Ch, EditNo);
|
|||
|
end; { HandleInput }
|
|||
|
|
|||
|
procedure ProgramObject.GetCommands;
|
|||
|
{ Read the keyboard and process the next command }
|
|||
|
var
|
|||
|
Ch : Word;
|
|||
|
begin
|
|||
|
repeat
|
|||
|
CurrSS^.DisplayCellData;
|
|||
|
ClearInputBuffer;
|
|||
|
Ch := GetKey;
|
|||
|
case Ch of
|
|||
|
F2 : SaveCurrSpreadsheet;
|
|||
|
AltF2 : NameSaveSpreadsheet;
|
|||
|
F3 : ReplaceSpreadsheet;
|
|||
|
AltF3 : NewSpreadsheet;
|
|||
|
F4 : DeleteSheet;
|
|||
|
F6 : NextSpreadsheet;
|
|||
|
F7 : ToggleFormulas;
|
|||
|
F8 : ToggleAutoCalc;
|
|||
|
F9 : Recalc;
|
|||
|
F10 : MainMenu.RunMenu;
|
|||
|
AltX : Stop := True;
|
|||
|
InsKey : ToggleCurrBlock;
|
|||
|
DelKey : RemoveCell;
|
|||
|
HomeKey : MoveHome;
|
|||
|
EndKey : MoveEnd;
|
|||
|
UpKey : MoveUp;
|
|||
|
DownKey : MoveDown;
|
|||
|
LeftKey : MoveLeft;
|
|||
|
RightKey : MoveRight;
|
|||
|
PgUpKey : MovePgUp;
|
|||
|
PgDnKey : MovePgDn;
|
|||
|
CtrlLeftKey : MovePgLeft;
|
|||
|
CtrlRightKey : MovePgRight;
|
|||
|
Ord(' ')..Ord('~') : HandleInput(Ch);
|
|||
|
end;
|
|||
|
until Stop;
|
|||
|
end; { ProgramObject.GetCommands }
|
|||
|
|
|||
|
procedure ProgramObject.SetDisplayAreas;
|
|||
|
{ Set the display areas of the various spreadsheets }
|
|||
|
var
|
|||
|
S : SpreadsheetPtr;
|
|||
|
Total, StartRow, Amt : Word;
|
|||
|
begin
|
|||
|
S := SSData;
|
|||
|
StartRow := Succ(EmptyRowsAtTop);
|
|||
|
Amt := (Scr.CurrRows - EmptyRowsAtTop - EmptyRowsAtBottom) div
|
|||
|
TotalSheets;
|
|||
|
Total := 1;
|
|||
|
repeat
|
|||
|
if S^.Next = nil then
|
|||
|
Amt := Succ(Scr.CurrRows - EmptyRowsAtBottom - StartRow);
|
|||
|
S^.SetAreas(Total, 1, StartRow, Scr.CurrCols, Pred(StartRow + Amt));
|
|||
|
Inc(StartRow, Amt);
|
|||
|
S := S^.Next;
|
|||
|
Inc(Total);
|
|||
|
until S = nil;
|
|||
|
end; { ProgramObject.SetDisplayAreas }
|
|||
|
|
|||
|
procedure ProgramObject.DisplayAll;
|
|||
|
{ Display all of the spreadsheets }
|
|||
|
var
|
|||
|
S : SpreadsheetPtr;
|
|||
|
begin
|
|||
|
TextAttr := Colors.BlankColor;
|
|||
|
ClrScr;
|
|||
|
WriteColor(TitleString, Colors.TitleColor);
|
|||
|
Scr.PrintHelpLine(HelpLine);
|
|||
|
WriteXY(MemoryString, Scr.CurrCols - Length(MemoryString) - 5, 1,
|
|||
|
Colors.PromptColor);
|
|||
|
S := SSData;
|
|||
|
repeat
|
|||
|
S^.Display;
|
|||
|
S := S^.Next;
|
|||
|
until S = nil;
|
|||
|
end; { ProgramObject.DisplayAll }
|
|||
|
|
|||
|
function ProgramObject.AddSheet(Name : PathStr) : Boolean;
|
|||
|
{ Add a new spreadsheet }
|
|||
|
var
|
|||
|
A, S : SpreadsheetPtr;
|
|||
|
Good, AllocatingNext : Boolean;
|
|||
|
begin
|
|||
|
AddSheet := False;
|
|||
|
if TotalSheets = MaxSpreadsheets then
|
|||
|
Exit;
|
|||
|
S := SSData;
|
|||
|
while (S <> nil) and (S^.Next <> nil) do
|
|||
|
S := S^.Next;
|
|||
|
if SSData <> nil then
|
|||
|
begin
|
|||
|
A := S;
|
|||
|
New(S^.Next);
|
|||
|
S := S^.Next;
|
|||
|
AllocatingNext := True;
|
|||
|
end
|
|||
|
else begin
|
|||
|
New(S);
|
|||
|
AllocatingNext := False;
|
|||
|
end;
|
|||
|
if S = nil then
|
|||
|
Exit;
|
|||
|
if Name = '' then
|
|||
|
Good := S^.Init(0, DefaultMaxCols, DefaultMaxRows,
|
|||
|
DefaultMaxDecimalPlaces, DefaultDefaultDecimalPlaces,
|
|||
|
DefaultDefaultColWidth)
|
|||
|
else
|
|||
|
Good := S^.FromFile(Name);
|
|||
|
if not Good then
|
|||
|
begin
|
|||
|
Dispose(S);
|
|||
|
if AllocatingNext then
|
|||
|
A^.Next := nil;
|
|||
|
Exit;
|
|||
|
end;
|
|||
|
if SSData = nil then
|
|||
|
SSData := S;
|
|||
|
if CurrSS <> nil then
|
|||
|
CurrSS^.Current := False;
|
|||
|
CurrSS := S;
|
|||
|
Inc(TotalSheets);
|
|||
|
S^.Next := nil;
|
|||
|
AddSheet := True;
|
|||
|
end; { ProgramObject.AddSheet }
|
|||
|
|
|||
|
procedure ProgramObject.DeleteSheet;
|
|||
|
{ Delete a spreadsheet }
|
|||
|
var
|
|||
|
S : SpreadsheetPtr;
|
|||
|
begin
|
|||
|
if TotalSheets > 1 then
|
|||
|
begin
|
|||
|
S := SSData;
|
|||
|
if S = CurrSS then
|
|||
|
SSData := S^.Next
|
|||
|
else begin
|
|||
|
while S^.Next <> CurrSS do
|
|||
|
S := S^.Next;
|
|||
|
S^.Next := S^.Next^.Next;
|
|||
|
end;
|
|||
|
end;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
CheckForSave;
|
|||
|
Done;
|
|||
|
end; { with }
|
|||
|
if TotalSheets > 1 then
|
|||
|
begin
|
|||
|
FreeMem(CurrSS, SizeOf(Spreadsheet));
|
|||
|
Dec(TotalSheets);
|
|||
|
CurrSS := SSData;
|
|||
|
end
|
|||
|
else
|
|||
|
CurrSS^.Init(0, DefaultMaxCols, DefaultMaxRows,
|
|||
|
DefaultMaxDecimalPlaces, DefaultDefaultDecimalPlaces,
|
|||
|
DefaultDefaultColWidth);
|
|||
|
SetDisplayAreas;
|
|||
|
DisplayAll;
|
|||
|
with CurrSS^ do
|
|||
|
begin
|
|||
|
MakeCurrent;
|
|||
|
DisplayCell(CurrPos);
|
|||
|
end; { with }
|
|||
|
end; { ProgramObject.DeleteSheet }
|
|||
|
|
|||
|
procedure InitMenus;
|
|||
|
{ Initialize the menu items }
|
|||
|
var
|
|||
|
Good : Boolean;
|
|||
|
P : Word;
|
|||
|
begin
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
with MainMenu do
|
|||
|
begin
|
|||
|
Init(MainMenuString, nil);
|
|||
|
Good := AddItemMenu(@SpreadsheetMenu);
|
|||
|
Good := AddItemMenu(@BlockMenu);
|
|||
|
Good := AddItemMenu(@ColumnMenu);
|
|||
|
Good := AddItemMenu(@RowMenu);
|
|||
|
Good := AddItemProc(FormatCell);
|
|||
|
Good := AddItemProc(GotoCell);
|
|||
|
Good := AddItemProc(EditCell);
|
|||
|
Good := AddItemMenu(@UtilityMenu);
|
|||
|
Good := AddItemProc(Quit);
|
|||
|
end; { with }
|
|||
|
with SpreadsheetMenu do
|
|||
|
begin
|
|||
|
Init(SpreadsheetMenuString, @MainMenu);
|
|||
|
Good := AddItemProc(Replacespreadsheet);
|
|||
|
Good := AddItemProc(SaveCurrSpreadsheet);
|
|||
|
Good := AddItemProc(ZapSpreadsheet);
|
|||
|
Good := AddItemProc(NameSaveSpreadsheet);
|
|||
|
Good := AddItemMenu(@OpenMenu);
|
|||
|
Good := AddItemProc(CloseSpreadsheet);
|
|||
|
Good := AddItemProc(NextSpreadsheet);
|
|||
|
Good := AddItemProc(PrintSpreadsheet);
|
|||
|
end; { with }
|
|||
|
with OpenMenu do
|
|||
|
begin
|
|||
|
Init(OpenMenuString, @SpreadsheetMenu);
|
|||
|
Good := AddItemProc(NewSpreadsheet);
|
|||
|
Good := AddItemProc(NewBlankSpreadsheet);
|
|||
|
end; { with }
|
|||
|
with BlockMenu do
|
|||
|
begin
|
|||
|
Init(BlockMenuString, @MainMenu);
|
|||
|
Good := AddItemProc(CopyBlock);
|
|||
|
Good := AddItemProc(DeleteBlock);
|
|||
|
Good := AddItemProc(FormatBlock);
|
|||
|
Good := AddItemProc(FormatDefault);
|
|||
|
end; { with }
|
|||
|
with ColumnMenu do
|
|||
|
begin
|
|||
|
Init(ColumnMenuString, @MainMenu);
|
|||
|
Good := AddItemProc(ColInsert);
|
|||
|
Good := AddItemProc(ColDelete);
|
|||
|
Good := AddItemProc(ChangeColWidth);
|
|||
|
end; { with }
|
|||
|
with RowMenu do
|
|||
|
begin
|
|||
|
Init(RowMenuString, @MainMenu);
|
|||
|
Good := AddItemProc(RowInsert);
|
|||
|
Good := AddItemProc(RowDelete);
|
|||
|
end; { with }
|
|||
|
with UtilityMenu do
|
|||
|
begin
|
|||
|
if Scr.VideoType >= MCGA then
|
|||
|
begin
|
|||
|
Init(UtilityMenuString1, @MainMenu);
|
|||
|
Good := AddItemProc(ToggleMaxLines);
|
|||
|
end
|
|||
|
else
|
|||
|
Init(UtilityMenuString2, @MainMenu);
|
|||
|
Good := AddItemProc(Recalc);
|
|||
|
Good := AddItemProc(ToggleFormulas);
|
|||
|
Good := AddItemProc(ToggleAutoCalc);
|
|||
|
end; { with }
|
|||
|
end; { with }
|
|||
|
end; { InitMenus }
|
|||
|
|
|||
|
procedure Run;
|
|||
|
{ The main part of the program - it sets up the spreadsheets, reads commands,
|
|||
|
and them releases all of the memory that it used }
|
|||
|
begin
|
|||
|
SetCursor(NoCursor);
|
|||
|
with Vars do
|
|||
|
begin
|
|||
|
Init;
|
|||
|
GetCommands;
|
|||
|
Done;
|
|||
|
end;
|
|||
|
end; { Run }
|
|||
|
|
|||
|
begin
|
|||
|
CheckBreak := False;
|
|||
|
FreeMin := FreeListItems shl 3;
|
|||
|
HeapError := @RunHeapError;
|
|||
|
end.
|
|||
|
|