chmhelp fixes from mftq75

git-svn-id: trunk@9797 -
This commit is contained in:
andrew 2006-09-02 21:33:17 +00:00
parent b45d740067
commit 8cbbf72054
4 changed files with 50 additions and 47 deletions

View File

@ -124,7 +124,8 @@ procedure TIpChmDataProvider.DoGetImage(Sender: TIpHtmlNode; const URL: string;
var Picture: TPicture);
var
Stream: TMemoryStream = nil;
OrigImage: TFPCustomImageReader;
ImageClass: TFPCustomImageReaderClass;
ImageReader: TFPCustomImageReader;
OutImage: TFPWriterBMP= nil;
Img : TFPMemoryImage = nil;
FileExt: String;
@ -132,21 +133,10 @@ begin
//DebugLn('Getting Image ',(Url));
FileExt := ExtractFileExt(URL);
if FileExt = '.jpg' then
OrigImage := TFPReaderJPEG.Create
else if FileExt = '.png' then
OrigImage := TFPReaderPNG.Create
else if FileExt = '.xpm' then
OrigImage := TFPReaderXPM.Create
else if FileExt = '.bmp' then
OrigImage := TFPReaderBMP.Create
else if FileExt = '.ico' then
OrigImage := TFPReaderBMP.Create
else begin
OrigImage := nil;
end;
ImageClass := GetFPImageReaderForFileExtension(FileExt);
if OrigImage <> nil then begin
if ImageClass <> nil then begin
ImageReader := ImageClass.Create;
try
Picture := TPicture.Create;
Picture.Graphic := TBitmap.Create;
@ -154,7 +144,7 @@ begin
if Stream = nil then exit;
Img := TFPMemoryImage.Create(0,0);
Img.UsePalette:=False;
Img.LoadFromStream(Stream, OrigImage);
Img.LoadFromStream(Stream, ImageReader);
Stream.Free;
Stream := TMemoryStream.Create;
OutImage := TFPWriterBMP.Create;
@ -167,7 +157,7 @@ begin
finally
if Assigned(OutImage) then OutImage.Free;
if Assigned(Img) then Img.Free;
if Assigned(OrigImage) then OrigImage.Free;
if Assigned(ImageReader) then ImageReader.Free;
if Assigned(Stream) then Stream.Free;
end;
end

View File

@ -121,7 +121,6 @@ begin
end;
end;
Result := (total shl 7) + temp;
Result := LEtoN(Result);
end;

View File

