1259 lines
33 KiB
Plaintext
1259 lines
33 KiB
Plaintext
|
|
|||
|
|
|||
|
{ This program is hereby donated to the public domain }
|
|||
|
{ for non commercial use only }
|
|||
|
|
|||
|
{Here is a note to the compiler: }
|
|||
|
{$R-,U-,V-,X-,C-}
|
|||
|
|
|||
|
program MicroCalc;
|
|||
|
|
|||
|
const
|
|||
|
FXMax: Char = 'G'; { Maximum number of columns in spread sheet }
|
|||
|
FYMax = 21; { Maximum number of lines in spread sheet }
|
|||
|
|
|||
|
type
|
|||
|
Anystring = string[70];
|
|||
|
SheetIndex = 'A'..'G';
|
|||
|
Attributes = (Constant,Formula,Txt,OverWritten,Locked,Calculated);
|
|||
|
|
|||
|
{ The spreadsheet is made out of Cells every Cell is defined as }
|
|||
|
{ the following record:}
|
|||
|
|
|||
|
CellRec = record
|
|||
|
CellStatus: set of Attributes; { Status of cell (see type def.) }
|
|||
|
Contents: String[70]; { Contains a formula or some text }
|
|||
|
Value: Real; { Last calculated cell value }
|
|||
|
DEC,FW: 0..20; { Decimals and Cell Whith }
|
|||
|
end;
|
|||
|
|
|||
|
Cells = array[SheetIndex,1..FYMax] of CellRec;
|
|||
|
|
|||
|
const
|
|||
|
XPOS: array[SheetIndex] of integer = (3,14,25,36,47,58,68);
|
|||
|
|
|||
|
var
|
|||
|
Sheet: Cells; { Definition of the spread sheet }
|
|||
|
FX: SheetIndex; { Culumn of current cell }
|
|||
|
FY: Integer; { Line of current cell }
|
|||
|
Ch: Char; { Last read character }
|
|||
|
MCFile: file of CellRec; { File to store sheets in }
|
|||
|
AutoCalc: boolean; { Recalculate after each entry? }
|
|||
|
|
|||
|
|
|||
|
{ For easy reference the procedures and functions are grouped in mo-}
|
|||
|
{ dules called MC-MOD00 through MC-MOD05. }
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD00 *}
|
|||
|
{* PURPOSE: Micellaneous utilities and commands. *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
|
|||
|
procedure Msg(S: AnyString);
|
|||
|
begin
|
|||
|
GotoXY(1,24);
|
|||
|
ClrEol;
|
|||
|
Write(S);
|
|||
|
end;
|
|||
|
|
|||
|
procedure Flash(X: integer; S: AnyString; Blink: boolean);
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
GotoXY(X,23);
|
|||
|
Write(S);
|
|||
|
if Blink then
|
|||
|
begin
|
|||
|
repeat
|
|||
|
GotoXY(X,23);
|
|||
|
Blink:=not Blink; if Blink then HighVideo else LowVideo;
|
|||
|
Write(S);
|
|||
|
Delay(175);
|
|||
|
until KeyPressed;
|
|||
|
end;
|
|||
|
LowVideo;
|
|||
|
end;
|
|||
|
|
|||
|
procedure IBMCh(var Ch: Char);
|
|||
|
begin
|
|||
|
case Ch of
|
|||
|
'H': Ch:=^E;
|
|||
|
'P': Ch:=^X;
|
|||
|
'M': Ch:=^D;
|
|||
|
'K': Ch:=^S;
|
|||
|
'S': Ch:=#127;
|
|||
|
'R': Ch:=^V;
|
|||
|
'G',
|
|||
|
'I',
|
|||
|
'O',
|
|||
|
'Q': Ch:=#00;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
procedure Auto;
|
|||
|
begin
|
|||
|
AutoCalc:=not AutoCalc;
|
|||
|
if AutoCalc then Flash(60,'AutoCalc: ON ',false)
|
|||
|
else Flash(60,'AutoCalc: OFF',false);
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD01 *}
|
|||
|
{* PURPOSE: Display grid and initialize all cells *}
|
|||
|
{* in the spread sheet. *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
procedure Grid;
|
|||
|
var I: integer;
|
|||
|
Count: Char;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
For Count:='A' to FXMax do
|
|||
|
begin
|
|||
|
GotoXY(XPos[Count],1);
|
|||
|
Write(Count);
|
|||
|
end;
|
|||
|
GotoXY(1,2);
|
|||
|
for I:=1 to FYMax do writeln(I:2);
|
|||
|
LowVideo;
|
|||
|
if AutoCalc then Flash(60,'AutoCalc: ON' ,false)
|
|||
|
else Flash(60,'AutoCalc: OFF',false);
|
|||
|
Flash(33,' Type / for Commands',false);
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
procedure Init;
|
|||
|
var
|
|||
|
I: SheetIndex;
|
|||
|
J: Integer;
|
|||
|
LastName: string[2];
|
|||
|
begin
|
|||
|
for I:='A' to FXMAX do
|
|||
|
begin
|
|||
|
for J:=1 to FYMAX do
|
|||
|
begin
|
|||
|
with Sheet[I,J] do
|
|||
|
begin
|
|||
|
CellStatus:=[Txt];
|
|||
|
Contents:='';
|
|||
|
Value:=0;
|
|||
|
DEC:=2; { Default number of decimals }
|
|||
|
FW:=10; { Default field width }
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
AutoCalc:=True;
|
|||
|
FX:='A'; FY:=1; { First field in upper left corner }
|
|||
|
end;
|
|||
|
|
|||
|
procedure Clear;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
GotoXY(1,24); ClrEol;
|
|||
|
Write('Clear this worksheet? (Y/N) ');
|
|||
|
repeat Read(Kbd,Ch) until Upcase(Ch) in ['Y','N'];
|
|||
|
Write(Upcase(Ch));
|
|||
|
if UpCase(Ch)='Y' then
|
|||
|
begin
|
|||
|
ClrScr;
|
|||
|
Init;
|
|||
|
Grid;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD02 *}
|
|||
|
{* PURPOSE: Display values in cells and move between *}
|
|||
|
{* cells in the spread sheet. *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
|
|||
|
procedure FlashType;
|
|||
|
begin
|
|||
|
with Sheet[FX,FY] do
|
|||
|
begin
|
|||
|
GotoXY(1,23);
|
|||
|
Write(FX,FY:2,' ');
|
|||
|
if Formula in CellStatus then write('Formula:') else
|
|||
|
if Constant in CellStatus then Write('Numeric ') else
|
|||
|
if Txt in CellStatus then Write('Text ');
|
|||
|
GotoXY(1,24); ClrEol;
|
|||
|
if Formula in CellStatus then Write(Contents);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{ The following procedures move between the Cells on the calc sheet.}
|
|||
|
{ Each Cell has an associated record containing its X,Y coordinates }
|
|||
|
{ and data. See the type definition for "Cell". }
|
|||
|
|
|||
|
procedure GotoCell(GX: SheetIndex; GY: integer);
|
|||
|
begin
|
|||
|
with Sheet[GX,GY] do
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
GotoXY(XPos[GX],GY+1);
|
|||
|
Write(' ');
|
|||
|
GotoXY(XPos[GX],GY+1);
|
|||
|
if Txt in CellStatus then Write(Contents)
|
|||
|
else
|
|||
|
begin
|
|||
|
if DEC>=0 then Write(Value:FW:DEC)
|
|||
|
else Write(Value:FW);
|
|||
|
end;
|
|||
|
FlashType;
|
|||
|
GotoXY(XPos[GX],GY+1);
|
|||
|
end;
|
|||
|
LowVideo;
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure LeaveCell(FX:SheetIndex;FY: integer);
|
|||
|
begin
|
|||
|
with Sheet[FX,FY] do
|
|||
|
begin
|
|||
|
GotoXY(XPos[FX],FY+1);
|
|||
|
LowVideo;
|
|||
|
if Txt in CellStatus then Write(Contents)
|
|||
|
else
|
|||
|
begin
|
|||
|
if DEC>=0 then Write(Value:FW:DEC)
|
|||
|
else Write(Value:FW);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure Update;
|
|||
|
var
|
|||
|
UFX: SheetIndex;
|
|||
|
UFY: integer;
|
|||
|
begin
|
|||
|
ClrScr;
|
|||
|
Grid;
|
|||
|
for UFX:='A' to FXMax do for UFY:=1 to FYMax do
|
|||
|
if Sheet[UFX,UFY].Contents<>'' then LeaveCell(UFX,UFY);
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure MoveDown;
|
|||
|
var Start: integer;
|
|||
|
begin
|
|||
|
LeaveCell(FX,FY);
|
|||
|
Start:=FY;
|
|||
|
repeat
|
|||
|
FY:=FY+1;
|
|||
|
if FY>FYMax then FY:=1;
|
|||
|
until (Sheet[FX,FY].CellStatus*[OverWritten,Locked]=[]) or (FY=Start);
|
|||
|
if FY<>Start then GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure MoveUp;
|
|||
|
var Start: integer;
|
|||
|
begin
|
|||
|
LeaveCell(FX,FY);
|
|||
|
Start:=FY;
|
|||
|
repeat
|
|||
|
FY:=FY-1;
|
|||
|
if FY<1 then FY:=FYMax;
|
|||
|
until (Sheet[FX,FY].CellStatus*[OverWritten,Locked]=[]) or (FY=Start);
|
|||
|
if FY<>Start then GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure MoveRight;
|
|||
|
var Start: SheetIndex;
|
|||
|
begin
|
|||
|
LeaveCell(FX,FY);
|
|||
|
Start:=FX;
|
|||
|
repeat
|
|||
|
FX:=Succ(FX);
|
|||
|
if FX>FXMax then
|
|||
|
begin
|
|||
|
FX:='A';
|
|||
|
FY:=FY+1;
|
|||
|
if FY>FYMax then FY:=1;
|
|||
|
end;
|
|||
|
until (Sheet[FX,FY].CellStatus*[OverWritten,Locked]=[]) or (FX=Start);
|
|||
|
if FX<>Start then GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure MoveLeft;
|
|||
|
var Start: SheetIndex;
|
|||
|
begin
|
|||
|
LeaveCell(FX,FY);
|
|||
|
Start:=FX;
|
|||
|
repeat
|
|||
|
FX:=Pred(FX);
|
|||
|
if FX<'A' then
|
|||
|
begin
|
|||
|
FX:=FXMax;
|
|||
|
FY:=FY-1;
|
|||
|
if FY<1 then FY:=FYMax;
|
|||
|
end;
|
|||
|
until (Sheet[FX,FY].CellStatus*[OverWritten,Locked]=[]) or (FX=Start);
|
|||
|
if FX<>Start then GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD03 *}
|
|||
|
{* PURPOSE: Read, Save and Print a spread sheet. *}
|
|||
|
{* Display on-line manual. *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
type
|
|||
|
String3 = string[3];
|
|||
|
|
|||
|
var
|
|||
|
FileName: string[14];
|
|||
|
Line: string[100];
|
|||
|
|
|||
|
function Exist(FileN: AnyString): boolean;
|
|||
|
var F: file;
|
|||
|
begin
|
|||
|
{$I-}
|
|||
|
assign(F,FileN);
|
|||
|
reset(F);
|
|||
|
{$I+}
|
|||
|
if IOResult<>0 then Exist:=false
|
|||
|
else Exist:=true;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
procedure GetFileName(var Line: AnyString; FileType:String3);
|
|||
|
begin
|
|||
|
Line:='';
|
|||
|
repeat
|
|||
|
Read(Kbd,Ch);
|
|||
|
if Upcase(Ch) in ['A'..'Z',^M] then
|
|||
|
begin
|
|||
|
write(Upcase(Ch));
|
|||
|
Line:=Line+Ch;
|
|||
|
end;
|
|||
|
until (Ch=^M) or (length(Line)=8);
|
|||
|
if Ch=^M then Delete(Line,Length(Line),1);
|
|||
|
if Line<>'' then Line:=Line+'.'+FileType;
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
|
|||
|
procedure Save;
|
|||
|
var I: SheetIndex;
|
|||
|
J: integer;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
Msg('Save: Enter filename ');
|
|||
|
GetFileName(Filename,'MCS');
|
|||
|
if FileName<>'' then
|
|||
|
begin
|
|||
|
Assign(MCFile,FileName);
|
|||
|
Rewrite(MCFile);
|
|||
|
for I:='A' to FXmax do
|
|||
|
begin
|
|||
|
for J:=1 to FYmax do
|
|||
|
write(MCfile,Sheet[I,J]);
|
|||
|
end;
|
|||
|
Grid;
|
|||
|
Close(MCFile);
|
|||
|
LowVideo;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
{.CP30}
|
|||
|
|
|||
|
procedure Load;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
Msg('Load: Enter filename ');
|
|||
|
GetFileName(Filename,'MCS');
|
|||
|
if (Filename<>'') then if (not exist(FileName)) then
|
|||
|
repeat
|
|||
|
Msg('File not Found: Enter another filename ');
|
|||
|
GetFileName(Filename,'MCS');
|
|||
|
until exist(FileName) or (FileName='');
|
|||
|
if FileName<>'' then
|
|||
|
begin
|
|||
|
ClrScr;
|
|||
|
Msg('Please Wait. Loading definition...');
|
|||
|
Assign(MCFile,FileName);
|
|||
|
Reset(MCFile);
|
|||
|
for FX:='A' to FXmax do
|
|||
|
for FY:=1 to FYmax do read(MCFile,Sheet[FX,FY]);
|
|||
|
FX:='A'; FY:=1;
|
|||
|
LowVideo;
|
|||
|
UpDate;
|
|||
|
end;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
|
|||
|
procedure Print;
|
|||
|
var
|
|||
|
I: SheetIndex;
|
|||
|
J,Count,
|
|||
|
LeftMargin: Integer;
|
|||
|
P: string[20];
|
|||
|
MCFile: Text;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
Msg('Print: Enter filename "P" for Printer> ');
|
|||
|
GetFileName(Filename,'LST');
|
|||
|
Msg('Left margin > '); Read(LeftMargin);
|
|||
|
if FileName='P.LST' then FileName:='Printer';
|
|||
|
Msg('Printing to: ' + FileName + '....');
|
|||
|
Assign(MCFile,FileName);
|
|||
|
Rewrite(MCFile);
|
|||
|
For Count:=1 to 5 do Writeln(MCFile);
|
|||
|
for J:=1 to FYmax do
|
|||
|
begin
|
|||
|
Line:='';
|
|||
|
for I:='A' to FXmax do
|
|||
|
begin
|
|||
|
with Sheet[I,J] do
|
|||
|
begin
|
|||
|
while (Length(Line)<XPOS[I]-4) do Line:=Line+' ';
|
|||
|
if (Constant in CellStatus) or (Formula in CellStatus) then
|
|||
|
begin
|
|||
|
if not (Locked in CellStatus) then
|
|||
|
begin
|
|||
|
if DEC>0 then Str(Value:FW:DEC,P) else Str(Value:FW,P);
|
|||
|
Line:=Line+P;
|
|||
|
end;
|
|||
|
end else Line:=Line+Contents;
|
|||
|
end; { With }
|
|||
|
end; { One line }
|
|||
|
For Count:=1 to LeftMargin do Write(MCFile,' ');
|
|||
|
writeln(MCFile,Line);
|
|||
|
end; { End Column }
|
|||
|
Grid;
|
|||
|
Close(MCFile);
|
|||
|
LowVideo;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.PA}
|
|||
|
|
|||
|
procedure Help;
|
|||
|
var
|
|||
|
H: text;
|
|||
|
Line: string[80];
|
|||
|
J: integer;
|
|||
|
Bold: boolean;
|
|||
|
|
|||
|
begin
|
|||
|
if Exist('CALC.HLP') then
|
|||
|
begin
|
|||
|
Assign(H,'CALC.HLP');
|
|||
|
Reset(H);
|
|||
|
while not Eof(H) do
|
|||
|
begin
|
|||
|
ClrScr; Bold:=false; LowVideo;
|
|||
|
Readln(H,Line);
|
|||
|
repeat
|
|||
|
Write(' ');
|
|||
|
For J:=1 to Length(Line) do
|
|||
|
begin
|
|||
|
if Line[J]=^B then
|
|||
|
begin
|
|||
|
Bold:=not Bold;
|
|||
|
if Bold then HighVideo else LowVideo;
|
|||
|
end else write(Line[J]);
|
|||
|
end;
|
|||
|
Writeln;
|
|||
|
Readln(H,Line);
|
|||
|
until Eof(H) or (Copy(Line,1,3)='.PA');
|
|||
|
GotoXY(26,24); HighVideo;
|
|||
|
write('<<< Please press any key to continue >>>');
|
|||
|
LowVideo;
|
|||
|
read(Kbd,Ch);
|
|||
|
end;
|
|||
|
GotoXY(20,24); HighVideo;
|
|||
|
write('<<< Please press <RETURN> to start MicroCalc >>>');
|
|||
|
LowVideo;
|
|||
|
Readln(Ch);
|
|||
|
UpDate;
|
|||
|
end else { Help file did not exist }
|
|||
|
begin
|
|||
|
Msg('To get help the file CALC.HLP must be on your disk. Press <RETURN>');
|
|||
|
repeat Read(kbd,Ch) until Ch=^M;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD04 *}
|
|||
|
{* PURPOSE: Evaluate formulas. *}
|
|||
|
{* Recalculate spread sheet. *}
|
|||
|
{* *}
|
|||
|
{* NOTE: This module contains recursive procedures *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
var
|
|||
|
Form: Boolean;
|
|||
|
|
|||
|
{$A-}
|
|||
|
procedure Evaluate(var IsFormula: Boolean; { True if formula}
|
|||
|
var Formula: AnyString; { Fomula to evaluate}
|
|||
|
var Value: Real; { Result of formula }
|
|||
|
var ErrPos: Integer);{ Position of error }
|
|||
|
const
|
|||
|
Numbers: set of Char = ['0'..'9'];
|
|||
|
EofLine = ^M;
|
|||
|
|
|||
|
var
|
|||
|
Pos: Integer; { Current position in formula }
|
|||
|
Ch: Char; { Current character being scanned }
|
|||
|
EXY: string[3]; { Intermidiate string for conversion }
|
|||
|
|
|||
|
{ Procedure NextCh returns the next character in the formula }
|
|||
|
{ The variable Pos contains the position ann Ch the character }
|
|||
|
|
|||
|
procedure NextCh;
|
|||
|
begin
|
|||
|
repeat
|
|||
|
Pos:=Pos+1;
|
|||
|
if Pos<=Length(Formula) then
|
|||
|
Ch:=Formula[Pos] else Ch:=eofline;
|
|||
|
until Ch<>' ';
|
|||
|
end { NextCh };
|
|||
|
|
|||
|
|
|||
|
function Expression: Real;
|
|||
|
var
|
|||
|
E: Real;
|
|||
|
Opr: Char;
|
|||
|
|
|||
|
function SimpleExpression: Real;
|
|||
|
var
|
|||
|
S: Real;
|
|||
|
Opr: Char;
|
|||
|
|
|||
|
function Term: Real;
|
|||
|
var
|
|||
|
T: Real;
|
|||
|
|
|||
|
function SignedFactor: Real;
|
|||
|
|
|||
|
function Factor: Real;
|
|||
|
type
|
|||
|
StandardFunction = (fabs,fsqrt,fsqr,fsin,fcos,
|
|||
|
farctan,fln,flog,fexp,ffact);
|
|||
|
StandardFunctionList = array[StandardFunction] of string[6];
|
|||
|
|
|||
|
const
|
|||
|
StandardFunctionNames: StandardFunctionList =('ABS','SQRT','SQR','SIN','COS',
|
|||
|
'ARCTAN','LN','LOG','EXP','FACT');
|
|||
|
var
|
|||
|
E,EE,L: Integer; { intermidiate variables }
|
|||
|
Found:Boolean;
|
|||
|
F: Real;
|
|||
|
Sf:StandardFunction;
|
|||
|
OldEFY, { Current cell }
|
|||
|
EFY,
|
|||
|
SumFY,
|
|||
|
Start:Integer;
|
|||
|
OldEFX,
|
|||
|
EFX,
|
|||
|
SumFX:SheetIndex;
|
|||
|
CellSum: Real;
|
|||
|
|
|||
|
function Fact(I: Integer): Real;
|
|||
|
begin
|
|||
|
if I > 0 then begin Fact:=I*Fact(I-1); end
|
|||
|
else Fact:=1;
|
|||
|
end { Fact };
|
|||
|
|
|||
|
{.PA}
|
|||
|
begin { Function Factor }
|
|||
|
if Ch in Numbers then
|
|||
|
begin
|
|||
|
Start:=Pos;
|
|||
|
repeat NextCh until not (Ch in Numbers);
|
|||
|
if Ch='.' then repeat NextCh until not (Ch in Numbers);
|
|||
|
if Ch='E' then
|
|||
|
begin
|
|||
|
NextCh;
|
|||
|
repeat NextCh until not (Ch in Numbers);
|
|||
|
end;
|
|||
|
Val(Copy(Formula,Start,Pos-Start),F,ErrPos);
|
|||
|
end else
|
|||
|
if Ch='(' then
|
|||
|
begin
|
|||
|
NextCh;
|
|||
|
F:=Expression;
|
|||
|
if Ch=')' then NextCh else ErrPos:=Pos;
|
|||
|
end else
|
|||
|
if Ch in ['A'..'G'] then { Maybe a cell reference }
|
|||
|
begin
|
|||
|
EFX:=Ch;
|
|||
|
NextCh;
|
|||
|
if Ch in Numbers then
|
|||
|
begin
|
|||
|
F:=0;
|
|||
|
EXY:=Ch; NextCh;
|
|||
|
if Ch in Numbers then
|
|||
|
begin
|
|||
|
EXY:=EXY+Ch;
|
|||
|
NextCh;
|
|||
|
end;
|
|||
|
Val(EXY,EFY,ErrPos);
|
|||
|
IsFormula:=true;
|
|||
|
if (Constant in Sheet[EFX,EFY].CellStatus) and
|
|||
|
not (Calculated in Sheet[EFX,EFY].CellStatus) then
|
|||
|
begin
|
|||
|
Evaluate(Form,Sheet[EFX,EFY].contents,f,ErrPos);
|
|||
|
Sheet[EFX,EFY].CellStatus:=Sheet[EFX,EFY].CellStatus+[Calculated]
|
|||
|
end else if not (Txt in Sheet[EFX,EFY].CellStatus) then
|
|||
|
F:=Sheet[EFX,EFY].Value;
|
|||
|
if Ch='>' then
|
|||
|
begin
|
|||
|
OldEFX:=EFX; OldEFY:=EFY;
|
|||
|
NextCh;
|
|||
|
EFX:=Ch;
|
|||
|
NextCh;
|
|||
|
if Ch in Numbers then
|
|||
|
begin
|
|||
|
EXY:=Ch;
|
|||
|
NextCh;
|
|||
|
if Ch in Numbers then
|
|||
|
begin
|
|||
|
EXY:=EXY+Ch;
|
|||
|
NextCh;
|
|||
|
end;
|
|||
|
val(EXY,EFY,ErrPos);
|
|||
|
Cellsum:=0;
|
|||
|
for SumFY:=OldEFY to EFY do
|
|||
|
begin
|
|||
|
for SumFX:=OldEFX to EFX do
|
|||
|
begin
|
|||
|
F:=0;
|
|||
|
if (Constant in Sheet[SumFX,SumFY].CellStatus) and
|
|||
|
not (Calculated in Sheet[SumFX,SumFY].CellStatus) then
|
|||
|
begin
|
|||
|
Evaluate(Form,Sheet[SumFX,SumFY].contents,f,errPos);
|
|||
|
Sheet[SumFX,SumFY].CellStatus:=
|
|||
|
Sheet[SumFX,SumFY].CellStatus+[Calculated];
|
|||
|
end else if not (Txt in Sheet[SumFX,SumFY].CellStatus) then
|
|||
|
F:=Sheet[SumFX,SumFY].Value;
|
|||
|
Cellsum:=Cellsum+f;
|
|||
|
f:=Cellsum;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end else
|
|||
|
begin
|
|||
|
found:=false;
|
|||
|
for sf:=fabs to ffact do
|
|||
|
if not found then
|
|||
|
begin
|
|||
|
l:=Length(StandardFunctionNames[sf]);
|
|||
|
if copy(Formula,Pos,l)=StandardFunctionNames[sf] then
|
|||
|
begin
|
|||
|
Pos:=Pos+l-1; NextCh;
|
|||
|
F:=Factor;
|
|||
|
case sf of
|
|||
|
fabs: f:=abs(f);
|
|||
|
fsqrt: f:=sqrt(f);
|
|||
|
fsqr: f:=sqr(f);
|
|||
|
fsin: f:=sin(f);
|
|||
|
fcos: f:=cos(f);
|
|||
|
farctan: f:=arctan(f);
|
|||
|
fln : f:=ln(f);
|
|||
|
flog: f:=ln(f)/ln(10);
|
|||
|
fexp: f:=exp(f);
|
|||
|
ffact: f:=fact(trunc(f));
|
|||
|
end;
|
|||
|
Found:=true;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if not Found then ErrPos:=Pos;
|
|||
|
end;
|
|||
|
Factor:=F;
|
|||
|
end { function Factor};
|
|||
|
{.PA}
|
|||
|
|
|||
|
begin { SignedFactor }
|
|||
|
if Ch='-' then
|
|||
|
begin
|
|||
|
NextCh; SignedFactor:=-Factor;
|
|||
|
end else SignedFactor:=Factor;
|
|||
|
end { SignedFactor };
|
|||
|
|
|||
|
begin { Term }
|
|||
|
T:=SignedFactor;
|
|||
|
while Ch='^' do
|
|||
|
begin
|
|||
|
NextCh; t:=exp(ln(t)*SignedFactor);
|
|||
|
end;
|
|||
|
Term:=t;
|
|||
|
end { Term };
|
|||
|
|
|||
|
|
|||
|
begin { SimpleExpression }
|
|||
|
s:=term;
|
|||
|
while Ch in ['*','/'] do
|
|||
|
begin
|
|||
|
Opr:=Ch; NextCh;
|
|||
|
case Opr of
|
|||
|
'*': s:=s*term;
|
|||
|
'/': s:=s/term;
|
|||
|
end;
|
|||
|
end;
|
|||
|
SimpleExpression:=s;
|
|||
|
end { SimpleExpression };
|
|||
|
|
|||
|
begin { Expression }
|
|||
|
E:=SimpleExpression;
|
|||
|
while Ch in ['+','-'] do
|
|||
|
begin
|
|||
|
Opr:=Ch; NextCh;
|
|||
|
case Opr of
|
|||
|
'+': e:=e+SimpleExpression;
|
|||
|
'-': e:=e-SimpleExpression;
|
|||
|
end;
|
|||
|
end;
|
|||
|
Expression:=E;
|
|||
|
end { Expression };
|
|||
|
|
|||
|
|
|||
|
begin { procedure Evaluate }
|
|||
|
if Formula[1]='.' then Formula:='0'+Formula;
|
|||
|
if Formula[1]='+' then delete(Formula,1,1);
|
|||
|
IsFormula:=false;
|
|||
|
Pos:=0; NextCh;
|
|||
|
Value:=Expression;
|
|||
|
if Ch=EofLine then ErrPos:=0 else ErrPos:=Pos;
|
|||
|
end { Evaluate };
|
|||
|
|
|||
|
{.PA}
|
|||
|
|
|||
|
procedure Recalculate;
|
|||
|
var
|
|||
|
RFX: SheetIndex;
|
|||
|
RFY:integer;
|
|||
|
OldValue: real;
|
|||
|
Err: integer;
|
|||
|
|
|||
|
begin
|
|||
|
LowVideo;
|
|||
|
GotoXY(1,24); ClrEol;
|
|||
|
Write('Calculating..');
|
|||
|
for RFY:=1 to FYMax do
|
|||
|
begin
|
|||
|
for RFX:='A' to FXMax do
|
|||
|
begin
|
|||
|
with Sheet[RFX,RFY] do
|
|||
|
begin
|
|||
|
if (Formula in CellStatus) then
|
|||
|
begin
|
|||
|
CellStatus:=CellStatus+[Calculated];
|
|||
|
OldValue:=Value;
|
|||
|
Evaluate(Form,Contents,Value,Err);
|
|||
|
if OldValue<>Value then
|
|||
|
begin
|
|||
|
GotoXY(XPos[RFX],RFY+1);
|
|||
|
if (DEC>=0) then Write(Value:FW:DEC)
|
|||
|
else Write(Value:FW);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*******************************************************************}
|
|||
|
{* SOURCE CODE MODULE: MC-MOD05 *}
|
|||
|
{* PURPOSE: Read the contents of a cell and update *}
|
|||
|
{* associated cells. *}
|
|||
|
{*******************************************************************}
|
|||
|
|
|||
|
|
|||
|
procedure GetLine(var S: AnyString; { String to edit }
|
|||
|
ColNO,LineNO, { Where start line }
|
|||
|
MAX, { Max length }
|
|||
|
ErrPos: integer; { Where to begin }
|
|||
|
UpperCase:Boolean); { True if auto Upcase }
|
|||
|
var
|
|||
|
X: integer;
|
|||
|
InsertOn: boolean;
|
|||
|
OkChars: set of Char;
|
|||
|
|
|||
|
|
|||
|
procedure GotoX;
|
|||
|
begin
|
|||
|
GotoXY(X+ColNo-1,LineNo);
|
|||
|
end;
|
|||
|
|
|||
|
begin
|
|||
|
OkChars:=[' '..'}'];
|
|||
|
InsertOn:=true;
|
|||
|
X:=1; GotoX;
|
|||
|
Write(S);
|
|||
|
if Length(S)=1 then X:=2;
|
|||
|
if ErrPos<>0 then X:=ErrPos;
|
|||
|
GotoX;
|
|||
|
repeat
|
|||
|
Read(Kbd,Ch);
|
|||
|
if KeyPressed then
|
|||
|
begin
|
|||
|
Read(kbd,Ch);
|
|||
|
IBMCh(Ch);
|
|||
|
end;
|
|||
|
if UpperCase then Ch:=UpCase(Ch);
|
|||
|
case Ch of
|
|||
|
^[: begin
|
|||
|
S:=chr($FF); { abort editing }
|
|||
|
Ch:=^M;
|
|||
|
end;
|
|||
|
^D: begin { Move cursor right }
|
|||
|
X:=X+1;
|
|||
|
if (X>length(S)+1) or (X>MAX) then X:=X-1;
|
|||
|
GotoX;
|
|||
|
end;
|
|||
|
^G: begin { Delete right char }
|
|||
|
if X<=Length(S) then
|
|||
|
begin
|
|||
|
Delete(S,X,1);
|
|||
|
Write(copy(S,X,Length(S)-X+1),' ');
|
|||
|
GotoX;
|
|||
|
end;
|
|||
|
end;
|
|||
|
^S,^H: begin { Move cursor left }
|
|||
|
X:=X-1;
|
|||
|
if X<1 then X:=1;
|
|||
|
GotoX;
|
|||
|
end;
|
|||
|
^F: begin { Move cursor to end of line }
|
|||
|
X:=Length(S)+1;
|
|||
|
GotoX;
|
|||
|
end;
|
|||
|
^A: begin { Move cursor to beginning of line }
|
|||
|
X:=1;
|
|||
|
GotoX;
|
|||
|
end;
|
|||
|
#127: begin { Delete left char }
|
|||
|
X:=X-1;
|
|||
|
if (Length(S)>0) and (X>0) then
|
|||
|
begin
|
|||
|
Delete(S,X,1);
|
|||
|
Write(copy(S,X,Length(S)-X+1),' ');
|
|||
|
GotoX;
|
|||
|
if X<1 then X:=1;
|
|||
|
end else X:=1;
|
|||
|
end;
|
|||
|
^V: InsertOn:= not InsertOn;
|
|||
|
|
|||
|
{.PA}
|
|||
|
|
|||
|
else
|
|||
|
begin
|
|||
|
if Ch in OkChars then
|
|||
|
begin
|
|||
|
if InsertOn then
|
|||
|
begin
|
|||
|
insert(Ch,S,X);
|
|||
|
Write(copy(S,X,Length(S)-X+1),' ');
|
|||
|
end else
|
|||
|
begin
|
|||
|
write(Ch);
|
|||
|
if X=length(S) then S:=S+Ch
|
|||
|
else S[X]:=Ch;
|
|||
|
end;
|
|||
|
if Length(S)+1<=MAX then X:=X+1
|
|||
|
else OkChars:=[]; { Line too Long }
|
|||
|
GotoX;
|
|||
|
end else
|
|||
|
if Length(S)+1<=Max then
|
|||
|
OkChars:= [' '..'}']; { Line ok again }
|
|||
|
end;
|
|||
|
end;
|
|||
|
until CH=^M;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
|
|||
|
|
|||
|
procedure GetCell(FX: SheetIndex;FY: Integer);
|
|||
|
var
|
|||
|
S: AnyString;
|
|||
|
NewStat: Set of Attributes;
|
|||
|
ErrorPosition: Integer;
|
|||
|
I: SheetIndex;
|
|||
|
Result: Real;
|
|||
|
Abort: Boolean;
|
|||
|
IsForm: Boolean;
|
|||
|
|
|||
|
{ Procedure ClearCells clears the current cell and its associated }
|
|||
|
{ cells. An associated cell is a cell overwritten by data from the }
|
|||
|
{ current cell. The data can be text in which case the cell has the }
|
|||
|
{ attribute "OverWritten". If the data is a result from an expression}
|
|||
|
{ and the field with is larger tahn 11 then the cell is "Locked" }
|
|||
|
|
|||
|
procedure ClearCells;
|
|||
|
begin
|
|||
|
I:=FX;
|
|||
|
repeat
|
|||
|
with Sheet[I,FY] do
|
|||
|
begin
|
|||
|
GotoXY(XPos[I],FY+1);
|
|||
|
write(' '); I:=Succ(I);
|
|||
|
end;
|
|||
|
until ([OverWritten,Locked]*Sheet[I,FY].CellStatus=[]);
|
|||
|
{ Cell is not OVerWritten not Locked }
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
{ The new type of the cell is flashed at the bottom of the Sheet }
|
|||
|
{ Notice that a constant of type array is used to indicate the type }
|
|||
|
|
|||
|
procedure FlashType;
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
GotoXY(5,23);
|
|||
|
LowVideo;
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
procedure GetFormula;
|
|||
|
begin
|
|||
|
FlashType;
|
|||
|
repeat
|
|||
|
GetLine(S,1,24,70,ErrorPosition,True);
|
|||
|
if S<>Chr($FF) then
|
|||
|
begin
|
|||
|
Evaluate(IsForm,S,Result,ErrorPosition);
|
|||
|
if ErrorPosition<>0 then
|
|||
|
Flash(15,'Error at cursor'+^G,false)
|
|||
|
else Flash(15,' ',false);
|
|||
|
end;
|
|||
|
until (ErrorPosition=0) or (S=Chr($FF));
|
|||
|
if IsForm then NewStat:=NewStat+[Formula];
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
{ Procedure GetText calls the procedure GetLine with the current }
|
|||
|
{ cells X,Y position as parameters. This means that text entering }
|
|||
|
{ takes place direcly at the cells position on the Sheet. }
|
|||
|
|
|||
|
procedure GetText;
|
|||
|
begin
|
|||
|
FlashType;
|
|||
|
with Sheet[FX,FY] do GetLine(S,XPos[FX],FY+1,70,ErrorPosition,False);
|
|||
|
end;
|
|||
|
|
|||
|
{.CP20}
|
|||
|
{ Procedure EditCell loads a copy of the current cells contents in }
|
|||
|
{ in the variable S before calling either GetText or GetFormula. In }
|
|||
|
{ this way no changes are made to the current cell. }
|
|||
|
|
|||
|
procedure EditCell;
|
|||
|
begin
|
|||
|
with Sheet[FX,FY] do
|
|||
|
begin
|
|||
|
S:=Contents;
|
|||
|
if Txt in CellStatus then GetText else GetFormula;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
{.PA}
|
|||
|
{ Procedure UpdateCells is a little more complicated. Basically it }
|
|||
|
{ makes sure to tag and untag cells which has been overwritten or }
|
|||
|
{ cleared from data from another cell. It also updates the current }
|
|||
|
{ with the new type and the contents which still is in the temporaly }
|
|||
|
{ variable "S". }
|
|||
|
|
|||
|
|
|||
|
procedure UpdateCells;
|
|||
|
var
|
|||
|
Flength: Integer;
|
|||
|
begin
|
|||
|
Sheet[FX,FY].Contents:=S;
|
|||
|
if Txt in NewStat {Sheet[FX,FY].CellStatus} then
|
|||
|
begin
|
|||
|
I:=FX; FLength:=Length(S);
|
|||
|
repeat
|
|||
|
I:=Succ(I);
|
|||
|
with Sheet[I,FY] do
|
|||
|
begin
|
|||
|
FLength:=Flength-11;
|
|||
|
if (Flength>0) then
|
|||
|
begin
|
|||
|
CellStatus:=[Overwritten,Txt];
|
|||
|
Contents:='';
|
|||
|
end else
|
|||
|
begin
|
|||
|
if OverWritten in CellStatus then
|
|||
|
begin
|
|||
|
CellStatus:=[Txt];
|
|||
|
GotoCell(I,FY);LeaveCell(I,FY);
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
until (I=FXMax) or (Sheet[I,FY].Contents<>'');
|
|||
|
Sheet[FX,FY].CellStatus:=[Txt];
|
|||
|
end else { string changed to formula or constant }
|
|||
|
begin { Event number two }
|
|||
|
I:=FX;
|
|||
|
repeat
|
|||
|
with Sheet[I,FY] do
|
|||
|
begin
|
|||
|
if OverWritten in CellStatus then
|
|||
|
begin
|
|||
|
CellStatus:=[Txt];
|
|||
|
Contents:='';
|
|||
|
end;
|
|||
|
I:=Succ(I);
|
|||
|
end;
|
|||
|
until not (OverWritten in Sheet[I,FY].CellStatus);
|
|||
|
with Sheet[FX,FY] do
|
|||
|
begin
|
|||
|
CellStatus:=[Constant];
|
|||
|
if IsForm then CellStatus:=CellStatus+[Formula];
|
|||
|
Value:=Result;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{ Procedure GetCell finnaly starts here. This procedure uses all }
|
|||
|
{ all the above local procedures. First it initializes the temporaly }
|
|||
|
{ variable "S" with the last read character. It then depending on }
|
|||
|
{ this character calls GetFormula, GetText, or EditCell. }
|
|||
|
|
|||
|
begin { procedure GetCell }
|
|||
|
S:=Ch; ErrorPosition:=0; Abort:=false;
|
|||
|
NewStat:=[];
|
|||
|
if Ch in ['0'..'9','+','-','.','(',')'] then
|
|||
|
begin
|
|||
|
NewStat:=[Constant];
|
|||
|
if not (Formula in Sheet[FX,FY].CellStatus) then
|
|||
|
begin
|
|||
|
GotoXY(11,24); ClrEol;
|
|||
|
ClearCells;
|
|||
|
GetFormula;
|
|||
|
end else
|
|||
|
begin
|
|||
|
Flash(15,'Edit formula Y/N?',true);
|
|||
|
repeat read(Kbd,Ch) until UpCase(CH) in ['Y','N'];
|
|||
|
Flash(15,' ',false);
|
|||
|
if UpCase(Ch)='Y' then EditCell Else Abort:=true;
|
|||
|
end;
|
|||
|
end else
|
|||
|
begin
|
|||
|
if Ch=^[ then
|
|||
|
begin
|
|||
|
NewStat:=(Sheet[FX,FY].CellStatus)*[Txt,Constant];
|
|||
|
EditCell;
|
|||
|
end else
|
|||
|
begin
|
|||
|
if formula in Sheet[FX,FY].CellStatus then
|
|||
|
begin
|
|||
|
Flash(15,'Edit formula Y/N?',true);
|
|||
|
repeat read(Kbd,Ch) until UpCase(CH) in ['Y','N'];
|
|||
|
Flash(15,' ',false);
|
|||
|
if UpCase(Ch)='Y' then EditCell Else Abort:=true;
|
|||
|
end else
|
|||
|
begin
|
|||
|
NewStat:=[Txt];
|
|||
|
ClearCells;
|
|||
|
GetText;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if not Abort then
|
|||
|
begin
|
|||
|
if S<>Chr($FF) then UpDateCells;
|
|||
|
GotoCell(FX,FY);
|
|||
|
if AutoCalc and (Constant in Sheet[FX,FY].CellStatus) then Recalculate;
|
|||
|
if Txt in NewStat then
|
|||
|
begin
|
|||
|
GotoXY(3,FY+1); Clreol;
|
|||
|
For I:='A' to FXMax do
|
|||
|
LeaveCell(I,FY);
|
|||
|
end;
|
|||
|
end;
|
|||
|
Flash(15,' ',False);
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
{.PA}
|
|||
|
{ Procedure Format is used to }
|
|||
|
|
|||
|
|
|||
|
procedure Format;
|
|||
|
var
|
|||
|
J,FW,DEC,
|
|||
|
FromLine,ToLine: integer;
|
|||
|
Lock: Boolean;
|
|||
|
|
|||
|
|
|||
|
procedure GetInt(var I: integer; Max: Integer);
|
|||
|
var
|
|||
|
S: string[8];
|
|||
|
Err: Integer;
|
|||
|
Ch: Char;
|
|||
|
begin
|
|||
|
S:='';
|
|||
|
repeat
|
|||
|
repeat Read(Kbd,Ch) until Ch in ['0'..'9','-',^M];
|
|||
|
if Ch<>^M then
|
|||
|
begin
|
|||
|
Write(Ch); S:=S+Ch;
|
|||
|
Val(S,I,Err);
|
|||
|
end;
|
|||
|
until (I>=Max) or (Ch=^M);
|
|||
|
if I>Max then I:=Max;
|
|||
|
end;
|
|||
|
|
|||
|
begin
|
|||
|
HighVideo;
|
|||
|
Msg('Format: Enter number of decimals (Max 11): ');
|
|||
|
GetInt(DEC,11);
|
|||
|
Msg('Enter Cell whith remember if larger than 10 next column will lock: ');
|
|||
|
GetInt(FW,20);
|
|||
|
Msg('From which line in column '+FX+': ');
|
|||
|
GetInt(FromLine,FYMax);
|
|||
|
Msg('To which line in column '+FX+': ');
|
|||
|
GetInt(ToLine,FYMax);
|
|||
|
if FW>10 then Lock:=true else Lock:=False;
|
|||
|
for J:=FromLine to ToLine do
|
|||
|
begin
|
|||
|
Sheet[FX,J].DEC:=DEC;
|
|||
|
Sheet[FX,J].FW:=FW;
|
|||
|
with Sheet[Succ(FX),J] do
|
|||
|
begin
|
|||
|
if Lock then
|
|||
|
begin
|
|||
|
CellStatus:=CellStatus+[Locked,Txt];
|
|||
|
Contents:='';
|
|||
|
end else CellStatus:=CellStatus-[Locked];
|
|||
|
end;
|
|||
|
end;
|
|||
|
NormVideo;
|
|||
|
UpDate;
|
|||
|
GotoCell(FX,FY);
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*********************************************************************}
|
|||
|
{* START OF MAIN PROGRAM PROCEDURES *}
|
|||
|
{*********************************************************************}
|
|||
|
|
|||
|
|
|||
|
{ Procedure Commands is activated from the main loop in this program }
|
|||
|
{ when the user types a slash (/). a procedure activates a procedure}
|
|||
|
{ which will execute the command. These procedures are located in the}
|
|||
|
{ above modules. }
|
|||
|
|
|||
|
{ For easy reference the source code module number is shown in a }
|
|||
|
{ comment on the right following the procedure call. }
|
|||
|
|
|||
|
procedure Commands;
|
|||
|
begin
|
|||
|
GotoXY(1,24);
|
|||
|
HighVideo;
|
|||
|
Write('/ restore Quit, Load, Save, Recalculate, Print, Format, AutoCalc, Help ');
|
|||
|
Read(Kbd,Ch);
|
|||
|
Ch:=UpCase(Ch);
|
|||
|
case Ch of { In module }
|
|||
|
'Q': Halt;
|
|||
|
'F': Format; { 04 }
|
|||
|
'S': Save; { 03 }
|
|||
|
'L': Load; { 03 }
|
|||
|
'H': Help; { 03 }
|
|||
|
'R': Recalculate; { 05 }
|
|||
|
'A': Auto; { 00 }
|
|||
|
'/': Update; { 01 }
|
|||
|
'C': Clear; { 01 }
|
|||
|
'P': Print; { 03 }
|
|||
|
end;
|
|||
|
Grid; { 01 }
|
|||
|
GotoCell(FX,FY); { 02 }
|
|||
|
end;
|
|||
|
|
|||
|
{ Procedure Hello says hello and activates the help procedure if the }
|
|||
|
{ user presses anything but Return }
|
|||
|
|
|||
|
procedure Welcome;
|
|||
|
|
|||
|
procedure Center(S: AnyString);
|
|||
|
var I: integer;
|
|||
|
begin
|
|||
|
for I:=1 to (80-Length(S)) div 2 do Write(' ');
|
|||
|
writeln(S);
|
|||
|
end;
|
|||
|
|
|||
|
begin { procedure Wellcome }
|
|||
|
ClrScr; GotoXY(1,9);
|
|||
|
Center('Welcome to MicroCalc. A Turbo demonstation program');
|
|||
|
Center('Press any key for help or <RETURN> to start');
|
|||
|
GotoXY(40,12);
|
|||
|
Read(Kbd,Ch);
|
|||
|
if Ch<>^M then Help;
|
|||
|
end;
|
|||
|
|
|||
|
{.PA}
|
|||
|
{*********************************************************************}
|
|||
|
{* THIS IS WHERE THE PROGRAM STARTS EXECUTING *}
|
|||
|
{*********************************************************************}
|
|||
|
|
|||
|
begin
|
|||
|
Init; { 01 }
|
|||
|
Welcome;
|
|||
|
ClrScr; Grid; { 01 }
|
|||
|
GotoCell(FX,FY);
|
|||
|
repeat
|
|||
|
Read(Kbd,Ch);
|
|||
|
if KeyPressed then
|
|||
|
begin
|
|||
|
read(kbd,Ch);
|
|||
|
IBMCh(Ch);
|
|||
|
end;
|
|||
|
case Ch of
|
|||
|
^E: MoveUp; { 02 }
|
|||
|
^X,^J: MoveDown; { 02 }
|
|||
|
^D,^M,^F: MoveRight; { 02 }
|
|||
|
^S,^A: MoveLeft; { 02 }
|
|||
|
'/': Commands;
|
|||
|
^[: GetCell(FX,FY); { 04 }
|
|||
|
else
|
|||
|
if Ch in [' '..'~'] then
|
|||
|
GetCell(FX,FY); { 04 }
|
|||
|
end;
|
|||
|
until true=false; { (program stops in procedure Commands) }
|
|||
|
end.
|
|||
|
|
|||
|
|