|
@@ -28,18 +28,18 @@ unit chmreader;
|
|
interface
|
|
interface
|
|
|
|
|
|
uses
|
|
uses
|
|
- Classes, SysUtils, chmbase, paslzx, chmFIftiMain, chmsitemap;
|
|
|
|
-
|
|
|
|
|
|
+ Classes, SysUtils, Contnrs, chmbase, paslzx, chmFIftiMain, chmsitemap;
|
|
|
|
+
|
|
type
|
|
type
|
|
|
|
|
|
TLZXResetTableArr = array of QWord;
|
|
TLZXResetTableArr = array of QWord;
|
|
-
|
|
|
|
|
|
+
|
|
PContextItem = ^TContextItem;
|
|
PContextItem = ^TContextItem;
|
|
TContextItem = record
|
|
TContextItem = record
|
|
Context: THelpContext;
|
|
Context: THelpContext;
|
|
Url: String;
|
|
Url: String;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+
|
|
TContextList = class(TList)
|
|
TContextList = class(TList)
|
|
public
|
|
public
|
|
procedure AddContext(Context: THelpContext; Url: String);
|
|
procedure AddContext(Context: THelpContext; Url: String);
|
|
@@ -89,7 +89,7 @@ type
|
|
function GetObject(Name: String): TMemoryStream; virtual; // YOU must Free the stream
|
|
function GetObject(Name: String): TMemoryStream; virtual; // YOU must Free the stream
|
|
property CachedEntry: TPMGListChunkEntry read fCachedEntry;
|
|
property CachedEntry: TPMGListChunkEntry read fCachedEntry;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+
|
|
{ TChmReader }
|
|
{ TChmReader }
|
|
|
|
|
|
TChmReader = class(TITSFReader)
|
|
TChmReader = class(TITSFReader)
|
|
@@ -105,12 +105,16 @@ type
|
|
fURLTBLStream,
|
|
fURLTBLStream,
|
|
fStringsStream: TMemoryStream;
|
|
fStringsStream: TMemoryStream;
|
|
fLocaleID: DWord;
|
|
fLocaleID: DWord;
|
|
|
|
+ fWindows : TObjectList;
|
|
|
|
+ fDefaultWindow: String;
|
|
private
|
|
private
|
|
FSearchReader: TChmSearchReader;
|
|
FSearchReader: TChmSearchReader;
|
|
procedure ReadCommonData;
|
|
procedure ReadCommonData;
|
|
function ReadStringsEntry(APosition: DWord): String;
|
|
function ReadStringsEntry(APosition: DWord): String;
|
|
|
|
+ function ReadStringsEntryFromStream ( strm:TStream ) : String;
|
|
function ReadURLSTR(APosition: DWord): String;
|
|
function ReadURLSTR(APosition: DWord): String;
|
|
function CheckCommonStreams: Boolean;
|
|
function CheckCommonStreams: Boolean;
|
|
|
|
+ procedure ReadWindows(mem:TMemoryStream);
|
|
public
|
|
public
|
|
constructor Create(AStream: TStream; FreeStreamOnDestroy: Boolean); override;
|
|
constructor Create(AStream: TStream; FreeStreamOnDestroy: Boolean); override;
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
@@ -128,6 +132,8 @@ type
|
|
property LocaleID: dword read fLocaleID;
|
|
property LocaleID: dword read fLocaleID;
|
|
property SearchReader: TChmSearchReader read FSearchReader write FSearchReader;
|
|
property SearchReader: TChmSearchReader read FSearchReader write FSearchReader;
|
|
property contextlist : tcontextlist read fcontextlist;
|
|
property contextlist : tcontextlist read fcontextlist;
|
|
|
|
+ property Windows : TObjectlist read fwindows;
|
|
|
|
+ property DefaultWindow : string read fdefaultwindow;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TChmFileList }
|
|
{ TChmFileList }
|
|
@@ -157,7 +163,7 @@ type
|
|
property FileName[Index: Integer]: String read GetFileName;
|
|
property FileName[Index: Integer]: String read GetFileName;
|
|
property OnOpenNewFile: TChmFileOpenEvent read fOnOpenNewFile write SetOnOpenNewFile;
|
|
property OnOpenNewFile: TChmFileOpenEvent read fOnOpenNewFile write SetOnOpenNewFile;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+
|
|
//ErrorCodes
|
|
//ErrorCodes
|
|
const
|
|
const
|
|
ERR_NO_ERR = 0;
|
|
ERR_NO_ERR = 0;
|
|
@@ -165,7 +171,7 @@ const
|
|
ERR_NOT_SUPPORTED_VERSION = 2;
|
|
ERR_NOT_SUPPORTED_VERSION = 2;
|
|
ERR_NOT_VALID_FILE = 3;
|
|
ERR_NOT_VALID_FILE = 3;
|
|
ERR_UNKNOWN_ERROR = 10;
|
|
ERR_UNKNOWN_ERROR = 10;
|
|
-
|
|
|
|
|
|
+
|
|
function ChmErrorToStr(Error: Integer): String;
|
|
function ChmErrorToStr(Error: Integer): String;
|
|
|
|
|
|
implementation
|
|
implementation
|
|
@@ -209,12 +215,12 @@ begin
|
|
fITSFHeader.TimeStamp := BEtoN(fITSFHeader.TimeStamp);//bigendian
|
|
fITSFHeader.TimeStamp := BEtoN(fITSFHeader.TimeStamp);//bigendian
|
|
fITSFHeader.LanguageID := LEtoN(fITSFHeader.LanguageID);
|
|
fITSFHeader.LanguageID := LEtoN(fITSFHeader.LanguageID);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
-
|
|
|
|
|
|
+
|
|
if fITSFHeader.Version < 4 then
|
|
if fITSFHeader.Version < 4 then
|
|
fStream.Seek(SizeOf(TGuid)*2, soCurrent);
|
|
fStream.Seek(SizeOf(TGuid)*2, soCurrent);
|
|
|
|
|
|
if not IsValidFile then Exit;
|
|
if not IsValidFile then Exit;
|
|
-
|
|
|
|
|
|
+
|
|
ReadHeaderEntries;
|
|
ReadHeaderEntries;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -416,6 +422,7 @@ procedure TChmReader.ReadCommonData;
|
|
fDefaultPage := '/'+ReadString(fStrings);
|
|
fDefaultPage := '/'+ReadString(fStrings);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ ReadWindows(FWindows);
|
|
end;
|
|
end;
|
|
procedure ReadContextIds;
|
|
procedure ReadContextIds;
|
|
var
|
|
var
|
|
@@ -447,7 +454,7 @@ begin
|
|
ReadFromSystem;
|
|
ReadFromSystem;
|
|
ReadFromWindows;
|
|
ReadFromWindows;
|
|
ReadContextIds;
|
|
ReadContextIds;
|
|
- {$IFDEF CHM_DEBUG}
|
|
|
|
|
|
+ {$IFDEF CHM_DEBUG}
|
|
WriteLn('TOC=',fTocfile);
|
|
WriteLn('TOC=',fTocfile);
|
|
WriteLn('DefaultPage=',fDefaultPage);
|
|
WriteLn('DefaultPage=',fDefaultPage);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
@@ -466,6 +473,13 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TChmReader.ReadStringsEntryFromStream ( strm:TStream ) : String;
|
|
|
|
+var APosition : DWord;
|
|
|
|
+begin
|
|
|
|
+ APosition:=LEtoN(strm.ReadDWord);
|
|
|
|
+ result:=ReadStringsEntry(APosition);
|
|
|
|
+end;
|
|
|
|
+
|
|
function TChmReader.ReadURLSTR ( APosition: DWord ) : String;
|
|
function TChmReader.ReadURLSTR ( APosition: DWord ) : String;
|
|
var
|
|
var
|
|
URLStrURLOffset: DWord;
|
|
URLStrURLOffset: DWord;
|
|
@@ -497,6 +511,74 @@ begin
|
|
and (fURLTBLStream <> nil);
|
|
and (fURLTBLStream <> nil);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TChmReader.ReadWindows(mem:TMemoryStream);
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ i,cnt,
|
|
|
|
+ version : integer;
|
|
|
|
+ x : TChmWindow;
|
|
|
|
+begin
|
|
|
|
+ fWindows.Clear;
|
|
|
|
+ mem.Position:=0;
|
|
|
|
+ cnt := LEtoN(mem.ReadDWord);
|
|
|
|
+ version := LEtoN(mem.ReadDWord);
|
|
|
|
+ while (cnt>0) do
|
|
|
|
+ begin
|
|
|
|
+ x:=TChmWindow.Create;
|
|
|
|
+ version := LEtoN(mem.ReadDWord); // 0 size of entry.
|
|
|
|
+ mem.readDWord; // 4 unknown (bool Unicodestrings?)
|
|
|
|
+ x.window_type :=ReadStringsEntryFromStream(mem); // 8 Arg 0, name of window
|
|
|
|
+ x.flags := TValidWindowFields(LEtoN(mem.ReadDWord)); // C valid fields
|
|
|
|
+ x.nav_style := LEtoN(mem.ReadDWord); // 10 arg 10 navigation pane style
|
|
|
|
+ x.title_bar_text :=ReadStringsEntryFromStream(mem); // 14 Arg 1, title bar text
|
|
|
|
+ x.styleflags := LEtoN(mem.ReadDWord); // 18 Arg 14, style flags
|
|
|
|
+ x.xtdstyleflags := LEtoN(mem.ReadDWord); // 1C Arg 15, xtd style flags
|
|
|
|
+ x.left := LEtoN(mem.ReadDWord); // 20 Arg 13, rect.left
|
|
|
|
+ x.right := LEtoN(mem.ReadDWord); // 24 Arg 13, rect.top
|
|
|
|
+ x.top := LEtoN(mem.ReadDWord); // 28 Arg 13, rect.right
|
|
|
|
+ x.bottom := LEtoN(mem.ReadDWord); // 2C Arg 13, rect.bottom
|
|
|
|
+ x.window_show_state:= LEtoN(mem.ReadDWord); // 30 Arg 16, window show state
|
|
|
|
+ mem.readdword; // 34 - , HWND hwndhelp OUT: window handle"
|
|
|
|
+ mem.readdword; // 38 - , HWND hwndcaller OUT: who called this window"
|
|
|
|
+ mem.readdword; // 3C - , HH_INFO_TYPE paINFO_TYPES IN: Pointer to an array of Information Types"
|
|
|
|
+ mem.readdword; // 40 - , HWND hwndtoolbar OUT: toolbar window in tri-pane window"
|
|
|
|
+ mem.readdword; // 44 - , HWND hwndnavigation OUT: navigation window in tri-pane window"
|
|
|
|
+ mem.readdword; // 48 - , HWND hwndhtml OUT: window displaying HTML in tri-pane window"
|
|
|
|
+ x.navpanewidth := LEtoN(mem.ReadDWord); // 4C Arg 11, width of nav pane
|
|
|
|
+ mem.readdword; // 50 - , rect.left, OUT:Specifies the coordinates of the Topic pane
|
|
|
|
+ mem.readdword; // 54 - , rect.top , OUT:Specifies the coordinates of the Topic pane
|
|
|
|
+ mem.readdword; // 58 - , rect.right, OUT:Specifies the coordinates of the Topic pane
|
|
|
|
+ mem.readdword; // 5C - , rect.bottom, OUT:Specifies the coordinates of the Topic pane
|
|
|
|
+ x.toc_file :=ReadStringsEntryFromStream(mem); // 60 Arg 2, toc file
|
|
|
|
+ x.index_file :=ReadStringsEntryFromStream(mem); // 64 Arg 3, index file
|
|
|
|
+ x.default_file :=ReadStringsEntryFromStream(mem); // 68 Arg 4, default file
|
|
|
|
+ x.home_button_file :=ReadStringsEntryFromStream(mem); // 6c Arg 5, home button file.
|
|
|
|
+ x.buttons := LEtoN(mem.ReadDWord); // 70 arg 12,
|
|
|
|
+ x.navpane_initially_closed := LEtoN(mem.ReadDWord); // 74 arg 17
|
|
|
|
+ x.navpane_default := LEtoN(mem.ReadDWord); // 78 arg 18,
|
|
|
|
+ x.navpane_location := LEtoN(mem.ReadDWord); // 7C arg 19,
|
|
|
|
+ x.wm_notify_id := LEtoN(mem.ReadDWord); // 80 arg 20,
|
|
|
|
+ for i:=0 to 4 do
|
|
|
|
+ mem.ReadDWord; // 84 - byte[20] unknown - "BYTE tabOrder[HH_MAX_TABS + 1]; // IN/OUT: tab order: Contents, Index, Search, History, Favorites, Reserved 1-5, Custom tabs"
|
|
|
|
+ mem.ReadDWord; // 94 - int cHistory; // IN/OUT: number of history items to keep (default is 30)
|
|
|
|
+ x.jumpbutton_1_text:=ReadStringsEntryFromStream(mem); // 9C Arg 7, The text of the Jump 1 button.
|
|
|
|
+ x.jumpbutton_2_text:=ReadStringsEntryFromStream(mem); // A0 Arg 9, The text of the Jump 2 button.
|
|
|
|
+ x.jumpbutton_1_file:=ReadStringsEntryFromStream(mem); // A4 Arg 6, The file shown for Jump 1 button.
|
|
|
|
+ x.jumpbutton_2_file:=ReadStringsEntryFromStream(mem); // A8 Arg 8, The file shown for Jump 1 button.
|
|
|
|
+ for i:=0 to 3 do
|
|
|
|
+ mem.ReadDWord;
|
|
|
|
+ dec(version,188); // 1.1 specific onesf
|
|
|
|
+ while (version>=4) do
|
|
|
|
+ begin
|
|
|
|
+ mem.readdword;
|
|
|
|
+ dec(version,4);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ fWindows.Add(x);
|
|
|
|
+ dec(cnt);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
constructor TChmReader.Create(AStream: TStream; FreeStreamOnDestroy: Boolean);
|
|
constructor TChmReader.Create(AStream: TStream; FreeStreamOnDestroy: Boolean);
|
|
begin
|
|
begin
|
|
inherited Create(AStream, FreeStreamOnDestroy);
|
|
inherited Create(AStream, FreeStreamOnDestroy);
|
|
@@ -504,11 +586,14 @@ begin
|
|
|
|
|
|
fContextList := TContextList.Create;
|
|
fContextList := TContextList.Create;
|
|
ReadCommonData;
|
|
ReadCommonData;
|
|
|
|
+ fWindows := TObjectlist.Create(True);
|
|
|
|
+ fDefaultWindow:='';
|
|
end;
|
|
end;
|
|
|
|
|
|
destructor TChmReader.Destroy;
|
|
destructor TChmReader.Destroy;
|
|
begin
|
|
begin
|
|
- fContextList.Free;
|
|
|
|
|
|
+ FreeAndNil(fContextList);
|
|
|
|
+ FreeAndNil(FWindows);
|
|
FreeAndNil(FSearchReader);
|
|
FreeAndNil(FSearchReader);
|
|
FreeAndNil(fTOPICSStream);
|
|
FreeAndNil(fTOPICSStream);
|
|
FreeAndNil(fURLSTRStream);
|
|
FreeAndNil(fURLSTRStream);
|
|
@@ -600,7 +685,7 @@ begin
|
|
|
|
|
|
buf[NameLength] := #0;
|
|
buf[NameLength] := #0;
|
|
PMGIEntry.Name := buf;
|
|
PMGIEntry.Name := buf;
|
|
-
|
|
|
|
|
|
+
|
|
PMGIEntry.ListingChunk := GetCompressedInteger(Stream);
|
|
PMGIEntry.ListingChunk := GetCompressedInteger(Stream);
|
|
if NameLength = 0 then Exit; // failed GetCompressedInteger sanity check
|
|
if NameLength = 0 then Exit; // failed GetCompressedInteger sanity check
|
|
Result := True;
|
|
Result := True;
|
|
@@ -717,7 +802,7 @@ var
|
|
OldPosn := ChunkStream.Position;
|
|
OldPosn := ChunkStream.Position;
|
|
Posn := ChunkStream.Size-SizeOf(Word);
|
|
Posn := ChunkStream.Size-SizeOf(Word);
|
|
ChunkStream.Position := Posn;
|
|
ChunkStream.Position := Posn;
|
|
-
|
|
|
|
|
|
+
|
|
ItemCount := LEToN(ChunkStream.ReadWord);
|
|
ItemCount := LEToN(ChunkStream.ReadWord);
|
|
//WriteLn('Max ITems for next block = ', ItemCount-1);
|
|
//WriteLn('Max ITems for next block = ', ItemCount-1);
|
|
QuickRefCount := ItemCount div (1 + (1 shl fDirectoryHeader.Density));
|
|
QuickRefCount := ItemCount div (1 + (1 shl fDirectoryHeader.Density));
|
|
@@ -745,10 +830,10 @@ var
|
|
var
|
|
var
|
|
PMGLChunk: TPMGListChunk;
|
|
PMGLChunk: TPMGListChunk;
|
|
PMGIChunk: TPMGIIndexChunk;
|
|
PMGIChunk: TPMGIIndexChunk;
|
|
- //ChunkStream: TMemoryStream; declared above
|
|
|
|
|
|
+ //ChunkStream: TMemoryStream; declared above
|
|
Entry: TPMGListChunkEntry;
|
|
Entry: TPMGListChunkEntry;
|
|
NextIndex: Integer;
|
|
NextIndex: Integer;
|
|
- EntryName: String;
|
|
|
|
|
|
+ EntryName: String;
|
|
CRes: Integer;
|
|
CRes: Integer;
|
|
I: Integer;
|
|
I: Integer;
|
|
begin
|
|
begin
|
|
@@ -764,10 +849,10 @@ begin
|
|
ChunkStream := TMemoryStream.Create;
|
|
ChunkStream := TMemoryStream.Create;
|
|
|
|
|
|
try
|
|
try
|
|
-
|
|
|
|
|
|
+
|
|
NextIndex := fDirectoryHeader.IndexOfRootChunk;
|
|
NextIndex := fDirectoryHeader.IndexOfRootChunk;
|
|
if NextIndex < 0 then NextIndex := 0; // no PMGI chunks
|
|
if NextIndex < 0 then NextIndex := 0; // no PMGI chunks
|
|
-
|
|
|
|
|
|
+
|
|
while NextIndex > -1 do begin
|
|
while NextIndex > -1 do begin
|
|
GetDirectoryChunk(NextIndex, ChunkStream);
|
|
GetDirectoryChunk(NextIndex, ChunkStream);
|
|
NextIndex := -1;
|
|
NextIndex := -1;
|
|
@@ -783,7 +868,7 @@ begin
|
|
end;
|
|
end;
|
|
ctPMGI: // we must follow the PMGI tree until we reach a PMGL block
|
|
ctPMGI: // we must follow the PMGI tree until we reach a PMGL block
|
|
begin
|
|
begin
|
|
- LookupPMGIchunk(ChunkStream, PMGIChunk);
|
|
|
|
|
|
+ LookupPMGIchunk(ChunkStream, PMGIChunk);
|
|
|
|
|
|
//QuickRefIndex[0] := ChunkStream.Position;
|
|
//QuickRefIndex[0] := ChunkStream.Position;
|
|
|
|
|
|
@@ -794,13 +879,13 @@ begin
|
|
if ChunkStream.Position >= ChunkStream.Size - PMGIChunk.UnusedSpace then break;
|
|
if ChunkStream.Position >= ChunkStream.Size - PMGIChunk.UnusedSpace then break;
|
|
CRes := ChmCompareText(Name, EntryName);
|
|
CRes := ChmCompareText(Name, EntryName);
|
|
if CRes = 0 then begin
|
|
if CRes = 0 then begin
|
|
- // no more need of this block. onto the next!
|
|
|
|
|
|
+ // no more need of this block. onto the next!
|
|
NextIndex := GetCompressedInteger(ChunkStream);
|
|
NextIndex := GetCompressedInteger(ChunkStream);
|
|
Break;
|
|
Break;
|
|
end;
|
|
end;
|
|
if CRes < 0 then begin
|
|
if CRes < 0 then begin
|
|
if I = 0 then Break; // File doesn't exist
|
|
if I = 0 then Break; // File doesn't exist
|
|
- // file is in previous entry
|
|
|
|
|
|
+ // file is in previous entry
|
|
Break;
|
|
Break;
|
|
end;
|
|
end;
|
|
NextIndex := GetCompressedInteger(ChunkStream);
|
|
NextIndex := GetCompressedInteger(ChunkStream);
|
|
@@ -813,7 +898,7 @@ begin
|
|
QuickRefIndex[0] := ChunkStream.Position;
|
|
QuickRefIndex[0] := ChunkStream.Position;
|
|
I := 0;
|
|
I := 0;
|
|
while ChunkStream.Position <= ChunkStream.Size - PMGLChunk.UnusedSpace do begin
|
|
while ChunkStream.Position <= ChunkStream.Size - PMGLChunk.UnusedSpace do begin
|
|
- // we consume the entry by reading it
|
|
|
|
|
|
+ // we consume the entry by reading it
|
|
Entry.Name := ReadString;
|
|
Entry.Name := ReadString;
|
|
if Entry.Name = '' then break;
|
|
if Entry.Name = '' then break;
|
|
if ChunkStream.Position >= ChunkStream.Size - PMGLChunk.UnusedSpace then break;
|
|
if ChunkStream.Position >= ChunkStream.Size - PMGLChunk.UnusedSpace then break;
|
|
@@ -825,7 +910,7 @@ begin
|
|
CRes := ChmCompareText(Name, Entry.Name);
|
|
CRes := ChmCompareText(Name, Entry.Name);
|
|
if CRes = 0 then begin
|
|
if CRes = 0 then begin
|
|
fCachedEntry := Entry;
|
|
fCachedEntry := Entry;
|
|
- Result := Entry.DecompressedLength;
|
|
|
|
|
|
+ Result := Entry.DecompressedLength;
|
|
Break;
|
|
Break;
|
|
end;
|
|
end;
|
|
Inc(I);
|
|
Inc(I);
|
|
@@ -944,7 +1029,7 @@ function TChmReader.GetIndexSitemap(ForceXML:boolean=false): TChmSiteMap;
|
|
var Index : TMemoryStream;
|
|
var Index : TMemoryStream;
|
|
sitemap : TChmSiteMap;
|
|
sitemap : TChmSiteMap;
|
|
Item : TChmSiteMapItem;
|
|
Item : TChmSiteMapItem;
|
|
-
|
|
|
|
|
|
+
|
|
function AbortAndTryTextual:tchmsitemap;
|
|
function AbortAndTryTextual:tchmsitemap;
|
|
|
|
|
|
begin
|
|
begin
|
|
@@ -995,7 +1080,7 @@ begin
|
|
litem.local:=topic;
|
|
litem.local:=topic;
|
|
litem.text :=Title; // recursively split this? No examples.
|
|
litem.text :=Title; // recursively split this? No examples.
|
|
end;
|
|
end;
|
|
- end;
|
|
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure parselistingblock(p:pbyte);
|
|
procedure parselistingblock(p:pbyte);
|
|
@@ -1021,7 +1106,7 @@ begin
|
|
|
|
|
|
tail:=p+(2048-hdr^.length);
|
|
tail:=p+(2048-hdr^.length);
|
|
head:=p+sizeof(TBtreeBlockHeader);
|
|
head:=p+sizeof(TBtreeBlockHeader);
|
|
-
|
|
|
|
|
|
+
|
|
{$ifdef binindex}
|
|
{$ifdef binindex}
|
|
writeln('previndex : ',hdr^.IndexOfPrevBlock);
|
|
writeln('previndex : ',hdr^.IndexOfPrevBlock);
|
|
writeln('nextindex : ',hdr^.IndexOfNextBlock);
|
|
writeln('nextindex : ',hdr^.IndexOfNextBlock);
|
|
@@ -1101,12 +1186,12 @@ begin
|
|
Exit;
|
|
Exit;
|
|
end;
|
|
end;
|
|
SiteMap:=TChmSitemap.Create(StIndex);
|
|
SiteMap:=TChmSitemap.Create(StIndex);
|
|
- Item :=Nil; // cached last created item, in case we need to make
|
|
|
|
|
|
+ Item :=Nil; // cached last created item, in case we need to make
|
|
// a child.
|
|
// a child.
|
|
TryTextual:=True;
|
|
TryTextual:=True;
|
|
BHdr.LastLstBlock:=0;
|
|
BHdr.LastLstBlock:=0;
|
|
if LoadBtreeHeader(index,BHdr) and (BHdr.LastLstBlock>0) Then
|
|
if LoadBtreeHeader(index,BHdr) and (BHdr.LastLstBlock>0) Then
|
|
- begin
|
|
|
|
|
|
+ begin
|
|
if BHdr.BlockSize=defblocksize then
|
|
if BHdr.BlockSize=defblocksize then
|
|
begin
|
|
begin
|
|
for i:=0 to BHdr.lastlstblock do
|
|
for i:=0 to BHdr.lastlstblock do
|
|
@@ -1118,8 +1203,8 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
trytextual:=false;
|
|
trytextual:=false;
|
|
- result:=sitemap;
|
|
|
|
- end;
|
|
|
|
|
|
+ result:=sitemap;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
if trytextual then
|
|
if trytextual then
|
|
begin
|
|
begin
|
|
@@ -1239,7 +1324,7 @@ begin
|
|
//WriteLn('Failed to get ::DataSpace/NameList!');
|
|
//WriteLn('Failed to get ::DataSpace/NameList!');
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+
|
|
Stream.Position := 2;
|
|
Stream.Position := 2;
|
|
EntryCount := LEtoN(Stream.ReadWord);
|
|
EntryCount := LEtoN(Stream.ReadWord);
|
|
for X := 0 to EntryCount -1 do begin
|
|
for X := 0 to EntryCount -1 do begin
|
|
@@ -1355,7 +1440,7 @@ begin
|
|
ReadCount := ResetTable[X+1] - ResetTable[X];
|
|
ReadCount := ResetTable[X+1] - ResetTable[X];
|
|
|
|
|
|
BlockWriteLength := BlockSize;
|
|
BlockWriteLength := BlockSize;
|
|
-
|
|
|
|
|
|
+
|
|
if FirstBlock = LastBlock then begin
|
|
if FirstBlock = LastBlock then begin
|
|
WriteCount := BlockLength;
|
|
WriteCount := BlockLength;
|
|
end
|
|
end
|
|
@@ -1381,7 +1466,7 @@ begin
|
|
LZXteardown(LZXState);
|
|
LZXteardown(LZXState);
|
|
Exit;
|
|
Exit;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+
|
|
// if the next block is an even numbered block we have to reset the decompressor state
|
|
// if the next block is an even numbered block we have to reset the decompressor state
|
|
if (X < LastBlock) and (X and 1 = 1) then LZXreset(LZXState);
|
|
if (X < LastBlock) and (X and 1 = 1) then LZXreset(LZXState);
|
|
|
|
|
|
@@ -1501,7 +1586,7 @@ end;
|
|
function TChmFileList.CheckOpenFile(AFileName: String): Boolean;
|
|
function TChmFileList.CheckOpenFile(AFileName: String): Boolean;
|
|
var
|
|
var
|
|
X: Integer;
|
|
X: Integer;
|
|
-
|
|
|
|
|
|
+
|
|
begin
|
|
begin
|
|
Result := False;
|
|
Result := False;
|
|
for X := 0 to Count-1 do begin
|
|
for X := 0 to Count-1 do begin
|