home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / turbo55 / install / tcalc.arc / TCCELL.PAS < prev    next >
Pascal/Delphi Source File  |  1989-05-02  |  63KB  |  1,926 lines

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