mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-08 06:47:24 +01:00
* Patch from Andrew Haines to support FPDOC generating CHMs
git-svn-id: trunk@9406 -
This commit is contained in:
parent
e6087db326
commit
853c34fda0
@ -36,6 +36,7 @@ type
|
|||||||
|
|
||||||
TChmProject = class
|
TChmProject = class
|
||||||
private
|
private
|
||||||
|
FWriter: TChmWriter;
|
||||||
FAutoFollowLinks: Boolean;
|
FAutoFollowLinks: Boolean;
|
||||||
FDefaultFont: String;
|
FDefaultFont: String;
|
||||||
FDefaultPage: String;
|
FDefaultPage: String;
|
||||||
@ -49,6 +50,7 @@ type
|
|||||||
FTitle: String;
|
FTitle: String;
|
||||||
protected
|
protected
|
||||||
function GetData(const DataName: String; out PathInChm: String; out FileName: String; var Stream: TStream): Boolean;
|
function GetData(const DataName: String; out PathInChm: String; out FileName: String; var Stream: TStream): Boolean;
|
||||||
|
procedure LastFileAdded(Sender: TObject);
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -93,6 +95,25 @@ begin
|
|||||||
if Assigned(FOnProgress) then FOnProgress(Self, DataName);
|
if Assigned(FOnProgress) then FOnProgress(Self, DataName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChmProject.LastFileAdded(Sender: TObject);
|
||||||
|
var
|
||||||
|
IndexStream: TFileStream;
|
||||||
|
TOCStream: TFileStream;
|
||||||
|
begin
|
||||||
|
// Assign the TOC and index files
|
||||||
|
if (IndexFileName <> '') and FileExists(IndexFileName) then begin
|
||||||
|
IndexStream := TFileStream.Create(IndexFileName, fmOpenRead);
|
||||||
|
FWriter.AppendIndex(IndexStream);
|
||||||
|
IndexStream.Free;
|
||||||
|
end;
|
||||||
|
if (TableOfContentsFileName <> '') and FileExists(TableOfContentsFileName) then begin
|
||||||
|
TOCStream := TFileStream.Create(TableOfContentsFileName, fmOpenRead);
|
||||||
|
FWriter.AppendTOC(TOCStream);
|
||||||
|
TOCStream.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TChmProject.Create;
|
constructor TChmProject.Create;
|
||||||
begin
|
begin
|
||||||
FFiles := TStringList.Create;
|
FFiles := TStringList.Create;
|
||||||
@ -174,20 +195,11 @@ begin
|
|||||||
Writer := TChmWriter.Create(AOutStream, False);
|
Writer := TChmWriter.Create(AOutStream, False);
|
||||||
// our callback to get data
|
// our callback to get data
|
||||||
Writer.OnGetFileData := @GetData;
|
Writer.OnGetFileData := @GetData;
|
||||||
|
Writer.OnLastFile := @LastFileAdded;
|
||||||
|
|
||||||
// give it the list of files
|
// give it the list of files
|
||||||
Writer.FilesToCompress.AddStrings(Files);
|
Writer.FilesToCompress.AddStrings(Files);
|
||||||
|
|
||||||
// Assign the TOC and index files
|
|
||||||
if (IndexFileName <> '') and FileExists(IndexFileName) then begin
|
|
||||||
IndexStream := TFileStream.Create(IndexFileName, fmOpenRead);
|
|
||||||
Writer.IndexStream := IndexStream;
|
|
||||||
end;
|
|
||||||
if (TableOfContentsFileName <> '') and FileExists(TableOfContentsFileName) then begin
|
|
||||||
TOCStream := TFileStream.Create(TableOfContentsFileName, fmOpenRead);
|
|
||||||
Writer.TOCStream := TOCStream;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// now some settings in the chm
|
// now some settings in the chm
|
||||||
Writer.DefaultPage := DefaultPage;
|
Writer.DefaultPage := DefaultPage;
|
||||||
Writer.Title := Title;
|
Writer.Title := Title;
|
||||||
|
|||||||
@ -671,7 +671,7 @@ var
|
|||||||
I: Integer;
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
|
WriteLn('Looking for URL : ', Name);
|
||||||
if Name = '' then Exit;
|
if Name = '' then Exit;
|
||||||
if fDirectoryHeader.DirectoryChunkCount = 0 then exit;
|
if fDirectoryHeader.DirectoryChunkCount = 0 then exit;
|
||||||
|
|
||||||
@ -1117,6 +1117,7 @@ begin
|
|||||||
Found := True;
|
Found := True;
|
||||||
end;
|
end;
|
||||||
if not Found then exit;
|
if not Found then exit;
|
||||||
|
WriteLn('Looking for URL ', URL, ' in ', AFileName);
|
||||||
if CheckOpenFile(AFileName) then
|
if CheckOpenFile(AFileName) then
|
||||||
Result := fLastChm.ObjectExists(URL);
|
Result := fLastChm.ObjectExists(URL);
|
||||||
if Result > 0 then NAme := Url;
|
if Result > 0 then NAme := Url;
|
||||||
|
|||||||
@ -39,6 +39,7 @@ type
|
|||||||
FComment: String;
|
FComment: String;
|
||||||
FImageNumber: Integer;
|
FImageNumber: Integer;
|
||||||
FIncreaseImageIndex: Boolean;
|
FIncreaseImageIndex: Boolean;
|
||||||
|
FKeyWord: String;
|
||||||
FLocal: String;
|
FLocal: String;
|
||||||
FOwner: TChmSiteMapItems;
|
FOwner: TChmSiteMapItems;
|
||||||
FSeeAlso: String;
|
FSeeAlso: String;
|
||||||
@ -50,6 +51,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property Children: TChmSiteMapItems read FChildren write SetChildren;
|
property Children: TChmSiteMapItems read FChildren write SetChildren;
|
||||||
property Text: String read FText write FText; // Name for TOC; KeyWord for index
|
property Text: String read FText write FText; // Name for TOC; KeyWord for index
|
||||||
|
property KeyWord: String read FKeyWord write FKeyWord;
|
||||||
property Local: String read FLocal write FLocal;
|
property Local: String read FLocal write FLocal;
|
||||||
property URL: String read FURL write FURL;
|
property URL: String read FURL write FURL;
|
||||||
property SeeAlso: String read FSeeAlso write FSeeAlso;
|
property SeeAlso: String read FSeeAlso write FSeeAlso;
|
||||||
@ -81,6 +83,7 @@ type
|
|||||||
function NewItem: TChmSiteMapItem;
|
function NewItem: TChmSiteMapItem;
|
||||||
function Insert(AItem: TChmSiteMapItem; AIndex: Integer): Integer;
|
function Insert(AItem: TChmSiteMapItem; AIndex: Integer): Integer;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
|
procedure Sort(Compare: TListSortCompare);
|
||||||
property Item[AIndex: Integer]: TChmSiteMapItem read GetItem write SetItem;
|
property Item[AIndex: Integer]: TChmSiteMapItem read GetItem write SetItem;
|
||||||
property Count: Integer read GetCount;
|
property Count: Integer read GetCount;
|
||||||
property ParentItem: TChmSiteMapItem read FParentItem;
|
property ParentItem: TChmSiteMapItem read FParentItem;
|
||||||
@ -338,15 +341,15 @@ var
|
|||||||
Item: TChmSiteMapItem;
|
Item: TChmSiteMapItem;
|
||||||
begin
|
begin
|
||||||
for I := 0 to AItems.Count-1 do begin
|
for I := 0 to AItems.Count-1 do begin
|
||||||
|
|
||||||
|
|
||||||
Item := AItems.Item[I];
|
Item := AItems.Item[I];
|
||||||
WriteString('<LI> <OBJECT type="text/sitemap">');
|
WriteString('<LI> <OBJECT type="text/sitemap">');
|
||||||
Inc(Indent, 8);
|
Inc(Indent, 8);
|
||||||
//Merge
|
|
||||||
//if (SiteMapType = stIndex) and (Item.Text <> '') then WriteParam('Keyword', Item.Text);
|
if (SiteMapType = stIndex) and (Item.Children.Count > 0) then
|
||||||
|
WriteParam('Keyword', Item.Text);
|
||||||
|
//if Item.KeyWord <> '' then WriteParam('Keyword', Item.KeyWord);
|
||||||
if Item.Text <> '' then WriteParam('Name', Item.Text);
|
if Item.Text <> '' then WriteParam('Name', Item.Text);
|
||||||
if Item.Local <> '' then WriteParam('Local', Item.Local);
|
if (Item.Local <> '') or (SiteMapType = stIndex) then WriteParam('Local', Item.Local);
|
||||||
if Item.URL <> '' then WriteParam('URL', Item.URL);
|
if Item.URL <> '' then WriteParam('URL', Item.URL);
|
||||||
if (SiteMapType = stIndex) and (Item.SeeAlso <> '') then WriteParam('See Also', Item.SeeAlso);
|
if (SiteMapType = stIndex) and (Item.SeeAlso <> '') then WriteParam('See Also', Item.SeeAlso);
|
||||||
//if Item.FrameName <> '' then WriteParam('FrameName', Item.FrameName);
|
//if Item.FrameName <> '' then WriteParam('FrameName', Item.FrameName);
|
||||||
@ -367,9 +370,6 @@ var
|
|||||||
Dec(Indent, 8);
|
Dec(Indent, 8);
|
||||||
WriteString('</UL>');
|
WriteString('</UL>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
begin
|
begin
|
||||||
@ -498,5 +498,10 @@ begin
|
|||||||
for I := Count-1 downto 0 do Delete(I);
|
for I := Count-1 downto 0 do Delete(I);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChmSiteMapItems.Sort(Compare: TListSortCompare);
|
||||||
|
begin
|
||||||
|
FList.Sort(Compare);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ uses
|
|||||||
function WriteSpanInfoToStream(const AStream: TStream; UncompressedSize: QWord): Integer;
|
function WriteSpanInfoToStream(const AStream: TStream; UncompressedSize: QWord): Integer;
|
||||||
function WriteTransformListToStream(const AStream: TStream): Integer;
|
function WriteTransformListToStream(const AStream: TStream): Integer;
|
||||||
function WriteResetTableToStream(const AStream: TStream; ResetTableStream: TMemoryStream): Integer;
|
function WriteResetTableToStream(const AStream: TStream; ResetTableStream: TMemoryStream): Integer;
|
||||||
function WriteContentToStream(const AStream: TStream; ContentStream: TMemoryStream): Integer;
|
function WriteContentToStream(const AStream: TStream; ContentStream: TStream): Integer;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ begin
|
|||||||
Result := AStream.CopyFrom(ResetTableStream, ResetTableStream.Size-SizeOf(QWord));
|
Result := AStream.CopyFrom(ResetTableStream, ResetTableStream.Size-SizeOf(QWord));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function WriteContentToStream(const AStream: TStream; ContentStream: TMemoryStream): Integer;
|
function WriteContentToStream(const AStream: TStream; ContentStream: TStream): Integer;
|
||||||
begin
|
begin
|
||||||
// ::DataSpace/Storage/MSCompressed/Content
|
// ::DataSpace/Storage/MSCompressed/Content
|
||||||
ContentStream.Position := 0;
|
ContentStream.Position := 0;
|
||||||
|
|||||||
@ -34,17 +34,14 @@ type
|
|||||||
// Stream : the file opened with DataName should be written to this stream
|
// Stream : the file opened with DataName should be written to this stream
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ TChmWriter }
|
{ TChmWriter }
|
||||||
|
|
||||||
TChmWriter = class(TObject)
|
TChmWriter = class(TObject)
|
||||||
|
FOnLastFile: TNotifyEvent;
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
ForceExit: Boolean;
|
ForceExit: Boolean;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FDefaultFont: String;
|
FDefaultFont: String;
|
||||||
FDefaultPage: String;
|
FDefaultPage: String;
|
||||||
FFullTextSearch: Boolean;
|
FFullTextSearch: Boolean;
|
||||||
@ -56,16 +53,18 @@ type
|
|||||||
FStringsStream: TMemoryStream;
|
FStringsStream: TMemoryStream;
|
||||||
FContextStream: TMemoryStream; // the #IVB file
|
FContextStream: TMemoryStream; // the #IVB file
|
||||||
FSection0: TMemoryStream;
|
FSection0: TMemoryStream;
|
||||||
FSection1: TMemoryStream; // Compressed Stream
|
FSection1: TStream; // Compressed Stream
|
||||||
FSection1Size: Int64;
|
FSection1Size: Int64;
|
||||||
FSection1ResetTable: TMemoryStream; // has a list of frame positions NOT window positions
|
FSection1ResetTable: TMemoryStream; // has a list of frame positions NOT window positions
|
||||||
FDirectoryListings: TStream;
|
FDirectoryListings: TStream;
|
||||||
FIndexStream: TStream;
|
|
||||||
FOutStream: TStream;
|
FOutStream: TStream;
|
||||||
FFileNames: TStrings;
|
FFileNames: TStrings;
|
||||||
FDestroyStream: Boolean;
|
FDestroyStream: Boolean;
|
||||||
|
FTempStream: TStream;
|
||||||
|
FPostStream: TStream;
|
||||||
FTitle: String;
|
FTitle: String;
|
||||||
FTOCStream: TStream;
|
FHasTOC: Boolean;
|
||||||
|
FHasIndex: Boolean;
|
||||||
FWindowSize: LongWord;
|
FWindowSize: LongWord;
|
||||||
FReadCompressedSize: Int64; // Current Size of Uncompressed data that went in Section1 (compressed)
|
FReadCompressedSize: Int64; // Current Size of Uncompressed data that went in Section1 (compressed)
|
||||||
// Linear order of file
|
// Linear order of file
|
||||||
@ -81,12 +80,11 @@ type
|
|||||||
// end linear header parts
|
// end linear header parts
|
||||||
procedure InitITSFHeader;
|
procedure InitITSFHeader;
|
||||||
procedure InitHeaderSectionTable;
|
procedure InitHeaderSectionTable;
|
||||||
|
procedure SetTempRawStream(const AValue: TStream);
|
||||||
procedure WriteHeader(Stream: TStream);
|
procedure WriteHeader(Stream: TStream);
|
||||||
procedure CreateDirectoryListings;
|
procedure CreateDirectoryListings;
|
||||||
procedure WriteDirectoryListings(Stream: TStream);
|
procedure WriteDirectoryListings(Stream: TStream);
|
||||||
procedure StartCompressingStream;
|
procedure StartCompressingStream;
|
||||||
procedure WriteTOC;
|
|
||||||
procedure WriteIndex;
|
|
||||||
procedure WriteSYSTEM;
|
procedure WriteSYSTEM;
|
||||||
procedure WriteITBITS;
|
procedure WriteITBITS;
|
||||||
procedure WriteSTRINGS;
|
procedure WriteSTRINGS;
|
||||||
@ -106,19 +104,23 @@ type
|
|||||||
constructor Create(OutStream: TStream; FreeStreamOnDestroy: Boolean);
|
constructor Create(OutStream: TStream; FreeStreamOnDestroy: Boolean);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Execute;
|
procedure Execute;
|
||||||
|
procedure AppendTOC(AStream: TStream);
|
||||||
|
procedure AppendIndex(AStream: TStream);
|
||||||
|
procedure AppendSearchDB(AName: String; AStream: TStream);
|
||||||
procedure AddStreamToArchive(AFileName, APath: String; AStream: TStream; Compress: Boolean = True);
|
procedure AddStreamToArchive(AFileName, APath: String; AStream: TStream; Compress: Boolean = True);
|
||||||
|
procedure PostAddStreamToArchive(AFileName, APath: String; AStream: TStream; Compress: Boolean = True);
|
||||||
procedure AddContext(AContext: DWord; ATopic: String);
|
procedure AddContext(AContext: DWord; ATopic: String);
|
||||||
property WindowSize: LongWord read FWindowSize write FWindowSize default 2; // in $8000 blocks
|
property WindowSize: LongWord read FWindowSize write FWindowSize default 2; // in $8000 blocks
|
||||||
property FrameSize: LongWord read FFrameSize write FFrameSize default 1; // in $8000 blocks
|
property FrameSize: LongWord read FFrameSize write FFrameSize default 1; // in $8000 blocks
|
||||||
property FilesToCompress: TStrings read FFileNames;
|
property FilesToCompress: TStrings read FFileNames;
|
||||||
property OnGetFileData: TGetDataFunc read FOnGetFileData write FOnGetFileData;
|
property OnGetFileData: TGetDataFunc read FOnGetFileData write FOnGetFileData;
|
||||||
|
property OnLastFile: TNotifyEvent read FOnLastFile write FOnLastFile;
|
||||||
property OutStream: TStream read FOutStream;
|
property OutStream: TStream read FOutStream;
|
||||||
property Title: String read FTitle write FTitle;
|
property Title: String read FTitle write FTitle;
|
||||||
property FullTextSearch: Boolean read FFullTextSearch write FFullTextSearch;
|
property FullTextSearch: Boolean read FFullTextSearch write FFullTextSearch;
|
||||||
property DefaultFont: String read FDefaultFont write FDefaultFont;
|
property DefaultFont: String read FDefaultFont write FDefaultFont;
|
||||||
property DefaultPage: String read FDefaultPage write FDefaultPage;
|
property DefaultPage: String read FDefaultPage write FDefaultPage;
|
||||||
property TOCStream: TStream read FTOCStream write FTOCStream;
|
property TempRawStream: TStream read FTempStream write SetTempRawStream;
|
||||||
property IndexStream: TStream read FIndexStream write FIndexStream;
|
|
||||||
//property LocaleID: dword read ITSFHeader.LanguageID write ITSFHeader.LanguageID;
|
//property LocaleID: dword read ITSFHeader.LanguageID write ITSFHeader.LanguageID;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -200,6 +202,18 @@ begin
|
|||||||
HeaderSuffix.Offset := NToLE(HeaderSuffix.Offset);
|
HeaderSuffix.Offset := NToLE(HeaderSuffix.Offset);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChmWriter.SetTempRawStream(const AValue: TStream);
|
||||||
|
begin
|
||||||
|
if (FCurrentStream.Size > 0) or (FSection1.Size > 0) then
|
||||||
|
raise Exception.Create('Cannot set the TempRawStream once data has been written to it!');
|
||||||
|
if AValue = nil then
|
||||||
|
raise Exception.Create('TempRawStream cannot be nil!');
|
||||||
|
if FCurrentStream = AValue then
|
||||||
|
exit;
|
||||||
|
FCurrentStream.Free;
|
||||||
|
FCurrentStream := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TChmWriter.WriteHeader(Stream: TStream);
|
procedure TChmWriter.WriteHeader(Stream: TStream);
|
||||||
begin
|
begin
|
||||||
Stream.Write(ITSFHeader, SizeOf(TITSFHeader));
|
Stream.Write(ITSFHeader, SizeOf(TITSFHeader));
|
||||||
@ -225,8 +239,7 @@ var
|
|||||||
FESize: Integer;
|
FESize: Integer;
|
||||||
FileName: String;
|
FileName: String;
|
||||||
FileNameSize: Integer;
|
FileNameSize: Integer;
|
||||||
LastListIndex,
|
LastListIndex: Integer;
|
||||||
LastIndexIndex: Integer;
|
|
||||||
FirstListEntry: TFirstListEntry;
|
FirstListEntry: TFirstListEntry;
|
||||||
ChunkIndex: Integer;
|
ChunkIndex: Integer;
|
||||||
ListHeader: TPMGListChunk;
|
ListHeader: TPMGListChunk;
|
||||||
@ -312,7 +325,6 @@ begin
|
|||||||
IndexBlock := TPMGIDirectoryChunk.Create(SizeOf(TPMGIIndexChunk));
|
IndexBlock := TPMGIDirectoryChunk.Create(SizeOf(TPMGIIndexChunk));
|
||||||
ListingBlock := TDirectoryChunk.Create(SizeOf(TPMGListChunk));
|
ListingBlock := TDirectoryChunk.Create(SizeOf(TPMGListChunk));
|
||||||
|
|
||||||
LastIndexIndex := -1;
|
|
||||||
LastListIndex := -1;
|
LastListIndex := -1;
|
||||||
|
|
||||||
// add files to a pmgl block until it is full.
|
// add files to a pmgl block until it is full.
|
||||||
@ -373,24 +385,9 @@ begin
|
|||||||
//TMemoryStream(FDirectoryListings).SaveToFile('dirlistings.pmg');
|
//TMemoryStream(FDirectoryListings).SaveToFile('dirlistings.pmg');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChmWriter.WriteIndex;
|
|
||||||
var
|
|
||||||
Entry: TFileEntryRec;
|
|
||||||
TmpTitle: String;
|
|
||||||
begin
|
|
||||||
if IndexStream = nil then Exit;
|
|
||||||
|
|
||||||
if Title <> '' then TmpTitle := Title
|
|
||||||
else TmpTitle := 'default';
|
|
||||||
|
|
||||||
AddStreamToArchive(TmpTitle+'.hhk', '/', IndexStream);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TChmWriter.WriteSystem;
|
procedure TChmWriter.WriteSystem;
|
||||||
var
|
var
|
||||||
Entry: TFileEntryRec;
|
Entry: TFileEntryRec;
|
||||||
EntryCode,
|
|
||||||
EntryLength: Word;
|
|
||||||
TmpStr: String;
|
TmpStr: String;
|
||||||
TmpTitle: String;
|
TmpTitle: String;
|
||||||
const
|
const
|
||||||
@ -449,6 +446,7 @@ begin
|
|||||||
FSection0.WriteWord(NToLE(Word(3)));
|
FSection0.WriteWord(NToLE(Word(3)));
|
||||||
FSection0.WriteWord(NToLE(Word(Length(FTitle)+1)));
|
FSection0.WriteWord(NToLE(Word(Length(FTitle)+1)));
|
||||||
FSection0.Write(FTitle[1], Length(FTitle));
|
FSection0.Write(FTitle[1], Length(FTitle));
|
||||||
|
FSection0.WriteByte(0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 16 Default Font
|
// 16 Default Font
|
||||||
@ -456,14 +454,15 @@ begin
|
|||||||
FSection0.WriteWord(NToLE(Word(16)));
|
FSection0.WriteWord(NToLE(Word(16)));
|
||||||
FSection0.WriteWord(NToLE(Word(Length(FDefaultFont)+1)));
|
FSection0.WriteWord(NToLE(Word(Length(FDefaultFont)+1)));
|
||||||
FSection0.Write(FDefaultFont[1], Length(FDefaultFont));
|
FSection0.Write(FDefaultFont[1], Length(FDefaultFont));
|
||||||
|
FSection0.WriteByte(0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 6
|
// 6
|
||||||
// unneeded. if output file is : /somepath/OutFile.chm the value here is outfile(lowercase)
|
// unneeded. if output file is : /somepath/OutFile.chm the value here is outfile(lowercase)
|
||||||
|
|
||||||
// 0 Table of contents filename
|
// 0 Table of contents filename
|
||||||
if TOCStream <> nil then begin
|
if FHasTOC then begin
|
||||||
TmpStr := TmpTitle+'.hhc';
|
TmpStr := 'default.hhc';
|
||||||
FSection0.WriteWord(0);
|
FSection0.WriteWord(0);
|
||||||
FSection0.WriteWord(NToLE(Word(Length(TmpStr)+1)));
|
FSection0.WriteWord(NToLE(Word(Length(TmpStr)+1)));
|
||||||
FSection0.Write(TmpStr[1], Length(TmpStr));
|
FSection0.Write(TmpStr[1], Length(TmpStr));
|
||||||
@ -471,8 +470,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
// 1
|
// 1
|
||||||
// hhk Index
|
// hhk Index
|
||||||
if IndexStream <> nil then begin
|
if FHasIndex then begin
|
||||||
TmpStr := TmpTitle+'.hhk';
|
TmpStr := 'default.hhk';
|
||||||
FSection0.WriteWord(NToLE(Word(1)));
|
FSection0.WriteWord(NToLE(Word(1)));
|
||||||
FSection0.WriteWord(NToLE(Word(Length(TmpStr)+1)));
|
FSection0.WriteWord(NToLE(Word(Length(TmpStr)+1)));
|
||||||
FSection0.Write(TmpStr[1], Length(TmpStr));
|
FSection0.Write(TmpStr[1], Length(TmpStr));
|
||||||
@ -530,7 +529,7 @@ begin
|
|||||||
FSection0.Write(DISCLAIMER_STR, SizeOf(DISCLAIMER_STR));
|
FSection0.Write(DISCLAIMER_STR, SizeOf(DISCLAIMER_STR));
|
||||||
Entry.DecompressedSize := FSection0.Position - Entry.DecompressedOffset;
|
Entry.DecompressedSize := FSection0.Position - Entry.DecompressedOffset;
|
||||||
Entry.Path := '/';
|
Entry.Path := '/';
|
||||||
Entry.Name := '_::_README_::_'; //try to use a name that won't conflict with normal names
|
Entry.Name := '_#_README_#_'; //try to use a name that won't conflict with normal names
|
||||||
FInternalFiles.AddEntry(Entry);
|
FInternalFiles.AddEntry(Entry);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -649,6 +648,19 @@ begin
|
|||||||
Inc(FReadCompressedSize, FileEntry.DecompressedSize);
|
Inc(FReadCompressedSize, FileEntry.DecompressedSize);
|
||||||
FCurrentStream.Position := 0;
|
FCurrentStream.Position := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// this is intended for programs to add perhaps a file
|
||||||
|
// after all the other files have been added.
|
||||||
|
if (AtEndOfData)
|
||||||
|
and (FCurrentStream <> FPostStream) then
|
||||||
|
begin
|
||||||
|
if Assigned(FOnLastFile) then
|
||||||
|
FOnLastFile(Self);
|
||||||
|
FCurrentStream.Free;
|
||||||
|
FCurrentStream := FPostStream;
|
||||||
|
FCurrentStream.Position := 0;
|
||||||
|
Inc(FReadCompressedSize, FCurrentStream.Size);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -661,11 +673,11 @@ function TChmWriter.WriteCompressedData(Count: Longint; Buffer: Pointer): LongIn
|
|||||||
begin
|
begin
|
||||||
// we allocate a MB at a time to limit memory reallocation since this
|
// we allocate a MB at a time to limit memory reallocation since this
|
||||||
// writes usually 2 bytes at a time
|
// writes usually 2 bytes at a time
|
||||||
if FSection1.Position >= FSection1.Size-1 then begin
|
if (FSection1 is TMemoryStream) and (FSection1.Position >= FSection1.Size-1) then begin
|
||||||
FSection1.Size := FSection1.Size+$100000;
|
FSection1.Size := FSection1.Size+$100000;
|
||||||
end;
|
end;
|
||||||
Inc(FSection1Size, FSection1.Write(Buffer^, Count));
|
Result := FSection1.Write(Buffer^, Count);
|
||||||
|
Inc(FSection1Size, Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure _MarkFrame(arg: pointer; UncompressedTotal, CompressedTotal: LongWord); cdecl;
|
procedure _MarkFrame(arg: pointer; UncompressedTotal, CompressedTotal: LongWord); cdecl;
|
||||||
@ -693,7 +705,6 @@ procedure TChmWriter.MarkFrame(UnCompressedTotal, CompressedTotal: LongWord);
|
|||||||
procedure UpdateTotalSizes;
|
procedure UpdateTotalSizes;
|
||||||
var
|
var
|
||||||
OldPos: Int64;
|
OldPos: Int64;
|
||||||
Value: DWord;
|
|
||||||
begin
|
begin
|
||||||
OldPos := FSection1ResetTable.Position;
|
OldPos := FSection1ResetTable.Position;
|
||||||
FSection1ResetTable.Position := $10;
|
FSection1ResetTable.Position := $10;
|
||||||
@ -701,8 +712,6 @@ procedure TChmWriter.MarkFrame(UnCompressedTotal, CompressedTotal: LongWord);
|
|||||||
WriteQWord(CompressedTotal);
|
WriteQWord(CompressedTotal);
|
||||||
FSection1ResetTable.Position := OldPos;
|
FSection1ResetTable.Position := OldPos;
|
||||||
end;
|
end;
|
||||||
var
|
|
||||||
Tmp : QWord;
|
|
||||||
begin
|
begin
|
||||||
if FSection1ResetTable.Size = 0 then begin
|
if FSection1ResetTable.Size = 0 then begin
|
||||||
// Write the header
|
// Write the header
|
||||||
@ -733,6 +742,7 @@ begin
|
|||||||
FSection1 := TMemoryStream.Create;
|
FSection1 := TMemoryStream.Create;
|
||||||
FSection1ResetTable := TMemoryStream.Create;
|
FSection1ResetTable := TMemoryStream.Create;
|
||||||
FDirectoryListings := TMemoryStream.Create;
|
FDirectoryListings := TMemoryStream.Create;
|
||||||
|
FPostStream := TMemoryStream.Create;;
|
||||||
FDestroyStream := FreeStreamOnDestroy;
|
FDestroyStream := FreeStreamOnDestroy;
|
||||||
FFileNames := TStringList.Create;
|
FFileNames := TStringList.Create;
|
||||||
end;
|
end;
|
||||||
@ -760,8 +770,6 @@ begin
|
|||||||
|
|
||||||
// write any internal files to FCurrentStream that we want in the compressed section
|
// write any internal files to FCurrentStream that we want in the compressed section
|
||||||
WriteIVB;
|
WriteIVB;
|
||||||
WriteTOC;
|
|
||||||
WriteIndex;
|
|
||||||
WriteSTRINGS;
|
WriteSTRINGS;
|
||||||
|
|
||||||
// written to Section0 (uncompressed)
|
// written to Section0 (uncompressed)
|
||||||
@ -798,10 +806,27 @@ begin
|
|||||||
WriteSection1; // writes section 1 to FOutStream
|
WriteSection1; // writes section 1 to FOutStream
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChmWriter.AppendTOC(AStream: TStream);
|
||||||
|
begin
|
||||||
|
FHasTOC := True;
|
||||||
|
PostAddStreamToArchive('default.hhc', '/', AStream, True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TChmWriter.AppendIndex(AStream: TStream);
|
||||||
|
begin
|
||||||
|
FHasIndex := True;
|
||||||
|
PostAddStreamToArchive('default.hhk', '/', AStream, True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TChmWriter.AppendSearchDB(AName: String; AStream: TStream);
|
||||||
|
begin
|
||||||
|
PostAddStreamToArchive(AName, '/', AStream);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
// this procedure is used to manually add files to compress to an internal stream that is
|
// this procedure is used to manually add files to compress to an internal stream that is
|
||||||
// processed before FileToCompress is called. Files added this way should not be
|
// processed before FileToCompress is called. Files added this way should not be
|
||||||
// in the FilesToCompress property.
|
// duplicated in the FilesToCompress property.
|
||||||
procedure TChmWriter.AddStreamToArchive(AFileName, APath: String; AStream: TStream; Compress: Boolean = True);
|
procedure TChmWriter.AddStreamToArchive(AFileName, APath: String; AStream: TStream; Compress: Boolean = True);
|
||||||
var
|
var
|
||||||
TargetStream: TStream;
|
TargetStream: TStream;
|
||||||
@ -823,6 +848,31 @@ begin
|
|||||||
TargetStream.CopyFrom(AStream, AStream.Size);
|
TargetStream.CopyFrom(AStream, AStream.Size);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChmWriter.PostAddStreamToArchive(AFileName, APath: String;
|
||||||
|
AStream: TStream; Compress: Boolean);
|
||||||
|
var
|
||||||
|
TargetStream: TStream;
|
||||||
|
Entry: TFileEntryRec;
|
||||||
|
begin
|
||||||
|
if AStream = nil then Exit;
|
||||||
|
if Compress then
|
||||||
|
TargetStream := FPostStream
|
||||||
|
else
|
||||||
|
TargetStream := FSection0;
|
||||||
|
|
||||||
|
Entry.Name := AFileName;
|
||||||
|
Entry.Path := APath;
|
||||||
|
Entry.Compressed := Compress;
|
||||||
|
if not Compress then
|
||||||
|
Entry.DecompressedOffset := TargetStream.Position
|
||||||
|
else
|
||||||
|
Entry.DecompressedOffset := FReadCompressedSize + TargetStream.Position;
|
||||||
|
Entry.DecompressedSize := AStream.Size;
|
||||||
|
FInternalFiles.AddEntry(Entry);
|
||||||
|
AStream.Position := 0;
|
||||||
|
TargetStream.CopyFrom(AStream, AStream.Size);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TChmWriter.AddContext(AContext: DWord; ATopic: String);
|
procedure TChmWriter.AddContext(AContext: DWord; ATopic: String);
|
||||||
var
|
var
|
||||||
Offset: DWord;
|
Offset: DWord;
|
||||||
@ -858,16 +908,4 @@ begin
|
|||||||
lzx_finish(LZXdata, nil);
|
lzx_finish(LZXdata, nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChmWriter.WriteTOC;
|
|
||||||
var
|
|
||||||
TmpTitle: String;
|
|
||||||
begin
|
|
||||||
if TOCStream = nil then Exit;
|
|
||||||
if Title <> '' then TmpTitle := Title
|
|
||||||
else TmpTitle := 'default';
|
|
||||||
|
|
||||||
AddStreamToArchive(TmpTitle+'.hhc', '/', TOCStream);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user