mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-02 11:01:20 +02:00
chmhelp fixes from mftq75
git-svn-id: trunk@9797 -
This commit is contained in:
parent
b45d740067
commit
8cbbf72054
@ -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
|
||||
|
@ -121,7 +121,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
Result := (total shl 7) + temp;
|
||||
Result := LEtoN(Result);
|
||||
|
||||
end;
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -23,7 +23,7 @@ unit LazChmHelp;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LazHelpIntf, HelpManager, HelpIntfs, LazConfigStorage,
|
||||
Classes, SysUtils, LazHelpIntf, HelpIntfs, LazConfigStorage,
|
||||
PropEdits, LHelpControl;
|
||||
|
||||
type
|
||||
|
Loading…
Reference in New Issue
Block a user