@ -21,7 +21,7 @@
unit chmreader;
{$mode objfpc}{$H+}
{ $DEFINE CHM_DEBUG}
interface
uses
@ -74,7 +74,7 @@ type
//procedure LookupPMGIchunk(var PMGLChunk: TPMGIndexChunk);
procedure FillDirectoryEntries(StartCount: Integer);
procedure GetSections(out Sections: TStringList);
function GetBlockFromSection(SectionPrefix: String; StartPos: QWord; Length: QWord): TMemoryStream;
function GetBlockFromSection(SectionPrefix: String; StartPos: QWord; BlockLength: QWord): TMemoryStream;
function FindBlocksFromUnCompressedAddr(var ResetTableEntry: TPMGListChunkEntry;
out CompressedSize: Int64; out UnCompressedSize: Int64; out LZXResetTable: TLZXResetTableArr): QWord; // Returns the blocksize
public
@ -175,6 +175,7 @@ begin
if fChmHeader.Version > 2 then
fStream.Read(fHeaderSuffix.Offset, SizeOf(QWord));
fHeaderSuffix.Offset := LEtoN(fHeaderSuffix.Offset);
// otherwise this is set in fill directory entries
fStream.Position := LEtoN(fHeaderEntries[1].PosFromZero);
@ -188,9 +189,9 @@ begin
ChunkSize := LEtoN(ChunkSize);
Density := LEtoN(Density);
IndexTreeDepth := LEtoN(IndexTreeDepth);
IndexOfRootTrunk := LEtoN(IndexOfRootChunk);
FirstPMGLChunk := LEtoN(FirstPMGLChunkIndex);
LastPMGLChunk := LEtoN(LastPMGLChunkIndex);
IndexOfRootChunk := LEtoN(IndexOfRootChunk);
FirstPMGLChunkIndex := LEtoN(FirstPMGLChunkIndex);
LastPMGLChunkIndex := LEtoN(LastPMGLChunkIndex);
//Unknown2
DirectoryChunkCount := LEtoN(DirectoryChunkCount);
LanguageID := LEtoN(LanguageID);
@ -270,7 +271,7 @@ procedure TChmReader.ReadCommonData;
fLocaleID := LEtoN(fSystem.ReadDWord);
fSystem.Position := (fSystem.Position + EntryLength) - SizeOf(DWord);
end;
6: // chm file name. use this to get the index an toc name
6: // chm file name. use this to get the index and toc name
begin
if EntryLength > 511 then EntryLength := 511;
fSystem.Read(Data[0], EntryLength);
@ -389,8 +390,10 @@ begin
ReadFromSystem;
ReadFromWindows;
ReadContextIds;
//WriteLn('TOC=',fTocfile);
//WriteLn('DefaultPage=',fDefaultPage);
{$IFDEF CHM_DEBUG}
WriteLn('TOC=',fTocfile);
WriteLn('DefaultPage=',fDefaultPage);
{$ENDIF}
end;
function TChmReader.GetChunkType(Stream: TMemoryStream; ChunkIndex: LongInt): TPMGchunktype;
@ -584,7 +587,7 @@ procedure TChmReader.GetSections(out Sections: TStringList);
var
Stream: TStream;
EntryCount: Word;
X: Integer;
X, I: Integer;
WString: array [0..31] of WideChar;
StrLength: Word;
begin
@ -598,8 +601,11 @@ begin
for X := 0 to EntryCount -1 do begin
StrLength := LEtoN(Stream.ReadWord);
if StrLength > 31 then StrLength := 31;
// are widestrings endian specfic?
Stream.Read(WString, SizeOf(WideChar)*(StrLength+1)); // the strings are stored null terminated
{$IFDEF ENDIAN_BIG}
for I := 0 to StrLength-1 do
WString[I] := WideChar(LEtoN(Ord(WString[I])));
{$ENDIF}
Sections.Add(WString);
end;
// the sections are sorted alphabetically, this way section indexes will jive
@ -608,7 +614,7 @@ begin
end;
function TChmReader.GetBlockFromSection(SectionPrefix: String; StartPos: QWord;
Length: QWord): TMemoryStream;
BlockLength: QWord): TMemoryStream;
var
Compressed: Boolean;
Sig: Array [0..3] of char;
@ -625,12 +631,18 @@ var
WriteStart: LongWord;
ReadCount:LongInt;
LZXState: PLZXState;
InBuf: PByte;
InBuf: array of Byte;
OutBuf: PByte;
BlockSize: QWord;
X: Integer;
FirstBlock, LastBlock: LongInt;
ResultCode: LongInt;
procedure ReadBlock;
begin
if ReadCount > Length(InBuf) then
SetLength(InBuf, ReadCount);
fStream.Read(InBuf[0], ReadCount);
end;
begin
// okay now the fun stuff ;)
Result := nil;
@ -640,7 +652,7 @@ begin
if ObjectExists(SectionPrefix+'Content') > 0 then begin
Result := TMemoryStream.Create;
fStream.Position := fHeaderSuffix.Offset + fCachedEntry.ContentOffset + StartPos;
Result.CopyFrom(fStream, Length);
Result.CopyFrom(fStream, BlockLength);
end;
Exit;
end
@ -664,12 +676,12 @@ begin
FirstBlock := StartPos div BlockSize
else
FirstBlock := 0;
LastBlock := (StartPos+Length) div BlockSize;
LastBlock := (StartPos+BlockLength) div BlockSize;
if ObjectExists(SectionPrefix+'Content') = 0 then exit;
Result := TMemoryStream.Create;
Result.Size := Length;
InBuf := AllocMem(BlockSize);
Result.Size := BlockLength;
SetLength(InBuf,BlockSize);
OutBuf := GetMem(BlockSize);
// First Init a PLZXState
LZXState := LZXinit(16);
@ -681,8 +693,8 @@ begin
fStream.Position := fHeaderSuffix.Offset + fCachedEntry.ContentOffset + (ResetTable[FirstBLock-1]);
ReadCount := ResetTable[FirstBlock] - ResetTable[FirstBlock-1];
BlockWriteLength:=BlockSize;
fStream.Read(InBuf^, ReadCount);
ResultCode := LZXdecompress(LZXState, InBuf, OutBuf, ReadCount, LongInt(BlockWriteLength));
ReadBlock;
ResultCode := LZXdecompress(LZXState, @InBuf[0], OutBuf, ReadCount, LongInt(BlockWriteLength));
end;
// now start the actual decompression loop
for X := FirstBlock to LastBlock do begin
@ -701,24 +713,25 @@ begin
BlockWriteLength := BlockSize;
if FirstBlock = LastBlock then begin
WriteCount := Length;
WriteCount := BlockLength;
end
else if X = LastBlock then
WriteCount := (StartPos+Length) - (X*BlockSize)
WriteCount := (StartPos+BlockLength) - (X*BlockSize)
else WriteCount := BlockSize - WriteStart;
ReadCount := fStream.Read(InBuf^, ReadCount);
ResultCode := LZXdecompress(LZXState, InBuf, OutBuf, ReadCount, LongInt(BlockWriteLength));
ReadBlock;
ResultCode := LZXdecompress(LZXState, @InBuf[0], OutBuf, ReadCount, LongInt(BlockWriteLength));
//now write the decompressed data to the stream
if ResultCode = DECR_OK then begin
Result.Write(OutBuf[WriteStart], Int64(WriteCount));
end
else begin
//WriteLn('Decompress FAILED with error code: ', ResultCode);
{$IFDEF CHM_DEBUG} // windows gui program will cause an exception with writeln's
WriteLn('Decompress FAILED with error code: ', ResultCode);
{$ENDIF}
Result.Free;
Result := Nil;
FreeMem(InBuf);
FreeMem(OutBuf);
SetLength(ResetTable,0);
LZXteardown(LZXState);
@ -729,7 +742,6 @@ begin
if (X < LastBlock) and (X mod 2 > 0) then LZXreset(LZXState);
end;
Freemem(InBuf);
FreeMem(OutBuf);
SetLength(ResetTable,0);
LZXteardown(LZXState);
@ -740,7 +752,7 @@ function TChmReader.FindBlocksFromUnCompressedAddr(var ResetTableEntry: TPMGList
out CompressedSize: Int64; out UnCompressedSize: Int64; out LZXResetTable: TLZXResetTableArr): QWord;
var
BlockCount: LongWord;
X: Integer;
I: Integer;
begin
Result := 0;
fStream.Position := fHeaderSuffix.Offset + ResetTableEntry.ContentOffset;
@ -759,8 +771,10 @@ begin
SetLength(LZXResetTable, BlockCount);
fStream.Read(LZXResetTable[0], SizeOf(QWord)*BlockCount);
{$IFDEF ENDIAN_BIG}
for I := 0 to High(LZXResetTable) do
LZXResetTable[I] := LEtoN(LZXResetTable[I]);
{$ENDIF}
end;
{ TContextList }

View File

@ -23,7 +23,7 @@ unit LazChmHelp;
interface
uses
Classes, SysUtils, LazHelpIntf, HelpManager, HelpIntfs, LazConfigStorage,
Classes, SysUtils, LazHelpIntf, HelpIntfs, LazConfigStorage,
PropEdits, LHelpControl;
type