home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l044 / 4.ddi / TCALC.ZIP / TCCELL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-10-23  |  62.1 KB  |  1,962 lines

  1.  
  2. { Copyright (c) 1989,90 by Borland International, Inc. }
  3.  
  4. unit TCCell;
  5. { Turbo Pascal 6.0 object-oriented example cell routines.
  6.   This unit is used by TCALC.PAS.
  7.   See TCALC.DOC for an more information about this example.
  8. }
  9.  
  10. {$N+,S-}
  11.  
  12. interface
  13.  
  14. uses Objects, TCUtil, TCLStr, TCScreen, TCHash;
  15.  
  16. const
  17.   DollarString = ' $ ';
  18.   RepeatFirstChar = '\';
  19.   TextFirstChar = ' ';
  20.   EmptyCellName = 'Empty';
  21.   ValueCellName = 'Value';
  22.   TextCellName = 'Text';
  23.   FormulaCellName = 'Formula';
  24.   RepeatCellName = 'Repeat';
  25.   DecPlacesPart = $0F;
  26.   JustShift = 4;
  27.   JustPart = $03;
  28.   DollarPart = $40;
  29.   CommasPart = $80;
  30.   NoMemory = 203;
  31.  
  32. type
  33.   CellTypes = (ClEmpty, ClValue, ClText, ClFormula, ClRepeat);
  34.   CellPos = record
  35.     Col : Word;
  36.     Row : Word;
  37.   end;
  38.   FormatType = Byte;
  39.   Justification = (JLeft, JCenter, JRight);
  40.   DollarStr = String[Length(DollarString)];
  41.   Block = object
  42.     Start, Stop : CellPos;
  43.     constructor Init(InitStart : CellPos);
  44.     function ExtendTo(NewLoc : CellPos) : Boolean;
  45.     function CellInBlock(CheckCell : CellPos) : Boolean;
  46.   end;
  47.   CellHashTablePtr = ^CellHashTable;
  48.   CellPtr = ^Cell;
  49.   CellHashTable = object(HashTable)  { Keeps pointers to all cells }
  50.     CurrCell : CellPtr;    { Information about the cell that is being }
  51.     CurrLoc : CellPos;     { added, deleted, or searched for }
  52.     constructor Init(InitBuckets : BucketRange);
  53.     destructor Done;
  54.     function Add(ACell : CellPtr) : Boolean;
  55.     procedure Delete(DelLoc : CellPos; var DeletedCell : CellPtr);
  56.                            { Removes a cell from the hash table }
  57.     function Search(SPos : CellPos) : CellPtr;
  58.                         { Searches for a cell in the hash table }
  59.     function HashValue : Word; virtual;
  60.                         { Computes the hash value of the cell }
  61.     function Found(Item : HashItemPtr) : Boolean; virtual;
  62.            { Returns True if the hash item being searched for is found }
  63.     procedure CreateItem(var Item : HashItemPtr); virtual;
  64.                         { Fills in the information for a new hash item }
  65.     function ItemSize : HashItemSizeRange; virtual;
  66.     procedure Load(var S : TDosStream; Total : Longint);
  67.     procedure Store(var S : TDosStream);
  68.     function FirstItem : CellPtr;
  69.     function NextItem : CellPtr;
  70.   end;
  71.   FormatHashTable = object(HashTable)
  72.     CurrStart, CurrStop : CellPos;
  73.     CurrFormat : FormatType;
  74.     constructor Init;
  75.     destructor Done;
  76.     function Overwrite(NewStart, NewStop : CellPos) : Boolean;
  77.     function Add(NewStart, NewStop : CellPos;
  78.                  NewFormat : FormatType) : Boolean;
  79.     function Delete(DStart, DStop : CellPos) : Boolean;
  80.     function Search(SPos : CellPos; var F : FormatType) : Boolean;
  81.     function HashValue : Word; virtual;
  82.     function Found(Item : HashItemPtr) : Boolean; virtual;
  83.     procedure CreateItem(var Item : HashItemPtr); virtual;
  84.     function ItemSize : HashItemSizeRange; virtual;
  85.     procedure Load(var S : TDosStream; Total : Longint);
  86.     procedure Store(var S : TDosStream);
  87.   end;
  88.   WidthHashTable = object(HashTable)
  89.     CurrCol : Word;
  90.     CurrWidth : Byte;
  91.     DefaultColWidth : Byte;
  92.     constructor Init(InitBuckets : BucketRange; InitDefaultColWidth : Byte);
  93.     destructor Done;
  94.     function Add(SCol : Word; NewWidth : Byte) : Boolean;
  95.     procedure Delete(Col : Word);
  96.     function Search(Col : Word) : Byte;
  97.     function HashValue : Word; virtual;
  98.     function Found(Item : HashItemPtr) : Boolean; virtual;
  99.     procedure CreateItem(var Item : HashItemPtr); virtual;
  100.     function ItemSize : HashItemSizeRange; virtual;
  101.     function GetDefaultColWidth : Byte;
  102.     procedure Load(var S : TDosStream; Total : Longint);
  103.     procedure Store(var S : TDosStream);
  104.   end;
  105.   OverwriteHashTable = object(HashTable)
  106.     CurrCell : CellPtr;
  107.     CurrPos : CellPos;
  108.     EndCol : Word;
  109.     constructor Init(InitBuckets : BucketRange);
  110.     destructor Done;
  111.     function Add(SCell : CellPtr; Overwritten : Word) : Boolean;
  112.     procedure Delete(SPos : CellPos);
  113.     function Change(SCell : CellPtr; Overwritten : Word) : Boolean;
  114.     function Search(SPos : CellPos) : CellPtr;
  115.     function HashValue : Word; virtual;
  116.     function Found(Item : HashItemPtr) : Boolean; virtual;
  117.     procedure CreateItem(var Item : HashItemPtr); virtual;
  118.     function ItemSize : HashItemSizeRange; virtual;
  119.   end;
  120.   GetColWidthFunc = function(var WHash : WidthHashTable;
  121.                              C : Word) : Byte;
  122.   Cell = object(TObject)
  123.     Loc : CellPos;
  124.     constructor Init(InitLoc : CellPos);
  125.     destructor Done; virtual;
  126.     function CellType : CellTypes; virtual;
  127.     function LegalValue : Boolean; virtual;
  128.     function Name : String; virtual;
  129.     function Format(var FHash : FormatHashTable;
  130.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  131.     function Width(var FHash : FormatHashTable;
  132.                    FormulasDisplayed : Boolean) : Word; virtual;
  133.     function Overwritten(var CHash : CellHashTable;
  134.                          var FHash : FormatHashTable;
  135.                          var WHash : WidthHashTable; var LastPos : CellPos;
  136.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  137.                          FormulasDisplayed : Boolean) : Word; virtual;
  138.     function ShouldUpdate : Boolean; virtual;
  139.     function HasError : Boolean; virtual;
  140.     function CurrValue : Extended; virtual;
  141.     function OverwriteStart(var FHash : FormatHashTable;
  142.                             var WHash : WidthHashTable;
  143.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  144.                             DisplayFormulas : Boolean) : Word; virtual;
  145.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  146.     function DisplayString(FormulasDisplayed : Boolean;
  147.                            MaxDecPlaces : Byte) : String; virtual;
  148.     function FormattedString(var OHash : OverwriteHashTable;
  149.                              var FHash : FormatHashTable;
  150.                              var WHash : WidthHashTable;
  151.                              GetColWidth : GetColWidthFunc;
  152.                              CPos : CellPos; FormulasDisplayed : Boolean;
  153.                              Start : Word; ColWidth : Byte;
  154.                              var DString : DollarStr;
  155.                              var Color : Byte) : String; virtual;
  156.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  157.                         var L : LStringPtr) : LStringPtr; virtual;
  158.   end;
  159.   EmptyCellPtr = ^EmptyCell;
  160.   EmptyCell = object(Cell)
  161.     constructor Init;
  162.     function CellType : CellTypes; virtual;
  163.     function LegalValue : Boolean; virtual;
  164.     function Name : String; virtual;
  165.     function Format(var FHash : FormatHashTable;
  166.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  167.     function Width(var FHash : FormatHashTable;
  168.                    FormulasDisplayed : Boolean) : Word; virtual;
  169.     function Overwritten(var CHash : CellHashTable;
  170.                          var FHash : FormatHashTable;
  171.                          var WHash : WidthHashTable; var LastPos : CellPos;
  172.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  173.                          FormulasDisplayed : Boolean) : Word; virtual;
  174.     function ShouldUpdate : Boolean; virtual;
  175.     function HasError : Boolean; virtual;
  176.     function CurrValue : Extended; virtual;
  177.     function OverwriteStart(var FHash : FormatHashTable;
  178.                             var WHash : WidthHashTable;
  179.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  180.                             DisplayFormulas : Boolean) : Word; virtual;
  181.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  182.     function DisplayString(FormulasDisplayed : Boolean;
  183.                            MaxDecPlaces : Byte) : String; virtual;
  184.     function FormattedString(var OHash : OverwriteHashTable;
  185.                              var FHash : FormatHashTable;
  186.                              var WHash : WidthHashTable;
  187.                              GetColWidth : GetColWidthFunc;
  188.                              CPos : CellPos; FormulasDisplayed : Boolean;
  189.                              Start : Word; ColWidth : Byte;
  190.                              var DString : DollarStr;
  191.                              var Color : Byte) : String; virtual;
  192.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  193.                         var L : LStringPtr) : LStringPtr; virtual;
  194.   end;
  195.   ValueCellPtr = ^ValueCell;
  196.   ValueCell = object(Cell)
  197.     Error : Boolean;
  198.     Value : Extended;      { A cell with a numeric value }
  199.     constructor Init(InitLoc : CellPos; InitError : Boolean;
  200.                      InitValue : Extended);
  201.     function CellType : CellTypes; virtual;
  202.     function LegalValue : Boolean; virtual;
  203.     function Name : String; virtual;
  204.     function Format(var FHash : FormatHashTable;
  205.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  206.     function Width(var FHash : FormatHashTable;
  207.                    FormulasDisplayed : Boolean) : Word; virtual;
  208.     function Overwritten(var CHash : CellHashTable;
  209.                          var FHash : FormatHashTable;
  210.                          var WHash : WidthHashTable; var LastPos : CellPos;
  211.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  212.                          FormulasDisplayed : Boolean) : Word; virtual;
  213.     function ShouldUpdate : Boolean; virtual;
  214.     function HasError : Boolean; virtual;
  215.     function CurrValue : Extended; virtual;
  216.     function OverwriteStart(var FHash : FormatHashTable;
  217.                             var WHash : WidthHashTable;
  218.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  219.                             DisplayFormulas : Boolean) : Word; virtual;
  220.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  221.     function DisplayString(FormulasDisplayed : Boolean;
  222.                            MaxDecPlaces : Byte) : String; virtual;
  223.     function FormattedString(var OHash : OverwriteHashTable;
  224.                              var FHash : FormatHashTable;
  225.                              var WHash : WidthHashTable;
  226.                              GetColWidth : GetColWidthFunc;
  227.                              CPos : CellPos; FormulasDisplayed : Boolean;
  228.                              Start : Word; ColWidth : Byte;
  229.                              var DString : DollarStr;
  230.                              var Color : Byte) : String; virtual;
  231.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  232.                         var L : LStringPtr) : LStringPtr; virtual;
  233.     constructor Load(var S : TDosStream);
  234.     procedure Store(var S : TDosStream);
  235.   end;
  236.   TextCellPtr = ^TextCell;
  237.   TextCell = object(Cell)
  238.     Txt : LStringPtr;       { A cell with text }
  239.     constructor Init(InitLoc : CellPos; InitTxt : LStringPtr);
  240.     destructor Done; virtual;
  241.     function CellType : CellTypes; virtual;
  242.     function LegalValue : Boolean; virtual;
  243.     function Name : String; virtual;
  244.     function Format(var FHash : FormatHashTable;
  245.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  246.     function Width(var FHash : FormatHashTable;
  247.                    FormulasDisplayed : Boolean) : Word; virtual;
  248.     function Overwritten(var CHash : CellHashTable;
  249.                          var FHash : FormatHashTable;
  250.                          var WHash : WidthHashTable; var LastPos : CellPos;
  251.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  252.                          FormulasDisplayed : Boolean) : Word; virtual;
  253.     function ShouldUpdate : Boolean; virtual;
  254.     function HasError : Boolean; virtual;
  255.     function CurrValue : Extended; virtual;
  256.     function OverwriteStart(var FHash : FormatHashTable;
  257.                             var WHash : WidthHashTable;
  258.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  259.                             DisplayFormulas : Boolean) : Word; virtual;
  260.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  261.     function DisplayString(FormulasDisplayed : Boolean;
  262.                            MaxDecPlaces : Byte) : String; virtual;
  263.     function FormattedString(var OHash : OverwriteHashTable;
  264.                              var FHash : FormatHashTable;
  265.                              var WHash : WidthHashTable;
  266.                              GetColWidth : GetColWidthFunc;
  267.                              CPos : CellPos; FormulasDisplayed : Boolean;
  268.                              Start : Word; ColWidth : Byte;
  269.                              var DString : DollarStr;
  270.                              var Color : Byte) : String; virtual;
  271.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  272.                         var L : LStringPtr) : LStringPtr; virtual;
  273.     constructor Load(var S : TDosStream);
  274.     procedure Store(var S : TDosStream);
  275.   end;
  276.   FormulaCellPtr = ^FormulaCell;
  277.   FormulaCell = object(Cell)
  278.     Error : Boolean;
  279.     Value : Extended;
  280.     Formula : LStringPtr;   { A cell with a formula }
  281.     constructor Init(InitLoc : CellPos; InitError : Boolean;
  282.                      InitValue : Extended; InitFormula : LStringPtr);
  283.     destructor Done; virtual;
  284.     function CellType : CellTypes; virtual;
  285.     function LegalValue : Boolean; virtual;
  286.     function Name : String; virtual;
  287.     function Format(var FHash : FormatHashTable;
  288.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  289.     function Width(var FHash : FormatHashTable;
  290.                    FormulasDisplayed : Boolean) : Word; virtual;
  291.     function Overwritten(var CHash : CellHashTable;
  292.                          var FHash : FormatHashTable;
  293.                          var WHash : WidthHashTable; var LastPos : CellPos;
  294.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  295.                          FormulasDisplayed : Boolean) : Word; virtual;
  296.     function ShouldUpdate : Boolean; virtual;
  297.     function HasError : Boolean; virtual;
  298.     function CurrValue : Extended; virtual;
  299.     function OverwriteStart(var FHash : FormatHashTable;
  300.                             var WHash : WidthHashTable;
  301.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  302.                             DisplayFormulas : Boolean) : Word; virtual;
  303.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  304.     function DisplayString(FormulasDisplayed : Boolean;
  305.                            MaxDecPlaces : Byte) : String; virtual;
  306.     function FormattedString(var OHash : OverwriteHashTable;
  307.                              var FHash : FormatHashTable;
  308.                              var WHash : WidthHashTable;
  309.                              GetColWidth : GetColWidthFunc;
  310.                              CPos : CellPos; FormulasDisplayed : Boolean;
  311.                              Start : Word; ColWidth : Byte;
  312.                              var DString : DollarStr;
  313.                              var Color : Byte) : String; virtual;
  314.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  315.                         var L : LStringPtr) : LStringPtr; virtual;
  316.     constructor Load(var S : TDosStream);
  317.     procedure Store(var S : TDosStream);
  318.     function GetFormula : LStringPtr;
  319.   end;
  320.   RepeatCellPtr = ^RepeatCell;
  321.   RepeatCell = object(Cell)
  322.     RepeatChar : Char;   { A cell with text that will repeat - used for
  323.                            underlining, etc. }
  324.     constructor Init(InitLoc : CellPos; InitChar : Char);
  325.     function CellType : CellTypes; virtual;
  326.     function LegalValue : Boolean; virtual;
  327.     function Name : String; virtual;
  328.     function Format(var FHash : FormatHashTable;
  329.                     FormulasDisplayed : Boolean) : FormatType; virtual;
  330.     function Width(var FHash : FormatHashTable;
  331.                    FormulasDisplayed : Boolean) : Word; virtual;
  332.     function Overwritten(var CHash : CellHashTable;
  333.                          var FHash : FormatHashTable;
  334.                          var WHash : WidthHashTable; var LastPos : CellPos;
  335.                          MaxCols : Word; GetColWidth : GetColWidthFunc;
  336.                          FormulasDisplayed : Boolean) : Word; virtual;
  337.     function ShouldUpdate : Boolean; virtual;
  338.     function HasError : Boolean; virtual;
  339.     function CurrValue : Extended; virtual;
  340.     function OverwriteStart(var FHash : FormatHashTable;
  341.                             var WHash : WidthHashTable;
  342.                             GetColWidth : GetColWidthFunc; EndCol : Word;
  343.                             DisplayFormulas : Boolean) : Word; virtual;
  344.     procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
  345.     function DisplayString(FormulasDisplayed : Boolean;
  346.                            MaxDecPlaces : Byte) : String; virtual;
  347.     function FormattedString(var OHash : OverwriteHashTable;
  348.                              var FHash : FormatHashTable;
  349.                              var WHash : WidthHashTable;
  350.                              GetColWidth : GetColWidthFunc;
  351.                              CPos : CellPos; FormulasDisplayed : Boolean;
  352.                              Start : Word; ColWidth : Byte;
  353.                              var DString : DollarStr;
  354.                              var Color : Byte) : String; virtual;
  355.     function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  356.                         var L : LStringPtr) : LStringPtr; virtual;
  357.     constructor Load(var S : TDosStream);
  358.     procedure Store(var S : TDosStream);
  359.   end;
  360.  
  361. var
  362.   Empty : CellPtr;   { This is a special cell.  It is used as the return
  363.                        value if a cell cannot be found so that the EmptyCell
  364.                        methods can be executed instead of having special
  365.                        routines that act differently depending on whether a
  366.                        cell is found ot not. }
  367.  
  368. const
  369.  
  370.   { Stream registration records for the object types that will be written
  371.     to and read from the stream.  }
  372.  
  373.   RValueCell: TStreamRec = (
  374.     ObjType: 1000;                   { an arbitrary, but unique number }
  375.     VmtLink: Ofs(TypeOf(ValueCell)^);
  376.     Load: @ValueCell.Load;
  377.     Store: @ValueCell.Store
  378.   );
  379.  
  380.   RTextCell: TStreamRec = (
  381.     ObjType: 1001;
  382.     VmtLink: Ofs(TypeOf(TextCell)^);
  383.     Load: @TextCell.Load;
  384.     Store: @TextCell.Store
  385.   );
  386.  
  387.   RFormulaCell: TStreamRec = (
  388.     ObjType: 1002;
  389.     VmtLink: Ofs(TypeOf(FormulaCell)^);
  390.     Load: @FormulaCell.Load;
  391.     Store: @FormulaCell.Store
  392.   );
  393.  
  394.   RRepeatCell: TStreamRec = (
  395.     ObjType: 1003;
  396.     VmtLink: Ofs(TypeOf(RepeatCell)^);
  397.     Load: @RepeatCell.Load;
  398.     Store: @RepeatCell.Store
  399.   );
  400.  
  401.  
  402.  
  403. procedure RegisterCellTypes;
  404.  
  405.  
  406.  
  407. implementation
  408.  
  409. var
  410.   SavedExitProc : Pointer;
  411.  
  412.  
  413. procedure RegisterCellTypes;
  414. { Registers the different cell types so that they will be written out
  415.   correctly to disk }
  416. begin
  417.   RegisterType(RValueCell);
  418.   RegisterType(RTextCell);
  419.   RegisterType(RFormulaCell);
  420.   RegisterType(RRepeatCell);
  421. end; { RegisterCellTypes }
  422.  
  423. constructor Block.Init(InitStart : CellPos);
  424. { Initializes a block of cells, setting the end to be the same as the start }
  425. begin
  426.   Start := InitStart;
  427.   Stop := Start;
  428. end; { Block.Init }
  429.  
  430. function Block.ExtendTo(NewLoc : CellPos) : Boolean;
  431. { Extends a block to a new position, as long as the new position is to the
  432.   right and down from the old position }
  433. begin
  434.   if (NewLoc.Col >= Start.Col) and (NewLoc.Row >= Start.Row) then
  435.   begin
  436.     Stop := NewLoc;
  437.     ExtendTo := True;
  438.   end
  439.   else
  440.     ExtendTo := False;
  441. end; { Block.ExtendTo }
  442.  
  443. function Block.CellInBlock(CheckCell : CellPos) : Boolean;
  444. { Checks to see if a cell is inside a particular block }
  445. begin
  446.   CellInBlock := (CheckCell.Col >= Start.Col) and
  447.                  (CheckCell.Col <= Stop.Col) and
  448.                  (CheckCell.Row >= Start.Row) and
  449.                  (CheckCell.Row <= Stop.Row);
  450. end; { Block.CellInBlock }
  451.  
  452. constructor CellHashTable.Init(InitBuckets : BucketRange);
  453. { Initializes a cell hash table, which stores pointers to the cells in a
  454.   spreadsheet }
  455. begin
  456.   if not HashTable.Init(InitBuckets) then
  457.     Fail;
  458. end; { CellHashTable.Init }
  459.  
  460. destructor CellHashTable.Done;
  461. { Removes a cell hash table from memory }
  462. var
  463.   CP : CellPtr;
  464. begin
  465.   CP := FirstItem;
  466.   while CP <> nil do
  467.   begin
  468.     Dispose(CP, Done);
  469.     CP := NextItem;
  470.   end;
  471.   HashTable.Done;
  472. end; { CellHashTable.Done }
  473.  
  474. function CellHashTable.Add(ACell : CellPtr) : Boolean;
  475. { Adds a cell to a cell hash table }
  476. begin
  477.   CurrCell := ACell;
  478.   CurrLoc := CurrCell^.Loc;
  479.   Add := HashTable.Add;
  480. end; { CellHashTable.Add }
  481.  
  482. procedure CellHashTable.Delete(DelLoc : CellPos; var DeletedCell : CellPtr);
  483. { Deletes a cell from a cell hash table }
  484. begin
  485.   CurrLoc := DelLoc;
  486.   HashTable.Delete(@DeletedCell);
  487. end; { CellHashTable.Delete }
  488.  
  489. function CellHashTable.Search(SPos : CellPos) : CellPtr;
  490. { Searches for a cell in a cell hash table, returning the cell if found, or
  491.   returning the Empty cell if not found }
  492. var
  493.   I : HashItemPtr;
  494.   C : CellPtr;
  495. begin
  496.   CurrLoc := SPos;
  497.   I := HashTable.Search;
  498.   if I = nil then
  499.     Search := Empty
  500.   else begin
  501.     Move(I^.Data, C, SizeOf(C));
  502.     Search := C;
  503.   end;
  504. end; { CellHashTable.Search }
  505.  
  506. function CellHashTable.HashValue : Word;
  507. { Calculates the hash value of a cell }
  508. begin
  509.   HashValue := CurrLoc.Col + CurrLoc.Row;
  510. end; { CellHashTable.HashValue }
  511.  
  512. function CellHashTable.Found(Item : HashItemPtr) : Boolean;
  513. { Checks to see if a hash item is the one searched for by comparing the
  514.   location information in both }
  515. var
  516.   C : CellPtr;
  517. begin
  518.   Move(Item^.Data, C, SizeOf(C));
  519.   Found := Compare(C^.Loc, CurrLoc, SizeOf(CurrLoc));
  520. end; { CellHashTable.Found }
  521.  
  522. procedure CellHashTable.CreateItem(var Item : HashItemPtr);
  523. { Writes the cell poionter information out to the hash item }
  524. begin
  525.   Move(CurrCell, Item^.Data, SizeOf(CurrCell));
  526. end; { CellHashTable.CreateItem }
  527.  
  528. function CellHashTable.ItemSize : HashItemSizeRange;
  529. { The hash item size is current - just cell pointers are stored }
  530. begin
  531.   ItemSize := SizeOf(CurrCell);
  532. end; { CellHashTable.ItemSize }
  533.  
  534. procedure CellHashTable.Load(var S : TDosStream; Total : Longint);
  535. { Loads a cell hash table from disk }
  536. var
  537.   Counter : Longint;
  538. begin
  539.   for Counter := 1 to Total do
  540.   begin
  541.     if not Add(CellPtr(S.Get)) then
  542.     begin
  543.       S.Error(NoMemory, 0);
  544.       Exit;
  545.     end;
  546.   end;
  547. end; { CellHashTable.Load }
  548.  
  549. procedure CellHashTable.Store(var S : TDosStream);
  550. { Writes a cell hash table to disk }
  551. var
  552.   CP : CellPtr;
  553. begin
  554.   CP := FirstItem;
  555.   while CP <> nil do
  556.   begin
  557.     S.Put(CP);
  558.     CP := NextItem;
  559.   end;
  560. end; { CellHashTable.Store }
  561.  
  562. function HashItemPtrToCellPtr(H : HashItemPtr) : CellPtr;
  563. { Converts a hash item pointer to a cell pointer }
  564. var
  565.   CP : CellPtr;
  566. begin
  567.   if H = nil then
  568.     HashItemPtrToCellPtr := nil
  569.   else begin
  570.     Move(H^.Data, CP, SizeOf(CP));
  571.     HashItemPtrToCellPtr := CP;
  572.   end;
  573. end; { HashItemPtrToCellPtr }
  574.  
  575. function CellHashTable.FirstItem : CellPtr;
  576. { Returns the first hash item in a cell hash table }
  577. begin
  578.   FirstItem := HashItemPtrToCellPtr(HashTable.FirstItem);
  579. end; { CellHashTable.FirstItem }
  580.  
  581. function CellHashTable.NextItem : CellPtr;
  582. { Returns the second and subsequent hash items in a cell hash table }
  583. begin
  584.   NextItem := HashItemPtrToCellPtr(HashTable.NextItem);
  585. end; { CellHashTable.NextItem }
  586.  
  587. constructor WidthHashTable.Init(InitBuckets : BucketRange;
  588.                                 InitDefaultColWidth : Byte);
  589. { Initializes the width hash table, which stores column widths that are
  590.   different than the default.  It stores the column and the width in the
  591.   hash table }
  592. begin
  593.   if not HashTable.Init(InitBuckets) then
  594.     Fail;
  595.   DefaultColWidth := InitDefaultColWidth;
  596. end; { WidthHashTable.Init }
  597.  
  598. destructor WidthHashTable.Done;
  599. begin
  600.   HashTable.Done;
  601. end; { WidthHashTable.Done }
  602.  
  603. function WidthHashTable.Add(SCol : Word; NewWidth : Byte) : Boolean;
  604. begin
  605.   CurrCol := SCol;
  606.   CurrWidth := NewWidth;
  607.   Add := HashTable.Add;
  608. end; { WidthHashTable }
  609.  
  610. procedure WidthHashTable.Delete(Col : Word);
  611. begin
  612.   CurrCol := Col;
  613.   HashTable.Delete(nil);
  614. end; { WidthHashTable.Delete }
  615.  
  616. function WidthHashTable.Search(Col : Word) : Byte;
  617. var
  618.   I : HashItemPtr;
  619.   W : Byte;
  620. begin
  621.   CurrCol := Col;
  622.   I := HashTable.Search;
  623.   if I = nil then
  624.     Search := 0
  625.   else begin
  626.     Move(I^.Data[SizeOf(CurrCol)], W, SizeOf(W));
  627.     Search := W;
  628.   end;
  629. end; { WidthHashTable.Search }
  630.  
  631. function WidthHashTable.HashValue : Word;
  632. begin
  633.   HashValue := CurrCol;
  634. end; { WidthHashTable.HashValue }
  635.  
  636. function WidthHashTable.Found(Item : HashItemPtr) : Boolean;
  637. var
  638.   C : Word;
  639. begin
  640.   Move(Item^.Data, C, SizeOf(C));
  641.   Found := CurrCol = C;
  642. end; { WidthHashTable.Found }
  643.  
  644. procedure WidthHashTable.CreateItem(var Item : HashItemPtr);
  645. begin
  646.   Move(CurrCol, Item^.Data, SizeOf(CurrCol));
  647.   Move(CurrWidth, Item^.Data[SizeOf(CurrCol)], SizeOf(CurrWidth));
  648. end; { WidthHashTable.CreateItem }
  649.  
  650. function WidthHashTable.ItemSize : HashItemSizeRange;
  651. begin
  652.   ItemSize := SizeOf(CurrCol) + SizeOf(CurrWidth);
  653. end; { WidthHashTable.ItemSize }
  654.  
  655. function WidthHashTable.GetDefaultColWidth : Byte;
  656. begin
  657.   GetDefaultColWidth := DefaultColWidth;
  658. end; { WidthHashTable.GetDefaultColWidth }
  659.  
  660. procedure WidthHashTable.Load(var S : TDosStream; Total : Longint);
  661. var
  662.   Counter : Longint;
  663.   Col : Word;
  664.   Width : Byte;
  665. begin
  666.   for Counter := 1 to Total do
  667.   begin
  668.     S.Read(Col, SizeOf(Col));
  669.     S.Read(Width, SizeOf(Width));
  670.     if not Add(Col, Width) then
  671.     begin
  672.       S.Error(NoMemory, 0);
  673.       Exit;
  674.     end;
  675.   end;
  676. end; { WidthHashTable.Load }
  677.  
  678. procedure WidthHashTable.Store(var S : TDosStream);
  679. var
  680.   H : HashItemPtr;
  681.   Col : Word;
  682.   Width : Byte;
  683. begin
  684.   H := FirstItem;
  685.   while H <> nil do
  686.   begin
  687.     Move(H^.Data, Col, SizeOf(Col));
  688.     S.Write(Col, SizeOf(Col));
  689.     Move(H^.Data[SizeOf(Col)], Width, SizeOf(Width));
  690.     S.Write(Width, SizeOf(Width));
  691.     H := NextItem;
  692.   end;
  693. end; { WidthHashTable.Store }
  694.  
  695. constructor FormatHashTable.Init;
  696. { Initializes a format hash table, which is used to store formatted areas
  697.   that differ from the default.  The area and the format are stored in the
  698.   hash table }
  699. begin
  700.   if not HashTable.Init(1) then   { Use a single bucket so that a search
  701.     Fail;                           will be possible }
  702. end; { FormatHashTable.Init }
  703.  
  704. destructor FormatHashTable.Done;
  705. begin
  706.   HashTable.Done;
  707. end; { FormatHashTable.Done }
  708.  
  709. function FormatHashTable.Overwrite(NewStart, NewStop : CellPos) : Boolean;
  710. { Checks to see if a new format area has overwritten an old one, requiring
  711.   the old area to be overwritten or broken into parts }
  712. var
  713.   H : HashItemPtr;
  714.   AStart, AStop, BStart, BStop : CellPos;
  715.   OldF, F : FormatType;
  716.   P : CellPos;
  717.   Added : Boolean;
  718. begin
  719.   Overwrite := False;
  720.   H := HashData^[1];
  721.   while H <> nil do
  722.   begin
  723.     Move(H^.Data, BStart, SizeOf(CellPos));
  724.     Move(H^.Data[SizeOf(CellPos)], BStop, SizeOf(CellPos));
  725.     if ((((NewStart.Col >= BStart.Col) and (NewStart.Col <= BStop.Col)) or
  726.          ((NewStop.Col >= BStart.Col) and (NewStop.Col <= BStop.Col))) and
  727.         (((NewStart.Row >= BStart.Row) and (NewStart.Row <= BStop.Row)) or
  728.          ((NewStop.Row >= BStart.Row) and (NewStop.Row <= BStop.Row)))) or
  729.        ((((BStart.Col >= NewStart.Col) and (BStart.Col <= NewStop.Col)) or
  730.          ((BStop.Col >= NewStart.Col) and (BStop.Col <= NewStop.Col))) and
  731.         (((BStart.Row >= NewStart.Row) and (BStart.Row <= NewStop.Row)) or
  732.          ((BStop.Row >= NewStart.Row) and (BStop.Row <= NewStop.Row)))) then
  733.     begin
  734.       Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
  735.       CurrStart := BStart;
  736.       CurrStop := BStop;
  737.       HashTable.Delete(nil);
  738.       if BStart.Row < NewStart.Row then
  739.       begin
  740.         AStart := BStart;
  741.         AStop.Col := BStop.Col;
  742.         AStop.Row := Pred(NewStart.Row);
  743.         if not Add(AStart, AStop, F) then
  744.           Exit;
  745.       end;
  746.       if BStop.Row > NewStop.Row then
  747.       begin
  748.         AStart.Col := BStart.Col;
  749.         AStart.Row := Succ(NewStop.Row);
  750.         AStop.Col := BStop.Col;
  751.         AStop.Row := BStop.Row;
  752.         if not Add(AStart, AStop, F) then
  753.           Exit;
  754.       end;
  755.       if BStart.Col < NewStart.Col then
  756.       begin
  757.         AStart.Col := BStart.Col;
  758.         AStart.Row := Max(BStart.Row, NewStart.Row);
  759.         AStop.Col := Pred(NewStart.Col);
  760.         AStop.Row := Min(BStop.Row, NewStop.Row);
  761.         if not Add(AStart, AStop, F) then
  762.           Exit;
  763.       end;
  764.       if BStop.Col > NewStop.Col then
  765.       begin
  766.         AStart.Col := Succ(NewStop.Col);
  767.         AStart.Row := Max(BStart.Row, NewStart.Row);
  768.         AStop.Col := BStop.Col;
  769.         AStop.Row := Min(BStop.Row, NewStop.Row);
  770.         if not Add(AStart, AStop, F) then
  771.           Exit;
  772.       end;
  773.     end;
  774.     H := H^.Next;
  775.   end;
  776.   Overwrite := True;
  777. end; { FormatHashTable.Overwrite }
  778.  
  779. function FormatHashTable.Add(NewStart, NewStop : CellPos;
  780.                              NewFormat : FormatType) : Boolean;
  781. begin
  782.   if not Overwrite(NewStart, NewStop) then
  783.   begin
  784.     Add := False;
  785.     Exit;
  786.   end;
  787.   CurrStart := NewStart;
  788.   CurrStop := NewStop;
  789.   CurrFormat := NewFormat;
  790.   Add := HashTable.Add;
  791. end; { FormatHashTable.Add }
  792.  
  793. function FormatHashTable.Delete(DStart, DStop : CellPos) : Boolean;
  794. begin
  795.   Delete := Overwrite(DStart, DStop);
  796. end; { FormatHashTable.Delete }
  797.  
  798. function FormatHashTable.Search(SPos : CellPos; var F : FormatType) :
  799.                                 Boolean;
  800. var
  801.   H : HashItemPtr;
  802. begin
  803.   CurrStart := SPos;
  804.   H := HashTable.Search;
  805.   if H = nil then
  806.     Search := False
  807.   else begin
  808.     Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
  809.     Search := True;
  810.   end;
  811. end; { FormatHashTable.Search }
  812.  
  813. function FormatHashTable.HashValue : Word;
  814. { Since the hash table has only one bucket, the hash value is always 1 }
  815. begin
  816.   HashValue := 1;
  817. end; { FormatHashTable.HashValue }
  818.  
  819. function FormatHashTable.Found(Item : HashItemPtr) : Boolean;
  820. var
  821.   P : CellPos;
  822.   B : Block;
  823.   Start, Stop : CellPos;
  824.   Good : Boolean;
  825. begin
  826.   Move(Item^.Data, Start, SizeOf(CellPos));
  827.   Move(Item^.Data[SizeOf(CellPos)], Stop, SizeOf(CellPos));
  828.   B.Init(Start);
  829.   B.Stop := Stop;
  830.   Found := B.CellInBlock(CurrStart);
  831. end; { FormatHashTable.Found }
  832.  
  833. procedure FormatHashTable.CreateItem(var Item : HashItemPtr);
  834. begin
  835.   with Item^ do
  836.   begin
  837.     Move(CurrStart, Data, SizeOf(CellPos));
  838.     Move(CurrStop, Data[SizeOf(CellPos)], SizeOf(CellPos));
  839.     Move(CurrFormat, Data[SizeOf(CellPos) shl 1], SizeOf(CurrFormat));
  840.   end; { with }
  841. end; { FormatHashTable.CreateItem }
  842.  
  843. function FormatHashTable.ItemSize : HashItemSizeRange;
  844. begin
  845.   ItemSize := (SizeOf(CellPos) shl 1) + SizeOf(FormatType);
  846. end; { FormatHashTable.ItemSize }
  847.  
  848. procedure FormatHashTable.Load(var S : TDosStream; Total : Longint);
  849. var
  850.   Counter : Longint;
  851.   C1, C2 : CellPos;
  852.   Format : FormatType;
  853. begin
  854.   for Counter := 1 to Total do
  855.   begin
  856.     S.Read(C1, SizeOf(C1));
  857.     S.Read(C2, SizeOf(C2));
  858.     S.Read(Format, SizeOf(Format));
  859.     if not Add(C1, C2, Format) then
  860.     begin
  861.       S.Error(NoMemory, 0);
  862.       Exit;
  863.     end;
  864.   end;
  865. end; { FormatHashTable.Load }
  866.  
  867. procedure FormatHashTable.Store(var S : TDosStream);
  868. var
  869.   H : HashItemPtr;
  870.   C : CellPos;
  871.   Format : Byte;
  872. begin
  873.   H := FirstItem;
  874.   while H <> nil do
  875.   begin
  876.     Move(H^.Data, C, SizeOf(C));
  877.     S.Write(C, SizeOf(C));
  878.     Move(H^.Data[SizeOf(CellPos)], C, SizeOf(C));
  879.     S.Write(C, SizeOf(C));
  880.     Move(H^.Data[SizeOf(CellPos) shl 1], Format, SizeOf(Format));
  881.     S.Write(Format, SizeOf(Format));
  882.     H := NextItem;
  883.   end;
  884. end; { FormatHashTable.Store }
  885.  
  886. constructor OverwriteHashTable.Init(InitBuckets : BucketRange);
  887. { Initializes an overwrite hash table, which keeps track of which cells are
  888.   overwritten by other cells }
  889. begin
  890.   if not HashTable.Init(InitBuckets) then
  891.     Fail;
  892. end; { OverwriteHashTable.Init }
  893.  
  894. destructor OverwriteHashTable.Done;
  895. begin
  896.   HashTable.Done;
  897. end; { OverwriteHashTable.Done }
  898.  
  899. function OverwriteHashTable.Add(SCell : CellPtr;
  900.                                 Overwritten : Word) : Boolean;
  901. var
  902.   CP : CellPtr;
  903. begin
  904.   if Overwritten = 0 then
  905.   begin
  906.     Add := True;
  907.     Exit;
  908.   end;
  909.   CP := Search(SCell^.Loc);
  910.   if CP <> Empty then
  911.   begin
  912.     if not Change(CP, Pred(SCell^.Loc.Col)) then
  913.     begin
  914.       Add := False;
  915.       Exit;
  916.     end;
  917.   end;
  918.   CurrCell := SCell;
  919.   CurrPos := SCell^.Loc;
  920.   EndCol := CurrPos.Col + Overwritten;
  921.   Add := HashTable.Add;
  922. end; { OverwriteHashTable.Add }
  923.  
  924. procedure OverwriteHashTable.Delete(SPos : CellPos);
  925. begin
  926.   CurrPos := SPos;
  927.   HashTable.Delete(nil);
  928. end; { OverwriteHashTable.Delete }
  929.  
  930. function OverwriteHashTable.Change(SCell : CellPtr;
  931.                                    Overwritten : Word) : Boolean;
  932. begin
  933.   if Overwritten = 0 then
  934.   begin
  935.     Delete(SCell^.Loc);
  936.     Change := True;
  937.   end
  938.   else begin
  939.     CurrCell := SCell;
  940.     CurrPos := CurrCell^.Loc;
  941.     EndCol := SCell^.Loc.Col + Overwritten;
  942.     Change := HashTable.Change;
  943.   end;
  944. end; { OverwriteHashTable.Change }
  945.  
  946. function OverwriteHashTable.Search(SPos : CellPos) : CellPtr;
  947. var
  948.   I : HashItemPtr;
  949.   C : CellPtr;
  950. begin
  951.   CurrPos := SPos;
  952.   I := HashTable.Search;
  953.   if I = nil then
  954.     Search := Empty
  955.   else begin
  956.     Move(I^.Data, C, SizeOf(C));
  957.     Search := C;
  958.   end;
  959. end; { OverwriteHashTable.Search }
  960.  
  961. function OverwriteHashTable.HashValue : Word;
  962. begin
  963.   HashValue := CurrPos.Row;
  964. end; { OverwriteHashTable.HashValue }
  965.  
  966. function OverwriteHashTable.Found(Item : HashItemPtr) : Boolean;
  967. var
  968.   C : CellPtr;
  969.   E : Word;
  970. begin
  971.   Move(Item^.Data, C, SizeOf(C));
  972.   Move(Item^.Data[SizeOf(C)], E, SizeOf(E));
  973.   with CurrPos do
  974.     Found := (Row = C^.Loc.Row) and (Col >= C^.Loc.Col) and
  975.              (Col <= E);
  976. end; { OverwriteHashTable.Found }
  977.  
  978. procedure OverwriteHashTable.CreateItem(var Item : HashItemPtr);
  979. begin
  980.   Move(CurrCell, Item^.Data, SizeOf(CurrCell));
  981.   Move(EndCol, Item^.Data[SizeOf(CurrCell)], SizeOf(EndCol));
  982. end; { OverwriteHashTable.CreateItem }
  983.  
  984. function OverwriteHashTable.ItemSize : HashItemSizeRange;
  985. begin
  986.   ItemSize := SizeOf(CurrCell) + SizeOf(EndCol);
  987. end; { OverwriteHashTable.ItemSize }
  988.  
  989. constructor Cell.Init(InitLoc : CellPos);
  990. { Initializes a cell's location }
  991. begin
  992.   Loc := InitLoc;
  993. end; { Cell.Init }
  994.  
  995. destructor Cell.Done;
  996. { Frees memory used by the cell }
  997. begin
  998. end; { Cell.Done }
  999.  
  1000. function Cell.CellType : CellTypes;
  1001. { Returns the type of a cell - used in copying cells }
  1002. begin
  1003.   Abstract('Cell.CellType');
  1004. end; { Cell.CellType }
  1005.  
  1006. function Cell.LegalValue : Boolean;
  1007. { Returns True if the cell has a legal numeric value }
  1008. begin
  1009.   Abstract('Cell.LegalValue');
  1010. end; { Cell.LegalValue }
  1011.  
  1012. function Cell.Name : String;
  1013. { Returns the name of the cell type }
  1014. begin
  1015.   Abstract('Cell.Name');
  1016. end; { Cell.Name }
  1017.  
  1018. function Cell.Format(var FHash : FormatHashTable; FormulasDisplayed : Boolean) :
  1019.                          FormatType;
  1020. { Returns the format of a cell }
  1021. begin
  1022.   Abstract('Cell.Format');
  1023. end; { Cell.Format }
  1024.  
  1025. function Cell.Width(var FHash : FormatHashTable; FormulasDisplayed : Boolean) :
  1026.                         Word;
  1027. { Returns the width of a cell (including the cells that it will overwrite) }
  1028. begin
  1029.   Abstract('Cell.Width');
  1030. end; { Cell.Width }
  1031.  
  1032. function Cell.Overwritten(var CHash : CellHashTable;
  1033.                                var FHash : FormatHashTable;
  1034.                                var WHash : WidthHashTable;
  1035.                                var LastPos : CellPos;
  1036.                                MaxCols : Word;
  1037.                                GetColWidth : GetColWidthFunc;
  1038.                                FormulasDisplayed : Boolean) : Word;
  1039. { Calculates how many cells a cell will overwrite }
  1040. begin
  1041.   Abstract('Cell.Overwritten');
  1042. end; { Cell.Overwritten }
  1043.  
  1044. function Cell.ShouldUpdate : Boolean;
  1045. { Returns True if the cell needs to be updated when the spreadsheet changes }
  1046. begin
  1047.   Abstract('Cell.ShouldUpdate');
  1048. end; { Cell.ShouldUpdate }
  1049.  
  1050. function Cell.HasError : Boolean;
  1051. { Returns True if the cell has a numeric error in it }
  1052. begin
  1053.   Abstract('Cell.HasError');
  1054. end; { Cell.HasError }
  1055.  
  1056. function Cell.CurrValue : Extended;
  1057. { Returns the current numeric value of a cell }
  1058. begin
  1059.   Abstract('Cell.CurrValue');
  1060. end; { Cell.CurrValue }
  1061.  
  1062. function Cell.OverwriteStart(var FHash : FormatHashTable;
  1063.                              var WHash : WidthHashTable;
  1064.                              GetColWidth : GetColWidthFunc; EndCol : Word;
  1065.                              DisplayFormulas : Boolean) : Word;
  1066. { Determines, for overwritten cells, where in the overwriting data they will
  1067.   Start to display a value }
  1068. begin
  1069.   Abstract('Cell.OverwriteStart');
  1070. end; { Cell.OverwriteStart }
  1071.  
  1072. procedure Cell.EditString(MaxDecPlaces : Byte;
  1073.                           var L : LStringPtr);
  1074. { Sets up a long string with the cell's value that can be edited }
  1075. begin
  1076.   Abstract('Cell.EditString');
  1077. end; { Cell.EditString }
  1078.  
  1079. function Cell.DisplayString(FormulasDisplayed : Boolean;
  1080.                             MaxDecPlaces : Byte) : String;
  1081. { Returns the string that will be displayed just above the input line }
  1082. begin
  1083.   Abstract('Cell.DisplayString');
  1084. end; { Cell.DisplayString }
  1085.  
  1086. function Cell.FormattedString(var OHash : OverwriteHashTable;
  1087.                               var FHash : FormatHashTable;
  1088.                               var WHash : WidthHashTable;
  1089.                               GetColWidth : GetColWidthFunc;
  1090.                               CPos : CellPos; FormulasDisplayed : Boolean;
  1091.                               Start : Word; ColWidth : Byte;
  1092.                               var DString : DollarStr;
  1093.                               var Color : Byte) : String;
  1094. { Returns the string that will be printed in a cell }
  1095. begin
  1096.   Abstract('Cell.FormattedString');
  1097. end; { Cell.FormattedString }
  1098.  
  1099. function Cell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1100.                          var L : LStringPtr) : LStringPtr;
  1101. { Copies a cell's string information to another cell's }
  1102. begin
  1103.   Abstract('Cell.CopyString');
  1104. end; { Cell.CopyString }
  1105.  
  1106. constructor EmptyCell.Init;
  1107. var
  1108.   NewLoc : CellPos;
  1109. begin
  1110.   NewLoc.Col := 0;
  1111.   NewLoc.Row := 0;
  1112.   Cell.Init(NewLoc);
  1113. end; { EmptyCell.Init }
  1114.  
  1115. function EmptyCell.CellType : CellTypes;
  1116. begin
  1117.   CellType := ClEmpty;
  1118. end; { EmptyCell.CellType }
  1119.  
  1120. function EmptyCell.LegalValue : Boolean;
  1121. begin
  1122.   LegalValue := True;
  1123. end; { EmptyCell.LegalValue }
  1124.  
  1125. function EmptyCell.Name : String;
  1126. begin
  1127.   Name := EmptyCellName;
  1128. end; { EmptyCell.Name }
  1129.  
  1130. function EmptyCell.Format(var FHash : FormatHashTable;
  1131.                               FormulasDisplayed : Boolean) : FormatType;
  1132. begin
  1133.   Format := 0;
  1134. end; { EmptyCell.Format }
  1135.  
  1136. function EmptyCell.Width(var FHash : FormatHashTable;
  1137.                              FormulasDisplayed : Boolean) : Word;
  1138. begin
  1139.   Width := 0;
  1140. end; { EmptyCell.Width }
  1141.  
  1142. function EmptyCell.Overwritten(var CHash : CellHashTable;
  1143.                                     var FHash : FormatHashTable;
  1144.                                     var WHash : WidthHashTable;
  1145.                                     var LastPos : CellPos;
  1146.                                     MaxCols : Word;
  1147.                                     GetColWidth : GetColWidthFunc;
  1148.                                     FormulasDisplayed : Boolean) : Word;
  1149. begin
  1150.   Overwritten := 0;
  1151. end; { EmptyCell.Overwritten }
  1152.  
  1153. function EmptyCell.ShouldUpdate : Boolean;
  1154. begin
  1155.   ShouldUpdate := False;
  1156. end; { EmptyCell.ShouldUpdate }
  1157.  
  1158. function EmptyCell.HasError : Boolean;
  1159. begin
  1160.   HasError := False;
  1161. end; { Cell.HasError }
  1162.  
  1163. function EmptyCell.CurrValue : Extended;
  1164. begin
  1165.   CurrValue := 0;
  1166. end; { EmptyCell.CurrValue }
  1167.  
  1168. function EmptyCell.OverwriteStart(var FHash : FormatHashTable;
  1169.                                   var WHash : WidthHashTable;
  1170.                                   GetColWidth : GetColWidthFunc;
  1171.                                   EndCol : Word;
  1172.                                   DisplayFormulas : Boolean) : Word;
  1173. begin
  1174.   OverwriteStart := 1;
  1175. end; { EmptyCell.OverwriteStart }
  1176.  
  1177. procedure EmptyCell.EditString(MaxDecPlaces : Byte;
  1178.                                      var L : LStringPtr);
  1179. var
  1180.   Good : Boolean;
  1181. begin
  1182.   Good := L^.FromString('');
  1183. end; { EmptyCell.EditString }
  1184.  
  1185. function EmptyCell.DisplayString(FormulasDisplayed : Boolean;
  1186.                                        MaxDecPlaces : Byte) : String;
  1187. begin
  1188.   DisplayString := '';
  1189. end; { EmptyCell.DisplayString }
  1190.  
  1191. function EmptyCell.FormattedString(var OHash : OverwriteHashTable;
  1192.                                    var FHash : FormatHashTable;
  1193.                                    var WHash : WidthHashTable;
  1194.                                    GetColWidth : GetColWidthFunc;
  1195.                                    CPos : CellPos;
  1196.                                    FormulasDisplayed : Boolean;
  1197.                                    Start : Word; ColWidth : Byte;
  1198.                                    var DString : DollarStr;
  1199.                                    var Color : Byte) : String;
  1200. var
  1201.   CP : CellPtr;
  1202. begin
  1203.   CP := OHash.Search(CPos);
  1204.   if CP <> Empty then
  1205.     FormattedString := CP^.FormattedString(OHash, FHash, WHash, GetColWidth,
  1206.                                            Loc, FormulasDisplayed,
  1207.                                            CP^.OverWriteStart(FHash, WHash,
  1208.                                            GetColWidth, CPos.Col,
  1209.                                            FormulasDisplayed), ColWidth,
  1210.                                            DString, Color)
  1211.   else begin
  1212.     FormattedString := '';
  1213.     DString := '';
  1214.     Color := Colors.BlankColor;
  1215.   end;
  1216. end; { EmptyCell.FormattedString }
  1217.  
  1218. function EmptyCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1219.                               var L : LStringPtr) : LStringPtr;
  1220. begin
  1221.   CopyString := L;
  1222. end; { EmptyCell.CopyString }
  1223.  
  1224. constructor ValueCell.Init(InitLoc : CellPos; InitError : Boolean;
  1225.                            InitValue : Extended);
  1226. begin
  1227.   Cell.Init(InitLoc);
  1228.   Error := InitError;
  1229.   Value := InitValue;
  1230. end; { ValueCell.Init }
  1231.  
  1232. function ValueCell.CellType : CellTypes;
  1233. begin
  1234.   CellType := ClValue;
  1235. end; { ValueCell.CellType }
  1236.  
  1237. function ValueCell.LegalValue : Boolean;
  1238. begin
  1239.   LegalValue := True;
  1240. end; { ValueCell.LegalValue }
  1241.  
  1242. function ValueCell.Name : String;
  1243. begin
  1244.   Name := ValueCellName;
  1245. end; { ValueCell.Name }
  1246.  
  1247. function ValueCell.Format(var FHash : FormatHashTable;
  1248.                               FormulasDisplayed : Boolean) : FormatType;
  1249. var
  1250.   F : FormatType;
  1251. begin
  1252.   if FHash.Search(Loc, F) then
  1253.     Format := F
  1254.   else
  1255.     Format := (Ord(JRight) shl 4) + 4;
  1256. end; { ValueCell.Format }
  1257.  
  1258. function ValueCell.Width(var FHash : FormatHashTable;
  1259.                              FormulasDisplayed : Boolean) : Word;
  1260. var
  1261.   S : String;
  1262.   F : FormatType;
  1263.   P, W : Word;
  1264. begin
  1265.   F := Format(FHash, FormulasDisplayed);
  1266.   Str(Value:1:(F and DecPlacesPart), S);
  1267.   W := Length(S);
  1268.   if (F and DollarPart) <> 0 then
  1269.     Inc(W, Length(DollarString));
  1270.   if (F and CommasPart) <> 0 then
  1271.   begin
  1272.     P := Pos('.', S);
  1273.     if P = 0 then
  1274.       P := Length(S);
  1275.     Inc(W, (P - 2) div 3);
  1276.   end;
  1277.   Width := W;
  1278. end; { ValueCell.Width }
  1279.  
  1280. function ValueCell.Overwritten(var CHash : CellHashTable;
  1281.                                var FHash : FormatHashTable;
  1282.                                var WHash : WidthHashTable;
  1283.                                var LastPos : CellPos;
  1284.                                MaxCols : Word;
  1285.                                GetColWidth : GetColWidthFunc;
  1286.                                FormulasDisplayed : Boolean) : Word;
  1287. var
  1288.   CellWidth : Longint;
  1289.   Total : Word;
  1290.   P : CellPos;
  1291. begin
  1292.   P := Loc;
  1293.   CellWidth := Width(FHash, FormulasDisplayed);
  1294.   Total := 0;
  1295.   repeat
  1296.     Inc(Total);
  1297.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  1298.     Inc(P.Col);
  1299.   until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
  1300.   Dec(Total);
  1301.   Overwritten := Total;
  1302. end; { ValueCell.Overwritten }
  1303.  
  1304. function ValueCell.ShouldUpdate : Boolean;
  1305. begin
  1306.   ShouldUpdate := False;
  1307. end; { ValueCell.ShouldUpdate }
  1308.  
  1309. function ValueCell.HasError : Boolean;
  1310. begin
  1311.   HasError := Error;
  1312. end; { ValueCell.HasError }
  1313.  
  1314. function ValueCell.CurrValue : Extended;
  1315. begin
  1316.   CurrValue := Value;
  1317. end; { ValueCell.CurrValue }
  1318.  
  1319. function ValueCell.OverwriteStart(var FHash : FormatHashTable;
  1320.                                   var WHash : WidthHashTable;
  1321.                                   GetColWidth : GetColWidthFunc;
  1322.                                   EndCol : Word;
  1323.                                   DisplayFormulas : Boolean) : Word;
  1324. var
  1325.   F : FormatType;
  1326.   C, Place : Word;
  1327. begin
  1328.   F := Format(FHash, DisplayFormulas);
  1329.   Place := 1;
  1330.   C := Loc.Col;
  1331.   repeat
  1332.     Inc(Place, GetColWidth(WHash, C));
  1333.     Inc(C);
  1334.   until C = EndCol;
  1335.   if (F and DollarPart) <> 0 then
  1336.     Dec(Place, Length(DollarString));
  1337.   OverwriteStart := Place;
  1338. end; { ValueCell.OverwriteStart }
  1339.  
  1340. procedure ValueCell.EditString(MaxDecPlaces : Byte;
  1341.                                      var L : LStringPtr);
  1342. var
  1343.   S : String;
  1344.   Good : Boolean;
  1345. begin
  1346.   Str(Value:1:MaxDecPlaces, S);
  1347.   Good := L^.FromString(S);
  1348. end; { ValueCell.EditString }
  1349.  
  1350. function ValueCell.DisplayString(FormulasDisplayed : Boolean;
  1351.                                        MaxDecPlaces : Byte) : String;
  1352. var
  1353.   S : String;
  1354. begin
  1355.   Str(Value:1:MaxDecPlaces, S);
  1356.   DisplayString := S;
  1357. end; { ValueCell.DisplayString }
  1358.  
  1359. function ValueCell.FormattedString(var OHash : OverwriteHashTable;
  1360.                                    var FHash : FormatHashTable;
  1361.                                    var WHash : WidthHashTable;
  1362.                                    GetColWidth : GetColWidthFunc;
  1363.                                    CPos : CellPos;
  1364.                                    FormulasDisplayed : Boolean;
  1365.                                    Start : Word; ColWidth : Byte;
  1366.                                    var DString : DollarStr;
  1367.                                    var Color : Byte) : String;
  1368. var
  1369.   Counter : Word;
  1370.   S : String;
  1371.   F : FormatType;
  1372. begin
  1373.   F := Format(FHash, FormulasDisplayed);
  1374.   Str(Value:1:F and DecPlacesPart, S);
  1375.   if (Start = 1) and ((F and DollarPart) <> 0) then
  1376.     DString := ' $ '
  1377.   else
  1378.     DString := '';
  1379.   if (F and CommasPart) <> 0 then
  1380.   begin
  1381.     Counter := Pos('.', S);
  1382.     if Counter = 0 then
  1383.       Counter := System.Length(S);
  1384.     while Counter > 4 do
  1385.     begin
  1386.       System.Insert(',', S, Counter - 3);
  1387.       Dec(Counter, 3);
  1388.     end;
  1389.   end;
  1390.   Color := Colors.ValueCellColor;
  1391.   FormattedString := Copy(S, Start, ColWidth);
  1392. end; { ValueCell.FormattedString }
  1393.  
  1394. function ValueCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1395.                               var L : LStringPtr) : LStringPtr;
  1396. begin
  1397.   CopyString := L;
  1398. end; { ValueCell.CopyString }
  1399.  
  1400. constructor ValueCell.Load(var S : TDosStream);
  1401. begin
  1402.   S.Read(Loc, SizeOf(Loc));
  1403.   S.Read(Error, SizeOf(Error));
  1404.   S.Read(Value, SizeOf(Value));
  1405. end; { ValueCell.Load }
  1406.  
  1407. procedure ValueCell.Store(var S : TDosStream);
  1408. begin
  1409.   S.Write(Loc, SizeOf(Loc));
  1410.   S.Write(Error, SizeOf(Error));
  1411.   S.Write(Value, SizeOf(Value));
  1412. end; { ValueCell.Store }
  1413.  
  1414. constructor TextCell.Init(InitLoc : CellPos; InitTxt : LStringPtr);
  1415. begin
  1416.   Cell.Init(InitLoc);
  1417.   Txt := New(LStringPtr, Init);
  1418.   if Txt = nil then
  1419.     Fail;
  1420.   if not Txt^.Assign(InitTxt^) then
  1421.   begin
  1422.     Done;
  1423.     Fail;
  1424.   end;
  1425. end; { TextCell.Init }
  1426.  
  1427. destructor TextCell.Done;
  1428. begin
  1429.   Dispose(Txt, Done);
  1430. end; { TextCell.Done }
  1431.  
  1432. function TextCell.CellType : CellTypes;
  1433. begin
  1434.   CellType := ClText;
  1435. end; { TextCell.CellType }
  1436.  
  1437. function TextCell.LegalValue : Boolean;
  1438. begin
  1439.   LegalValue := False;
  1440. end; { TextCell.LegalValue }
  1441.  
  1442. function TextCell.Name : String;
  1443. begin
  1444.   Name := TextCellName;
  1445. end; { TextCell.Name }
  1446.  
  1447. function TextCell.Format(var FHash : FormatHashTable;
  1448.                              FormulasDisplayed : Boolean) : FormatType;
  1449. var
  1450.   F : FormatType;
  1451. begin
  1452.   if FHash.Search(Loc, F) then
  1453.     Format := F
  1454.   else
  1455.     Format := 0;
  1456. end; { TextCell.Format }
  1457.  
  1458. function TextCell.Width(var FHash : FormatHashTable;
  1459.                             FormulasDisplayed : Boolean) : Word;
  1460. begin
  1461.   Width := Txt^.Length;
  1462. end; { TextCell.Width }
  1463.  
  1464. function TextCell.Overwritten(var CHash : CellHashTable;
  1465.                                    var FHash : FormatHashTable;
  1466.                                    var WHash : WidthHashTable;
  1467.                                    var LastPos : CellPos;
  1468.                                    MaxCols : Word;
  1469.                                    GetColWidth : GetColWidthFunc;
  1470.                                    FormulasDisplayed : Boolean) : Word;
  1471. var
  1472.   CellWidth : Longint;
  1473.   Total : Word;
  1474.   P : CellPos;
  1475. begin
  1476.   P := Loc;
  1477.   CellWidth := Width(FHash, FormulasDisplayed);
  1478.   Total := 0;
  1479.   repeat
  1480.     Inc(Total);
  1481.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  1482.     Inc(P.Col);
  1483.   until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
  1484.   Dec(Total);
  1485.   Overwritten := Total;
  1486. end; { TextCell.Overwritten }
  1487.  
  1488. function TextCell.ShouldUpdate : Boolean;
  1489. begin
  1490.   ShouldUpdate := False;
  1491. end; { TextCell.ShouldUpdate }
  1492.  
  1493. function TextCell.HasError : Boolean;
  1494. begin
  1495.   HasError := False;
  1496. end; { TextCell.HasError }
  1497.  
  1498. function TextCell.CurrValue : Extended;
  1499. begin
  1500.   CurrValue := 0;
  1501. end; { TextCell.CurrValue }
  1502.  
  1503. function TextCell.OverwriteStart(var FHash : FormatHashTable;
  1504.                                  var WHash : WidthHashTable;
  1505.                                  GetColWidth : GetColWidthFunc;
  1506.                                  EndCol : Word;
  1507.                                  DisplayFormulas : Boolean) : Word;
  1508. var
  1509.   F : FormatType;
  1510.   C, Place : Word;
  1511. begin
  1512.   F := Format(FHash, DisplayFormulas);
  1513.   Place := 1;
  1514.   C := Loc.Col;
  1515.   repeat
  1516.     Inc(Place, GetColWidth(WHash, C));
  1517.     Inc(C);
  1518.   until C = EndCol;
  1519.   OverwriteStart := Place;
  1520. end; { TextCell.OverwriteStart }
  1521.  
  1522. procedure TextCell.EditString(MaxDecPlaces : Byte;
  1523.                               var L : LStringPtr);
  1524. var
  1525.   Good : Boolean;
  1526. begin
  1527.   Good := L^.Assign(Txt^);
  1528. end; { TextCell.EditString }
  1529.  
  1530. function TextCell.DisplayString(FormulasDisplayed : Boolean;
  1531.                                       MaxDecPlaces : Byte) : String;
  1532. begin
  1533.   DisplayString := Txt^.Copy(2, Scr.CurrCols);
  1534. end; { TextCell.DisplayString }
  1535.  
  1536. function TextCell.FormattedString(var OHash : OverwriteHashTable;
  1537.                                   var FHash : FormatHashTable;
  1538.                                   var WHash : WidthHashTable;
  1539.                                   GetColWidth : GetColWidthFunc;
  1540.                                   CPos : CellPos;
  1541.                                   FormulasDisplayed : Boolean;
  1542.                                   Start : Word; ColWidth : Byte;
  1543.                                   var DString : DollarStr;
  1544.                                   var Color : Byte) : String;
  1545. begin
  1546.   DString := '';
  1547.   Color := Colors.TextCellColor;
  1548.   FormattedString := Txt^.Copy(Succ(Start), ColWidth);
  1549. end; { TextCell.FormattedString }
  1550.  
  1551. function TextCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1552.                              var L : LStringPtr) : LStringPtr;
  1553. var
  1554.   Good : Boolean;
  1555. begin
  1556.   Good := L^.Assign(Txt^);
  1557.   CopyString := L;
  1558. end; { TextCell.CopyString }
  1559.  
  1560. constructor TextCell.Load(var S : TDosStream);
  1561. begin
  1562.   S.Read(Loc, SizeOf(Loc));
  1563.   Txt := New(LStringPtr, Init);
  1564.   if Txt = nil then
  1565.   begin
  1566.     S.Error(NoMemory, 0);
  1567.     Exit;
  1568.   end;
  1569.   if not Txt^.FromStream(S) then
  1570.   begin
  1571.     Dispose(Txt, Done);
  1572.     S.Error(NoMemory, 0);
  1573.   end;
  1574. end; { TextCell.Load }
  1575.  
  1576. procedure TextCell.Store(var S : TDosStream);
  1577. begin
  1578.   S.Write(Loc, SizeOf(Loc));
  1579.   Txt^.ToStream(S);
  1580. end; { TextCell.Store }
  1581.  
  1582. constructor FormulaCell.Init(InitLoc : CellPos; InitError : Boolean;
  1583.                              InitValue : Extended; InitFormula : LStringPtr);
  1584. begin
  1585.   Cell.Init(InitLoc);
  1586.   Formula := New(LStringPtr, Init);
  1587.   if Formula = nil then
  1588.     Fail;
  1589.   if not Formula^.Assign(InitFormula^) then
  1590.   begin
  1591.     Done;
  1592.     Fail;
  1593.   end;
  1594.   Error := InitError;
  1595.   Value := InitValue;
  1596. end; { FormulaCell.Init }
  1597.  
  1598. destructor FormulaCell.Done;
  1599. begin
  1600.   Dispose(Formula, Done);
  1601. end; { FormulaCell.Done }
  1602.  
  1603. function FormulaCell.CellType : CellTypes;
  1604. begin
  1605.   CellType := ClFormula;
  1606. end; { FormulaCell.CellType }
  1607.  
  1608. function FormulaCell.LegalValue : Boolean;
  1609. begin
  1610.   LegalValue := True;
  1611. end; { FormulaCell.LegalValue }
  1612.  
  1613. function FormulaCell.Name : String;
  1614. begin
  1615.   Name := FormulaCellName;
  1616. end; { FormulaCell.Name }
  1617.  
  1618. function FormulaCell.Format(var FHash : FormatHashTable;
  1619.                                 FormulasDisplayed : Boolean) : FormatType;
  1620. var
  1621.   F : FormatType;
  1622. begin
  1623.   if FHash.Search(Loc, F) then
  1624.     Format := F
  1625.   else if FormulasDisplayed then
  1626.     Format := 0
  1627.   else
  1628.     Format := (Ord(JRight) shl 4) + 4;
  1629. end; { FormulaCell.Format }
  1630.  
  1631. function FormulaCell.Width(var FHash : FormatHashTable;
  1632.                                FormulasDisplayed : Boolean) : Word;
  1633. var
  1634.   S : String;
  1635.   F : Byte;
  1636.   P, W : Word;
  1637. begin
  1638.   if FormulasDisplayed then
  1639.     Width := Formula^.Length
  1640.   else begin
  1641.     F := Format(FHash, FormulasDisplayed);
  1642.     Str(Value:1:(F and DecPlacesPart), S);
  1643.     W := Length(S);
  1644.     if (F and DollarPart) <> 0 then
  1645.       Inc(W, Length(DollarString));
  1646.     if (F and CommasPart) <> 0 then
  1647.     begin
  1648.       P := Pos('.', S);
  1649.       if P = 0 then
  1650.         P := Length(S);
  1651.       Inc(W, (P - 2) div 3);
  1652.     end;
  1653.     Width := W;
  1654.   end;
  1655. end; { FormulaCell.Width }
  1656.  
  1657. function FormulaCell.Overwritten(var CHash : CellHashTable;
  1658.                                       var FHash : FormatHashTable;
  1659.                                       var WHash : WidthHashTable;
  1660.                                       var LastPos : CellPos;
  1661.                                       MaxCols : Word;
  1662.                                       GetColWidth : GetColWidthFunc;
  1663.                                       FormulasDisplayed : Boolean) : Word;
  1664. var
  1665.   CellWidth : Longint;
  1666.   Total : Word;
  1667.   P : CellPos;
  1668. begin
  1669.   P := Loc;
  1670.   CellWidth := Width(FHash, FormulasDisplayed);
  1671.   Total := 0;
  1672.   repeat
  1673.     Inc(Total);
  1674.     Dec(CellWidth, GetColWidth(WHash, P.Col));
  1675.     Inc(P.Col);
  1676.   until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
  1677.   Dec(Total);
  1678.   Overwritten := Total;
  1679. end; { FormulaCell.Overwritten }
  1680.  
  1681. function FormulaCell.ShouldUpdate : Boolean;
  1682. begin
  1683.   ShouldUpdate := True;
  1684. end; { FormulaCell.ShouldUpdate }
  1685.  
  1686. function FormulaCell.HasError : Boolean;
  1687. begin
  1688.   HasError := Error;
  1689. end; { FormulaCell.HasError }
  1690.  
  1691. function FormulaCell.CurrValue : Extended;
  1692. begin
  1693.   CurrValue := Value;
  1694. end; { FormulaCell.CurrValue }
  1695.  
  1696. function FormulaCell.OverwriteStart(var FHash : FormatHashTable;
  1697.                                     var WHash : WidthHashTable;
  1698.                                     GetColWidth : GetColWidthFunc;
  1699.                                     EndCol : Word;
  1700.                                     DisplayFormulas : Boolean) : Word;
  1701. var
  1702.   F : FormatType;
  1703.   C, Place : Word;
  1704. begin
  1705.   F := Format(FHash, DisplayFormulas);
  1706.   Place := 1;
  1707.   C := Loc.Col;
  1708.   repeat
  1709.     Inc(Place, GetColWidth(WHash, C));
  1710.     Inc(C);
  1711.   until C = EndCol;
  1712.   if (not DisplayFormulas) and ((F and DollarPart) <> 0) then
  1713.     Dec(Place, Length(DollarString));
  1714.   OverwriteStart := Place;
  1715. end; { FormulaCell.OverwriteStart }
  1716.  
  1717. procedure FormulaCell.EditString(MaxDecPlaces : Byte;
  1718.                                        var L : LStringPtr);
  1719. var
  1720.   Good : Boolean;
  1721. begin
  1722.   Good := L^.Assign(Formula^);
  1723. end; { FormulaCell.EditString }
  1724.  
  1725. function FormulaCell.DisplayString(FormulasDisplayed : Boolean;
  1726.                                          MaxDecPlaces : Byte) : String;
  1727. var
  1728.   S : String;
  1729. begin
  1730.   if not FormulasDisplayed then
  1731.     DisplayString := Formula^.ToString
  1732.   else begin
  1733.     Str(Value:1:MaxDecPlaces, S);
  1734.     DisplayString := S;
  1735.   end;
  1736. end; { FormulaCell.DisplayString }
  1737.  
  1738. function FormulaCell.FormattedString(var OHash : OverwriteHashTable;
  1739.                                      var FHash : FormatHashTable;
  1740.                                      var WHash : WidthHashTable;
  1741.                                      GetColWidth : GetColWidthFunc;
  1742.                                      CPos : CellPos;
  1743.                                      FormulasDisplayed : Boolean;
  1744.                                      Start : Word; ColWidth : Byte;
  1745.                                      var DString : DollarStr;
  1746.                                      var Color : Byte) : String;
  1747. var
  1748.   S : String;
  1749.   Counter : Word;
  1750.   F : FormatType;
  1751. begin
  1752.   if FormulasDisplayed then
  1753.   begin
  1754.     DString := '';
  1755.     Color := Colors.FormulaCellColor;
  1756.     FormattedString := Formula^.Copy(1, ColWidth);
  1757.   end
  1758.   else begin
  1759.     F := Format(FHash, FormulasDisplayed);
  1760.     Str(Value:1:F and DecPlacesPart, S);
  1761.     if (Start = 1) and ((F and DollarPart) <> 0) then
  1762.       DString := ' $ '
  1763.     else
  1764.       DString := '';
  1765.     if (F and CommasPart) <> 0 then
  1766.     begin
  1767.       Counter := Pos('.', S);
  1768.       if Counter = 0 then
  1769.         Counter := Length(S);
  1770.       while Counter > 4 do
  1771.       begin
  1772.         Insert(',', S, Counter - 3);
  1773.         Dec(Counter, 3);
  1774.       end;
  1775.     end;
  1776.     Color := Colors.ValueCellColor;
  1777.     FormattedString := Copy(S, Start, ColWidth);
  1778.   end;
  1779. end; { FormulaCell.FormattedString }
  1780.  
  1781. function FormulaCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1782.                                 var L : LStringPtr) : LStringPtr;
  1783. var
  1784.   Good : Boolean;
  1785. begin
  1786.   Good := L^.Assign(Formula^);
  1787.   CopyString := L;
  1788. end; { FormulaCell.CopyString }
  1789.  
  1790. constructor FormulaCell.Load(var S : TDosStream);
  1791. begin
  1792.   S.Read(Loc, SizeOf(Loc));
  1793.   Formula := New(LStringPtr, Init);
  1794.   if Formula = nil then
  1795.   begin
  1796.     S.Error(NoMemory, 0);
  1797.     Exit;
  1798.   end;
  1799.   if not Formula^.FromStream(S) then
  1800.   begin
  1801.     Dispose(Formula, Done);
  1802.     S.Error(NoMemory, 0);
  1803.   end;
  1804. end; { FormulaCell.Load }
  1805.  
  1806. procedure FormulaCell.Store(var S : TDosStream);
  1807. begin
  1808.   S.Write(Loc, SizeOf(Loc));
  1809.   Formula^.ToStream(S);
  1810. end; { FormulaCell.Store }
  1811.  
  1812. function FormulaCell.GetFormula : LStringPtr;
  1813. begin
  1814.   GetFormula := Formula;
  1815. end; { FormulaCell.GetFormula }
  1816.  
  1817. constructor RepeatCell.Init(InitLoc : CellPos; InitChar : Char);
  1818. begin
  1819.   Cell.Init(InitLoc);
  1820.   RepeatChar := InitChar;
  1821. end; { RepeatCell.Init }
  1822.  
  1823. function RepeatCell.CellType : CellTypes;
  1824. begin
  1825.   CellType := ClRepeat;
  1826. end; { RepeatCell.CellType }
  1827.  
  1828. function RepeatCell.LegalValue : Boolean;
  1829. begin
  1830.   LegalValue := False;
  1831. end; { RepeatCell.LegalValue }
  1832.  
  1833. function RepeatCell.Name : String;
  1834. begin
  1835.   Name := RepeatCellName;
  1836. end; { RepeatCell.Name }
  1837.  
  1838. function RepeatCell.Format(var FHash : FormatHashTable;
  1839.                                FormulasDisplayed : Boolean) : FormatType;
  1840. begin
  1841.   Format := 0;
  1842. end; { RepeatCell.Format }
  1843.  
  1844. function RepeatCell.Width(var FHash : FormatHashTable;
  1845.                               FormulasDisplayed : Boolean) : Word;
  1846. begin
  1847.   Width := 2;
  1848. end; { RepeatCell.Width }
  1849.  
  1850. function RepeatCell.Overwritten(var CHash : CellHashTable;
  1851.                                 var FHash : FormatHashTable;
  1852.                                 var WHash : WidthHashTable;
  1853.                                 var LastPos : CellPos;
  1854.                                 MaxCols : Word;
  1855.                                 GetColWidth : GetColWidthFunc;
  1856.                                 FormulasDisplayed : Boolean) : Word;
  1857. var
  1858.   Total : Word;
  1859.   P : CellPos;
  1860. begin
  1861.   P := Loc;
  1862.   Total := 0;
  1863.   repeat
  1864.     Inc(Total);
  1865.     Inc(P.Col);
  1866.   until (P.Col > LastPos.Col) or (CHash.Search(P) <> Empty) or
  1867.         (P.Col = 0);
  1868.   Dec(Total);
  1869.   if (P.Col > LastPos.Col) or (P.Col = 0) then
  1870.     Total := MaxCols - Loc.Col;
  1871.   Overwritten := Total;
  1872. end; { RepeatCell.Overwritten }
  1873.  
  1874. function RepeatCell.ShouldUpdate : Boolean;
  1875. begin
  1876.   ShouldUpdate := False;
  1877. end; { RepeatCell.ShouldUpdate }
  1878.  
  1879. function RepeatCell.HasError : Boolean;
  1880. begin
  1881.   HasError := False;
  1882. end; { RepeatCell.HasError }
  1883.  
  1884. function RepeatCell.CurrValue : Extended;
  1885. begin
  1886.   CurrValue := 0;
  1887. end; { RepeatCell.CurrValue }
  1888.  
  1889. function RepeatCell.OverwriteStart(var FHash : FormatHashTable;
  1890.                                    var WHash : WidthHashTable;
  1891.                                    GetColWidth : GetColWidthFunc;
  1892.                                    EndCol : Word;
  1893.                                    DisplayFormulas : Boolean) : Word;
  1894. begin
  1895.   OverwriteStart := 1;
  1896. end; { RepeatCell.OverwriteStart }
  1897.  
  1898. procedure RepeatCell.EditString(MaxDecPlaces : Byte;
  1899.                                 var L : LStringPtr);
  1900. var
  1901.   Good : Boolean;
  1902. begin
  1903.   Good := L^.FromString(RepeatFirstChar + RepeatChar);
  1904. end; { RepeatCell.EditString }
  1905.  
  1906. function RepeatCell.DisplayString(FormulasDisplayed : Boolean;
  1907.                                         MaxDecPlaces : Byte) : String;
  1908. begin
  1909.   DisplayString := FillString(Scr.CurrCols, RepeatChar);
  1910. end; { RepeatCell.DisplayString }
  1911.  
  1912. function RepeatCell.FormattedString(var OHash : OverwriteHashTable;
  1913.                                     var FHash : FormatHashTable;
  1914.                                     var WHash : WidthHashTable;
  1915.                                     GetColWidth : GetColWidthFunc;
  1916.                                     CPos : CellPos;
  1917.                                     FormulasDisplayed : Boolean;
  1918.                                     Start : Word; ColWidth : Byte;
  1919.                                     var DString : DollarStr;
  1920.                                     var Color : Byte) : String;
  1921. begin
  1922.   DString := '';
  1923.   Color := Colors.RepeatCellColor;
  1924.   FormattedString := PadChar('', RepeatChar, ColWidth);
  1925. end; { RepeatCell.FormattedString }
  1926.  
  1927. function RepeatCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
  1928.                                var L : LStringPtr) : LStringPtr;
  1929. begin
  1930.   EditString(0, L);
  1931.   CopyString := L;
  1932. end; { RepeatCell.CopyString }
  1933.  
  1934. constructor RepeatCell.Load(var S : TDosStream);
  1935. begin
  1936.   S.Read(Loc, SizeOf(Loc));
  1937.   S.Read(RepeatChar, SizeOf(RepeatChar));
  1938. end; { RepeatCell.Load }
  1939.  
  1940. procedure RepeatCell.Store(var S : TDosStream);
  1941. begin
  1942.   S.Write(Loc, SizeOf(Loc));
  1943.   S.Write(RepeatChar, SizeOf(RepeatChar));
  1944. end; { RepeatCell.Store }
  1945.  
  1946. {$F+}
  1947.  
  1948. procedure CellExit;
  1949. { Removes Empty cell from memory, restores ExitProc }
  1950. begin
  1951.   Dispose(Empty, Done);
  1952.   ExitProc := SavedExitProc;
  1953. end; { CellExit }
  1954.  
  1955. {$F-}
  1956.  
  1957. begin
  1958.   SavedExitProc := ExitProc;
  1959.   ExitProc := @CellExit;
  1960.   Empty := New(EmptyCellPtr, Init);
  1961. end.
  1962.