dos_compilers/Borland Turbo Pascal v6/DEMOS/TCALC/TCCELL.PAS
2024-07-02 07:11:05 -07:00

1962 lines
62 KiB
Plaintext

{ Copyright (c) 1989,90 by Borland International, Inc. }
unit TCCell;
{ Turbo Pascal 6.0 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
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 : TDosStream; Total : Longint);
procedure Store(var S : TDosStream);
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 : TDosStream; Total : Longint);
procedure Store(var S : TDosStream);
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 : TDosStream; Total : Longint);
procedure Store(var S : TDosStream);
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(TObject)
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 : TDosStream);
procedure Store(var S : TDosStream);
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 : TDosStream);
procedure Store(var S : TDosStream);
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 : TDosStream);
procedure Store(var S : TDosStream);
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 : TDosStream);
procedure Store(var S : TDosStream);
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. }
const
{ Stream registration records for the object types that will be written
to and read from the stream. }
RValueCell: TStreamRec = (
ObjType: 1000; { an arbitrary, but unique number }
VmtLink: Ofs(TypeOf(ValueCell)^);
Load: @ValueCell.Load;
Store: @ValueCell.Store
);
RTextCell: TStreamRec = (
ObjType: 1001;
VmtLink: Ofs(TypeOf(TextCell)^);
Load: @TextCell.Load;
Store: @TextCell.Store
);
RFormulaCell: TStreamRec = (
ObjType: 1002;
VmtLink: Ofs(TypeOf(FormulaCell)^);
Load: @FormulaCell.Load;
Store: @FormulaCell.Store
);
RRepeatCell: TStreamRec = (
ObjType: 1003;
VmtLink: Ofs(TypeOf(RepeatCell)^);
Load: @RepeatCell.Load;
Store: @RepeatCell.Store
);
procedure RegisterCellTypes;
implementation
var
SavedExitProc : Pointer;
procedure RegisterCellTypes;
{ Registers the different cell types so that they will be written out
correctly to disk }
begin
RegisterType(RValueCell);
RegisterType(RTextCell);
RegisterType(RFormulaCell);
RegisterType(RRepeatCell);
end; { RegisterCellTypes }
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 : TDosStream; 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, 0);
Exit;
end;
end;
end; { CellHashTable.Load }
procedure CellHashTable.Store(var S : TDosStream);
{ 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 : TDosStream; 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, 0);
Exit;
end;
end;
end; { WidthHashTable.Load }
procedure WidthHashTable.Store(var S : TDosStream);
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 : TDosStream; 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, 0);
Exit;
end;
end;
end; { FormatHashTable.Load }
procedure FormatHashTable.Store(var S : TDosStream);
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 : TDosStream);
begin
S.Read(Loc, SizeOf(Loc));
S.Read(Error, SizeOf(Error));
S.Read(Value, SizeOf(Value));
end; { ValueCell.Load }
procedure ValueCell.Store(var S : TDosStream);
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 : TDosStream);
begin
S.Read(Loc, SizeOf(Loc));
Txt := New(LStringPtr, Init);
if Txt = nil then
begin
S.Error(NoMemory, 0);
Exit;
end;
if not Txt^.FromStream(S) then
begin
Dispose(Txt, Done);
S.Error(NoMemory, 0);
end;
end; { TextCell.Load }
procedure TextCell.Store(var S : TDosStream);
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 : TDosStream);
begin
S.Read(Loc, SizeOf(Loc));
Formula := New(LStringPtr, Init);
if Formula = nil then
begin
S.Error(NoMemory, 0);
Exit;
end;
if not Formula^.FromStream(S) then
begin
Dispose(Formula, Done);
S.Error(NoMemory, 0);
end;
end; { FormulaCell.Load }
procedure FormulaCell.Store(var S : TDosStream);
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 : TDosStream);
begin
S.Read(Loc, SizeOf(Loc));
S.Read(RepeatChar, SizeOf(RepeatChar));
end; { RepeatCell.Load }
procedure RepeatCell.Store(var S : TDosStream);
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.