dos_compilers/Borland Turbo Pascal v55/TCCELL.PAS
2024-07-02 06:49:04 -07:00

1926 lines
61 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ Copyright (c) 1989 by Borland International, Inc. }
unit TCCell;
{ Turbo Pascal 5.5 object-oriented example cell routines.
This unit is used by TCALC.PAS.
See TCALC.DOC for an more information about this example.
}
{$N+,S-}
interface
uses Objects, TCUtil, TCLStr, TCScreen, TCHash;
const
DollarString = ' $ ';
RepeatFirstChar = '\';
TextFirstChar = ' ';
EmptyCellName = 'Empty';
ValueCellName = 'Value';
TextCellName = 'Text';
FormulaCellName = 'Formula';
RepeatCellName = 'Repeat';
DecPlacesPart = $0F;
JustShift = 4;
JustPart = $03;
DollarPart = $40;
CommasPart = $80;
NoMemory = 203;
type
SSStream = object(DosStream)
procedure RegisterTypes; virtual;
end;
CellTypes = (ClEmpty, ClValue, ClText, ClFormula, ClRepeat);
CellPos = record
Col : Word;
Row : Word;
end;
FormatType = Byte;
Justification = (JLeft, JCenter, JRight);
DollarStr = String[Length(DollarString)];
Block = object
Start, Stop : CellPos;
constructor Init(InitStart : CellPos);
function ExtendTo(NewLoc : CellPos) : Boolean;
function CellInBlock(CheckCell : CellPos) : Boolean;
end;
CellHashTablePtr = ^CellHashTable;
CellPtr = ^Cell;
CellHashTable = object(HashTable) { Keeps pointers to all cells }
CurrCell : CellPtr; { Information about the cell that is being }
CurrLoc : CellPos; { added, deleted, or searched for }
constructor Init(InitBuckets : BucketRange);
destructor Done;
function Add(ACell : CellPtr) : Boolean;
procedure Delete(DelLoc : CellPos; var DeletedCell : CellPtr);
{ Removes a cell from the hash table }
function Search(SPos : CellPos) : CellPtr;
{ Searches for a cell in the hash table }
function HashValue : Word; virtual;
{ Computes the hash value of the cell }
function Found(Item : HashItemPtr) : Boolean; virtual;
{ Returns True if the hash item being searched for is found }
procedure CreateItem(var Item : HashItemPtr); virtual;
{ Fills in the information for a new hash item }
function ItemSize : HashItemSizeRange; virtual;
procedure Load(var S : SSStream; Total : Longint);
procedure Store(var S : SSStream);
function FirstItem : CellPtr;
function NextItem : CellPtr;
end;
FormatHashTable = object(HashTable)
CurrStart, CurrStop : CellPos;
CurrFormat : FormatType;
constructor Init;
destructor Done;
function Overwrite(NewStart, NewStop : CellPos) : Boolean;
function Add(NewStart, NewStop : CellPos;
NewFormat : FormatType) : Boolean;
function Delete(DStart, DStop : CellPos) : Boolean;
function Search(SPos : CellPos; var F : FormatType) : Boolean;
function HashValue : Word; virtual;
function Found(Item : HashItemPtr) : Boolean; virtual;
procedure CreateItem(var Item : HashItemPtr); virtual;
function ItemSize : HashItemSizeRange; virtual;
procedure Load(var S : SSStream; Total : Longint);
procedure Store(var S : SSStream);
end;
WidthHashTable = object(HashTable)
CurrCol : Word;
CurrWidth : Byte;
DefaultColWidth : Byte;
constructor Init(InitBuckets : BucketRange; InitDefaultColWidth : Byte);
destructor Done;
function Add(SCol : Word; NewWidth : Byte) : Boolean;
procedure Delete(Col : Word);
function Search(Col : Word) : Byte;
function HashValue : Word; virtual;
function Found(Item : HashItemPtr) : Boolean; virtual;
procedure CreateItem(var Item : HashItemPtr); virtual;
function ItemSize : HashItemSizeRange; virtual;
function GetDefaultColWidth : Byte;
procedure Load(var S : SSStream; Total : Longint);
procedure Store(var S : SSStream);
end;
OverwriteHashTable = object(HashTable)
CurrCell : CellPtr;
CurrPos : CellPos;
EndCol : Word;
constructor Init(InitBuckets : BucketRange);
destructor Done;
function Add(SCell : CellPtr; Overwritten : Word) : Boolean;
procedure Delete(SPos : CellPos);
function Change(SCell : CellPtr; Overwritten : Word) : Boolean;
function Search(SPos : CellPos) : CellPtr;
function HashValue : Word; virtual;
function Found(Item : HashItemPtr) : Boolean; virtual;
procedure CreateItem(var Item : HashItemPtr); virtual;
function ItemSize : HashItemSizeRange; virtual;
end;
GetColWidthFunc = function(var WHash : WidthHashTable;
C : Word) : Byte;
Cell = object(Base)
Loc : CellPos;
constructor Init(InitLoc : CellPos);
destructor Done; virtual;
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
end;
EmptyCellPtr = ^EmptyCell;
EmptyCell = object(Cell)
constructor Init;
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
end;
ValueCellPtr = ^ValueCell;
ValueCell = object(Cell)
Error : Boolean;
Value : Extended; { A cell with a numeric value }
constructor Init(InitLoc : CellPos; InitError : Boolean;
InitValue : Extended);
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
constructor Load(var S : SSStream);
procedure Store(var S : SSStream);
end;
TextCellPtr = ^TextCell;
TextCell = object(Cell)
Txt : LStringPtr; { A cell with text }
constructor Init(InitLoc : CellPos; InitTxt : LStringPtr);
destructor Done; virtual;
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
constructor Load(var S : SSStream);
procedure Store(var S : SSStream);
end;
FormulaCellPtr = ^FormulaCell;
FormulaCell = object(Cell)
Error : Boolean;
Value : Extended;
Formula : LStringPtr; { A cell with a formula }
constructor Init(InitLoc : CellPos; InitError : Boolean;
InitValue : Extended; InitFormula : LStringPtr);
destructor Done; virtual;
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
constructor Load(var S : SSStream);
procedure Store(var S : SSStream);
function GetFormula : LStringPtr;
end;
RepeatCellPtr = ^RepeatCell;
RepeatCell = object(Cell)
RepeatChar : Char; { A cell with text that will repeat - used for
underlining, etc. }
constructor Init(InitLoc : CellPos; InitChar : Char);
function CellType : CellTypes; virtual;
function LegalValue : Boolean; virtual;
function Name : String; virtual;
function Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType; virtual;
function Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word; virtual;
function Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable; var LastPos : CellPos;
MaxCols : Word; GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word; virtual;
function ShouldUpdate : Boolean; virtual;
function HasError : Boolean; virtual;
function CurrValue : Extended; virtual;
function OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word; virtual;
procedure EditString(MaxDecPlaces : Byte; var L : LStringPtr); virtual;
function DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String; virtual;
function FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String; virtual;
function CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr; virtual;
constructor Load(var S : SSStream);
procedure Store(var S : SSStream);
end;
var
Empty : CellPtr; { This is a special cell. It is used as the return
value if a cell cannot be found so that the EmptyCell
methods can be executed instead of having special
routines that act differently depending on whether a
cell is found ot not. }
implementation
var
SavedExitProc : Pointer;
procedure SSStream.RegisterTypes;
{ Registers the different cell types so that they will be written out
correctly to disk }
begin
DosStream.RegisterTypes;
Register(TypeOf(ValueCell), @ValueCell.Store, @ValueCell.Load);
Register(TypeOf(TextCell), @TextCell.Store, @TextCell.Load);
Register(TypeOf(FormulaCell), @FormulaCell.Store, @FormulaCell.Load);
Register(TypeOf(RepeatCell), @RepeatCell.Store, @RepeatCell.Load);
end; { SSStream.RegisterTypes }
constructor Block.Init(InitStart : CellPos);
{ Initializes a block of cells, setting the end to be the same as the start }
begin
Start := InitStart;
Stop := Start;
end; { Block.Init }
function Block.ExtendTo(NewLoc : CellPos) : Boolean;
{ Extends a block to a new position, as long as the new position is to the
right and down from the old position }
begin
if (NewLoc.Col >= Start.Col) and (NewLoc.Row >= Start.Row) then
begin
Stop := NewLoc;
ExtendTo := True;
end
else
ExtendTo := False;
end; { Block.ExtendTo }
function Block.CellInBlock(CheckCell : CellPos) : Boolean;
{ Checks to see if a cell is inside a particular block }
begin
CellInBlock := (CheckCell.Col >= Start.Col) and
(CheckCell.Col <= Stop.Col) and
(CheckCell.Row >= Start.Row) and
(CheckCell.Row <= Stop.Row);
end; { Block.CellInBlock }
constructor CellHashTable.Init(InitBuckets : BucketRange);
{ Initializes a cell hash table, which stores pointers to the cells in a
spreadsheet }
begin
if not HashTable.Init(InitBuckets) then
Fail;
end; { CellHashTable.Init }
destructor CellHashTable.Done;
{ Removes a cell hash table from memory }
var
CP : CellPtr;
begin
CP := FirstItem;
while CP <> nil do
begin
Dispose(CP, Done);
CP := NextItem;
end;
HashTable.Done;
end; { CellHashTable.Done }
function CellHashTable.Add(ACell : CellPtr) : Boolean;
{ Adds a cell to a cell hash table }
begin
CurrCell := ACell;
CurrLoc := CurrCell^.Loc;
Add := HashTable.Add;
end; { CellHashTable.Add }
procedure CellHashTable.Delete(DelLoc : CellPos; var DeletedCell : CellPtr);
{ Deletes a cell from a cell hash table }
begin
CurrLoc := DelLoc;
HashTable.Delete(@DeletedCell);
end; { CellHashTable.Delete }
function CellHashTable.Search(SPos : CellPos) : CellPtr;
{ Searches for a cell in a cell hash table, returning the cell if found, or
returning the Empty cell if not found }
var
I : HashItemPtr;
C : CellPtr;
begin
CurrLoc := SPos;
I := HashTable.Search;
if I = nil then
Search := Empty
else begin
Move(I^.Data, C, SizeOf(C));
Search := C;
end;
end; { CellHashTable.Search }
function CellHashTable.HashValue : Word;
{ Calculates the hash value of a cell }
begin
HashValue := CurrLoc.Col + CurrLoc.Row;
end; { CellHashTable.HashValue }
function CellHashTable.Found(Item : HashItemPtr) : Boolean;
{ Checks to see if a hash item is the one searched for by comparing the
location information in both }
var
C : CellPtr;
begin
Move(Item^.Data, C, SizeOf(C));
Found := Compare(C^.Loc, CurrLoc, SizeOf(CurrLoc));
end; { CellHashTable.Found }
procedure CellHashTable.CreateItem(var Item : HashItemPtr);
{ Writes the cell poionter information out to the hash item }
begin
Move(CurrCell, Item^.Data, SizeOf(CurrCell));
end; { CellHashTable.CreateItem }
function CellHashTable.ItemSize : HashItemSizeRange;
{ The hash item size is current - just cell pointers are stored }
begin
ItemSize := SizeOf(CurrCell);
end; { CellHashTable.ItemSize }
procedure CellHashTable.Load(var S : SSStream; Total : Longint);
{ Loads a cell hash table from disk }
var
Counter : Longint;
begin
for Counter := 1 to Total do
begin
if not Add(CellPtr(S.Get)) then
begin
S.Error(NoMemory);
Exit;
end;
end;
end; { CellHashTable.Load }
procedure CellHashTable.Store(var S : SSStream);
{ Writes a cell hash table to disk }
var
CP : CellPtr;
begin
CP := FirstItem;
while CP <> nil do
begin
S.Put(CP);
CP := NextItem;
end;
end; { CellHashTable.Store }
function HashItemPtrToCellPtr(H : HashItemPtr) : CellPtr;
{ Converts a hash item pointer to a cell pointer }
var
CP : CellPtr;
begin
if H = nil then
HashItemPtrToCellPtr := nil
else begin
Move(H^.Data, CP, SizeOf(CP));
HashItemPtrToCellPtr := CP;
end;
end; { HashItemPtrToCellPtr }
function CellHashTable.FirstItem : CellPtr;
{ Returns the first hash item in a cell hash table }
begin
FirstItem := HashItemPtrToCellPtr(HashTable.FirstItem);
end; { CellHashTable.FirstItem }
function CellHashTable.NextItem : CellPtr;
{ Returns the second and subsequent hash items in a cell hash table }
begin
NextItem := HashItemPtrToCellPtr(HashTable.NextItem);
end; { CellHashTable.NextItem }
constructor WidthHashTable.Init(InitBuckets : BucketRange;
InitDefaultColWidth : Byte);
{ Initializes the width hash table, which stores column widths that are
different than the default. It stores the column and the width in the
hash table }
begin
if not HashTable.Init(InitBuckets) then
Fail;
DefaultColWidth := InitDefaultColWidth;
end; { WidthHashTable.Init }
destructor WidthHashTable.Done;
begin
HashTable.Done;
end; { WidthHashTable.Done }
function WidthHashTable.Add(SCol : Word; NewWidth : Byte) : Boolean;
begin
CurrCol := SCol;
CurrWidth := NewWidth;
Add := HashTable.Add;
end; { WidthHashTable }
procedure WidthHashTable.Delete(Col : Word);
begin
CurrCol := Col;
HashTable.Delete(nil);
end; { WidthHashTable.Delete }
function WidthHashTable.Search(Col : Word) : Byte;
var
I : HashItemPtr;
W : Byte;
begin
CurrCol := Col;
I := HashTable.Search;
if I = nil then
Search := 0
else begin
Move(I^.Data[SizeOf(CurrCol)], W, SizeOf(W));
Search := W;
end;
end; { WidthHashTable.Search }
function WidthHashTable.HashValue : Word;
begin
HashValue := CurrCol;
end; { WidthHashTable.HashValue }
function WidthHashTable.Found(Item : HashItemPtr) : Boolean;
var
C : Word;
begin
Move(Item^.Data, C, SizeOf(C));
Found := CurrCol = C;
end; { WidthHashTable.Found }
procedure WidthHashTable.CreateItem(var Item : HashItemPtr);
begin
Move(CurrCol, Item^.Data, SizeOf(CurrCol));
Move(CurrWidth, Item^.Data[SizeOf(CurrCol)], SizeOf(CurrWidth));
end; { WidthHashTable.CreateItem }
function WidthHashTable.ItemSize : HashItemSizeRange;
begin
ItemSize := SizeOf(CurrCol) + SizeOf(CurrWidth);
end; { WidthHashTable.ItemSize }
function WidthHashTable.GetDefaultColWidth : Byte;
begin
GetDefaultColWidth := DefaultColWidth;
end; { WidthHashTable.GetDefaultColWidth }
procedure WidthHashTable.Load(var S : SSStream; Total : Longint);
var
Counter : Longint;
Col : Word;
Width : Byte;
begin
for Counter := 1 to Total do
begin
S.Read(Col, SizeOf(Col));
S.Read(Width, SizeOf(Width));
if not Add(Col, Width) then
begin
S.Error(NoMemory);
Exit;
end;
end;
end; { WidthHashTable.Load }
procedure WidthHashTable.Store(var S : SSStream);
var
H : HashItemPtr;
Col : Word;
Width : Byte;
begin
H := FirstItem;
while H <> nil do
begin
Move(H^.Data, Col, SizeOf(Col));
S.Write(Col, SizeOf(Col));
Move(H^.Data[SizeOf(Col)], Width, SizeOf(Width));
S.Write(Width, SizeOf(Width));
H := NextItem;
end;
end; { WidthHashTable.Store }
constructor FormatHashTable.Init;
{ Initializes a format hash table, which is used to store formatted areas
that differ from the default. The area and the format are stored in the
hash table }
begin
if not HashTable.Init(1) then { Use a single bucket so that a search
Fail; will be possible }
end; { FormatHashTable.Init }
destructor FormatHashTable.Done;
begin
HashTable.Done;
end; { FormatHashTable.Done }
function FormatHashTable.Overwrite(NewStart, NewStop : CellPos) : Boolean;
{ Checks to see if a new format area has overwritten an old one, requiring
the old area to be overwritten or broken into parts }
var
H : HashItemPtr;
AStart, AStop, BStart, BStop : CellPos;
OldF, F : FormatType;
P : CellPos;
Added : Boolean;
begin
Overwrite := False;
H := HashData^[1];
while H <> nil do
begin
Move(H^.Data, BStart, SizeOf(CellPos));
Move(H^.Data[SizeOf(CellPos)], BStop, SizeOf(CellPos));
if ((((NewStart.Col >= BStart.Col) and (NewStart.Col <= BStop.Col)) or
((NewStop.Col >= BStart.Col) and (NewStop.Col <= BStop.Col))) and
(((NewStart.Row >= BStart.Row) and (NewStart.Row <= BStop.Row)) or
((NewStop.Row >= BStart.Row) and (NewStop.Row <= BStop.Row)))) or
((((BStart.Col >= NewStart.Col) and (BStart.Col <= NewStop.Col)) or
((BStop.Col >= NewStart.Col) and (BStop.Col <= NewStop.Col))) and
(((BStart.Row >= NewStart.Row) and (BStart.Row <= NewStop.Row)) or
((BStop.Row >= NewStart.Row) and (BStop.Row <= NewStop.Row)))) then
begin
Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
CurrStart := BStart;
CurrStop := BStop;
HashTable.Delete(nil);
if BStart.Row < NewStart.Row then
begin
AStart := BStart;
AStop.Col := BStop.Col;
AStop.Row := Pred(NewStart.Row);
if not Add(AStart, AStop, F) then
Exit;
end;
if BStop.Row > NewStop.Row then
begin
AStart.Col := BStart.Col;
AStart.Row := Succ(NewStop.Row);
AStop.Col := BStop.Col;
AStop.Row := BStop.Row;
if not Add(AStart, AStop, F) then
Exit;
end;
if BStart.Col < NewStart.Col then
begin
AStart.Col := BStart.Col;
AStart.Row := Max(BStart.Row, NewStart.Row);
AStop.Col := Pred(NewStart.Col);
AStop.Row := Min(BStop.Row, NewStop.Row);
if not Add(AStart, AStop, F) then
Exit;
end;
if BStop.Col > NewStop.Col then
begin
AStart.Col := Succ(NewStop.Col);
AStart.Row := Max(BStart.Row, NewStart.Row);
AStop.Col := BStop.Col;
AStop.Row := Min(BStop.Row, NewStop.Row);
if not Add(AStart, AStop, F) then
Exit;
end;
end;
H := H^.Next;
end;
Overwrite := True;
end; { FormatHashTable.Overwrite }
function FormatHashTable.Add(NewStart, NewStop : CellPos;
NewFormat : FormatType) : Boolean;
begin
if not Overwrite(NewStart, NewStop) then
begin
Add := False;
Exit;
end;
CurrStart := NewStart;
CurrStop := NewStop;
CurrFormat := NewFormat;
Add := HashTable.Add;
end; { FormatHashTable.Add }
function FormatHashTable.Delete(DStart, DStop : CellPos) : Boolean;
begin
Delete := Overwrite(DStart, DStop);
end; { FormatHashTable.Delete }
function FormatHashTable.Search(SPos : CellPos; var F : FormatType) :
Boolean;
var
H : HashItemPtr;
begin
CurrStart := SPos;
H := HashTable.Search;
if H = nil then
Search := False
else begin
Move(H^.Data[SizeOf(CellPos) shl 1], F, SizeOf(F));
Search := True;
end;
end; { FormatHashTable.Search }
function FormatHashTable.HashValue : Word;
{ Since the hash table has only one bucket, the hash value is always 1 }
begin
HashValue := 1;
end; { FormatHashTable.HashValue }
function FormatHashTable.Found(Item : HashItemPtr) : Boolean;
var
P : CellPos;
B : Block;
Start, Stop : CellPos;
Good : Boolean;
begin
Move(Item^.Data, Start, SizeOf(CellPos));
Move(Item^.Data[SizeOf(CellPos)], Stop, SizeOf(CellPos));
B.Init(Start);
B.Stop := Stop;
Found := B.CellInBlock(CurrStart);
end; { FormatHashTable.Found }
procedure FormatHashTable.CreateItem(var Item : HashItemPtr);
begin
with Item^ do
begin
Move(CurrStart, Data, SizeOf(CellPos));
Move(CurrStop, Data[SizeOf(CellPos)], SizeOf(CellPos));
Move(CurrFormat, Data[SizeOf(CellPos) shl 1], SizeOf(CurrFormat));
end; { with }
end; { FormatHashTable.CreateItem }
function FormatHashTable.ItemSize : HashItemSizeRange;
begin
ItemSize := (SizeOf(CellPos) shl 1) + SizeOf(FormatType);
end; { FormatHashTable.ItemSize }
procedure FormatHashTable.Load(var S : SSStream; Total : Longint);
var
Counter : Longint;
C1, C2 : CellPos;
Format : FormatType;
begin
for Counter := 1 to Total do
begin
S.Read(C1, SizeOf(C1));
S.Read(C2, SizeOf(C2));
S.Read(Format, SizeOf(Format));
if not Add(C1, C2, Format) then
begin
S.Error(NoMemory);
Exit;
end;
end;
end; { FormatHashTable.Load }
procedure FormatHashTable.Store(var S : SSStream);
var
H : HashItemPtr;
C : CellPos;
Format : Byte;
begin
H := FirstItem;
while H <> nil do
begin
Move(H^.Data, C, SizeOf(C));
S.Write(C, SizeOf(C));
Move(H^.Data[SizeOf(CellPos)], C, SizeOf(C));
S.Write(C, SizeOf(C));
Move(H^.Data[SizeOf(CellPos) shl 1], Format, SizeOf(Format));
S.Write(Format, SizeOf(Format));
H := NextItem;
end;
end; { FormatHashTable.Store }
constructor OverwriteHashTable.Init(InitBuckets : BucketRange);
{ Initializes an overwrite hash table, which keeps track of which cells are
overwritten by other cells }
begin
if not HashTable.Init(InitBuckets) then
Fail;
end; { OverwriteHashTable.Init }
destructor OverwriteHashTable.Done;
begin
HashTable.Done;
end; { OverwriteHashTable.Done }
function OverwriteHashTable.Add(SCell : CellPtr;
Overwritten : Word) : Boolean;
var
CP : CellPtr;
begin
if Overwritten = 0 then
begin
Add := True;
Exit;
end;
CP := Search(SCell^.Loc);
if CP <> Empty then
begin
if not Change(CP, Pred(SCell^.Loc.Col)) then
begin
Add := False;
Exit;
end;
end;
CurrCell := SCell;
CurrPos := SCell^.Loc;
EndCol := CurrPos.Col + Overwritten;
Add := HashTable.Add;
end; { OverwriteHashTable.Add }
procedure OverwriteHashTable.Delete(SPos : CellPos);
begin
CurrPos := SPos;
HashTable.Delete(nil);
end; { OverwriteHashTable.Delete }
function OverwriteHashTable.Change(SCell : CellPtr;
Overwritten : Word) : Boolean;
begin
if Overwritten = 0 then
begin
Delete(SCell^.Loc);
Change := True;
end
else begin
CurrCell := SCell;
CurrPos := CurrCell^.Loc;
EndCol := SCell^.Loc.Col + Overwritten;
Change := HashTable.Change;
end;
end; { OverwriteHashTable.Change }
function OverwriteHashTable.Search(SPos : CellPos) : CellPtr;
var
I : HashItemPtr;
C : CellPtr;
begin
CurrPos := SPos;
I := HashTable.Search;
if I = nil then
Search := Empty
else begin
Move(I^.Data, C, SizeOf(C));
Search := C;
end;
end; { OverwriteHashTable.Search }
function OverwriteHashTable.HashValue : Word;
begin
HashValue := CurrPos.Row;
end; { OverwriteHashTable.HashValue }
function OverwriteHashTable.Found(Item : HashItemPtr) : Boolean;
var
C : CellPtr;
E : Word;
begin
Move(Item^.Data, C, SizeOf(C));
Move(Item^.Data[SizeOf(C)], E, SizeOf(E));
with CurrPos do
Found := (Row = C^.Loc.Row) and (Col >= C^.Loc.Col) and
(Col <= E);
end; { OverwriteHashTable.Found }
procedure OverwriteHashTable.CreateItem(var Item : HashItemPtr);
begin
Move(CurrCell, Item^.Data, SizeOf(CurrCell));
Move(EndCol, Item^.Data[SizeOf(CurrCell)], SizeOf(EndCol));
end; { OverwriteHashTable.CreateItem }
function OverwriteHashTable.ItemSize : HashItemSizeRange;
begin
ItemSize := SizeOf(CurrCell) + SizeOf(EndCol);
end; { OverwriteHashTable.ItemSize }
constructor Cell.Init(InitLoc : CellPos);
{ Initializes a cell's location }
begin
Loc := InitLoc;
end; { Cell.Init }
destructor Cell.Done;
{ Frees memory used by the cell }
begin
end; { Cell.Done }
function Cell.CellType : CellTypes;
{ Returns the type of a cell - used in copying cells }
begin
Abstract('Cell.CellType');
end; { Cell.CellType }
function Cell.LegalValue : Boolean;
{ Returns True if the cell has a legal numeric value }
begin
Abstract('Cell.LegalValue');
end; { Cell.LegalValue }
function Cell.Name : String;
{ Returns the name of the cell type }
begin
Abstract('Cell.Name');
end; { Cell.Name }
function Cell.Format(var FHash : FormatHashTable; FormulasDisplayed : Boolean) :
FormatType;
{ Returns the format of a cell }
begin
Abstract('Cell.Format');
end; { Cell.Format }
function Cell.Width(var FHash : FormatHashTable; FormulasDisplayed : Boolean) :
Word;
{ Returns the width of a cell (including the cells that it will overwrite) }
begin
Abstract('Cell.Width');
end; { Cell.Width }
function Cell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
{ Calculates how many cells a cell will overwrite }
begin
Abstract('Cell.Overwritten');
end; { Cell.Overwritten }
function Cell.ShouldUpdate : Boolean;
{ Returns True if the cell needs to be updated when the spreadsheet changes }
begin
Abstract('Cell.ShouldUpdate');
end; { Cell.ShouldUpdate }
function Cell.HasError : Boolean;
{ Returns True if the cell has a numeric error in it }
begin
Abstract('Cell.HasError');
end; { Cell.HasError }
function Cell.CurrValue : Extended;
{ Returns the current numeric value of a cell }
begin
Abstract('Cell.CurrValue');
end; { Cell.CurrValue }
function Cell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc; EndCol : Word;
DisplayFormulas : Boolean) : Word;
{ Determines, for overwritten cells, where in the overwriting data they will
Start to display a value }
begin
Abstract('Cell.OverwriteStart');
end; { Cell.OverwriteStart }
procedure Cell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
{ Sets up a long string with the cell's value that can be edited }
begin
Abstract('Cell.EditString');
end; { Cell.EditString }
function Cell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
{ Returns the string that will be displayed just above the input line }
begin
Abstract('Cell.DisplayString');
end; { Cell.DisplayString }
function Cell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos; FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
{ Returns the string that will be printed in a cell }
begin
Abstract('Cell.FormattedString');
end; { Cell.FormattedString }
function Cell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
{ Copies a cell's string information to another cell's }
begin
Abstract('Cell.CopyString');
end; { Cell.CopyString }
constructor EmptyCell.Init;
var
NewLoc : CellPos;
begin
NewLoc.Col := 0;
NewLoc.Row := 0;
Cell.Init(NewLoc);
end; { EmptyCell.Init }
function EmptyCell.CellType : CellTypes;
begin
CellType := ClEmpty;
end; { EmptyCell.CellType }
function EmptyCell.LegalValue : Boolean;
begin
LegalValue := True;
end; { EmptyCell.LegalValue }
function EmptyCell.Name : String;
begin
Name := EmptyCellName;
end; { EmptyCell.Name }
function EmptyCell.Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType;
begin
Format := 0;
end; { EmptyCell.Format }
function EmptyCell.Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word;
begin
Width := 0;
end; { EmptyCell.Width }
function EmptyCell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
begin
Overwritten := 0;
end; { EmptyCell.Overwritten }
function EmptyCell.ShouldUpdate : Boolean;
begin
ShouldUpdate := False;
end; { EmptyCell.ShouldUpdate }
function EmptyCell.HasError : Boolean;
begin
HasError := False;
end; { Cell.HasError }
function EmptyCell.CurrValue : Extended;
begin
CurrValue := 0;
end; { EmptyCell.CurrValue }
function EmptyCell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
EndCol : Word;
DisplayFormulas : Boolean) : Word;
begin
OverwriteStart := 1;
end; { EmptyCell.OverwriteStart }
procedure EmptyCell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
var
Good : Boolean;
begin
Good := L^.FromString('');
end; { EmptyCell.EditString }
function EmptyCell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
begin
DisplayString := '';
end; { EmptyCell.DisplayString }
function EmptyCell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos;
FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
var
CP : CellPtr;
begin
CP := OHash.Search(CPos);
if CP <> Empty then
FormattedString := CP^.FormattedString(OHash, FHash, WHash, GetColWidth,
Loc, FormulasDisplayed,
CP^.OverWriteStart(FHash, WHash,
GetColWidth, CPos.Col,
FormulasDisplayed), ColWidth,
DString, Color)
else begin
FormattedString := '';
DString := '';
Color := Colors.BlankColor;
end;
end; { EmptyCell.FormattedString }
function EmptyCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
begin
CopyString := L;
end; { EmptyCell.CopyString }
constructor ValueCell.Init(InitLoc : CellPos; InitError : Boolean;
InitValue : Extended);
begin
Cell.Init(InitLoc);
Error := InitError;
Value := InitValue;
end; { ValueCell.Init }
function ValueCell.CellType : CellTypes;
begin
CellType := ClValue;
end; { ValueCell.CellType }
function ValueCell.LegalValue : Boolean;
begin
LegalValue := True;
end; { ValueCell.LegalValue }
function ValueCell.Name : String;
begin
Name := ValueCellName;
end; { ValueCell.Name }
function ValueCell.Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType;
var
F : FormatType;
begin
if FHash.Search(Loc, F) then
Format := F
else
Format := (Ord(JRight) shl 4) + 4;
end; { ValueCell.Format }
function ValueCell.Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word;
var
S : String;
F : FormatType;
P, W : Word;
begin
F := Format(FHash, FormulasDisplayed);
Str(Value:1:(F and DecPlacesPart), S);
W := Length(S);
if (F and DollarPart) <> 0 then
Inc(W, Length(DollarString));
if (F and CommasPart) <> 0 then
begin
P := Pos('.', S);
if P = 0 then
P := Length(S);
Inc(W, (P - 2) div 3);
end;
Width := W;
end; { ValueCell.Width }
function ValueCell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
var
CellWidth : Longint;
Total : Word;
P : CellPos;
begin
P := Loc;
CellWidth := Width(FHash, FormulasDisplayed);
Total := 0;
repeat
Inc(Total);
Dec(CellWidth, GetColWidth(WHash, P.Col));
Inc(P.Col);
until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
Dec(Total);
Overwritten := Total;
end; { ValueCell.Overwritten }
function ValueCell.ShouldUpdate : Boolean;
begin
ShouldUpdate := False;
end; { ValueCell.ShouldUpdate }
function ValueCell.HasError : Boolean;
begin
HasError := Error;
end; { ValueCell.HasError }
function ValueCell.CurrValue : Extended;
begin
CurrValue := Value;
end; { ValueCell.CurrValue }
function ValueCell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
EndCol : Word;
DisplayFormulas : Boolean) : Word;
var
F : FormatType;
C, Place : Word;
begin
F := Format(FHash, DisplayFormulas);
Place := 1;
C := Loc.Col;
repeat
Inc(Place, GetColWidth(WHash, C));
Inc(C);
until C = EndCol;
if (F and DollarPart) <> 0 then
Dec(Place, Length(DollarString));
OverwriteStart := Place;
end; { ValueCell.OverwriteStart }
procedure ValueCell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
var
S : String;
Good : Boolean;
begin
Str(Value:1:MaxDecPlaces, S);
Good := L^.FromString(S);
end; { ValueCell.EditString }
function ValueCell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
var
S : String;
begin
Str(Value:1:MaxDecPlaces, S);
DisplayString := S;
end; { ValueCell.DisplayString }
function ValueCell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos;
FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
var
Counter : Word;
S : String;
F : FormatType;
begin
F := Format(FHash, FormulasDisplayed);
Str(Value:1:F and DecPlacesPart, S);
if (Start = 1) and ((F and DollarPart) <> 0) then
DString := ' $ '
else
DString := '';
if (F and CommasPart) <> 0 then
begin
Counter := Pos('.', S);
if Counter = 0 then
Counter := System.Length(S);
while Counter > 4 do
begin
System.Insert(',', S, Counter - 3);
Dec(Counter, 3);
end;
end;
Color := Colors.ValueCellColor;
FormattedString := Copy(S, Start, ColWidth);
end; { ValueCell.FormattedString }
function ValueCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
begin
CopyString := L;
end; { ValueCell.CopyString }
constructor ValueCell.Load(var S : SSStream);
begin
S.Read(Loc, SizeOf(Loc));
S.Read(Error, SizeOf(Error));
S.Read(Value, SizeOf(Value));
end; { ValueCell.Load }
procedure ValueCell.Store(var S : SSStream);
begin
S.Write(Loc, SizeOf(Loc));
S.Write(Error, SizeOf(Error));
S.Write(Value, SizeOf(Value));
end; { ValueCell.Store }
constructor TextCell.Init(InitLoc : CellPos; InitTxt : LStringPtr);
begin
Cell.Init(InitLoc);
Txt := New(LStringPtr, Init);
if Txt = nil then
Fail;
if not Txt^.Assign(InitTxt^) then
begin
Done;
Fail;
end;
end; { TextCell.Init }
destructor TextCell.Done;
begin
Dispose(Txt, Done);
end; { TextCell.Done }
function TextCell.CellType : CellTypes;
begin
CellType := ClText;
end; { TextCell.CellType }
function TextCell.LegalValue : Boolean;
begin
LegalValue := False;
end; { TextCell.LegalValue }
function TextCell.Name : String;
begin
Name := TextCellName;
end; { TextCell.Name }
function TextCell.Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType;
var
F : FormatType;
begin
if FHash.Search(Loc, F) then
Format := F
else
Format := 0;
end; { TextCell.Format }
function TextCell.Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word;
begin
Width := Txt^.Length;
end; { TextCell.Width }
function TextCell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
var
CellWidth : Longint;
Total : Word;
P : CellPos;
begin
P := Loc;
CellWidth := Width(FHash, FormulasDisplayed);
Total := 0;
repeat
Inc(Total);
Dec(CellWidth, GetColWidth(WHash, P.Col));
Inc(P.Col);
until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
Dec(Total);
Overwritten := Total;
end; { TextCell.Overwritten }
function TextCell.ShouldUpdate : Boolean;
begin
ShouldUpdate := False;
end; { TextCell.ShouldUpdate }
function TextCell.HasError : Boolean;
begin
HasError := False;
end; { TextCell.HasError }
function TextCell.CurrValue : Extended;
begin
CurrValue := 0;
end; { TextCell.CurrValue }
function TextCell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
EndCol : Word;
DisplayFormulas : Boolean) : Word;
var
F : FormatType;
C, Place : Word;
begin
F := Format(FHash, DisplayFormulas);
Place := 1;
C := Loc.Col;
repeat
Inc(Place, GetColWidth(WHash, C));
Inc(C);
until C = EndCol;
OverwriteStart := Place;
end; { TextCell.OverwriteStart }
procedure TextCell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
var
Good : Boolean;
begin
Good := L^.Assign(Txt^);
end; { TextCell.EditString }
function TextCell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
begin
DisplayString := Txt^.Copy(2, Scr.CurrCols);
end; { TextCell.DisplayString }
function TextCell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos;
FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
begin
DString := '';
Color := Colors.TextCellColor;
FormattedString := Txt^.Copy(Succ(Start), ColWidth);
end; { TextCell.FormattedString }
function TextCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
var
Good : Boolean;
begin
Good := L^.Assign(Txt^);
CopyString := L;
end; { TextCell.CopyString }
constructor TextCell.Load(var S : SSStream);
begin
S.Read(Loc, SizeOf(Loc));
Txt := New(LStringPtr, Init);
if Txt = nil then
begin
S.Error(NoMemory);
Exit;
end;
if not Txt^.FromStream(S) then
begin
Dispose(Txt, Done);
S.Error(NoMemory);
end;
end; { TextCell.Load }
procedure TextCell.Store(var S : SSStream);
begin
S.Write(Loc, SizeOf(Loc));
Txt^.ToStream(S);
end; { TextCell.Store }
constructor FormulaCell.Init(InitLoc : CellPos; InitError : Boolean;
InitValue : Extended; InitFormula : LStringPtr);
begin
Cell.Init(InitLoc);
Formula := New(LStringPtr, Init);
if Formula = nil then
Fail;
if not Formula^.Assign(InitFormula^) then
begin
Done;
Fail;
end;
Error := InitError;
Value := InitValue;
end; { FormulaCell.Init }
destructor FormulaCell.Done;
begin
Dispose(Formula, Done);
end; { FormulaCell.Done }
function FormulaCell.CellType : CellTypes;
begin
CellType := ClFormula;
end; { FormulaCell.CellType }
function FormulaCell.LegalValue : Boolean;
begin
LegalValue := True;
end; { FormulaCell.LegalValue }
function FormulaCell.Name : String;
begin
Name := FormulaCellName;
end; { FormulaCell.Name }
function FormulaCell.Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType;
var
F : FormatType;
begin
if FHash.Search(Loc, F) then
Format := F
else if FormulasDisplayed then
Format := 0
else
Format := (Ord(JRight) shl 4) + 4;
end; { FormulaCell.Format }
function FormulaCell.Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word;
var
S : String;
F : Byte;
P, W : Word;
begin
if FormulasDisplayed then
Width := Formula^.Length
else begin
F := Format(FHash, FormulasDisplayed);
Str(Value:1:(F and DecPlacesPart), S);
W := Length(S);
if (F and DollarPart) <> 0 then
Inc(W, Length(DollarString));
if (F and CommasPart) <> 0 then
begin
P := Pos('.', S);
if P = 0 then
P := Length(S);
Inc(W, (P - 2) div 3);
end;
Width := W;
end;
end; { FormulaCell.Width }
function FormulaCell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
var
CellWidth : Longint;
Total : Word;
P : CellPos;
begin
P := Loc;
CellWidth := Width(FHash, FormulasDisplayed);
Total := 0;
repeat
Inc(Total);
Dec(CellWidth, GetColWidth(WHash, P.Col));
Inc(P.Col);
until (CellWidth <= 0) or (P.Col = MaxCols) or (CHash.Search(P) <> Empty);
Dec(Total);
Overwritten := Total;
end; { FormulaCell.Overwritten }
function FormulaCell.ShouldUpdate : Boolean;
begin
ShouldUpdate := True;
end; { FormulaCell.ShouldUpdate }
function FormulaCell.HasError : Boolean;
begin
HasError := Error;
end; { FormulaCell.HasError }
function FormulaCell.CurrValue : Extended;
begin
CurrValue := Value;
end; { FormulaCell.CurrValue }
function FormulaCell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
EndCol : Word;
DisplayFormulas : Boolean) : Word;
var
F : FormatType;
C, Place : Word;
begin
F := Format(FHash, DisplayFormulas);
Place := 1;
C := Loc.Col;
repeat
Inc(Place, GetColWidth(WHash, C));
Inc(C);
until C = EndCol;
if (not DisplayFormulas) and ((F and DollarPart) <> 0) then
Dec(Place, Length(DollarString));
OverwriteStart := Place;
end; { FormulaCell.OverwriteStart }
procedure FormulaCell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
var
Good : Boolean;
begin
Good := L^.Assign(Formula^);
end; { FormulaCell.EditString }
function FormulaCell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
var
S : String;
begin
if not FormulasDisplayed then
DisplayString := Formula^.ToString
else begin
Str(Value:1:MaxDecPlaces, S);
DisplayString := S;
end;
end; { FormulaCell.DisplayString }
function FormulaCell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos;
FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
var
S : String;
Counter : Word;
F : FormatType;
begin
if FormulasDisplayed then
begin
DString := '';
Color := Colors.FormulaCellColor;
FormattedString := Formula^.Copy(1, ColWidth);
end
else begin
F := Format(FHash, FormulasDisplayed);
Str(Value:1:F and DecPlacesPart, S);
if (Start = 1) and ((F and DollarPart) <> 0) then
DString := ' $ '
else
DString := '';
if (F and CommasPart) <> 0 then
begin
Counter := Pos('.', S);
if Counter = 0 then
Counter := Length(S);
while Counter > 4 do
begin
Insert(',', S, Counter - 3);
Dec(Counter, 3);
end;
end;
Color := Colors.ValueCellColor;
FormattedString := Copy(S, Start, ColWidth);
end;
end; { FormulaCell.FormattedString }
function FormulaCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
var
Good : Boolean;
begin
Good := L^.Assign(Formula^);
CopyString := L;
end; { FormulaCell.CopyString }
constructor FormulaCell.Load(var S : SSStream);
begin
S.Read(Loc, SizeOf(Loc));
Formula := New(LStringPtr, Init);
if Formula = nil then
begin
S.Error(NoMemory);
Exit;
end;
if not Formula^.FromStream(S) then
begin
Dispose(Formula, Done);
S.Error(NoMemory);
end;
end; { FormulaCell.Load }
procedure FormulaCell.Store(var S : SSStream);
begin
S.Write(Loc, SizeOf(Loc));
Formula^.ToStream(S);
end; { FormulaCell.Store }
function FormulaCell.GetFormula : LStringPtr;
begin
GetFormula := Formula;
end; { FormulaCell.GetFormula }
constructor RepeatCell.Init(InitLoc : CellPos; InitChar : Char);
begin
Cell.Init(InitLoc);
RepeatChar := InitChar;
end; { RepeatCell.Init }
function RepeatCell.CellType : CellTypes;
begin
CellType := ClRepeat;
end; { RepeatCell.CellType }
function RepeatCell.LegalValue : Boolean;
begin
LegalValue := False;
end; { RepeatCell.LegalValue }
function RepeatCell.Name : String;
begin
Name := RepeatCellName;
end; { RepeatCell.Name }
function RepeatCell.Format(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : FormatType;
begin
Format := 0;
end; { RepeatCell.Format }
function RepeatCell.Width(var FHash : FormatHashTable;
FormulasDisplayed : Boolean) : Word;
begin
Width := 2;
end; { RepeatCell.Width }
function RepeatCell.Overwritten(var CHash : CellHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
var LastPos : CellPos;
MaxCols : Word;
GetColWidth : GetColWidthFunc;
FormulasDisplayed : Boolean) : Word;
var
Total : Word;
P : CellPos;
begin
P := Loc;
Total := 0;
repeat
Inc(Total);
Inc(P.Col);
until (P.Col > LastPos.Col) or (CHash.Search(P) <> Empty) or
(P.Col = 0);
Dec(Total);
if (P.Col > LastPos.Col) or (P.Col = 0) then
Total := MaxCols - Loc.Col;
Overwritten := Total;
end; { RepeatCell.Overwritten }
function RepeatCell.ShouldUpdate : Boolean;
begin
ShouldUpdate := False;
end; { RepeatCell.ShouldUpdate }
function RepeatCell.HasError : Boolean;
begin
HasError := False;
end; { RepeatCell.HasError }
function RepeatCell.CurrValue : Extended;
begin
CurrValue := 0;
end; { RepeatCell.CurrValue }
function RepeatCell.OverwriteStart(var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
EndCol : Word;
DisplayFormulas : Boolean) : Word;
begin
OverwriteStart := 1;
end; { RepeatCell.OverwriteStart }
procedure RepeatCell.EditString(MaxDecPlaces : Byte;
var L : LStringPtr);
var
Good : Boolean;
begin
Good := L^.FromString(RepeatFirstChar + RepeatChar);
end; { RepeatCell.EditString }
function RepeatCell.DisplayString(FormulasDisplayed : Boolean;
MaxDecPlaces : Byte) : String;
begin
DisplayString := FillString(Scr.CurrCols, RepeatChar);
end; { RepeatCell.DisplayString }
function RepeatCell.FormattedString(var OHash : OverwriteHashTable;
var FHash : FormatHashTable;
var WHash : WidthHashTable;
GetColWidth : GetColWidthFunc;
CPos : CellPos;
FormulasDisplayed : Boolean;
Start : Word; ColWidth : Byte;
var DString : DollarStr;
var Color : Byte) : String;
begin
DString := '';
Color := Colors.RepeatCellColor;
FormattedString := PadChar('', RepeatChar, ColWidth);
end; { RepeatCell.FormattedString }
function RepeatCell.CopyString(ColLit, RowLit : Boolean; Diff : Longint;
var L : LStringPtr) : LStringPtr;
begin
EditString(0, L);
CopyString := L;
end; { RepeatCell.CopyString }
constructor RepeatCell.Load(var S : SSStream);
begin
S.Read(Loc, SizeOf(Loc));
S.Read(RepeatChar, SizeOf(RepeatChar));
end; { RepeatCell.Load }
procedure RepeatCell.Store(var S : SSStream);
begin
S.Write(Loc, SizeOf(Loc));
S.Write(RepeatChar, SizeOf(RepeatChar));
end; { RepeatCell.Store }
{$F+}
procedure CellExit;
{ Removes Empty cell from memory, restores ExitProc }
begin
Dispose(Empty, Done);
ExitProc := SavedExitProc;
end; { CellExit }
{$F-}
begin
SavedExitProc := ExitProc;
ExitProc := @CellExit;
Empty := New(EmptyCellPtr, Init);
end.