| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582 |
- {*************************************************************************}
- { MicroCalc Module 000 }
- { Last Modified : 7-22-85 }
- { }
- { Purpose : Miscellaneous utilities and commands. }
- { }
- {*************************************************************************}
- procedure Help; forward; { procedure Help is forward declared in the int- }
- { erest of keeping all miscellaneous routines }
- { grouped in one module. }
- { procedure Center centers the string passed as the paramater on the }
- { screen. NOTE : This routine assumes an 80 column screen. }
- procedure Center(S : AnyString);
- var
- I : Integer;
- begin
- for I := 1 to ((80-Length(S)) div 2) do
- Write(' '); {Fill beginning of line with spaces based on the length(S)}
- writeln(S);
- end; { end Sub-procedure Center }
- { procedure Welcome says Welcome and activates the help procedure if the }
- { user presses any key other than Carriage Return. }
- procedure Welcome;
- begin { procedure Welcome }
- ClrScr;
- GotoXY(1,9);
- Center('Welcome to MicroCalc. A Turbo Pascal demonstration program');
- Center('Press any key for help or <RETURN> to start');
- GotoXY(40,12);
- Read(Kbd,Ch);
- { If Ch entered does not equal a carriage return then call Help routine.}
- if Ch <> ^M then Help;
- end; { end procedure Welcome }
- { procedure Msg outputs the string, passed in as a paramater, to the }
- { screen. }
- procedure Msg(S : AnyString);
- begin
- GotoXY(1,24);
- ClrEol;
- Write(S);
- ClrEol;
- end; { End procedure Msg }
- { The procedure Flash causes the string input as a paramater to flash by }
- { alternately writeing it to the screen in LowVideo and NormVideo. }
- { NOTES :
- 1. procedure Flash allows you to specify the column in which
- the string will be written. A possible extension of the
- routine could be to allow the user to specify the row also.
- 2. By setting the blink paramater to true or false the string
- will flash or not flash. If Blink is true the string will
- Flash until a key is pressed.
- 3. Upon exit of the procedure, the string will be written in
- LowVideo regardless of the value of Blink }
- procedure Flash(X : Integer; S : AnyString; Blink : boolean);
- begin
- NormVideo;
- GotoXY(X,23);
- Write(S);
- if Blink then { Check value of Blink, if true then execute the repeat }
- begin { until loop. }
- repeat
- GotoXY(X,23);
- Blink := not Blink; { By modifying the value of Blink after }
- if Blink then { each iteration of the loop, we can use }
- NormVideo { Blink's value as a test for the appro- }
- else { priate Video attribute value. }
- LowVideo;
- Write(S);
- Delay(175);
- until KeyPressed;
- end;
- LowVideo;
- end; { End procedure Flash }
- { procedure IBMCh determines the extended scan code read in and returns }
- { a one character interpolation of the characters read in. }
- 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; { End procedure IBMCh }
- procedure Auto; { Toggles automatic calculation mode on and off }
- begin
- AutoCalc:=not AutoCalc;
- if AutoCalc then Flash(60,'AutoCalc: ON ',false)
- else Flash(60,'AutoCalc: OFF',false);
- end;
- {*************************************************************************}
- { MicroCalc Module 001 }
- { Last Modified 7-22-85 }
- { }
- { Purpose : initialize Spread sheet, redraw screen, and clear current }
- { spread sheet }
- { }
- {*************************************************************************}
- { procedure Grid Displays the entire spread sheet grid and command line. }
- procedure Grid;
- var
- I : Integer;
- Count : Char;
- begin
- NormVideo;
- For Count := 'A' to FXMax do { Display Column Names (A..FXMax) }
- begin
- GotoXY(XPos[Count],1);
- Write(Count);
- end;
- GotoXY(1,2);
- for I := 1 to FYMax do { Display Row numbers (1..FYMax) }
- writeln(I:2);
- LowVideo;
- if AutoCalc then { Display Status line }
- Flash(60,'AutoCalc: ON' ,false)
- else
- Flash(60,'AutoCalc: OFF',false);
- Flash(33,' Type / for Commands',false);
- end; { End procedure Grid }
- { procedure Init initializes the values of each of the cells in the grid. }
- { NOTE : Initializing variables in TURBO PASCAL is very important. }
- procedure Init;
- var
- I : ColumnName;
- J : Integer;
- LastName : string[2];
- begin
- for I := 'A' to FXMAX do { Traverse grid Column by Column - Row }
- begin { by Row, initializing each cell }
- for J := 1 to FYMAX do
- begin
- with Sheet[I,J] do { Access record representing this cell }
- begin
- CellStatus := [Txt]; { Default cell attribute }
- Contents := ''; { Value of default cell attribute }
- Value := 0; { Default value of numeric field }
- DEC := 2; { Default number of decimals }
- FW := 10; { Default field width }
- end;
- end;
- end;
- AutoCalc := True; { AutoCalc defaults to True or ON }
- FX:='A'; FY:=1; { Field A1 is default current field }
- end; { End procedure Init }
- { procedure Clear clears the current worksheet. }
- procedure Clear;
- begin
- NormVideo;
- 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; { End procedure Clear }
- {*************************************************************************}
- { MicroCalc Module 002 }
- { Last Modified 7-22-85 }
- { }
- { Purpose : Cursor movement whithin the spread sheet }
- { }
- {*************************************************************************}
- { procedure DisplayType outputs the current cell it's type and if the }
- { cell's type is a formula the formula is also output. }
- procedure DisplayType;
- begin
- with Sheet[FX,FY] do
- begin
- GotoXY(1,23);
- Write(FX,FY:2,' ');
- if Formula in CellStatus then { Determine Type of Cell }
- 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; { End procedure DisplayType }
- {*************************************************************************}
- { 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 goes to the cell indicated by the procedures }
- { paramaters and outputs it's current value. }
- procedure GotoCell(GX: ColumnName; GY: Integer);
- begin
- with Sheet[GX,GY] do { Get specified record (i.e. cell) }
- begin
- NormVideo;
- GotoXY(XPos[GX],GY+1); { Go to leftmost column of specified cell }
- Write(' '); { Clear the cell }
- GotoXY(XPos[GX],GY+1);
- if Txt in CellStatus then
- Write(Contents)
- else { cell does not contain text }
- begin
- if DEC >= 0 then { check if number of decimal spaces is }
- Write(Value:FW:DEC) { specified else output in scientific }
- else { notation. }
- Write(Value:FW);
- end;
- DisplayType;
- GotoXY(XPos[GX],GY+1);
- end;
- LowVideo;
- end;
- { procedure LeaveCell simply writes the current cell's contents in }
- { LowVideo. }
- procedure LeaveCell(FX : ColumnName; FY : Integer);
- begin
- with Sheet[FX,FY] do { Get record representing current cell }
- 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; { End procedure LeaveCell }
- procedure Update;
- var
- UFX : ColumnName;
- 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;
- { procedure MoveDown updates the current cell by calling procedure }
- { LeaveCell. It then moves the cursor down on position. Note : The repeat }
- { loop in this routine does the actuall moving of the cursor. A valid cell}
- { must be found before the cursor can be moved. The cell is valid if it's }
- { CellStatus is not in [OverWritten,Locked] . }
- 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; { End procedure MoveDown }
- { procedure MoveUp updates the current cell, then moves the cursor up one }
- { position. The note for the last procedure applies here also. }
- 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; { End procedure MoveUp }
- { procedure MoveRight acts the same as the previous two procedures with }
- { the exception of the direction it moves the cursor. }
- procedure MoveRight;
- var
- Start : ColumnName;
- 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; { End procedure MoveRight }
- { procedure MoveLeft acts the same as the previous three procedures with }
- { the exception of the direction it moves the cursor. }
- procedure MoveLeft;
- var
- Start : ColumnName;
- 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; { End procedure MoveLeft }
- {*************************************************************************}
- { MicroCalc Module 003 }
- { Last Modified : 7-22-85 }
- { }
- { PURPOSE: Load, Save and Print a spread sheet. }
- { Display on-line manual. }
- {*************************************************************************}
- { function Exist returns a boolean value indicating the existence of
- the file passed in as a paramater. }
- function Exist(FileN : AnyString): boolean;
- var
- F : file;
- begin
- {$I-}
- assign(F,FileN);
- reset(F);
- {$I+}
- if IOResult <> 0 then
- Exist := false
- else
- begin
- Exist := true;
- close(F);
- end;
- end; { End function Exist }
- { Procedure GetFileName reads a filename input by the user. The
- filename's extension is passed in as the second paramater of the
- procedure.
- Note : As the procedure stands, the user can not use path names. }
- Procedure GetFileName(var Line : AnyString; FileType : String3);
- var
- i : Integer;
- begin
- Line := '';
- Read(Line);
- clreol;
- if Length(Line) > 8 then
- begin
- clreol;
- Line[0] := chr(8);
- Msg('Filename Truncated to : ' + Line);
- end;
- for i := 1 to Length(Line) do
- begin
- Line[i] := UpCase(Line[i]);
- if not (Line[i] in ['A'..'Z','0'..'9'
- (*,'!','#'..')','-',',','/','@','\','_','`','{','}'*)
- ]) then
- Msg('Invalid Filename');
- end;
- if Line <> '' then
- Line := Line + '.' + FileType;
- end; { End Procedure GetFileName }
- { Procedure Save saves the current spreadsheet to a file.
- Note : this routine attaches the extension 'MCS' to the filename. }
- Procedure Save;
- var
- I : ColumnName;
- J : Integer;
- begin
- NormVideo;
- Msg('Save: Enter filename ');
- GetFileName(Filename,'MCS');
- if FileName <> '' then
- begin
- Assign(MCFile,FileName);
- Rewrite(MCFile);
- for I := 'A' to FXmax do
- for J := 1 to FYmax do
- write(MCfile,Sheet[I,J]);
- Grid;
- Close(MCFile);
- LowVideo;
- GotoCell(FX,FY);
- end;
- end; { End Procedure Save }
- { Procedure Load loads a spreadsheet from a file.
- Note : the procedure gives the user two chances to enter the
- correct filename. }
- Procedure Load;
- begin
- NormVideo;
- Msg('Load: Enter filename ');
- GetFileName(Filename,'MCS'); { Get filename }
- if (Filename <> '') then { Check if filename is legal }
- if (not exist(FileName)) then { if filename not legal then }
- repeat { prompt the user again. }
- 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 { Read records from file }
- for FY := 1 to FYmax do
- read(MCFile,Sheet[FX,FY]);
- FX := 'A';
- FY := 1;
- LowVideo;
- UpDate;
- end;
- GotoCell(FX,FY);
- end; { End Procedure Load }
- { Procedure Print prints the current spreadsheet to a file.
- Note : a possible improvement might be to allow the user to specify
- not only the left margin of the paper, but also the width
- of the paper. Also allowing output to go directly to the
- printer. }
- Procedure Print;
- var
- I : ColumnName;
- J, Count,
- LeftMargin : Integer;
- P : string[20];
- MCFile : Text;
- begin
- NormVideo;
- Msg('Print: Enter filename "P" for Printer> ');
- GetFileName(Filename,'LST');
- Msg('Left margin > ');
- Read(LeftMargin);
- if FileName = 'P.LST' then
- FileName := 'LST';
- 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 if not (Locked in CellStatus) then }
- end { End if or then }
- else
- Line := Line + Contents;
- end; { End With Statement }
- end; { End For Loop - have gotten one line }
- For Count := 1 to LeftMargin do { Insert left margin }
- Write(MCFile,' ');
- writeln(MCFile,Line);
- end; { End for loop - move to next line }
- Grid;
- Close(MCFile);
- LowVideo;
- GotoCell(FX,FY);
- end; { End Procedure Print }
- { Procedure Help dislpays the help file CALC.HLP for the user. }
- Procedure Help;
- type
- str80 = string[80];
- Pages = array[0..200] of str80;
- var
- H : text;
- Line : string[80];
- LineCounter, EndOfFile, ErrorResult, BeginPage,
- J : Integer;
- Bold : boolean;
- Buffer : ^Pages;
- Procedure DisplayMessage;
- begin
- GotoXY(6,24);
- NormVideo;
- write('Press ');
- LowVideo;
- Write('`P`');
- NormVideo;
- Write(' for previous page ');
- LowVideo;
- Write('`N`');
- NormVideo;
- Write(' for next,');
- LowVideo;
- Write('`Esc`');
- NormVideo;
- Write(' to exit Help file.');
- end;
- { Procedure GetPages reads the help file from disk into an array of a }
- { dynamicly allocated array. NOTE : the number of lines read in is kept }
- { in the zero'th index of the array. }
- Procedure GetPages;
- var
- st : string[10];
- count : integer;
- begin
- count := 1;
- Assign(H,'CALC.HLP');
- Reset(H);
- while not Eof(H) do
- begin
- Readln(H,Buffer^[count]);
- count := count + 1;
- end;
- close(H);
- Str(count,st);
- Buffer^[0] := st;
- end;
- begin
- LineCounter := 1; { Initialize line counter}
- if Exist('CALC.HLP') then
- begin
- New(Buffer); { Allocate dynamic array }
- GetPages; { Read in Help File }
- Val(Buffer^[0],EndOfFile,ErrorResult); { EndOfFile := # of Lines}
- while LineCounter < EndOfFile do
- begin
- BeginPage := LineCounter - 1;
- if BeginPage < 1 then { If Previous page is called while on }
- BeginPage := 1; { first page, Beginpage is off by 1. }
- ClrScr;
- Bold := false;
- LowVideo;
- Line := Buffer^[LineCounter]; { Get first line of current page. }
- { This while loop steps through the array looking for the end of }
- { page indicator '.PA', writing out each line as it goes. }
- while (LineCounter < EndOfFile) and (Line <> '.PA') do
- begin
- Write(' ');
- For J := 1 to Length(Line) do
- begin
- if Line[J] = ^B then { Check for bold face type }
- begin
- Bold := not Bold; { Toggle Bold type }
- if Bold then
- NormVideo
- else
- LowVideo;
- end
- else
- write(Line[J]);
- end; { End for loop - have written entire line }
- Writeln;
- LineCounter := LineCounter + 1;
- Line := Buffer^[LineCounter]; { Get next line }
- end; { end while }
- DisplayMessage;
- repeat
- read(Kbd,Ch);
- until Upcase(Ch) in ['P','N',#27];
- case UpCase(Ch) of
- 'P' : begin { Get start of previous page }
- repeat
- BeginPage := BeginPage - 1;
- until (Buffer^[BeginPage] = '.PA') or (BeginPage < 1);
- LineCounter := BeginPage + 1;
- end;
- 'N' : LineCounter := LineCounter + 1; { Get start of next page }
- #27 : LineCounter := EndOfFile; { force counter to end of file }
- end;
- end; { end while }
- Dispose(Buffer); { Deallocate dynamic array }
- UpDate; { Return to Spread Sheet }
- end { End if then statement }
- 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; { End procedure Help }
- {*************************************************************************}
- { MicroCalc Module 004 }
- { Last Modified 7-22-85 }
- { }
- { PURPOSE: Evaluate formulas. }
- { Recalculate spread sheet. }
- { }
- { NOTE: This module contains recursive procedures }
- {*************************************************************************}
- {$A-}
- { procedure NextCh returns the next Character in the formula of the cell }
- { currently being evaluated. }
- procedure NextCh(var Position : Integer;
- var NextChar : Char;
- Formula : AnyString);
- begin
- repeat
- Position := Position + 1;
- if Position <= Length(Formula) then
- NextChar := Formula[Position]
- else
- NextChar := eofline;
- until NextChar <> ' ';
- end; { End procedure NextCh }
- { procedure Evaluate evaluates a string passed to it, the string }
- { represents an expression or formula. }
- procedure Evaluate(var IsFormula : Boolean;
- var Formula : AnyString;
- var Value : Real;
- var ErrorPosition : Integer);
- var
- Position : Integer; { Current position in formula }
- EvalCh : Char; { Current Character being scanned }
- EXY : string[3]; { Intermediate string for conversion }
- function Expression(var ExpressionCh : Char):Real;forward;
- { Sub-function Fact returns the factorial value of the integer passed in}
- { as it's paramater. }
- function Fact(I : Real): Real;
- {WARNING: This program will not compile using TURBO-87.COM unless you
- have an 8087 math coprocessor installed in your computer. Use TURBO.
- COM to compile}
- begin
- if ((I > 0.0) and (I < 34.0)) then { check if value is in legal range.}
- Fact := I * Fact(I - 1) { Fact(34) is out of range. }
- else
- Fact := 1.0;
- end; { End sub-function Fact }
- { function Factor is the meat of procedure Evaluate. Within this pro- }
- { -cedure the current subexpression is actualy evaluated. Using nested }
- { If-Then-Else statements, the function determines if the sub-expression}
- { is a number, the sum of a subrange of cells (i.e A1>A5), or a }
- { function(i.e.ABS(X) ). }
- function Factor(var FactorCh : Char): Real;
- type
- { Declare a set of the standard functions }
- Standardfunction =
- (fabs,fsqrt,fsqr,fsin,fcos,farctan,fln,flog,fexp,ffact);
- { Declare array with indices being the Standard function names. }
- StandardfunctionList = array[Standardfunction] of string[6];
- const
- { Declare Typed Constant array initializing it with function names }
- StandardfunctionNames : StandardfunctionList =
- ('ABS','SQRT','SQR','SIN','COS','ARCTAN','LN','LOG','EXP','FACT');
- var
- E, EE, L : Integer; { temporary variables }
- Found : Boolean; { boolean value - expression found or not }
- CellSum, F : Real; { F holds value returned by recursive }
- { calls to Factor }
- Sf : Standardfunction;
- OldExpFY, { ExpEFX and ExpFY hold the positions of }
- ExpFY, { the cells referenced to in any formulas }
- SumFY, { SumFX and SumFY hold the sum to be }
- Start : Integer; { calculated at the fromula's position }
- OldExpFX, ExpFX, SumFX : ColumnName;
- begin { begin main block of function Factor }
- F := -1;
- if FactorCh in Numbers then { Get integer or real number }
- begin
- Start := Position; { Save first position of number in string }
- repeat { Skip to non number character }
- NextCh(Position,FactorCh,Formula);
- until not (FactorCh in Numbers);
- if FactorCh = '.' then { is decimal point }
- repeat
- NextCh(Position,FactorCh,Formula);
- until not (FactorCh in Numbers);
- if FactorCh = 'E' then { is Exponent symbol }
- begin
- NextCh(Position,FactorCh,Formula);
- repeat
- NextCh(Position,FactorCh,Formula)
- until not (FactorCh in Numbers);
- end;
- { Get value of number }
- Val(Copy(Formula,Start,Position - Start),F,ErrorPosition);
- if FactorCh = ')' then
- NextCh(Position,FactorCh,Formula);
- end { end if FactorCh in Numbers }
- else { FactorCh not a number }
- if FactorCh = '(' then
- begin
- NextCh(Position,FactorCh,Formula);
- F := Expression(FactorCh);
- if FactorCh = ')' then {if matching paren is found then read next }
- NextCh(Position,FactorCh,Formula)
- else { else there is an error in the expression. }
- ErrorPosition := Position;
- end { End if FactorCh = '(' }
- else { else FactorCh <> Number or '('}
- {FactorCh may be a cell reference or function name or a function name }
- if FactorCh in ['A'..'G','L','S'] then
- begin
- ExpFX := FactorCh;
- NextCh(Position,FactorCh,Formula);
- if FactorCh in Numbers then
- begin
- F := 0;
- EXY := FactorCh;
- NextCh(Position,FactorCh,Formula);
- if FactorCh in Numbers then
- begin
- EXY := EXY + FactorCh;
- NextCh(Position,FactorCh,Formula);
- end;
- Val(EXY,ExpFY,ErrorPosition);
- IsFormula := true; { the expression is a formula }
- { Check if content of the cell referenced in the formula is a }
- { constant. If so then verify that it has been calculated. If the }
- { constant has been calculated then make a recursive call to the }
- { procedure Evaluate to evaluate the contents of the cell. }
- if (Constant in Sheet[ExpFX,ExpFY].CellStatus) and
- not (Calculated in Sheet[ExpFX,ExpFY].CellStatus) then
- begin
- Evaluate(Form,Sheet[ExpFX,ExpFY].contents,f,ErrorPosition);
- { Update CellStatus to indicate that the cells value has been }
- { calculated. }
- Sheet[ExpFX,ExpFY].CellStatus :=
- Sheet[ExpFX,ExpFY].CellStatus + [Calculated]
- end { End if ... and not ... Statement }
- { The cell refered to either didn't contain a constant or the }
- { constants value was already calculated. }
- else { If the contents of the cell are not text then they must be }
- { a constant. }
- if not (Txt in Sheet[ExpFX,ExpFY].CellStatus) then
- F := Sheet[ExpFX,ExpFY].Value;
- if FactorCh = '>' then { Check for formula range designator }
- begin
- OldExpFX := ExpFX;
- OldExpFY := ExpFY;
- NextCh(Position,FactorCh,Formula);
- ExpFX := FactorCh;
- NextCh(Position,FactorCh,Formula);
- if FactorCh in Numbers then
- begin
- EXY := FactorCh;
- NextCh(Position,FactorCh,Formula);
- if FactorCh in Numbers then
- begin
- EXY := EXY + FactorCh;
- NextCh(Position,FactorCh,Formula);
- end;
- if FactorCh = ')' then
- NextCh(Position,FactorCh,Formula);
- val(EXY,ExpFY,ErrorPosition);
- Cellsum := 0;
- { visit each cell specified in sub-range of formula }
- for SumFY := OldExpFY to ExpFY do
- begin
- for SumFX := OldExpFX to ExpFX do
- begin
- F := 0;
- { Note that the next few statements are identical to the }
- { statements about fifty lines back. }
- if (Constant in Sheet[SumFX,SumFY].CellStatus) and
- not (Calculated in Sheet[SumFX,SumFY].CellStatus) then
- begin
- Evaluate(Form,Sheet[SumFX,SumFY].contents,f,ErrorPosition);
- 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; { for SumFX := OldExpFX to ExpFX do }
- end; { for SumFY := OldExpFY to ExpFY do }
- end; { if FactorCh in Numbers then }
- end { if FactorCh = '>' then }
- else { FactorCh = ')' }
- if FactorCh = ')' then
- begin
- NextCh(Position,FactorCh,Formula);
- found := true;
- end;
- end { if FactorCh in Numbers then }
- else {FactorCh is second letter in function name (i.e. ABS or LN )}
- begin
- found := false;
- for sf := fabs to ffact do { step through all possible func's }
- if not found then
- begin
- l := Length(StandardfunctionNames[sf]);
- if copy(Formula,Position - 1,l) = StandardfunctionNames[sf] then
- begin
- Position := Position + l - 1;
- NextCh(Position,FactorCh,Formula);
- F := Expression(FactorCh);
- case sf of
- fabs : f := abs(f);
- fsqrt : begin
- if f > 0 then
- f := sqrt(f) { WARNING: This progam will not
- compile with TURBOBCD.COM. (Sqrt,
- Sin, and similar operations are
- not implemented in the BCD
- version.) Use TURBO.COM to
- compile. }
- else
- F := -1;
- end;
- fsqr : begin
- if Abs(f) < Sqrt(exp(38) * ln(1)) then
- f := sqr(f)
- else
- F := -1;
- end;
- fsin : f := sin(f);
- fcos : f := cos(f);
- farctan : f := arctan(f);
- fln : f := ln(f);
- flog : f := ln(f)/ln(10);
- fexp : begin
- if abs(f) < 89 then { Exp(+/-89) will cause }
- f := exp(f) { floating point Overflow. }
- else
- f := -1;
- end;
- ffact : f := fact(int(f));
- end; { end case }
- Found := true;
- end; { if then Statement }
- end; { if not found Statement }
- if not Found then
- ErrorPosition := Position;
- end; { else statement }
- end; { if FactorCh in ['A'..'G'] then }
- Factor := F;
- end; { End Sub-function Factor}
- { Sub-function Signed Factor first determines the sign of the exp- }
- { -ression. It then calls the function Factor to get the value of the }
- { expression. }
- function SignedFactor(var SignedCh : Char):Real;
- begin { begin main block of procedure SignedFactor }
- if SignedCh = '-' then
- begin
- NextCh(Position,SignedCh,Formula);
- SignedFactor := -Factor(SignedCh);
- end
- else
- SignedFactor := Factor(SignedCh);
- end; { End Sub-function SignedFactor }
- { Sub-function Term returns the value of the sub-expression being eval- }
- { -uated. If the expression contains an exponent expression Term eval- }
- { -uates it. }
- function Term(var TermCh : Char):Real;
- var
- T : Real;
- begin { begin main block of procedure Term }
- T := SignedFactor(TermCh);
- while TermCh = '^' do
- begin
- NextCh(Position,TermCh,Formula);
- T := exp(ln(t) * SignedFactor(TermCh));
- end;
- Term := T;
- end; { End Sub-function Term }
- { Sub-function SimpleExpression calls the function term and evaluates }
- { the simple expression returned. }
- function SimpleExpression(var SimpleExpCh : Char):Real;
- var
- SimpExp : Real;
- Opr : Char;
- begin { begin main block of procedure SimpleExpression }
- SimpExp := Term(SimpleExpCh);
- while SimpleExpCh in ['*','/'] do
- begin
- Opr := SimpleExpCh;
- NextCh(Position,SimpleExpCh,Formula);
- case Opr of
- '*' : SimpExp := SimpExp * term(SimpleExpCh);
- '/' : SimpExp := SimpExp / term(SimpleExpCh);
- end;
- end;
- SimpleExpression := SimpExp;
- end; { End Sub-function SimpleExpression }
- { Sub-function Expression evaluates the expression contained in the }
- { current cell. }
- function Expression{(var ExpressionCh : Char):Real;forward};
- var
- E : Real;
- Opr : Char;
- begin { begin main block of function Expression }
- E := SimpleExpression(ExpressionCh);
- while ExpressionCh in ['+','-'] do
- begin
- Opr := ExpressionCh;
- NextCh(Position,ExpressionCh,Formula);
- case Opr of
- '+' : E := E +
- SimpleExpression(ExpressionCh);
- '-' : E := E -
- SimpleExpression(ExpressionCh);
- end;
- end;
- Expression := E;
- end; { End Sub-function Expression }
- begin { main body of procedure Evaluate }
- if Formula[1] = '.' then
- Formula := '0' + Formula;
- if Formula[1] = '+' then
- delete(Formula,1,1);
- IsFormula := false;
- Position := 0;
- NextCh(Position,EvalCh,Formula);
- Value := Expression(EvalCh);
- if EvalCh = EofLine then
- ErrorPosition := 0
- else
- ErrorPosition := Position;
- end; { End procedure Evaluate }
- { procedure Recalculate steps through the entire spreadsheet recalculating}
- { each cell. }
- procedure Recalculate;
- var
- RFX : ColumnName;
- RFY : Integer;
- OldValue : Real;
- Err : Integer;
- begin
- LowVideo;
- GotoXY(1,24);
- ClrEol;
- Write('Calculating..');
- for RFY := 1 to FYMax do { Reevaluate each cell updating it's }
- begin { contents when appropriate. }
- 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; { End procedure Recalculate }
- {*************************************************************************}
- { MicroCalc Module 005 }
- { Last Modified 7-22-85 }
- { }
- { PURPOSE: Read the contents of a cell and update }
- { associated cells. }
- { }
- {*************************************************************************}
- { procedure GetCell gets the contents of a cell from the user. This }
- { routine gets all input entered by the user. procedure GetCell }
- { initializes the temporary variable "S" with the last read Character. }
- { Depending on this character, it then calls GetFormula, GetText, or }
- { EditCell. }
- procedure GetCell(FX : ColumnName; FY : Integer);
- var
- S : AnyString;
- NewStatus : SetofAttri;
- ErrorPosition : Integer;
- EvalResult : Real;
- I : ColumnName;
- Abort,
- IsForm : Boolean;
- { Sub-procedure ClearCells clears the current cell and its associated }
- { cells. An associated cell is a cell overwritten by data from the cur- }
- { -rent cell. The data can be text in which case the cell has the attri-}
- { -bute "OverWritten". If the data is a result from an expression and }
- { the field width is larger than 11 then the associated cell is }
- { "Locked." }
- procedure ClearCells(FX : ColumnName; FY : Integer);
- var
- I : ColumnName;
- begin
- I := FX;
- repeat
- with Sheet[I,FY] do
- begin
- GotoXY(XPos[I],FY + 1);
- write(' ');
- I := Succ(I);
- end;
- { Cell is not OverWritten not Locked }
- until ([OverWritten,Locked] * Sheet[I,FY].CellStatus = []);
- end; { End Sub-procedure ClearCells }
- { Sub-procedure GetLine is the routine used to get input from the user. }
- { The procedure allows editing of input and checks that the input con- }
- { -tains legal characters. }
- procedure GetLine(ColNO, LineNO, { Where to start line }
- MAX : Integer; { Max length }
- 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 ErrorPosition <> 0 then { there was an error found }
- X := ErrorPosition;
- 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 Char under cursor }
- 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; { Toggle Insert/Overwrite }
- else { Not Upcase }
- 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 { end if Ch in OkChars }
- else
- if Length(S) + 1 <= Max then
- OkChars:= [' '..'}']; { Line ok again }
- end; { end case statement's else }
- end; { end case statement }
- until CH = ^M;
- end; { End Sub-procedure GetLine }
- { Sub-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;
- var
- LineLength : Integer;
- begin
- GotoXY(5,23);
- LowVideo;
- if FX = 'G' then
- LineLength := 10
- else
- LineLength := 70;
- with Sheet[FX,FY] do
- GetLine(XPos[FX],FY+1,LineLength,False);
- end; { End Sub-procedure GetText }
- { Sub-procedure GetFormula calls the routine GetLine to get a line from }
- { the user. It then calls the routine Evaluate to evaluate the Formula }
- { input by the user. }
- procedure GetFormula;
- begin
- GotoXY(5,23);
- LowVideo;
- repeat
- GetLine(1,24,70,True);
- if S <> Chr($FF) then
- begin
- Evaluate(IsForm,S,EvalResult ,ErrorPosition);
- if ErrorPosition <> 0 then
- Flash(15,'GetFormula Error at cursor' + ^G,false)
- else
- Flash(15,'get formula ok',false);
- end;
- until (ErrorPosition = 0) or (S = Chr($FF));
- if IsForm then
- NewStatus := NewStatus + [Formula];
- end; { End Sub-procedure GetFormula }
- { Sub-procedure EditCell loads a copy of the current cell's contents }
- { into the variable S before calling either GetText or GetFormula. In }
- { this way no changes are actually made to the current cell. }
- procedure EditCell;
- begin
- GotoXY(5,23);
- with Sheet[FX,FY] do
- begin
- S := Contents;
- if Txt in CellStatus then
- GetText
- else
- GetFormula;
- end;
- end; { End procedure EditCell }
- { Sub-procedure UpdateCells is a little more complicated. Basically it }
- { makes sure to tag and untag cells which have been overwritten or }
- { cleared by data from another cell. It also updates the current cell }
- { with the new type and contents which are still in the temporary }
- { variable "S". }
- procedure UpdateCells;
- var
- I : ColumnName;
- Flength : Integer;
- begin
- Sheet[FX,FY].Contents := S;
- if Txt in NewStatus then
- begin
- I := FX;
- FLength := Length(S);
- repeat { this repeat loop checks the status of adjoining cells to }
- { verify that they have or have not been overwritten. }
- 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; { if OverWritten in CellStatus }
- end; { else }
- end; { with Sheet[I,FY] do }
- until (I = FXMax) or (Sheet[I,FY].Contents <> '');
- Sheet[FX,FY].CellStatus := [Txt];
- end
- else { string changed to formula or constant }
- begin
- I := FX;
- repeat { this repeat loop checks whether or not the cell is }
- { overwritten. }
- 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 := EvalResult ;
- end; { with }
- end; { else }
- end; { End Sub-procedure UpdateCells }
- begin { begin main block of procedure GetCell }
- S := Ch;
- ErrorPosition := 0;
- Abort := false;
- NewStatus := [];
- EvalResult := -1;
- if Ch in ['0'..'9','+','-','.','(',')'] then
- begin
- NewStatus := [Constant];
- if not (Formula in Sheet[FX,FY].CellStatus) then
- begin
- GotoXY(11,24);
- ClrEol;
- ClearCells(FX,FY);
- GetFormula;
- end
- else { Formula in Sheet[FX,FY].CellStatus }
- 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
- begin
- EditCell;
- end
- Else
- Abort := true;
- end;
- end
- else { Ch not in ['0'..'9','+','-','.','(',')'] }
- begin
- if Ch = ^[ then
- begin
- NewStatus := (Sheet[FX,FY].CellStatus) * [Txt,Constant];
- EditCell;
- end
- else { Ch <> '^[' and not in ['0'..'9','+','-','.','(',')'] }
- 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
- begin
- EditCell;
- end
- Else
- Abort := true;
- end
- else { formula not in Sheet[FX,FY].CellStatus }
- begin
- NewStatus := [Txt];
- ClearCells(FX,FY);
- GetText;
- end; { End else }
- end; { end else }
- end; { end else }
- if not Abort then { do neccesary bookkeeping }
- begin
- if S <> Chr($FF) then
- UpDateCells;
- GotoCell(FX,FY);
- if AutoCalc and (Constant in Sheet[FX,FY].CellStatus) then
- Recalculate;
- if Txt in NewStatus then
- begin
- GotoXY(3,FY + 1);
- Clreol;
- For I := 'A' to FXMax do
- LeaveCell(I,FY);
- end;
- end; { end if not abort }
- Flash(15,' ',False);
- GotoCell(FX,FY);
- end; { End procedure GetCell }
- { procedure Format is used to modify the numeric format of a range of }
- { cells in the current column. }
- procedure Format;
- var
- J, FW, DEC,
- FromLine, ToLine : Integer;
- Lock : Boolean;
- { procedure GetInt reads an integer from the keyboard screening it for }
- { illegal characters. }
- procedure GetInt(var I: Integer; Max: Integer);
- var
- S : String[8];
- Result : 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,Result);
- end;
- until (I >= Max) or (Ch = ^M);
- if I > Max then I := Max;
- end; { End Subprocedure GetInt }
- begin
- NormVideo;
- Msg('Format: Enter number of places beyond decimal point (Max 11) : ');
- GetInt(DEC,11);
- Msg('Enter Cell width (if larger than 10 next column will be locked) : ');
- 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 { Format specified cells within }
- begin { current column. }
- 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 With Statement }
- end; { End For Loop }
- NormVideo;
- UpDate;
- GotoCell(FX,FY);
- end; { End procedure Format }
- { Procedure Commands is called from the program's main loop when the user }
- { types a slash '/'. The procedure in turn calls the appropriate procedure}
- { based on the users response to the menu displayed. }
- { }
- { 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);
- NormVideo;
- Write('Update, Quit, Load, Save, Recalculate, Print, Format, AutoCalc, Help ');
- ClrEol;
- Read(KBD,Ch);
- Ch := UpCase(Ch);
- case Ch of { module # }
- 'Q': Halt; { Halt execution of program }
- 'F': Format; { Format a range of cells 005 }
- 'S': Save; { Save the current spreadsheet to a file 003 }
- 'L': Load; { Load a spreadsheet from a file 003 }
- 'H': Help; { Call the Help procedure 003 }
- 'R': Recalculate; { Recalculate spreadsheet 005 }
- 'A': Auto; { Toggle AutoCalc On or Off 000 }
- 'U': Update; { Redraw the screen 001 }
- 'C': Clear; { Clear screen of spreadsheet 001 }
- 'P': Print; { Print spreadsheet to a file 003 }
- end;
- Grid; { 001 }
- GotoCell(FX,FY); { 002 }
- end; { End Procedure Commands }
|