addons update
git-svn-id: https://svn.code.sf.net/p/kolmck/code@67 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
This commit is contained in:
2623
Addons/ActiveKOL.pas
Normal file
2623
Addons/ActiveKOL.pas
Normal file
File diff suppressed because it is too large
Load Diff
1357
Addons/DHTMLEDLib_TLBKOL.pas
Normal file
1357
Addons/DHTMLEDLib_TLBKOL.pas
Normal file
File diff suppressed because it is too large
Load Diff
267
Addons/GIF_ASM.inc
Normal file
267
Addons/GIF_ASM.inc
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
asm
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, [SourcePtr]
|
||||||
|
mov edi, [Target]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
xor ebx, ebx
|
||||||
|
{$ELSE}
|
||||||
|
mov ebx, [StackPointer]
|
||||||
|
{$ENDIF}
|
||||||
|
mov ch, byte ptr [Bits]
|
||||||
|
mov cl, byte ptr [CodeSize]
|
||||||
|
|
||||||
|
@@loop:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp [Bad], 0
|
||||||
|
jnz @@exit
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
mov eax, [UnpackedSize]
|
||||||
|
test eax, eax
|
||||||
|
setle al
|
||||||
|
mov edx, [PackedSize]
|
||||||
|
test edx, edx
|
||||||
|
setle ah
|
||||||
|
or al, ah
|
||||||
|
jnz @@exit
|
||||||
|
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
mov eax, [UnpackedSize]
|
||||||
|
mov edx, [PackedSize]
|
||||||
|
mov ecx, [Data]
|
||||||
|
call doGifLog
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
movzx eax, byte ptr [esi]
|
||||||
|
xchg cl, ch
|
||||||
|
shl eax, cl
|
||||||
|
xchg cl, ch
|
||||||
|
add [Data], eax
|
||||||
|
add ch, 8
|
||||||
|
|
||||||
|
@@while:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp [Bad], 0
|
||||||
|
jnz @@exit
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
cmp ch, cl
|
||||||
|
jb @@e_while
|
||||||
|
|
||||||
|
mov eax, [Data]
|
||||||
|
and eax, [CodeMask]
|
||||||
|
shr [Data], cl
|
||||||
|
|
||||||
|
sub ch, cl
|
||||||
|
cmp eax, [EOICode]
|
||||||
|
jz @@e_while
|
||||||
|
|
||||||
|
@@1:
|
||||||
|
cmp eax, [ClearCode]
|
||||||
|
jnz @@2
|
||||||
|
|
||||||
|
mov cl, [initial_code_size]
|
||||||
|
inc cl
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
shl eax, cl
|
||||||
|
dec eax
|
||||||
|
mov [CodeMask], eax
|
||||||
|
mov eax, [ClearCode]
|
||||||
|
add eax, 2
|
||||||
|
mov [FreeCode], eax
|
||||||
|
mov [OldCode], NoLZWCode
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@2:
|
||||||
|
cmp eax, [FreeCode]
|
||||||
|
ja @@e_while
|
||||||
|
|
||||||
|
@@3:
|
||||||
|
cmp [OldCode], NoLZWCode
|
||||||
|
jne @@4
|
||||||
|
|
||||||
|
mov [OldCode], eax
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good1
|
||||||
|
mov [Bad], 1
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
@@suffix_good1:
|
||||||
|
{$ENDIF}
|
||||||
|
mov al, byte ptr [suffix+eax]
|
||||||
|
mov [FirstChar], al
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
call doGifLog2
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
stosb
|
||||||
|
dec [UnpackedSize]
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@4:
|
||||||
|
mov [InCode], eax
|
||||||
|
cmp eax, [FreeCode]
|
||||||
|
jne @@5
|
||||||
|
|
||||||
|
mov al, [FirstChar]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jae @@stk_bad1
|
||||||
|
mov byte ptr [Stack+ebx], al
|
||||||
|
inc ebx
|
||||||
|
jmp @@stk_good1
|
||||||
|
@@stk_bad1:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good1:
|
||||||
|
{$ELSE}
|
||||||
|
mov [ebx], al
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
mov eax, [OldCode]
|
||||||
|
|
||||||
|
@@5:
|
||||||
|
cmp eax, [ClearCode]
|
||||||
|
jbe @@6
|
||||||
|
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good2
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good2:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dl, byte ptr [Suffix+eax]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jb @@stk_good2
|
||||||
|
mov [Bad], 1
|
||||||
|
jmp @@exit
|
||||||
|
@@stk_good2:
|
||||||
|
mov byte ptr [Stack+ebx], dl
|
||||||
|
inc ebx
|
||||||
|
@@stk_bad2:
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@Prefix_good1
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@Prefix_good1:
|
||||||
|
{$ELSE}
|
||||||
|
mov byte ptr [ebx], dl
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
mov eax, dword ptr [Prefix+eax*4]
|
||||||
|
jmp @@5
|
||||||
|
|
||||||
|
@@6:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good3
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good3:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dl, byte ptr [Suffix+eax]
|
||||||
|
mov [FirstChar], dl
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jae @@stk_bad3
|
||||||
|
mov byte ptr [Stack+ebx], dl
|
||||||
|
inc ebx
|
||||||
|
jmp @@stk_good3
|
||||||
|
@@stk_bad3:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good3:
|
||||||
|
{$ELSE}
|
||||||
|
mov byte ptr [ebx], dl
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
mov eax, [FreeCode]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good4
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good4:
|
||||||
|
{$ENDIF}
|
||||||
|
mov byte ptr [Suffix+eax], dl
|
||||||
|
mov edx, [OldCode]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp edx, GIFBufSize-1
|
||||||
|
jle @@Prefix_good2
|
||||||
|
and edx, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@Prefix_good2:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dword ptr [Prefix+eax*4], edx
|
||||||
|
|
||||||
|
cmp eax, [CodeMask]
|
||||||
|
jnz @@7
|
||||||
|
cmp cl, 12
|
||||||
|
jae @@7
|
||||||
|
|
||||||
|
inc cl
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
shl eax, cl
|
||||||
|
dec eax
|
||||||
|
mov [CodeMask], eax
|
||||||
|
|
||||||
|
@@7:
|
||||||
|
cmp [FreeCode], GIFBufSize-1
|
||||||
|
jae @@8
|
||||||
|
inc [FreeCode]
|
||||||
|
|
||||||
|
@@8:
|
||||||
|
mov eax, [InCode]
|
||||||
|
mov [OldCode], eax
|
||||||
|
|
||||||
|
@@9:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
test ebx, ebx
|
||||||
|
jz @@stk_bad4
|
||||||
|
dec ebx
|
||||||
|
mov al, byte ptr [Stack+ebx]
|
||||||
|
jmp @@stk_good4
|
||||||
|
@@stk_bad4:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good4:
|
||||||
|
{$ELSE}
|
||||||
|
dec ebx
|
||||||
|
mov al, byte ptr [ebx]
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
call doGifLog2
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
stosb
|
||||||
|
dec [UnpackedSize]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
test ebx, ebx
|
||||||
|
{$ELSE}
|
||||||
|
cmp ebx, [StackPointer]
|
||||||
|
{$ENDIF}
|
||||||
|
jne @@9
|
||||||
|
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@e_while:
|
||||||
|
inc esi
|
||||||
|
dec [PackedSize]
|
||||||
|
|
||||||
|
jmp @@loop
|
||||||
|
|
||||||
|
@@exit:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
end;
|
315
Addons/GIF_MMX.inc
Normal file
315
Addons/GIF_MMX.inc
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
asm
|
||||||
|
pxor mm0, mm0
|
||||||
|
pxor mm1, mm1
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
movd mm1, eax
|
||||||
|
movd mm2, eax
|
||||||
|
psllq mm2, 32
|
||||||
|
mov edx, [UnpackedSize]
|
||||||
|
movd mm3, edx
|
||||||
|
psllq mm3, 32
|
||||||
|
mov edx, [PackedSize]
|
||||||
|
pxor mm4, mm4
|
||||||
|
movd mm4, edx
|
||||||
|
por mm3, mm4 // mm3 hi dword = UnpackedSize, mm3 lo dword = PackedSize
|
||||||
|
pxor mm4, mm4 // mm4 = Data
|
||||||
|
mov eax, [CodeMask]
|
||||||
|
movd mm5, eax
|
||||||
|
mov eax, [OldCode]
|
||||||
|
movd mm6, eax
|
||||||
|
//
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, [SourcePtr]
|
||||||
|
mov edi, [Target]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
xor ebx, ebx
|
||||||
|
{$ELSE}
|
||||||
|
mov ebx, [StackPointer]
|
||||||
|
{$ENDIF}
|
||||||
|
mov ch, byte ptr [Bits]
|
||||||
|
mov cl, byte ptr [CodeSize]
|
||||||
|
|
||||||
|
@@loop:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp [Bad], 0
|
||||||
|
jnz @@exit
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
movq mm7, mm3 // check if (PackedSize > 0) and (UnpackedSize > 0) then
|
||||||
|
pcmpgtd mm7, mm0
|
||||||
|
packsswb mm7, mm7
|
||||||
|
movd eax, mm7
|
||||||
|
inc eax
|
||||||
|
jnz @@exit // end of loop if not (one of operands = 0)
|
||||||
|
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
movq mm7, mm3
|
||||||
|
movd edx, mm7
|
||||||
|
psrlq mm7, 32
|
||||||
|
movd eax, mm7
|
||||||
|
movd ecx, mm4
|
||||||
|
call doGifLog
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
movzx eax, byte ptr [esi]
|
||||||
|
xchg cl, ch
|
||||||
|
shl eax, cl
|
||||||
|
xchg cl, ch
|
||||||
|
//add [Data], eax
|
||||||
|
movd mm7, eax
|
||||||
|
paddd mm4, mm7
|
||||||
|
add ch, 8
|
||||||
|
|
||||||
|
@@while:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp [Bad], 0
|
||||||
|
jnz @@exit
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
cmp ch, cl
|
||||||
|
jb @@e_while
|
||||||
|
|
||||||
|
//mov eax, [Data]
|
||||||
|
movd eax, mm4
|
||||||
|
//and eax, [CodeMask]
|
||||||
|
movd edx, mm5
|
||||||
|
and eax, edx
|
||||||
|
//shr [Data], cl
|
||||||
|
movzx edx, cl
|
||||||
|
movd mm7, edx
|
||||||
|
psrld mm4, mm7
|
||||||
|
|
||||||
|
sub ch, cl
|
||||||
|
cmp eax, [EOICode]
|
||||||
|
jz @@e_while
|
||||||
|
|
||||||
|
@@1:
|
||||||
|
cmp eax, [ClearCode]
|
||||||
|
jnz @@2
|
||||||
|
|
||||||
|
mov cl, [initial_code_size]
|
||||||
|
inc cl
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
shl eax, cl
|
||||||
|
dec eax
|
||||||
|
//mov [CodeMask], eax
|
||||||
|
movd mm5, eax
|
||||||
|
mov eax, [ClearCode]
|
||||||
|
add eax, 2
|
||||||
|
mov [FreeCode], eax
|
||||||
|
//mov [OldCode], NoLZWCode
|
||||||
|
mov edx, NoLZWCode
|
||||||
|
movd mm6, edx
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@2:
|
||||||
|
cmp eax, [FreeCode]
|
||||||
|
ja @@e_while
|
||||||
|
|
||||||
|
@@3:
|
||||||
|
//cmp [OldCode], NoLZWCode
|
||||||
|
movd edx, mm6
|
||||||
|
cmp edx, NoLZWCode
|
||||||
|
jne @@4
|
||||||
|
|
||||||
|
//mov [OldCode], eax
|
||||||
|
movd mm6, eax
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good1
|
||||||
|
mov [Bad], 1
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
@@suffix_good1:
|
||||||
|
{$ENDIF}
|
||||||
|
mov al, byte ptr [suffix+eax]
|
||||||
|
mov [FirstChar], al
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
call doGifLog2
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
stosb
|
||||||
|
//dec [UnpackedSize]
|
||||||
|
psubd mm3, mm2
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@4:
|
||||||
|
//mov [InCode], eax
|
||||||
|
movd mm7, eax
|
||||||
|
cmp eax, [FreeCode]
|
||||||
|
jne @@5
|
||||||
|
|
||||||
|
mov al, [FirstChar]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jae @@stk_bad1
|
||||||
|
mov byte ptr [Stack+ebx], al
|
||||||
|
inc ebx
|
||||||
|
jmp @@stk_good1
|
||||||
|
@@stk_bad1:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good1:
|
||||||
|
{$ELSE}
|
||||||
|
mov [ebx], al
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
//mov eax, [OldCode]
|
||||||
|
movd eax, mm6
|
||||||
|
|
||||||
|
@@5:
|
||||||
|
cmp eax, [ClearCode]
|
||||||
|
jbe @@6
|
||||||
|
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good2
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good2:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dl, byte ptr [Suffix+eax]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jb @@stk_good2
|
||||||
|
mov [Bad], 1
|
||||||
|
jmp @@exit
|
||||||
|
@@stk_good2:
|
||||||
|
mov byte ptr [Stack+ebx], dl
|
||||||
|
inc ebx
|
||||||
|
@@stk_bad2:
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@Prefix_good1
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@Prefix_good1:
|
||||||
|
{$ELSE}
|
||||||
|
mov byte ptr [ebx], dl
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
mov eax, dword ptr [Prefix+eax*4]
|
||||||
|
jmp @@5
|
||||||
|
|
||||||
|
@@6:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good3
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good3:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dl, byte ptr [Suffix+eax]
|
||||||
|
mov [FirstChar], dl
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp ebx, GIFBufSize
|
||||||
|
jae @@stk_bad3
|
||||||
|
mov byte ptr [Stack+ebx], dl
|
||||||
|
inc ebx
|
||||||
|
jmp @@stk_good3
|
||||||
|
@@stk_bad3:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good3:
|
||||||
|
{$ELSE}
|
||||||
|
mov byte ptr [ebx], dl
|
||||||
|
inc ebx
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
mov eax, [FreeCode]
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp eax, GIFBufSize-1
|
||||||
|
jle @@suffix_good4
|
||||||
|
and eax, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@suffix_good4:
|
||||||
|
{$ENDIF}
|
||||||
|
mov byte ptr [Suffix+eax], dl
|
||||||
|
//mov edx, [OldCode]
|
||||||
|
movd edx, mm6
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
cmp edx, GIFBufSize-1
|
||||||
|
jle @@Prefix_good2
|
||||||
|
and edx, GIFBufSize-1
|
||||||
|
mov [Bad], 1
|
||||||
|
@@Prefix_good2:
|
||||||
|
{$ENDIF}
|
||||||
|
mov dword ptr [Prefix+eax*4], edx
|
||||||
|
|
||||||
|
//cmp eax, [CodeMask]
|
||||||
|
movd edx, mm5
|
||||||
|
cmp eax, edx
|
||||||
|
jnz @@7
|
||||||
|
cmp cl, 12
|
||||||
|
jae @@7
|
||||||
|
|
||||||
|
inc cl
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
shl eax, cl
|
||||||
|
dec eax
|
||||||
|
//mov [CodeMask], eax
|
||||||
|
movd mm5, eax
|
||||||
|
|
||||||
|
@@7:
|
||||||
|
cmp [FreeCode], GIFBufSize-1
|
||||||
|
jae @@8
|
||||||
|
inc [FreeCode]
|
||||||
|
|
||||||
|
@@8:
|
||||||
|
//mov eax, [InCode]
|
||||||
|
movd eax, mm7
|
||||||
|
//mov [OldCode], eax
|
||||||
|
movd mm6, eax
|
||||||
|
|
||||||
|
@@9:
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
test ebx, ebx
|
||||||
|
jz @@stk_bad4
|
||||||
|
dec ebx
|
||||||
|
mov al, byte ptr [Stack+ebx]
|
||||||
|
jmp @@stk_good4
|
||||||
|
@@stk_bad4:
|
||||||
|
mov [Bad], 1
|
||||||
|
@@stk_good4:
|
||||||
|
{$ELSE}
|
||||||
|
dec ebx
|
||||||
|
mov al, byte ptr [ebx]
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{$IFDEF GIF_LOG}
|
||||||
|
pushad
|
||||||
|
call doGifLog2
|
||||||
|
popad
|
||||||
|
{$ENDIF}
|
||||||
|
stosb
|
||||||
|
//dec [UnpackedSize]
|
||||||
|
psubd mm3, mm2
|
||||||
|
{$IFDEF GIF_SAFE}
|
||||||
|
test ebx, ebx
|
||||||
|
{$ELSE}
|
||||||
|
cmp ebx, [StackPointer]
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
jne @@9
|
||||||
|
|
||||||
|
jmp @@while
|
||||||
|
|
||||||
|
@@e_while:
|
||||||
|
inc esi
|
||||||
|
//dec [PackedSize]
|
||||||
|
psubd mm3, mm1
|
||||||
|
jmp @@loop
|
||||||
|
|
||||||
|
@@exit:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
|
||||||
|
emms
|
||||||
|
end
|
2352
Addons/KOLComObj.pas
Normal file
2352
Addons/KOLComObj.pas
Normal file
File diff suppressed because it is too large
Load Diff
21
Addons/KOLDHTML.pas
Normal file
21
Addons/KOLDHTML.pas
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
unit KOLDHTML;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL, DHTMLEDLib_TLBKOL;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TDHTMLEDIT = DHTMLEDLib_TLBKOL.PDHTMLEDIT;
|
||||||
|
PDHTMLEDIT = DHTMLEDLib_TLBKOL.PDHTMLEDIT;
|
||||||
|
|
||||||
|
function NewDHTMLEDIT(AOwner: PControl): PDHTMLEDIT;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function NewDHTMLEDIT;
|
||||||
|
begin
|
||||||
|
new( Result, CreateParented( AOwner ) );
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
583
Addons/KOLOleRE.pas
Normal file
583
Addons/KOLOleRE.pas
Normal file
@ -0,0 +1,583 @@
|
|||||||
|
unit KOLOleRE;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
{$I KOLDEF.inc}
|
||||||
|
|
||||||
|
uses
|
||||||
|
Windows, Messages, KOL, ActiveX;//, KOLComObj; // {$IFDEF _D6orHigher}, Variants {$ENDIF};
|
||||||
|
|
||||||
|
type
|
||||||
|
ITextDocument = interface( IDispatch )
|
||||||
|
['{8CC497C0-A1DF-11ce-8098-00AA0047BE5D}']
|
||||||
|
function { [propget][id] } GetName(
|
||||||
|
var pName: WideString): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propget][id] } GetSelection(
|
||||||
|
var ppSel: {ITextSelection} Pointer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propget][id] } GetStoryCount(
|
||||||
|
var Count: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propget][id] } GetStoryRanges(
|
||||||
|
var ppStories: {ITextStoryRanges} Pointer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propget][id] } GetSaved(
|
||||||
|
var Value: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propput][id] } SetSaved(
|
||||||
|
Value: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propget][id] } GetDefaultTabStop(
|
||||||
|
var Value: Single): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [propput][id] } SetDefaultTabStop(
|
||||||
|
Value: Single): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } New: HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Open(
|
||||||
|
var pVar: Variant;
|
||||||
|
Flags: Integer;
|
||||||
|
CodePage: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Save(
|
||||||
|
var pVar: Variant;
|
||||||
|
Flags: Integer;
|
||||||
|
CodePage: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Freeze(
|
||||||
|
var Count: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Unfreeze(
|
||||||
|
var Count: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } BeginEditCollection: HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } EndEditCollection: HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Undo(
|
||||||
|
Count: Integer;
|
||||||
|
var prop: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Redo(
|
||||||
|
Count: Integer;
|
||||||
|
var prop: Integer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } Range(
|
||||||
|
cp1: Integer;
|
||||||
|
cp2: Integer;
|
||||||
|
var ppRange: {ITextRange} Pointer): HRESULT; stdcall;
|
||||||
|
|
||||||
|
function { [id] } RangeFromPoint(
|
||||||
|
x: Integer;
|
||||||
|
y: Integer;
|
||||||
|
var ppRange: {ITextRange} Pointer): HRESULT; stdcall;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
PKOLOleRichEdit =^TKOLOleRichEdit;
|
||||||
|
TKOLOleRichEdit = object(TControl)
|
||||||
|
private
|
||||||
|
function GetITD: ITextDocument;
|
||||||
|
protected
|
||||||
|
procedure CreateHandle;
|
||||||
|
function GetDragOle: boolean;
|
||||||
|
procedure SetDragOle(d: boolean);
|
||||||
|
public
|
||||||
|
function BitmapToRTF(pict: PBitmap): string;
|
||||||
|
procedure HideFrames;
|
||||||
|
property CanDragOle: boolean read GetDragOle write SetDragOle;
|
||||||
|
property ITD: ITextDocument read GetITD;
|
||||||
|
procedure Freeze( ACount: Integer );
|
||||||
|
procedure Unfreeze( ACount: Integer );
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NewOLERichEdit( AParent: PControl; Options: TEditOptions ): PKOLOleRichEdit;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$B-}
|
||||||
|
|
||||||
|
const
|
||||||
|
{$EXTERNALSYM EM_GETOLEINTERFACE}
|
||||||
|
EM_GETOLEINTERFACE = WM_USER + 60;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
_charrange = record
|
||||||
|
cpMin: Longint;
|
||||||
|
cpMax: LongInt;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$EXTERNALSYM _charrange}
|
||||||
|
TCharRange = _charrange;
|
||||||
|
CHARRANGE = _charrange;
|
||||||
|
{$EXTERNALSYM CHARRANGE}
|
||||||
|
|
||||||
|
TREOBJECT = packed record
|
||||||
|
cbStruct: DWORD; // Size of structure
|
||||||
|
cp: longint; // Character position of object
|
||||||
|
clsid: TCLSID; // Class ID of object
|
||||||
|
oleobj: IOleObject; // OLE object interface
|
||||||
|
stg: IStorage; // Associated storage interface
|
||||||
|
olesite: IOLEClientSite; // Associated client site interface
|
||||||
|
sizel: TSize; // Size of object (may be 0,0)
|
||||||
|
dvaspect: DWORD; // Display aspect to use
|
||||||
|
dwFlags: DWORD; // Object status flags
|
||||||
|
dwUser: DWORD; // Dword for user's use
|
||||||
|
end;
|
||||||
|
|
||||||
|
IRichEditOle = interface(IUnknown)
|
||||||
|
['{00020D00-0000-0000-C000-000000000046}']
|
||||||
|
function GetClientSite(out lplpolesite: IOLECLIENTSITE): HResult; stdcall;
|
||||||
|
function GetObjectCount: longint; stdcall;
|
||||||
|
function GetLinkCount: longint; stdcall;
|
||||||
|
function GetObject(iob: longint; out reobject: TREOBJECT; dwFlags: DWORD): HRESULT; stdcall;
|
||||||
|
function InsertObject(const reobject: TREOBJECT): HResult; stdcall;
|
||||||
|
function ConvertObject(iob: longint; const clsidNew: TCLSID;
|
||||||
|
lpStrUserTypeNew: POleStr): HRESULT; stdcall;
|
||||||
|
function ActivateAs(const clsid, clsidAs: TCLSID): HRESULT; stdcall;
|
||||||
|
function SetHostNames(lpstrContainerApp, lpstrContainerObj: POleStr): HRESULT; stdcall;
|
||||||
|
function SetLinkAvailable(iob: longint; fAvailable: BOOL): HRESULT; stdcall;
|
||||||
|
function SetDvaspect(iob: longint; dvaspect: DWORD): HRESULT; stdcall;
|
||||||
|
function HandsOffStorage(iob: longint): HRESULT; stdcall;
|
||||||
|
function SaveCompleted(iob: longint; stg: IStorage): HRESULT; stdcall;
|
||||||
|
function InPlaceDeactivate: HRESULT; stdcall;
|
||||||
|
function ContextSensitiveHelp(fEnterMode: BOOL): HRESULT; stdcall;
|
||||||
|
function GetClipboardData(const chrg: TCharRange; reco: DWORD;
|
||||||
|
out dataobj: IDataObject): HRESULT; stdcall;
|
||||||
|
function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;
|
||||||
|
hMetaPict: HGLOBAL): HRESULT; stdcall;
|
||||||
|
end;
|
||||||
|
|
||||||
|
IRichEditOleCallback = interface(IUnknown)
|
||||||
|
['{00020D03-0000-0000-C000-000000000046}']
|
||||||
|
function GetNewStorage: IStorage; safecall;
|
||||||
|
procedure GetInPlaceContext(out Frame: IOleInPlaceFrame;
|
||||||
|
out Doc: IOleInPlaceUIWindow; var FrameInfo: TOleInPlaceFrameInfo); safecall;
|
||||||
|
procedure ShowContainerUI(fShow: Bool); safecall;
|
||||||
|
procedure QueryInsertObject(const ClsID: TCLSID; Stg: IStorage; CP: Longint); safecall;
|
||||||
|
procedure DeleteObject(OleObj: IOleObject); safecall;
|
||||||
|
procedure QueryAcceptData(dataobj: IDataObject; var cfFormat: TClipFormat;
|
||||||
|
reCO: DWord; fReally: Bool; hMetaPict: HGlobal); safecall;
|
||||||
|
function ContextSensitiveHelp(fEnterMode: Bool): HResult; stdcall;
|
||||||
|
function GetClipboardData(const ChRg: TCharRange; reCO: DWord; out DataObj: IDataObject): HResult; stdcall;
|
||||||
|
procedure GetDragDropEffect(fDrag: Bool; grfKeyState: DWord;
|
||||||
|
var dwEffect: DWord); safecall;
|
||||||
|
procedure GetContextMenu(SelType: Word; OleObj: IOleObject;
|
||||||
|
const ChRg: TCharRange; var Menu: HMenu); safecall;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TRichEditOleCallback = class(TInterfacedObject, IRichEditOleCallback)
|
||||||
|
private
|
||||||
|
FOwner: PKOLOleRichEdit;
|
||||||
|
protected
|
||||||
|
{ IRichEditOleCallback }
|
||||||
|
function GetNewStorage: IStorage; safecall;
|
||||||
|
procedure GetInPlaceContext(out Frame: IOleInPlaceFrame;
|
||||||
|
out Doc: IOleInPlaceUIWindow; var FrameInfo: TOleInPlaceFrameInfo); safecall;
|
||||||
|
procedure ShowContainerUI(fShow: Bool); safecall;
|
||||||
|
procedure QueryInsertObject(const ClsID: TCLSID; Stg: IStorage; CP: Longint); safecall;
|
||||||
|
procedure DeleteObject(OleObj: IOleObject); safecall;
|
||||||
|
procedure QueryAcceptData(dataobj: IDataObject; var cfFormat: TClipFormat;
|
||||||
|
reCO: DWord; fReally: Bool; hMetaPict: HGlobal); safecall;
|
||||||
|
function ContextSensitiveHelp(fEnterMode: Bool): HResult; stdcall;
|
||||||
|
function GetClipboardData(const ChRg: TCharRange; reCO: DWord; out DataObj: IDataObject): HResult; stdcall;
|
||||||
|
procedure GetDragDropEffect(fDrag: Bool; grfKeyState: DWord;
|
||||||
|
var dwEffect: DWord); safecall;
|
||||||
|
procedure GetContextMenu(SelType: Word; OleObj: IOleObject;
|
||||||
|
const ChRg: TCharRange; var Menu: HMenu); safecall;
|
||||||
|
public
|
||||||
|
constructor Create(Owner: PKOLOleRichEdit);
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PData =^TData;
|
||||||
|
TData = object( TObj )
|
||||||
|
IOle: IRichEditOle;
|
||||||
|
IBck: TRichEditOleCallback;
|
||||||
|
ITD : ITextDocument;
|
||||||
|
Drag: boolean;
|
||||||
|
destructor Destroy; virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
{$EXTERNALSYM EM_SETOLECALLBACK}
|
||||||
|
EM_SETOLECALLBACK = WM_USER + 70;
|
||||||
|
|
||||||
|
procedure OleCheck(Result: HResult);
|
||||||
|
begin
|
||||||
|
if not Succeeded(Result) then
|
||||||
|
MsgOK('OleCheck Fail ');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NewOLERichEdit( AParent: PControl; Options: TEditOptions ): PKOLOleRichEdit;
|
||||||
|
label exit;
|
||||||
|
var p: PData;
|
||||||
|
begin
|
||||||
|
Result := PKOLOleRichEdit(KOL.NewRichEdit( AParent, Options ));
|
||||||
|
new(p, Create);
|
||||||
|
Result.CustomObj := p;
|
||||||
|
Result.CreateWindow;
|
||||||
|
Result.CreateHandle;
|
||||||
|
Result.Perform(EM_GETOLEINTERFACE, 0, integer(@p.IOle));
|
||||||
|
p.IOle.QueryInterface( ITextDocument, p.ITD );
|
||||||
|
|
||||||
|
{asm
|
||||||
|
MOV EDX, offset @@new_call + 4
|
||||||
|
MOV EDX, [EDX]
|
||||||
|
ADD EDX, 12
|
||||||
|
// MOV [EBX], EDX //-- may be this works for some cases, but not in case when optimization is off
|
||||||
|
MOV EAX, [Result]
|
||||||
|
MOV [EAX+12], EDX
|
||||||
|
jmp exit
|
||||||
|
@@new_call:
|
||||||
|
end;
|
||||||
|
|
||||||
|
new( Result, CreateParented( AParent ) );
|
||||||
|
exit:}
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLOleRichEdit.CreateHandle;
|
||||||
|
var I: IRichEditOleCallback;
|
||||||
|
T: TRichEditOleCallback;
|
||||||
|
P: PData;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
T := TRichEditOleCallback.Create(@Self);
|
||||||
|
I := T as IRichEditOleCallback;
|
||||||
|
Perform(em_SetOleCallback, 0, Longint(I));
|
||||||
|
P := Pointer( CustomObj );
|
||||||
|
P.IBck := T;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRichEditOleCallback }
|
||||||
|
|
||||||
|
constructor TRichEditOleCallback.Create(Owner: PKOLOleRichEdit);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FOwner := Owner;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TRichEditOleCallback.Destroy;
|
||||||
|
//var Form: PControl;
|
||||||
|
begin
|
||||||
|
{ Form := GetParentForm(FOwner);}
|
||||||
|
{ if Assigned(Form) and Assigned(Form.OleFormObject) then
|
||||||
|
(Form.OleFormObject as IOleInPlaceUIWindow).SetActiveObject(nil, nil);}
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRichEditOleCallback.ContextSensitiveHelp(fEnterMode: Bool): HResult;
|
||||||
|
begin
|
||||||
|
Result := E_NOTIMPL
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.DeleteObject(OleObj: IOleObject);
|
||||||
|
begin
|
||||||
|
OleObj.Close(OLECLOSE_NOSAVE);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRichEditOleCallback.GetClipboardData(const ChRg: TCharRange; reCO: DWord; out DataObj: IDataObject): HResult;
|
||||||
|
begin
|
||||||
|
Result := E_NOTIMPL;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.GetContextMenu(SelType: Word;
|
||||||
|
OleObj: IOleObject; const ChRg: TCharRange; var Menu: HMenu);
|
||||||
|
begin
|
||||||
|
Menu := 0
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.GetDragDropEffect(fDrag: Bool;
|
||||||
|
grfKeyState: DWord; var dwEffect: DWord);
|
||||||
|
var p: PData;
|
||||||
|
begin
|
||||||
|
if fOwner <> nil then begin
|
||||||
|
if fOwner.CustomObj <> nil then
|
||||||
|
begin
|
||||||
|
p := Pointer( fOwner.CustomObj );
|
||||||
|
if not p.Drag then begin
|
||||||
|
dwEffect := 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.GetInPlaceContext(
|
||||||
|
out Frame: IOleInPlaceFrame; out Doc: IOleInPlaceUIWindow;
|
||||||
|
var FrameInfo: TOleInPlaceFrameInfo);
|
||||||
|
//var Form: PControl;
|
||||||
|
begin
|
||||||
|
//Get richedit's underlying form
|
||||||
|
{ Form := ValidParentForm(FOwner);}
|
||||||
|
//Ensure there is a TOleForm object
|
||||||
|
{ if Form.OleFormObject = nil then
|
||||||
|
TOleForm.Create(Form);}
|
||||||
|
//Get relevant frame interface
|
||||||
|
{ Frame := Form.OleFormObject as IOleInPlaceFrame;}
|
||||||
|
Doc := nil; //Document window is same as frame window
|
||||||
|
FrameInfo.hWndFrame := 0; // Form.Handle;
|
||||||
|
FrameInfo.fMDIApp := False;
|
||||||
|
FrameInfo.hAccel := 0;
|
||||||
|
FrameInfo.cAccelEntries := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRichEditOleCallback.GetNewStorage: IStorage;
|
||||||
|
var
|
||||||
|
LockBytes: ILockBytes;
|
||||||
|
begin
|
||||||
|
//Basically copied from TOleContainer.CreateStorage
|
||||||
|
OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes));
|
||||||
|
OleCheck(StgCreateDocfileOnILockBytes(LockBytes,
|
||||||
|
STGM_READWRITE or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, Result));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.QueryAcceptData(dataobj: IDataObject;
|
||||||
|
var cfFormat: TClipFormat; reCO: DWord; fReally: Bool;
|
||||||
|
hMetaPict: HGlobal);
|
||||||
|
begin
|
||||||
|
//Accept anything
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.QueryInsertObject(const ClsID: TCLSID;
|
||||||
|
Stg: IStorage; CP: Integer);
|
||||||
|
begin
|
||||||
|
//Accept anything
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRichEditOleCallback.ShowContainerUI(fShow: Bool);
|
||||||
|
//var Form: PControl;
|
||||||
|
begin
|
||||||
|
if fShow then
|
||||||
|
begin
|
||||||
|
{ Form := GetParentForm(FOwner);}
|
||||||
|
{ if Assigned(Form) and Assigned(Form.Menu) then
|
||||||
|
begin
|
||||||
|
Form.Menu.SetOle2MenuHandle(0);
|
||||||
|
(Form.OleFormObject as IVCLFrameForm).ClearBorderSpace
|
||||||
|
end}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TOleRichEdit }
|
||||||
|
|
||||||
|
function BytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint;
|
||||||
|
begin
|
||||||
|
Dec(Alignment);
|
||||||
|
Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment;
|
||||||
|
Result := Result div 8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var BI: TBitmapInfoHeader;
|
||||||
|
Colors: Integer);
|
||||||
|
var
|
||||||
|
DS: TDIBSection;
|
||||||
|
Bytes: Integer;
|
||||||
|
begin
|
||||||
|
DS.dsbmih.biSize := 0;
|
||||||
|
Bytes := GetObject(Bitmap, SizeOf(DS), @DS);
|
||||||
|
if Bytes = 0 then {InvalidBitmap}
|
||||||
|
else if (Bytes >= (sizeof(DS.dsbm) + sizeof(DS.dsbmih))) and
|
||||||
|
(DS.dsbmih.biSize >= DWORD(sizeof(DS.dsbmih))) then
|
||||||
|
BI := DS.dsbmih
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
FillChar(BI, sizeof(BI), 0);
|
||||||
|
with BI, DS.dsbm do
|
||||||
|
begin
|
||||||
|
biSize := SizeOf(BI);
|
||||||
|
biWidth := bmWidth;
|
||||||
|
biHeight := bmHeight;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
case Colors of
|
||||||
|
2: BI.biBitCount := 1;
|
||||||
|
3..16:
|
||||||
|
begin
|
||||||
|
BI.biBitCount := 4;
|
||||||
|
BI.biClrUsed := Colors;
|
||||||
|
end;
|
||||||
|
17..256:
|
||||||
|
begin
|
||||||
|
BI.biBitCount := 8;
|
||||||
|
BI.biClrUsed := Colors;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
BI.biBitCount := DS.dsbm.bmBitsPixel * DS.dsbm.bmPlanes;
|
||||||
|
end;
|
||||||
|
BI.biPlanes := 1;
|
||||||
|
if BI.biClrImportant > BI.biClrUsed then
|
||||||
|
BI.biClrImportant := BI.biClrUsed;
|
||||||
|
if BI.biSizeImage = 0 then
|
||||||
|
BI.biSizeImage := BytesPerScanLine(BI.biWidth, BI.biBitCount, 32) * Abs(BI.biHeight);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: DWORD;
|
||||||
|
var ImageSize: DWORD; Colors: Integer);
|
||||||
|
var
|
||||||
|
BI: TBitmapInfoHeader;
|
||||||
|
begin
|
||||||
|
InitializeBitmapInfoHeader(Bitmap, BI, Colors);
|
||||||
|
if BI.biBitCount > 8 then
|
||||||
|
begin
|
||||||
|
InfoHeaderSize := SizeOf(TBitmapInfoHeader);
|
||||||
|
if (BI.biCompression and BI_BITFIELDS) <> 0 then
|
||||||
|
Inc(InfoHeaderSize, 12);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if BI.biClrUsed = 0 then
|
||||||
|
InfoHeaderSize := SizeOf(TBitmapInfoHeader) +
|
||||||
|
SizeOf(TRGBQuad) * (1 shl BI.biBitCount)
|
||||||
|
else
|
||||||
|
InfoHeaderSize := SizeOf(TBitmapInfoHeader) +
|
||||||
|
SizeOf(TRGBQuad) * BI.biClrUsed;
|
||||||
|
ImageSize := BI.biSizeImage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure GetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: DWORD;
|
||||||
|
var ImageSize: DWORD);
|
||||||
|
begin
|
||||||
|
InternalGetDIBSizes(Bitmap, InfoHeaderSize, ImageSize, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE;
|
||||||
|
var BitmapInfo; var Bits; Colors: Integer): Boolean;
|
||||||
|
var
|
||||||
|
OldPal: HPALETTE;
|
||||||
|
DC: HDC;
|
||||||
|
begin
|
||||||
|
InitializeBitmapInfoHeader(Bitmap, TBitmapInfoHeader(BitmapInfo), Colors);
|
||||||
|
OldPal := 0;
|
||||||
|
DC := CreateCompatibleDC(0);
|
||||||
|
try
|
||||||
|
if Palette <> 0 then
|
||||||
|
begin
|
||||||
|
OldPal := SelectPalette(DC, Palette, False);
|
||||||
|
RealizePalette(DC);
|
||||||
|
end;
|
||||||
|
Result := GetDIBits(DC, Bitmap, 0, TBitmapInfoHeader(BitmapInfo).biHeight, @Bits,
|
||||||
|
TBitmapInfo(BitmapInfo), DIB_RGB_COLORS) <> 0;
|
||||||
|
finally
|
||||||
|
if OldPal <> 0 then SelectPalette(DC, OldPal, False);
|
||||||
|
DeleteDC(DC);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetDIB(Bitmap: HBITMAP; Palette: HPALETTE; var BitmapInfo; var Bits): Boolean;
|
||||||
|
begin
|
||||||
|
Result := InternalGetDIB(Bitmap, Palette, BitmapInfo, Bits, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKOLOleRichEdit.BitmapToRTF(pict: PBitmap): string;
|
||||||
|
var
|
||||||
|
bi, bb, rtf: string;
|
||||||
|
bis, bbs: Cardinal;
|
||||||
|
achar: ShortString;
|
||||||
|
hexpict: string;
|
||||||
|
I: Integer;
|
||||||
|
begin
|
||||||
|
GetDIBSizes(pict.Handle, bis, bbs);
|
||||||
|
SetLength(bi, bis);
|
||||||
|
SetLength(bb, bbs);
|
||||||
|
GetDIB(pict.Handle, {pict.Palette}0, PChar(bi)^, PChar(bb)^);
|
||||||
|
rtf := '{\rtf1 {\pict\dibitmap ';
|
||||||
|
SetLength(hexpict, (Length(bb) + Length(bi)) * 2);
|
||||||
|
I := 2;
|
||||||
|
for bis := 1 to Length(bi) do
|
||||||
|
begin
|
||||||
|
achar := Format('%x', [Integer(bi[bis])]);
|
||||||
|
if Length(achar) = 1 then
|
||||||
|
achar := '0' + achar;
|
||||||
|
hexpict[I - 1] := achar[1];
|
||||||
|
hexpict[I] := achar[2];
|
||||||
|
Inc(I, 2);
|
||||||
|
end;
|
||||||
|
for bbs := 1 to Length(bb) do
|
||||||
|
begin
|
||||||
|
achar := Format('%x', [Integer(bb[bbs])]);
|
||||||
|
if Length(achar) = 1 then
|
||||||
|
achar := '0' + achar;
|
||||||
|
hexpict[I - 1] := achar[1];
|
||||||
|
hexpict[I] := achar[2];
|
||||||
|
Inc(I, 2);
|
||||||
|
end;
|
||||||
|
rtf := rtf + hexpict + ' }}';
|
||||||
|
Result := rtf;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLOleRichEdit.HideFrames;
|
||||||
|
var p: PData;
|
||||||
|
i: integer;
|
||||||
|
n: integer;
|
||||||
|
o: TREOBJECT;
|
||||||
|
begin
|
||||||
|
p := Pointer( CustomObj );
|
||||||
|
n := p.IOle.GetObjectCount;
|
||||||
|
for i := n - 1 downto 0 do begin
|
||||||
|
fillchar(o, sizeof(o), 0);
|
||||||
|
o.cbStruct := sizeof(O);
|
||||||
|
if p.IOle.GetObject(i, o, 7) = S_OK then begin
|
||||||
|
o.dwFlags := 0;
|
||||||
|
p.IOle.InsertObject(o);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKOLOleRichEdit.GetDragOle;
|
||||||
|
var p: PData;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if CustomObj <> nil then
|
||||||
|
begin
|
||||||
|
p := Pointer( CustomObj );
|
||||||
|
Result := p.Drag;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLOleRichEdit.SetDragOle;
|
||||||
|
var p: PData;
|
||||||
|
begin
|
||||||
|
if CustomObj <> nil then
|
||||||
|
begin
|
||||||
|
p := Pointer( CustomObj );
|
||||||
|
p.Drag := d;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKOLOleRichEdit.GetITD: ITextDocument;
|
||||||
|
var Data: PData;
|
||||||
|
begin
|
||||||
|
Data := Pointer( CustomObj );
|
||||||
|
Result := Data.ITD;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLOleRichEdit.Freeze(ACount: Integer);
|
||||||
|
var Data: PData;
|
||||||
|
begin
|
||||||
|
Data := Pointer( CustomObj );
|
||||||
|
if Data.ITD <> nil then
|
||||||
|
Data.ITD.Freeze( ACount );
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLOleRichEdit.Unfreeze(ACount: Integer);
|
||||||
|
var Data: PData;
|
||||||
|
begin
|
||||||
|
Data := Pointer( CustomObj );
|
||||||
|
if Data.ITD <> nil then
|
||||||
|
Data.ITD.Unfreeze( ACount );
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TData }
|
||||||
|
|
||||||
|
destructor TData.Destroy;
|
||||||
|
begin
|
||||||
|
IBck := nil;
|
||||||
|
ITD := nil;
|
||||||
|
IOLE := nil;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
5037
Addons/KOLPng.pas
Normal file
5037
Addons/KOLPng.pas
Normal file
File diff suppressed because it is too large
Load Diff
1190
Addons/KOLSHDocVw.pas
Normal file
1190
Addons/KOLSHDocVw.pas
Normal file
File diff suppressed because it is too large
Load Diff
1060
Addons/KOLTGA.pas
Normal file
1060
Addons/KOLTGA.pas
Normal file
File diff suppressed because it is too large
Load Diff
31
Addons/KOLWebBrowser.pas
Normal file
31
Addons/KOLWebBrowser.pas
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// TKOLWebBrowser v1.0 //
|
||||||
|
// //
|
||||||
|
// Author: Dimaxx (dimaxx@atnet.ru) //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
unit KOLWebBrowser;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL, KOLSHDocVw;
|
||||||
|
|
||||||
|
type
|
||||||
|
TKOLWebBrowser = PWebBrowser;
|
||||||
|
PKOLWebBrowser = PWebBrowser;
|
||||||
|
|
||||||
|
function NewKOLWebBrowser(AOwner: PControl): PKOLWebBrowser;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function NewKOLWebBrowser;
|
||||||
|
begin
|
||||||
|
New(Result,CreateParented(AOwner));
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
576
Addons/KolZLib.pas
Normal file
576
Addons/KolZLib.pas
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
{*******************************************************}
|
||||||
|
{ }
|
||||||
|
{ Delphi Supplemental Components }
|
||||||
|
{ ZLIB Data Compression Interface Unit }
|
||||||
|
{ }
|
||||||
|
{ Copyright (c) 1997 Borland International }
|
||||||
|
{ }
|
||||||
|
{*******************************************************}
|
||||||
|
|
||||||
|
{ Modified for zlib 1.1.3 by Davide Moretti <dave@rimini.com> }
|
||||||
|
{ Modified for KOL by Alexey Shuvalov <alekc_s@mail.ru> }
|
||||||
|
{ Updated to zlib 1.1.4 by Dimaxx <dimaxx@atnet.ru>}
|
||||||
|
|
||||||
|
// Important! As this unit does not use Kol_Err.pas and SysUtils.pas, there is no
|
||||||
|
// exceptions raised. Therefore check for errors by comparing the values returned by
|
||||||
|
// functions such as Read/Write/Seek with value ZLIB_ERROR.
|
||||||
|
|
||||||
|
|
||||||
|
//Uncomment this to enable CompressBuf & DecompressBuf procedures.
|
||||||
|
//!!! This procedures converted but UNTESTED and MAY BE UNSTABLE !!!
|
||||||
|
//{$DEFINE BUFFERPROCS}
|
||||||
|
|
||||||
|
unit KolZLib;
|
||||||
|
|
||||||
|
{$I KOLDEF.INC}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Windows, Kol;
|
||||||
|
|
||||||
|
const
|
||||||
|
ZLIB_ERROR = TStrmSize (-1);
|
||||||
|
|
||||||
|
type
|
||||||
|
TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer;
|
||||||
|
TFree = procedure (AppData, Block: Pointer);
|
||||||
|
|
||||||
|
// Internal structure. Ignore.
|
||||||
|
TZStreamRec = packed record
|
||||||
|
next_in: PChar; // next input byte
|
||||||
|
avail_in: Integer; // number of bytes available at next_in
|
||||||
|
total_in: Integer; // total nb of input bytes read so far
|
||||||
|
|
||||||
|
next_out: PChar; // next output byte should be put here
|
||||||
|
avail_out: Integer; // remaining free space at next_out
|
||||||
|
total_out: Integer; // total nb of bytes output so far
|
||||||
|
|
||||||
|
msg: PChar; // last error message, NULL if no error
|
||||||
|
internal: Pointer; // not visible by applications
|
||||||
|
|
||||||
|
zalloc: TAlloc; // used to allocate the internal state
|
||||||
|
zfree: TFree; // used to free the internal state
|
||||||
|
AppData: Pointer; // private data object passed to zalloc and zfree
|
||||||
|
|
||||||
|
data_type: Integer; // best guess about the data type: ascii or binary
|
||||||
|
adler: Integer; // adler32 value of the uncompressed data
|
||||||
|
reserved: Integer; // reserved for future use
|
||||||
|
end;
|
||||||
|
|
||||||
|
TZLibEvent = procedure (Sender: PStream) of Object;
|
||||||
|
|
||||||
|
PZLibData = ^TZLibData;
|
||||||
|
TZLibData = record
|
||||||
|
FStrm: PStream;
|
||||||
|
FStrmPos: Cardinal;
|
||||||
|
FOnProgress: TZLibEvent;
|
||||||
|
FZRec: TZStreamRec;
|
||||||
|
FBuffer: array [Word] of Char;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCompressionStream compresses data on the fly as data is written to it, and
|
||||||
|
stores the compressed data to another stream.
|
||||||
|
|
||||||
|
TCompressionStream is write-only and strictly sequential. Reading from the
|
||||||
|
stream will raise an exception. Using Seek to move the stream pointer
|
||||||
|
will raise an exception.
|
||||||
|
|
||||||
|
Output data is cached internally, written to the output stream only when
|
||||||
|
the internal output buffer is full. All pending output data is flushed
|
||||||
|
when the stream is destroyed.
|
||||||
|
|
||||||
|
The Position property returns the number of uncompressed bytes of
|
||||||
|
data that have been written to the stream so far.
|
||||||
|
|
||||||
|
CompressionRate returns the on-the-fly percentage by which the original
|
||||||
|
data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100
|
||||||
|
If raw data size = 100 and compressed data size = 25, the CompressionRate
|
||||||
|
is 75%
|
||||||
|
|
||||||
|
The OnProgress event is called each time the output buffer is filled and
|
||||||
|
written to the output stream. This is useful for updating a progress
|
||||||
|
indicator when you are writing a large chunk of data to the compression
|
||||||
|
stream in a single call.}
|
||||||
|
|
||||||
|
TCompressionLevel = (clNone, clFastest, clDefault, clMax);
|
||||||
|
|
||||||
|
//******************* NewCompressionStream *************************
|
||||||
|
// Creates new ZLib decompression stream. If ZLib initialization failed returns Nil;
|
||||||
|
// On Read/Write errors Read/Write functions return ZLIB_ERROR value (also for Seek).
|
||||||
|
|
||||||
|
function NewCompressionStream (CompressionLevel: TCompressionLevel; Destination: PStream; OnProgress: TZLibEvent): PStream;
|
||||||
|
|
||||||
|
{ TDecompressionStream decompresses data on the fly as data is read from it.
|
||||||
|
|
||||||
|
Compressed data comes from a separate source stream. TDecompressionStream
|
||||||
|
is read-only and unidirectional; you can seek forward in the stream, but not
|
||||||
|
backwards. The special case of setting the stream position to zero is
|
||||||
|
allowed. Seeking forward decompresses data until the requested position in
|
||||||
|
the uncompressed data has been reached. Seeking backwards, seeking relative
|
||||||
|
to the end of the stream, requesting the size of the stream, and writing to
|
||||||
|
the stream will return ZLIB_ERROR as a Result.
|
||||||
|
|
||||||
|
The Position property returns the number of bytes of uncompressed data that
|
||||||
|
have been read from the stream so far.
|
||||||
|
|
||||||
|
The OnProgress event is called each time the internal input buffer of
|
||||||
|
compressed data is exhausted and the next block is read from the input stream.
|
||||||
|
This is useful for updating a progress indicator when you are reading a
|
||||||
|
large chunk of data from the decompression stream in a single call.}
|
||||||
|
|
||||||
|
|
||||||
|
//******************* NewDecompressionStream *************************
|
||||||
|
// Creates new ZLib decompression stream. If ZLib initialization failed returns Nil;
|
||||||
|
// On Read/Write errors Read/Write functions return ZLIB_ERROR value (also for Seek).
|
||||||
|
|
||||||
|
function NewDecompressionStream (Source: PStream; OnProgress: TZLibEvent): PStream;
|
||||||
|
|
||||||
|
|
||||||
|
//******************* NewZLibXStream *************************
|
||||||
|
//Calls New[De]CompressionStream and returns True if Result<>Nil; Stream = Result.
|
||||||
|
// !!! Don't use Overload on this functions - it may cause compilation error
|
||||||
|
// when called with OnProgress=Nil !!!
|
||||||
|
|
||||||
|
function NewZLibDStream (var Stream: PStream; Source: PStream; OnProgress: TZLibEvent): Boolean;
|
||||||
|
function NewZLibCStream (var Stream: PStream; CompressionLevel: TCompressionLevel; Destination: PStream; OnProgress: TZLibEvent): Boolean;
|
||||||
|
|
||||||
|
|
||||||
|
{$IFDEF BUFFERPROCS}
|
||||||
|
{ CompressBuf compresses data, buffer to buffer, in one call.
|
||||||
|
In: InBuf = ptr to compressed data
|
||||||
|
InBytes = number of bytes in InBuf
|
||||||
|
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
||||||
|
OutBytes = number of bytes in OutBuf }
|
||||||
|
|
||||||
|
function CompressBuf(const InBuf: Pointer; InBytes: Integer; out OutBuf: Pointer; out OutBytes: Integer): Boolean;
|
||||||
|
|
||||||
|
{ DecompressBuf decompresses data, buffer to buffer, in one call.
|
||||||
|
In: InBuf = ptr to compressed data
|
||||||
|
InBytes = number of bytes in InBuf
|
||||||
|
OutEstimate = zero, or est. size of the decompressed data
|
||||||
|
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
||||||
|
OutBytes = number of bytes in OutBuf }
|
||||||
|
|
||||||
|
function DecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer): Boolean;
|
||||||
|
{$ENDIF BUFFERPROCS}
|
||||||
|
|
||||||
|
const
|
||||||
|
ZLib_Version = '1.1.4';
|
||||||
|
Z_NO_FLUSH = 0;
|
||||||
|
Z_PARTIAL_FLUSH = 1;
|
||||||
|
Z_SYNC_FLUSH = 2;
|
||||||
|
Z_FULL_FLUSH = 3;
|
||||||
|
Z_FINISH = 4;
|
||||||
|
|
||||||
|
Z_OK = 0;
|
||||||
|
Z_STREAM_END = 1;
|
||||||
|
Z_NEED_DICT = 2;
|
||||||
|
Z_ERRNO = (-1);
|
||||||
|
Z_STREAM_ERROR = (-2);
|
||||||
|
Z_DATA_ERROR = (-3);
|
||||||
|
Z_MEM_ERROR = (-4);
|
||||||
|
Z_BUF_ERROR = (-5);
|
||||||
|
Z_VERSION_ERROR = (-6);
|
||||||
|
|
||||||
|
Z_NO_COMPRESSION = 0;
|
||||||
|
Z_BEST_SPEED = 1;
|
||||||
|
Z_BEST_COMPRESSION = 9;
|
||||||
|
Z_DEFAULT_COMPRESSION = (-1);
|
||||||
|
|
||||||
|
Z_FILTERED = 1;
|
||||||
|
Z_HUFFMAN_ONLY = 2;
|
||||||
|
Z_DEFAULT_STRATEGY = 0;
|
||||||
|
|
||||||
|
Z_BINARY = 0;
|
||||||
|
Z_ASCII = 1;
|
||||||
|
Z_UNKNOWN = 2;
|
||||||
|
|
||||||
|
Z_DEFLATED = 8;
|
||||||
|
|
||||||
|
_z_errmsg: array[0..9] of PChar = (
|
||||||
|
'need dictionary', // Z_NEED_DICT (2)
|
||||||
|
'stream end', // Z_STREAM_END (1)
|
||||||
|
'', // Z_OK (0)
|
||||||
|
'file error', // Z_ERRNO (-1)
|
||||||
|
'stream error', // Z_STREAM_ERROR (-2)
|
||||||
|
'data error', // Z_DATA_ERROR (-3)
|
||||||
|
'insufficient memory', // Z_MEM_ERROR (-4)
|
||||||
|
'buffer error', // Z_BUF_ERROR (-5)
|
||||||
|
'incompatible version', // Z_VERSION_ERROR (-6)
|
||||||
|
'' );
|
||||||
|
|
||||||
|
function adler32(adler: Integer; buf: PChar; len: Integer): Integer;
|
||||||
|
|
||||||
|
{$L Obj\deflate.obj}
|
||||||
|
{$L Obj\trees.obj}
|
||||||
|
{$L Obj\inflate.obj}
|
||||||
|
{$L Obj\inftrees.obj}
|
||||||
|
{$L Obj\adler32.obj}
|
||||||
|
{$L Obj\infblock.obj}
|
||||||
|
{$L Obj\infcodes.obj}
|
||||||
|
{$L Obj\infutil.obj}
|
||||||
|
{$L Obj\inffast.obj}
|
||||||
|
|
||||||
|
procedure _tr_init; external;
|
||||||
|
procedure _tr_tally; external;
|
||||||
|
procedure _tr_flush_block; external;
|
||||||
|
procedure _tr_align; external;
|
||||||
|
procedure _tr_stored_block; external;
|
||||||
|
function adler32; external;
|
||||||
|
procedure inflate_blocks_new; external;
|
||||||
|
procedure inflate_blocks; external;
|
||||||
|
procedure inflate_blocks_reset; external;
|
||||||
|
procedure inflate_blocks_free; external;
|
||||||
|
procedure inflate_set_dictionary; external;
|
||||||
|
procedure inflate_trees_bits; external;
|
||||||
|
procedure inflate_trees_dynamic; external;
|
||||||
|
procedure inflate_trees_fixed; external;
|
||||||
|
procedure inflate_codes_new; external;
|
||||||
|
procedure inflate_codes; external;
|
||||||
|
procedure inflate_codes_free; external;
|
||||||
|
procedure _inflate_mask; external;
|
||||||
|
procedure inflate_flush; external;
|
||||||
|
procedure inflate_fast; external;
|
||||||
|
|
||||||
|
// deflate compresses data
|
||||||
|
function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; recsize: Integer): Integer; external;
|
||||||
|
function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
|
||||||
|
function deflateEnd(var strm: TZStreamRec): Integer; external;
|
||||||
|
|
||||||
|
// inflate decompresses data
|
||||||
|
function inflateInit_(var strm: TZStreamRec; Version: PChar; recsize: Integer): Integer; external;
|
||||||
|
function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
|
||||||
|
function inflateEnd(var strm: TZStreamRec): Integer; external;
|
||||||
|
function inflateReset(var strm: TZStreamRec): Integer; external;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure _memset(P: Pointer; B: Byte; count: Integer);cdecl;
|
||||||
|
begin
|
||||||
|
FillChar(P^, count, Char( B ));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure _memcpy(dest, source: Pointer; count: Integer);cdecl;
|
||||||
|
begin
|
||||||
|
Move(source^, dest^, count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function zcalloc(AppData: Pointer; Items, Size: Integer): Pointer;
|
||||||
|
begin
|
||||||
|
GetMem(Result, Items*Size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure zcfree(AppData, Block: Pointer);
|
||||||
|
begin
|
||||||
|
FreeMem(Block);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ZCheck(Code: Integer; var Clear: Boolean): Integer;
|
||||||
|
begin
|
||||||
|
Result:=Code;
|
||||||
|
Clear:=Code>=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$IFDEF BUFFERPROCS}
|
||||||
|
function CompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||||
|
out OutBuf: Pointer; out OutBytes: Integer): Boolean;
|
||||||
|
var
|
||||||
|
strm: TZStreamRec;
|
||||||
|
P: Pointer;
|
||||||
|
begin
|
||||||
|
Result:=True;
|
||||||
|
FillChar(strm, SizeOf(strm), 0);
|
||||||
|
OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
|
||||||
|
GetMem(OutBuf, OutBytes);
|
||||||
|
try
|
||||||
|
strm.next_in := InBuf;
|
||||||
|
strm.avail_in := InBytes;
|
||||||
|
strm.next_out := OutBuf;
|
||||||
|
strm.avail_out := OutBytes;
|
||||||
|
ZCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)), Result);
|
||||||
|
If not Result then Exit;
|
||||||
|
while (ZCheck(deflate(strm, Z_FINISH), Result)<>Z_STREAM_END) and Result do
|
||||||
|
begin
|
||||||
|
P := OutBuf;
|
||||||
|
Inc(OutBytes, 256);
|
||||||
|
ReallocMem(OutBuf, OutBytes);
|
||||||
|
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
||||||
|
strm.avail_out := 256;
|
||||||
|
end;
|
||||||
|
If Result then ZCheck(deflateEnd(strm), Result)
|
||||||
|
else deflateEnd(strm);
|
||||||
|
If not Result then Exit;
|
||||||
|
ReallocMem(OutBuf, strm.total_out);
|
||||||
|
OutBytes := strm.total_out;
|
||||||
|
finally
|
||||||
|
If not Result then begin
|
||||||
|
FreeMem(OutBuf);
|
||||||
|
OutBuf:=nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DecompressBuf(const InBuf: Pointer; InBytes: Integer;
|
||||||
|
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer): Boolean;
|
||||||
|
var
|
||||||
|
strm: TZStreamRec;
|
||||||
|
P: Pointer;
|
||||||
|
BufInc: Integer;
|
||||||
|
begin
|
||||||
|
Result:=True;
|
||||||
|
FillChar(strm, sizeof(strm), 0);
|
||||||
|
BufInc := (InBytes + 255) and not 255;
|
||||||
|
if OutEstimate = 0 then
|
||||||
|
OutBytes := BufInc
|
||||||
|
else
|
||||||
|
OutBytes := OutEstimate;
|
||||||
|
GetMem(OutBuf, OutBytes);
|
||||||
|
try
|
||||||
|
strm.next_in := InBuf;
|
||||||
|
strm.avail_in := InBytes;
|
||||||
|
strm.next_out := OutBuf;
|
||||||
|
strm.avail_out := OutBytes;
|
||||||
|
ZCheck(InflateInit_(strm, zlib_version, sizeof(strm)), Result);
|
||||||
|
If not Result then Exit;
|
||||||
|
while (ZCheck(Inflate(strm, Z_FINISH), Result) <> Z_STREAM_END) and Result do
|
||||||
|
begin
|
||||||
|
P := OutBuf;
|
||||||
|
Inc(OutBytes, BufInc);
|
||||||
|
ReallocMem(OutBuf, OutBytes);
|
||||||
|
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
||||||
|
strm.avail_out := BufInc;
|
||||||
|
end;
|
||||||
|
If Result then ZCheck(inflateEnd(strm), Result)
|
||||||
|
else InflateEnd(strm);
|
||||||
|
If not Result Then Exit;
|
||||||
|
ReallocMem(OutBuf, strm.total_out);
|
||||||
|
OutBytes := strm.total_out;
|
||||||
|
finally
|
||||||
|
If not Result then begin
|
||||||
|
FreeMem(OutBuf);
|
||||||
|
OutBuf:=nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$ENDIF BUFFERPROCS}
|
||||||
|
|
||||||
|
// Dummy methods
|
||||||
|
procedure DummySetSize(Strm: PStream; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Value: TStrmSize);
|
||||||
|
asm
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DummyReadWrite (Strm: PStream; var Buffer; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Count: TStrmSize): TStrmSize;
|
||||||
|
begin
|
||||||
|
Result:=ZLIB_ERROR;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DummyGetSize(Strm: PStream): TStrmSize;
|
||||||
|
begin
|
||||||
|
Result:=ZLIB_ERROR;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// CompressStream methods
|
||||||
|
function CZLibWriteStream(Strm: PStream; var Buffer; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Count: TStrmSize): TStrmSize;
|
||||||
|
var
|
||||||
|
Check: Boolean;
|
||||||
|
begin
|
||||||
|
Result:=ZLIB_ERROR;
|
||||||
|
With PZlibData (Strm.Methods.fCustom)^ do begin
|
||||||
|
FZRec.next_in := @Buffer;
|
||||||
|
FZRec.avail_in := Count;
|
||||||
|
If FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
|
||||||
|
While (FZRec.avail_in > 0) do begin
|
||||||
|
ZCheck(deflate(FZRec, 0), Check);
|
||||||
|
If not Check then Exit;
|
||||||
|
If FZRec.avail_out = 0 then begin
|
||||||
|
If FStrm.Write (FBuffer, SizeOf(FBuffer))<>SizeOf(FBuffer) then Exit;
|
||||||
|
FZRec.next_out := FBuffer;
|
||||||
|
FZRec.avail_out := SizeOf(FBuffer);
|
||||||
|
FStrmPos := FStrm.Position;
|
||||||
|
If Assigned (fOnProgress) then
|
||||||
|
fOnProgress (Strm);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result := Count;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CZLibSeekStream(Strm: PStream; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Offset: TStrmMove; Origin: TMoveMethod): TStrmSize;
|
||||||
|
begin
|
||||||
|
If (Offset = 0) and (Origin=spCurrent) then Result:=PZlibData (Strm.Methods.fCustom).FZRec.total_in
|
||||||
|
else Result:=ZLIB_ERROR;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure CZLibCloseStream(Strm: PStream);
|
||||||
|
var
|
||||||
|
Check: Boolean;
|
||||||
|
begin
|
||||||
|
With PZlibData (Strm.Methods.fCustom)^ do begin
|
||||||
|
FZRec.next_in := nil;
|
||||||
|
FZRec.avail_in := 0;
|
||||||
|
try
|
||||||
|
If FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
|
||||||
|
while (ZCheck(deflate(FZRec, Z_FINISH), Check) <> Z_STREAM_END) and (FZRec.avail_out = 0) do begin
|
||||||
|
If not Check then Exit;
|
||||||
|
If FStrm.Write (FBuffer, SizeOf(FBuffer))<>SizeOf(FBuffer) then Exit;
|
||||||
|
FZRec.next_out := FBuffer;
|
||||||
|
FZRec.avail_out := sizeof(FBuffer);
|
||||||
|
end;
|
||||||
|
If FZRec.avail_out < SizeOf(FBuffer) then
|
||||||
|
FStrm.Write (FBuffer, SizeOf(FBuffer) - FZRec.avail_out)
|
||||||
|
finally
|
||||||
|
deflateEnd(FZRec);
|
||||||
|
Dispose (PZLibData (Strm.Methods.fCustom));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// DecompressStream methods
|
||||||
|
procedure DZLibCloseStream(Strm: PStream);
|
||||||
|
begin
|
||||||
|
InflateEnd(PZLibData (Strm.Methods.fCustom).FZRec);
|
||||||
|
Dispose (PZLibData (Strm.Methods.fCustom));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DZLibSeekStream(Strm: PStream; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Offset: TStrmMove; Origin: TMoveMethod): TStrmSize;
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
Buf: array [0..4095] of Char;
|
||||||
|
Check: Boolean;
|
||||||
|
Off: TStrmMove;
|
||||||
|
begin
|
||||||
|
Result:=ZLIB_ERROR;
|
||||||
|
Off := Offset;
|
||||||
|
With PZlibData (Strm.Methods.fCustom)^ do begin
|
||||||
|
If (Off=0) and (Origin=spBegin) then begin
|
||||||
|
ZCheck(InflateReset(FZRec), Check);
|
||||||
|
If not Check then Exit;
|
||||||
|
FZRec.next_in := FBuffer;
|
||||||
|
FZRec.avail_in := 0;
|
||||||
|
FStrm.Position := 0;
|
||||||
|
FStrmPos := 0;
|
||||||
|
end
|
||||||
|
else If ((Off>=0) and (Origin=spCurrent)) or (((Off-FZRec.total_out)>0) and (Origin=spBegin)) then begin
|
||||||
|
If Origin=spBegin then Dec(Off, FZRec.total_out);
|
||||||
|
If Off>0 then begin
|
||||||
|
for I:=1 to Off div SizeOf(Buf) do
|
||||||
|
If Strm.Read(Buf, SizeOf(Buf))=ZLIB_ERROR then Exit;
|
||||||
|
If Strm.Read(Buf, Off mod SizeOf(Buf))=ZLIB_ERROR then Exit;
|
||||||
|
end;
|
||||||
|
end else Exit;
|
||||||
|
Result:=FZRec.total_out;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DZLibReadStream (Strm: PStream; var Buffer; {$IFNDEF STREAM_COMPAT} const {$ENDIF} Count: TStrmSize): TStrmSize;
|
||||||
|
var
|
||||||
|
Check: Boolean;
|
||||||
|
D: PZLibData;
|
||||||
|
begin
|
||||||
|
Result:=ZLIB_ERROR;
|
||||||
|
D := PZlibData (Strm.Methods.fCustom);
|
||||||
|
D.FZRec.next_out := @Buffer;
|
||||||
|
D.FZRec.avail_out := Count;
|
||||||
|
If D.FStrm.Position <> D.FStrmPos then
|
||||||
|
D.FStrm.Position := D.FStrmPos;
|
||||||
|
While (D.FZRec.avail_out > 0) do begin
|
||||||
|
If D.FZRec.avail_in = 0 then begin
|
||||||
|
D.FZRec.avail_in := D.FStrm.Read(D.FBuffer, SizeOf(D.FBuffer));
|
||||||
|
If D.FZRec.avail_in = 0 then begin
|
||||||
|
Result := Count - DWord(D.FZRec.avail_out);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
D.FZRec.next_in := D.FBuffer;
|
||||||
|
D.FStrmPos := D.FStrm.Position;
|
||||||
|
If Assigned (D.fOnProgress) then
|
||||||
|
D.fOnProgress (Strm);
|
||||||
|
end;
|
||||||
|
ZCheck(Inflate(D.FZRec, 0), Check);
|
||||||
|
If not Check then Exit;
|
||||||
|
end;
|
||||||
|
Result:=Count;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
BaseCZlibMethods: TStreamMethods = (
|
||||||
|
fSeek: CZLibSeekStream;
|
||||||
|
fGetSiz: DummyGetSize;
|
||||||
|
fSetSiz: DummySetSize;
|
||||||
|
fRead: DummyReadWrite;
|
||||||
|
fWrite: CZLibWriteStream;
|
||||||
|
fClose: CZLibCloseStream;
|
||||||
|
fCustom: nil; );
|
||||||
|
|
||||||
|
BaseDZlibMethods: TStreamMethods = (
|
||||||
|
fSeek: DZLibSeekStream;
|
||||||
|
fGetSiz: DummyGetSize;
|
||||||
|
fSetSiz: DummySetSize;
|
||||||
|
fRead: DZLibReadStream;
|
||||||
|
fWrite: DummyReadWrite;
|
||||||
|
fClose: DZLibCloseStream;
|
||||||
|
fCustom: nil; );
|
||||||
|
|
||||||
|
function NewDecompressionStream (Source: PStream; OnProgress: TZLibEvent): PStream;
|
||||||
|
var
|
||||||
|
Inited: Boolean;
|
||||||
|
ZLibData: PZLibData;
|
||||||
|
begin
|
||||||
|
New (ZLibData);
|
||||||
|
With ZLibData^ do begin
|
||||||
|
FillChar(FZRec, SizeOf(FZRec), #0);
|
||||||
|
FOnProgress:=OnProgress;
|
||||||
|
FStrm:=Source;
|
||||||
|
FStrmPos:=Source.Position;
|
||||||
|
FZRec.next_in := FBuffer;
|
||||||
|
FZRec.avail_in := 0;
|
||||||
|
ZCheck(InflateInit_(FZRec, ZLib_Version, SizeOf(FZRec)), Inited);
|
||||||
|
end;
|
||||||
|
If Inited then begin
|
||||||
|
Result:=_NewStream (BaseDZlibMethods);
|
||||||
|
Result.Methods.fCustom:=ZLibData;
|
||||||
|
end else begin
|
||||||
|
Dispose (ZLibData);
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NewCompressionStream (CompressionLevel: TCompressionLevel; Destination: PStream; OnProgress: TZLibEvent): PStream;
|
||||||
|
const
|
||||||
|
Levels: array [TCompressionLevel] of ShortInt = (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
|
||||||
|
var
|
||||||
|
Inited: Boolean;
|
||||||
|
ZLibData: PZLibData;
|
||||||
|
begin
|
||||||
|
New (ZLibData);
|
||||||
|
With ZLibData^ do begin
|
||||||
|
FillChar(FZRec, SizeOf(FZRec), #0);
|
||||||
|
FOnProgress:=OnProgress;
|
||||||
|
FStrm:=Destination;
|
||||||
|
FStrmPos:=Destination.Position;
|
||||||
|
FZRec.next_out := FBuffer;
|
||||||
|
FZRec.avail_out := SizeOf(FBuffer);
|
||||||
|
ZCheck(deflateInit_(FZRec, Levels[CompressionLevel], ZLib_Version, SizeOf(FZRec)), Inited);
|
||||||
|
end;
|
||||||
|
If Inited then begin
|
||||||
|
Result:=_NewStream (BaseCZlibMethods);
|
||||||
|
Result.Methods.fCustom:=ZLibData;
|
||||||
|
end else begin
|
||||||
|
Dispose (ZLibData);
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NewZLibDStream (var Stream: PStream; Source: PStream; OnProgress: TZLibEvent): boolean;
|
||||||
|
begin
|
||||||
|
Stream:=NewDecompressionStream (Source, OnProgress);
|
||||||
|
Result:=Assigned (Stream);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NewZLibCStream (var Stream: PStream; CompressionLevel: TCompressionLevel; Destination: PStream; OnProgress: TZLibEvent): boolean;
|
||||||
|
begin
|
||||||
|
Stream:=NewCompressionStream (CompressionLevel, Destination, OnProgress);
|
||||||
|
Result:=Assigned (Stream);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
1926
Addons/KolZLibBzip.pas
Normal file
1926
Addons/KolZLibBzip.pas
Normal file
File diff suppressed because it is too large
Load Diff
27016
Addons/MSHTML_TLBKOL.pas
Normal file
27016
Addons/MSHTML_TLBKOL.pas
Normal file
File diff suppressed because it is too large
Load Diff
693
Addons/SevenZip.pas
Normal file
693
Addons/SevenZip.pas
Normal file
@ -0,0 +1,693 @@
|
|||||||
|
unit SevenZip;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
const //Property IDs
|
||||||
|
kEnd = $00;
|
||||||
|
|
||||||
|
kHeader = $01;
|
||||||
|
|
||||||
|
kArchiveProperties = $02;
|
||||||
|
|
||||||
|
kAdditionalStreamsInfo = $03;
|
||||||
|
kMainStreamsInfo = $04;
|
||||||
|
kFilesInfo = $05;
|
||||||
|
|
||||||
|
kPackInfo = $06;
|
||||||
|
kUnPackInfo = $07;
|
||||||
|
kSubStreamsInfo = $08;
|
||||||
|
|
||||||
|
kSize = $09;
|
||||||
|
kCRC = $0A;
|
||||||
|
|
||||||
|
kFolder = $0B;
|
||||||
|
|
||||||
|
kCodersUnPackSize = $0C;
|
||||||
|
kNumUnPackStream = $0D;
|
||||||
|
|
||||||
|
kEmptyStream = $0E;
|
||||||
|
kEmptyFile = $0F;
|
||||||
|
kAnti = $10;
|
||||||
|
|
||||||
|
kName = $11;
|
||||||
|
kCreationTime = $12;
|
||||||
|
kLastAccessTime = $13;
|
||||||
|
kLastWriteTime = $14;
|
||||||
|
kWinAttributes = $15;
|
||||||
|
kComment = $16;
|
||||||
|
|
||||||
|
kEncodedHeader = $17;
|
||||||
|
|
||||||
|
const kSignature: array [0..5] of Char = ('7', 'z', #$BC, #$AF, #$27, #$1C);
|
||||||
|
|
||||||
|
type //7z format headers
|
||||||
|
REAL_UINT64 = Int64;
|
||||||
|
|
||||||
|
TArchiveVersion = packed record
|
||||||
|
Major: Byte; // now = 0
|
||||||
|
Minor: Byte; // now = 2
|
||||||
|
end;
|
||||||
|
|
||||||
|
TStartHeader = packed record
|
||||||
|
NextHeaderOffset: REAL_UINT64;
|
||||||
|
NextHeaderSize: REAL_UINT64;
|
||||||
|
NextHeaderCRC: Cardinal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TSignatureHeader = packed record
|
||||||
|
ArchiveVersion: TArchiveVersion;
|
||||||
|
StartHeaderCRC: Cardinal;
|
||||||
|
StartHeader: TStartHeader;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PUInt32 = ^UInt32;
|
||||||
|
UInt32 = Cardinal;
|
||||||
|
PUInt64 = ^UInt64;
|
||||||
|
UInt64 = Int64;
|
||||||
|
|
||||||
|
CFileSize = UInt64;
|
||||||
|
PCFileSize = PUInt64;
|
||||||
|
|
||||||
|
CMethodID= UInt64;
|
||||||
|
|
||||||
|
CSzByteBuffer = packed record
|
||||||
|
Capacity: Cardinal;
|
||||||
|
Items: PByte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PCCoderInfo = ^CCoderInfo;
|
||||||
|
CCoderInfo = packed record
|
||||||
|
NumInStreams: UInt32;
|
||||||
|
NumOutStreams: UInt32;
|
||||||
|
MethodID: CMethodID;
|
||||||
|
Properties: CSzByteBuffer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PCBindPair = ^CBindPair;
|
||||||
|
CBindPair = packed record
|
||||||
|
InIndex: UInt32;
|
||||||
|
OutIndex: UInt32;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PCFolder = ^CFolder;
|
||||||
|
CFolder = packed record
|
||||||
|
NumCoders: UInt32;
|
||||||
|
Coders: PCCoderInfo;
|
||||||
|
NumBindPairs: UInt32;
|
||||||
|
BindPairs: PCBindPair;
|
||||||
|
NumPackStreams: UInt32;
|
||||||
|
PackStreams: UInt32;
|
||||||
|
UnPackSizes: PCFileSize;
|
||||||
|
UnPackCRCDefined: Integer ;
|
||||||
|
UnPackCRC: UInt32;
|
||||||
|
NumUnPackStreams: UInt32;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CArchiveFileTime = packed record
|
||||||
|
Low:UInt32;
|
||||||
|
High:UInt32;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
PCFileItem = ^CFileItem;
|
||||||
|
CFileItem = packed record
|
||||||
|
LastWriteTime: CArchiveFileTime;
|
||||||
|
{
|
||||||
|
CFileSize StartPos;
|
||||||
|
UInt32 Attributes;
|
||||||
|
}
|
||||||
|
Size: CFileSize;
|
||||||
|
FileCRC: UInt32;
|
||||||
|
Name: PChar;
|
||||||
|
|
||||||
|
IsFileCRCDefined: Byte;
|
||||||
|
HasStream: Byte;
|
||||||
|
IsDirectory: Byte;
|
||||||
|
IsAnti: Byte;
|
||||||
|
IsLastWriteTimeDefined: Byte;
|
||||||
|
{
|
||||||
|
int AreAttributesDefined;
|
||||||
|
int IsLastWriteTimeDefined;
|
||||||
|
int IsStartPosDefined;
|
||||||
|
}
|
||||||
|
end;
|
||||||
|
|
||||||
|
CArchiveDatabase = packed record
|
||||||
|
NumPackStreams: UInt32;
|
||||||
|
PackSizes: PCFileSize;
|
||||||
|
PackCRCsDefined: PByte;
|
||||||
|
PackCRCs: PUInt32;
|
||||||
|
NumFolders: PUInt32;
|
||||||
|
Folders: PCFolder;
|
||||||
|
NumFiles:UInt32;
|
||||||
|
Files: PCFileItem;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CInArchiveInfo = packed record
|
||||||
|
StartPositionAfterHeader: CFileSize;
|
||||||
|
DataStartPosition: CFileSize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PCArchiveDatabaseEx= ^CArchiveDatabaseEx;
|
||||||
|
CArchiveDatabaseEx = packed record
|
||||||
|
Database: CArchiveDatabase;
|
||||||
|
ArchiveInfo: CInArchiveInfo;
|
||||||
|
FolderStartPackStreamIndex: PUInt32;
|
||||||
|
PackStreamStartPositions: PCFileSize;
|
||||||
|
FolderStartFileIndex: PUInt32;
|
||||||
|
FileIndexToFolderIndexMap: PUInt32;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CSzData = packed record
|
||||||
|
Data: PByte;
|
||||||
|
Size: UInt32;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
type SZ_RESULT = Integer;
|
||||||
|
|
||||||
|
const k7zMajorVersion = 0;
|
||||||
|
k7zStartHeaderSize = $20;
|
||||||
|
|
||||||
|
function SzArchiveOpen2: SZ_RESULT;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
|
||||||
|
function SzArchiveOpen2: SZ_RESULT;
|
||||||
|
var db: CArchiveDatabaseEx;
|
||||||
|
InStream: PStream;
|
||||||
|
|
||||||
|
signature: array [0..5] of Char;
|
||||||
|
version: Byte;
|
||||||
|
crcFromArchive: UInt32;
|
||||||
|
nextHeaderOffset: UInt64;
|
||||||
|
nextHeaderSize: UInt64;
|
||||||
|
nextHeaderCRC: UInt32;
|
||||||
|
crc: UInt32;
|
||||||
|
pos: CFileSize;
|
||||||
|
buffer: CSzByteBuffer;
|
||||||
|
sd: CSzData;
|
||||||
|
_type: UInt64;
|
||||||
|
|
||||||
|
begin
|
||||||
|
crc:= 0; pos:= 0;
|
||||||
|
|
||||||
|
InStream:= NewReadFileStream('D:\Work\Main\MDVReader\CE\_Books\_Books.7z');
|
||||||
|
|
||||||
|
if InStream.Read(signature, 6) <> 6 then Exit;
|
||||||
|
if signature <> kSignature then Exit;
|
||||||
|
|
||||||
|
{
|
||||||
|
db.Clear();
|
||||||
|
db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
if InStream.Read(version, 1) <> 1 then Exit;
|
||||||
|
if version <> k7zMajorVersion then Exit;
|
||||||
|
if InStream.Read(version, 1) <> 1 then Exit;
|
||||||
|
|
||||||
|
|
||||||
|
if InStream.Read(crcFromArchive, SizeOf(UInt32)) <> SizeOf(UInt32) then Exit; //RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc));
|
||||||
|
// crc:= CRC_INIT_VAL;
|
||||||
|
|
||||||
|
if InStream.Read(nextHeaderOffset, SizeOf(UInt64)) <> SizeOf(UInt64) then Exit; //RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc));
|
||||||
|
if InStream.Read(nextHeaderSize, SizeOf(UInt64)) <> SizeOf(UInt64) then Exit; //RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc));
|
||||||
|
if InStream.Read(nextHeaderCRC, SizeOf(UInt32)) <> SizeOf(UInt32) then Exit; //RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc));
|
||||||
|
|
||||||
|
pos:= k7zStartHeaderSize;
|
||||||
|
db.ArchiveInfo.StartPositionAfterHeader:= pos;
|
||||||
|
|
||||||
|
//if (CRC_GET_DIGEST(crc) != crcFromArchive) return SZE_ARCHIVE_ERROR;
|
||||||
|
|
||||||
|
if nextHeaderSize = 0 then begin Result:= 0; Exit; end;
|
||||||
|
|
||||||
|
InStream.Seek(pos + nextHeaderOffset, spBegin);
|
||||||
|
|
||||||
|
buffer.Capacity:= nextHeaderSize;
|
||||||
|
buffer.Items:= GetMemory(nextHeaderSize);
|
||||||
|
|
||||||
|
|
||||||
|
if InStream.Read(buffer.Items, nextHeaderSize) <> nextHeaderSize then Exit; //Result:= SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
|
||||||
|
(*
|
||||||
|
// if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC) then begin
|
||||||
|
|
||||||
|
while true do begin
|
||||||
|
|
||||||
|
sd.Data:= buffer.Items;
|
||||||
|
sd.Size:= buffer.Capacity;
|
||||||
|
Result:= SzReadID(&sd, &type);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (type == k7zIdHeader)
|
||||||
|
{
|
||||||
|
res = SzReadHeader(&sd, db, allocMain, allocTemp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (type != k7zIdEncodedHeader)
|
||||||
|
{
|
||||||
|
res = SZE_ARCHIVE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CSzByteBuffer outBuffer;
|
||||||
|
res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
|
||||||
|
db->ArchiveInfo.StartPositionAfterHeader,
|
||||||
|
allocTemp);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
{
|
||||||
|
SzByteBufferFree(&outBuffer, allocTemp->Free);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SzByteBufferFree(&buffer, allocTemp->Free);
|
||||||
|
buffer.Items = outBuffer.Items;
|
||||||
|
buffer.Capacity = outBuffer.Capacity;
|
||||||
|
}
|
||||||
|
end;
|
||||||
|
// end;
|
||||||
|
|
||||||
|
SzByteBufferFree(&buffer, allocTemp->Free);
|
||||||
|
return res;
|
||||||
|
*)
|
||||||
|
end;
|
||||||
|
|
||||||
|
(*
|
||||||
|
|
||||||
|
7z Format description (2.30 Beta 25)
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
This file contains description of 7z archive format.
|
||||||
|
7z archive can contain files compressed with any method.
|
||||||
|
See "Methods.txt" for description for defined compressing methods.
|
||||||
|
|
||||||
|
|
||||||
|
Format structure Overview
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Some fields can be optional.
|
||||||
|
|
||||||
|
Archive structure
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
SignatureHeader
|
||||||
|
[PackedStreams]
|
||||||
|
[PackedStreamsForHeaders]
|
||||||
|
[
|
||||||
|
Header
|
||||||
|
or
|
||||||
|
{
|
||||||
|
Packed Header
|
||||||
|
HeaderInfo
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Header structure
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
{
|
||||||
|
ArchiveProperties
|
||||||
|
AdditionalStreams
|
||||||
|
{
|
||||||
|
PackInfo
|
||||||
|
{
|
||||||
|
PackPos
|
||||||
|
NumPackStreams
|
||||||
|
Sizes[NumPackStreams]
|
||||||
|
CRCs[NumPackStreams]
|
||||||
|
}
|
||||||
|
CodersInfo
|
||||||
|
{
|
||||||
|
NumFolders
|
||||||
|
Folders[NumFolders]
|
||||||
|
{
|
||||||
|
NumCoders
|
||||||
|
CodersInfo[NumCoders]
|
||||||
|
{
|
||||||
|
ID
|
||||||
|
NumInStreams;
|
||||||
|
NumOutStreams;
|
||||||
|
PropertiesSize
|
||||||
|
Properties[PropertiesSize]
|
||||||
|
}
|
||||||
|
NumBindPairs
|
||||||
|
BindPairsInfo[NumBindPairs]
|
||||||
|
{
|
||||||
|
InIndex;
|
||||||
|
OutIndex;
|
||||||
|
}
|
||||||
|
PackedIndices
|
||||||
|
}
|
||||||
|
UnPackSize[Folders][Folders.NumOutstreams]
|
||||||
|
CRCs[NumFolders]
|
||||||
|
}
|
||||||
|
SubStreamsInfo
|
||||||
|
{
|
||||||
|
NumUnPackStreamsInFolders[NumFolders];
|
||||||
|
UnPackSizes[]
|
||||||
|
CRCs[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainStreamsInfo
|
||||||
|
{
|
||||||
|
(Same as in AdditionalStreams)
|
||||||
|
}
|
||||||
|
FilesInfo
|
||||||
|
{
|
||||||
|
NumFiles
|
||||||
|
Properties[]
|
||||||
|
{
|
||||||
|
ID
|
||||||
|
Size
|
||||||
|
Data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderInfo structure
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
{
|
||||||
|
(Same as in AdditionalStreams)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Notes about Notation and encoding
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
7z uses little endian encoding.
|
||||||
|
|
||||||
|
7z archive format has optional headers that are marked as
|
||||||
|
[]
|
||||||
|
Header
|
||||||
|
[]
|
||||||
|
|
||||||
|
REAL_UINT64 means real UINT64.
|
||||||
|
|
||||||
|
UINT64 means real UINT64 encoded with the following scheme:
|
||||||
|
|
||||||
|
Size of encoding sequence depends from first byte:
|
||||||
|
First_Byte Extra_Bytes Value
|
||||||
|
(binary)
|
||||||
|
0xxxxxxx : ( xxxxxxx )
|
||||||
|
10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y
|
||||||
|
110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y
|
||||||
|
...
|
||||||
|
1111110x BYTE y[6] : ( x << (8 * 6)) + y
|
||||||
|
11111110 BYTE y[7] : y
|
||||||
|
11111111 BYTE y[8] : y
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
...........................
|
||||||
|
|
||||||
|
|
||||||
|
ArchiveProperties
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
BYTE NID::kArchiveProperties (0x02)
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
BYTE PropertyType;
|
||||||
|
if (aType == 0)
|
||||||
|
break;
|
||||||
|
UINT64 PropertySize;
|
||||||
|
BYTE PropertyData[PropertySize];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Digests (NumStreams)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
BYTE AllAreDefined
|
||||||
|
if (AllAreDefined == 0)
|
||||||
|
{
|
||||||
|
for(NumStreams)
|
||||||
|
BIT Defined
|
||||||
|
}
|
||||||
|
UINT32 CRCs[NumDefined]
|
||||||
|
|
||||||
|
|
||||||
|
PackInfo
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
BYTE NID::kPackInfo (0x06)
|
||||||
|
UINT64 PackPos
|
||||||
|
UINT64 NumPackStreams
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kSize (0x09)
|
||||||
|
UINT64 PackSizes[NumPackStreams]
|
||||||
|
[]
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kCRC (0x0A)
|
||||||
|
PackStreamDigests[NumPackStreams]
|
||||||
|
[]
|
||||||
|
|
||||||
|
BYTE NID::kEnd
|
||||||
|
|
||||||
|
|
||||||
|
Folder
|
||||||
|
~~~~~~
|
||||||
|
UINT64 NumCoders;
|
||||||
|
for (NumCoders)
|
||||||
|
{
|
||||||
|
BYTE
|
||||||
|
{
|
||||||
|
0:3 DecompressionMethod.IDSize
|
||||||
|
4:
|
||||||
|
0 - IsSimple
|
||||||
|
1 - Is not simple
|
||||||
|
5:
|
||||||
|
0 - No Attributes
|
||||||
|
1 - There Are Attributes
|
||||||
|
7:
|
||||||
|
0 - Last Method in Alternative_Method_List
|
||||||
|
1 - There are more alternative methods
|
||||||
|
}
|
||||||
|
BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
|
||||||
|
if (!IsSimple)
|
||||||
|
{
|
||||||
|
UINT64 NumInStreams;
|
||||||
|
UINT64 NumOutStreams;
|
||||||
|
}
|
||||||
|
if (DecompressionMethod[0] != 0)
|
||||||
|
{
|
||||||
|
UINT64 PropertiesSize
|
||||||
|
BYTE Properties[PropertiesSize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NumBindPairs = NumOutStreamsTotal - 1;
|
||||||
|
|
||||||
|
for (NumBindPairs)
|
||||||
|
{
|
||||||
|
UINT64 InIndex;
|
||||||
|
UINT64 OutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumPackedStreams = NumInStreamsTotal - NumBindPairs;
|
||||||
|
if (NumPackedStreams > 1)
|
||||||
|
for(NumPackedStreams)
|
||||||
|
{
|
||||||
|
UINT64 Index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coders Info
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
BYTE NID::kUnPackInfo (0x07)
|
||||||
|
|
||||||
|
|
||||||
|
BYTE NID::kFolder (0x0B)
|
||||||
|
UINT64 NumFolders
|
||||||
|
BYTE External
|
||||||
|
switch(External)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Folders[NumFolders]
|
||||||
|
case 1:
|
||||||
|
UINT64 DataStreamIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BYTE ID::kCodersUnPackSize (0x0C)
|
||||||
|
for(Folders)
|
||||||
|
for(Folder.NumOutStreams)
|
||||||
|
UINT64 UnPackSize;
|
||||||
|
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kCRC (0x0A)
|
||||||
|
UnPackDigests[NumFolders]
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BYTE NID::kEnd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SubStreams Info
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
BYTE NID::kSubStreamsInfo; (0x08)
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kNumUnPackStream; (0x0D)
|
||||||
|
UINT64 NumUnPackStreamsInFolders[NumFolders];
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kSize (0x09)
|
||||||
|
UINT64 UnPackSizes[]
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kCRC (0x0A)
|
||||||
|
Digests[Number of streams with unknown CRC]
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
BYTE NID::kEnd
|
||||||
|
|
||||||
|
|
||||||
|
Streams Info
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
[]
|
||||||
|
PackInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
[]
|
||||||
|
CodersInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
[]
|
||||||
|
SubStreamsInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
BYTE NID::kEnd
|
||||||
|
|
||||||
|
|
||||||
|
FilesInfo
|
||||||
|
~~~~~~~~~
|
||||||
|
BYTE NID::kFilesInfo; (0x05)
|
||||||
|
UINT64 NumFiles
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
BYTE PropertyType;
|
||||||
|
if (aType == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
UINT64 Size;
|
||||||
|
|
||||||
|
switch(PropertyType)
|
||||||
|
{
|
||||||
|
kEmptyStream: (0x0E)
|
||||||
|
for(NumFiles)
|
||||||
|
BIT IsEmptyStream
|
||||||
|
|
||||||
|
kEmptyFile: (0x0F)
|
||||||
|
for(EmptyStreams)
|
||||||
|
BIT IsEmptyFile
|
||||||
|
|
||||||
|
kAnti: (0x10)
|
||||||
|
for(EmptyStreams)
|
||||||
|
BIT IsAntiFile
|
||||||
|
|
||||||
|
case kCreationTime: (0x12)
|
||||||
|
case kLastAccessTime: (0x13)
|
||||||
|
case kLastWriteTime: (0x14)
|
||||||
|
BYTE AllAreDefined
|
||||||
|
if (AllAreDefined == 0)
|
||||||
|
{
|
||||||
|
for(NumFiles)
|
||||||
|
BIT TimeDefined
|
||||||
|
}
|
||||||
|
BYTE External;
|
||||||
|
if(External != 0)
|
||||||
|
UINT64 DataIndex
|
||||||
|
[]
|
||||||
|
for(Definded Items)
|
||||||
|
UINT32 Time
|
||||||
|
[]
|
||||||
|
|
||||||
|
kNames: (0x11)
|
||||||
|
BYTE External;
|
||||||
|
if(External != 0)
|
||||||
|
UINT64 DataIndex
|
||||||
|
[]
|
||||||
|
for(Files)
|
||||||
|
{
|
||||||
|
wchar_t Names[NameSize];
|
||||||
|
wchar_t 0;
|
||||||
|
}
|
||||||
|
[]
|
||||||
|
|
||||||
|
kAttributes: (0x15)
|
||||||
|
BYTE AllAreDefined
|
||||||
|
if (AllAreDefined == 0)
|
||||||
|
{
|
||||||
|
for(NumFiles)
|
||||||
|
BIT AttributesAreDefined
|
||||||
|
}
|
||||||
|
BYTE External;
|
||||||
|
if(External != 0)
|
||||||
|
UINT64 DataIndex
|
||||||
|
[]
|
||||||
|
for(Definded Attributes)
|
||||||
|
UINT32 Attributes
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header
|
||||||
|
~~~~~~
|
||||||
|
BYTE NID::kHeader (0x01)
|
||||||
|
|
||||||
|
[]
|
||||||
|
ArchiveProperties
|
||||||
|
[]
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kAdditionalStreamsInfo; (0x03)
|
||||||
|
StreamsInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
[]
|
||||||
|
BYTE NID::kMainStreamsInfo; (0x04)
|
||||||
|
StreamsInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
[]
|
||||||
|
FilesInfo
|
||||||
|
[]
|
||||||
|
|
||||||
|
BYTE NID::kEnd
|
||||||
|
|
||||||
|
|
||||||
|
HeaderInfo
|
||||||
|
~~~~~~~~~~
|
||||||
|
[]
|
||||||
|
BYTE NID::kEncodedHeader; (0x17)
|
||||||
|
StreamsInfo for Encoded Header
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
End of document
|
||||||
|
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
74
Addons/UBitTreeDecoder.pas
Normal file
74
Addons/UBitTreeDecoder.pas
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
unit UBitTreeDecoder;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL, URangeDecoder;
|
||||||
|
|
||||||
|
type PBitTreeDecoder = ^TBitTreeDecoder;
|
||||||
|
TBitTreeDecoder=object(TObj)
|
||||||
|
public
|
||||||
|
Models: array of smallint;
|
||||||
|
NumBitLevels:integer;
|
||||||
|
constructor Create(const AnumBitLevels:integer);
|
||||||
|
procedure _Init;
|
||||||
|
function Decode(const ArangeDecoder:PRangeDecoder):integer;
|
||||||
|
function ReverseDecode(const ArangeDecoder:PRangeDecoder):integer;overload;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ReverseDecode(var AModels: array of smallint; const AstartIndex:integer;const ArangeDecoder:PRangeDecoder; const ANumBitLevels:integer):integer;overload;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
constructor TBitTreeDecoder.Create(const AnumBitLevels:integer);
|
||||||
|
begin
|
||||||
|
self.NumBitLevels := AnumBitLevels;
|
||||||
|
setlength(Models,1 shl AnumBitLevels);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBitTreeDecoder._Init;
|
||||||
|
begin
|
||||||
|
urangedecoder.InitBitModels(Models);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBitTreeDecoder.Decode(const ArangeDecoder:PRangeDecoder):integer;
|
||||||
|
var m,bitIndex:integer;
|
||||||
|
begin
|
||||||
|
m:=1;
|
||||||
|
for bitIndex := NumBitLevels downto 1 do begin
|
||||||
|
m:=m shl 1 + ArangeDecoder.DecodeBit(Models, m);
|
||||||
|
end;
|
||||||
|
result:=m - (1 shl NumBitLevels);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBitTreeDecoder.ReverseDecode(const ArangeDecoder:PRangeDecoder):integer;
|
||||||
|
var m,symbol,bitindex,bit:integer;
|
||||||
|
begin
|
||||||
|
m:=1;
|
||||||
|
symbol:=0;
|
||||||
|
for bitindex:=0 to numbitlevels-1 do begin
|
||||||
|
bit:=ArangeDecoder.DecodeBit(Models, m);
|
||||||
|
m:=(m shl 1) + bit;
|
||||||
|
symbol:=symbol or (bit shl bitIndex);
|
||||||
|
end;
|
||||||
|
result:=symbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ReverseDecode(var AModels: array of smallint;const AstartIndex:integer;
|
||||||
|
const ArangeDecoder:PRangeDecoder;const ANumBitLevels:integer):integer;
|
||||||
|
var m,symbol,bitindex,bit:integer;
|
||||||
|
begin
|
||||||
|
m:=1;
|
||||||
|
symbol:=0;
|
||||||
|
for bitindex:=0 to ANumBitLevels -1 do begin
|
||||||
|
bit := ArangeDecoder.DecodeBit(AModels, AstartIndex + m);
|
||||||
|
m := (m shl 1) + bit;
|
||||||
|
symbol := symbol or bit shl bitindex;
|
||||||
|
end;
|
||||||
|
result:=symbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
116
Addons/UBitTreeEncoder.pas
Normal file
116
Addons/UBitTreeEncoder.pas
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
unit UBitTreeEncoder;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL, URangeDecoder,URangeEncoder;
|
||||||
|
|
||||||
|
type PBitTreeEncoder =^TBitTreeEncoder;
|
||||||
|
TBitTreeEncoder=object(TObj)
|
||||||
|
public
|
||||||
|
Models: array of smallint;
|
||||||
|
NumBitLevels:integer;
|
||||||
|
constructor Create(const AnumBitLevels:integer);
|
||||||
|
procedure _Init;
|
||||||
|
procedure Encode(const ArangeEncoder:PRangeEncoder;const Asymbol:integer);
|
||||||
|
procedure ReverseEncode(const ArangeEncoder:PRangeEncoder;Asymbol:integer);
|
||||||
|
function GetPrice(const Asymbol:integer):integer;
|
||||||
|
function ReverseGetPrice(Asymbol:integer):integer;overload;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ReverseEncode(var AModels:array of smallint;const AstartIndex:integer;const ArangeEncoder:PRangeEncoder;const ANumBitLevels:integer; Asymbol:integer);
|
||||||
|
function ReverseGetPrice(var AModels:array of smallint;const AstartIndex,ANumBitLevels:integer; Asymbol:integer):integer;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
constructor TBitTreeEncoder.Create(const AnumBitLevels:integer);
|
||||||
|
begin
|
||||||
|
self.NumBitLevels:=AnumBitLevels;
|
||||||
|
setlength(Models,1 shl AnumBitLevels);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBitTreeEncoder._Init;
|
||||||
|
begin
|
||||||
|
URangeDecoder.InitBitModels(Models);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBitTreeEncoder.Encode(const ArangeEncoder:PRangeEncoder;const Asymbol:integer);
|
||||||
|
var m,bitindex,bit:integer;
|
||||||
|
begin
|
||||||
|
m := 1;
|
||||||
|
for bitIndex := NumBitLevels -1 downto 0 do begin
|
||||||
|
bit := (Asymbol shr bitIndex) and 1;
|
||||||
|
ArangeEncoder.Encode(Models, m, bit);
|
||||||
|
m := (m shl 1) or bit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBitTreeEncoder.ReverseEncode(const ArangeEncoder:PRangeEncoder;Asymbol:integer);
|
||||||
|
var m,i,bit:integer;
|
||||||
|
begin
|
||||||
|
m:=1;
|
||||||
|
for i:= 0 to NumBitLevels -1 do begin
|
||||||
|
bit := Asymbol and 1;
|
||||||
|
ArangeEncoder.Encode(Models, m, bit);
|
||||||
|
m := (m shl 1) or bit;
|
||||||
|
Asymbol := Asymbol shr 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBitTreeEncoder.GetPrice(const Asymbol:integer):integer;
|
||||||
|
var price,m,bitindex,bit:integer;
|
||||||
|
begin
|
||||||
|
price := 0;
|
||||||
|
m := 1;
|
||||||
|
for bitIndex := NumBitLevels - 1 downto 0 do begin
|
||||||
|
bit := (Asymbol shr bitIndex) and 1;
|
||||||
|
price := price + RangeEncoder.GetPrice(Models[m], bit);
|
||||||
|
m := (m shl 1) + bit;
|
||||||
|
end;
|
||||||
|
result:=price;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBitTreeEncoder.ReverseGetPrice(Asymbol:integer):integer;
|
||||||
|
var price,m,i,bit:integer;
|
||||||
|
begin
|
||||||
|
price := 0;
|
||||||
|
m := 1;
|
||||||
|
for i:= NumBitLevels downto 1 do begin
|
||||||
|
bit := Asymbol and 1;
|
||||||
|
Asymbol := Asymbol shr 1;
|
||||||
|
price :=price + RangeEncoder.GetPrice(Models[m], bit);
|
||||||
|
m := (m shl 1) or bit;
|
||||||
|
end;
|
||||||
|
result:=price;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ReverseGetPrice(var AModels:array of smallint;const AstartIndex,ANumBitLevels:integer;Asymbol:integer):integer;
|
||||||
|
var price,m,i,bit:integer;
|
||||||
|
begin
|
||||||
|
price := 0;
|
||||||
|
m := 1;
|
||||||
|
for i := ANumBitLevels downto 1 do begin
|
||||||
|
bit := Asymbol and 1;
|
||||||
|
Asymbol := Asymbol shr 1;
|
||||||
|
price := price + RangeEncoder.GetPrice(AModels[AstartIndex + m], bit);
|
||||||
|
m := (m shl 1) or bit;
|
||||||
|
end;
|
||||||
|
result:=price;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ReverseEncode(var AModels:array of smallint;const AstartIndex:integer;const ArangeEncoder:PRangeEncoder;const ANumBitLevels:integer;Asymbol:integer);
|
||||||
|
var m,i,bit:integer;
|
||||||
|
begin
|
||||||
|
m:=1;
|
||||||
|
for i := 0 to ANumBitLevels -1 do begin
|
||||||
|
bit := Asymbol and 1;
|
||||||
|
ArangeEncoder.Encode(AModels, AstartIndex + m, bit);
|
||||||
|
m := (m shl 1) or bit;
|
||||||
|
Asymbol := Asymbol shr 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
174
Addons/UBufferedFS.pas
Normal file
174
Addons/UBufferedFS.pas
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
unit UBufferedFS;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
type PBufferedFS = PStream;
|
||||||
|
{
|
||||||
|
const BufferSize=$10000;//64K
|
||||||
|
|
||||||
|
type TBFSMode=(BFMRead,BFMWrite);
|
||||||
|
|
||||||
|
TBufferedFS=class(TFileStream)
|
||||||
|
private
|
||||||
|
membuffer:array [0..BufferSize-1] of byte;
|
||||||
|
bytesinbuffer:integer;
|
||||||
|
bufferpos:integer;
|
||||||
|
bufferdirty:boolean;
|
||||||
|
Mode:TBFSMode;
|
||||||
|
procedure _Init;
|
||||||
|
procedure Flush;
|
||||||
|
procedure ReadBuffer;
|
||||||
|
public
|
||||||
|
constructor Create(const FileName: string; Mode: Word); overload;
|
||||||
|
constructor Create(const FileName: string; Mode: Word; Rights: Cardinal); overload;
|
||||||
|
destructor Destroy; override;
|
||||||
|
function Read(var Buffer; Count: Longint): Longint; override;
|
||||||
|
function Write(const Buffer; Count: Longint): Longint; override;
|
||||||
|
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type TByteArray = array of byte;
|
||||||
|
PByteArray = ^TByteArray;
|
||||||
|
}
|
||||||
|
implementation
|
||||||
|
{
|
||||||
|
function MovePointer(const P:pointer;const dist:integer):pointer;
|
||||||
|
begin
|
||||||
|
result:=pointer(integer(p)+dist);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBufferedFS.Init;
|
||||||
|
begin
|
||||||
|
bytesinbuffer:=0;
|
||||||
|
bufferpos:=0;
|
||||||
|
bufferdirty:=false;
|
||||||
|
mode:=BFMWrite;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBufferedFS.Flush;
|
||||||
|
begin
|
||||||
|
if bufferdirty then
|
||||||
|
inherited Write(membuffer[0],bufferpos);
|
||||||
|
bufferdirty:=false;
|
||||||
|
bytesinbuffer:=0;
|
||||||
|
bufferpos:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TBufferedFS.Create(const FileName: string; Mode: Word);
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
init;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TBufferedFS.Create(const FileName: string; Mode: Word; Rights: Cardinal);
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
init;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TBufferedFS.Destroy;
|
||||||
|
begin
|
||||||
|
flush;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBufferedFS.ReadBuffer;
|
||||||
|
begin
|
||||||
|
flush;
|
||||||
|
bytesinbuffer:=inherited Read(membuffer,buffersize);
|
||||||
|
bufferpos:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBufferedFS.Read(var Buffer; Count: Longint): Longint;
|
||||||
|
var p:PByteArray;
|
||||||
|
bytestoread:integer;
|
||||||
|
b:integer;
|
||||||
|
begin
|
||||||
|
if Mode=BFMWrite then flush;
|
||||||
|
mode:=BFMRead;
|
||||||
|
result:=0;
|
||||||
|
if count<=bytesinbuffer then begin
|
||||||
|
//all data already in buffer
|
||||||
|
move(membuffer[bufferpos],buffer,count);
|
||||||
|
bytesinbuffer:=bytesinbuffer-count;
|
||||||
|
bufferpos:=bufferpos+count;
|
||||||
|
result:=count;
|
||||||
|
end else begin
|
||||||
|
bytestoread:=count;
|
||||||
|
if (bytestoread<>0)and(bytesinbuffer<>0) then begin
|
||||||
|
//read data remaining in buffer and increment data pointer
|
||||||
|
b:=Read(buffer,bytesinbuffer);
|
||||||
|
p:=PByteArray(@(TByteArray(buffer)[b]));
|
||||||
|
bytestoread:=bytestoread-b;
|
||||||
|
result:=b;
|
||||||
|
end else p:=@buffer;
|
||||||
|
if bytestoread>=BufferSize then begin
|
||||||
|
//data to read is larger than the buffer, read it directly
|
||||||
|
result:=result+inherited Read(p^,bytestoread);
|
||||||
|
end else begin
|
||||||
|
//refill buffer
|
||||||
|
ReadBuffer;
|
||||||
|
//recurse
|
||||||
|
result:=result+Read(p^,math.Min(bytestoread,bytesinbuffer));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBufferedFS.Write(const Buffer; Count: Longint): Longint;
|
||||||
|
var p:pointer;
|
||||||
|
bytestowrite:integer;
|
||||||
|
b:integer;
|
||||||
|
begin
|
||||||
|
if mode=BFMRead then begin
|
||||||
|
seek(-BufferSize+bufferpos,soFromCurrent);
|
||||||
|
bytesinbuffer:=0;
|
||||||
|
bufferpos:=0;
|
||||||
|
end;
|
||||||
|
mode:=BFMWrite;
|
||||||
|
result:=0;
|
||||||
|
if count<=BufferSize-bytesinbuffer then begin
|
||||||
|
//all data fits in buffer
|
||||||
|
bufferdirty:=true;
|
||||||
|
move(buffer,membuffer[bufferpos],count);
|
||||||
|
bytesinbuffer:=bytesinbuffer+count;
|
||||||
|
bufferpos:=bufferpos+count;
|
||||||
|
result:=count;
|
||||||
|
end else begin
|
||||||
|
bytestowrite:=count;
|
||||||
|
if (bytestowrite<>0)and(bytesinbuffer<>BufferSize)and(bytesinbuffer<>0) then begin
|
||||||
|
//write data to remaining space in buffer and increment data pointer
|
||||||
|
b:=Write(buffer,BufferSize-bytesinbuffer);
|
||||||
|
p:=MovePointer(@buffer,b);
|
||||||
|
bytestowrite:=bytestowrite-b;
|
||||||
|
result:=b;
|
||||||
|
end else p:=@buffer;
|
||||||
|
if bytestowrite>=BufferSize then begin
|
||||||
|
//empty buffer
|
||||||
|
Flush;
|
||||||
|
//data to write is larger than the buffer, write it directly
|
||||||
|
result:=result+inherited Write(p^,bytestowrite);
|
||||||
|
end else begin
|
||||||
|
//empty buffer
|
||||||
|
Flush;
|
||||||
|
//recurse
|
||||||
|
result:=result+Write(p^,bytestowrite);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBufferedFS.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
|
||||||
|
begin
|
||||||
|
if (Origin=soCurrent)and(Offset=0) then result:=inherited seek(Offset,origin)+bufferpos
|
||||||
|
else begin
|
||||||
|
flush;
|
||||||
|
result:=inherited Seek(offset,origin);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
end.
|
80
Addons/UCRC.pas
Normal file
80
Addons/UCRC.pas
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
unit UCRC;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
type PCRC = ^TCRC;
|
||||||
|
TCRC = object(TObj)
|
||||||
|
public
|
||||||
|
Value:integer;
|
||||||
|
constructor Create;
|
||||||
|
procedure _Init;
|
||||||
|
procedure Update(const data: array of byte;const offset,size:integer);overload;
|
||||||
|
procedure Update(const data: array of byte);overload;
|
||||||
|
procedure UpdateByte(const b:integer);
|
||||||
|
function GetDigest:integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
var Table: array [0..255] of integer;
|
||||||
|
|
||||||
|
constructor TCRC.Create;
|
||||||
|
begin
|
||||||
|
Value:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCRC._Init;
|
||||||
|
begin
|
||||||
|
Value:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCRC.Update(const data: array of byte;const offset,size:integer);
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to size-1 do
|
||||||
|
value := Table[(value xor data[offset + i]) and $FF] xor (value shr 8);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCRC.Update(const data: array of byte);
|
||||||
|
var size:integer;
|
||||||
|
i:integer;
|
||||||
|
begin
|
||||||
|
size := length(data);
|
||||||
|
for i := 0 to size - 1 do
|
||||||
|
value := Table[(value xor data[i]) and $FF] xor (value shr 8);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCRC.UpdateByte(const b:integer);
|
||||||
|
begin
|
||||||
|
value := Table[(value xor b) and $FF] xor (value shr 8);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCRC.GetDigest:integer;
|
||||||
|
begin
|
||||||
|
result:=value xor (-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitCRC;
|
||||||
|
var i,j,r:integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to 255 do begin
|
||||||
|
r := i;
|
||||||
|
for j := 0 to 7 do begin
|
||||||
|
if ((r and 1) <> 0) then
|
||||||
|
r := (r shr 1) xor integer($EDB88320)
|
||||||
|
else r := r shr 1;
|
||||||
|
end;
|
||||||
|
Table[i] := r;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
InitCRC;
|
||||||
|
|
||||||
|
end.
|
420
Addons/ULZBinTree.pas
Normal file
420
Addons/ULZBinTree.pas
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
unit ULZBinTree;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses ULZInWindow, KOL;
|
||||||
|
|
||||||
|
type
|
||||||
|
TArrayOfInteger = array [0..0] of Integer;
|
||||||
|
PArrayOfInteger = ^TArrayOfInteger;
|
||||||
|
|
||||||
|
type PLZBinTree = ^TLZBinTree;
|
||||||
|
TLZBinTree = object(TLZInWindow)
|
||||||
|
public
|
||||||
|
cyclicBufferPos:integer;
|
||||||
|
cyclicBufferSize:integer;
|
||||||
|
matchMaxLen:integer;
|
||||||
|
|
||||||
|
son: PArrayOfInteger;//array of integer;
|
||||||
|
hash: array of integer;
|
||||||
|
|
||||||
|
cutValue:integer;
|
||||||
|
hashMask:integer;
|
||||||
|
hashSizeSum:integer;
|
||||||
|
|
||||||
|
HASH_ARRAY:boolean;
|
||||||
|
|
||||||
|
|
||||||
|
kNumHashDirectBytes:integer;
|
||||||
|
kMinMatchCheck:integer;
|
||||||
|
kFixHashSize:integer;
|
||||||
|
constructor Create;
|
||||||
|
procedure SetType(const AnumHashBytes:integer);
|
||||||
|
procedure _Init;virtual;
|
||||||
|
procedure MovePos;virtual;
|
||||||
|
function _Create(const AhistorySize,AkeepAddBufferBefore,AmatchMaxLen,AkeepAddBufferAfter:integer):boolean;
|
||||||
|
function GetMatches(var Adistances:array of integer):integer;
|
||||||
|
procedure Skip(Anum:integer);
|
||||||
|
procedure NormalizeLinks(var Aitems:array of integer;const AnumItems,AsubValue:integer);
|
||||||
|
procedure Normalize;
|
||||||
|
procedure SetCutValue(const AcutValue:integer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const kHash2Size = 1 shl 10;
|
||||||
|
kHash3Size = 1 shl 16;
|
||||||
|
kBT2HashSize = 1 shl 16;
|
||||||
|
kStartMaxLen = 1;
|
||||||
|
kHash3Offset = kHash2Size;
|
||||||
|
kEmptyHashValue = 0;
|
||||||
|
kMaxValForNormalize = (1 shl 30) - 1;
|
||||||
|
|
||||||
|
var CRCTable: array [0..255] of integer;
|
||||||
|
|
||||||
|
constructor TLZBinTree.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
cyclicBufferSize:=0;
|
||||||
|
cutValue:=$FF;
|
||||||
|
hashSizeSum:=0;
|
||||||
|
HASH_ARRAY:=true;
|
||||||
|
kNumHashDirectBytes:=0;
|
||||||
|
kMinMatchCheck:=4;
|
||||||
|
kFixHashsize:=kHash2Size + kHash3Size;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.SetType(const AnumHashBytes:integer);
|
||||||
|
begin
|
||||||
|
HASH_ARRAY := (AnumHashBytes > 2);
|
||||||
|
if HASH_ARRAY then begin
|
||||||
|
kNumHashDirectBytes := 0;
|
||||||
|
kMinMatchCheck := 4;
|
||||||
|
kFixHashSize := kHash2Size + kHash3Size;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
kNumHashDirectBytes := 2;
|
||||||
|
kMinMatchCheck := 2 + 1;
|
||||||
|
kFixHashSize := 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree._Init;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
inherited _init;
|
||||||
|
for i := 0 to hashSizeSum - 1 do
|
||||||
|
hash[i] := kEmptyHashValue;
|
||||||
|
cyclicBufferPos := 0;
|
||||||
|
ReduceOffsets(-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.MovePos;
|
||||||
|
begin
|
||||||
|
inc(cyclicBufferPos);
|
||||||
|
if cyclicBufferPos >= cyclicBufferSize then
|
||||||
|
cyclicBufferPos := 0;
|
||||||
|
inherited MovePos;
|
||||||
|
if pos = kMaxValForNormalize then
|
||||||
|
Normalize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZBinTree._Create(const AhistorySize,AkeepAddBufferBefore,AmatchMaxLen,AkeepAddBufferAfter:integer):boolean;
|
||||||
|
var windowReservSize:integer;
|
||||||
|
_cyclicBufferSize:integer;
|
||||||
|
hs:integer;
|
||||||
|
begin
|
||||||
|
if (AhistorySize > kMaxValForNormalize - 256) then begin
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
cutValue := 16 + (AmatchMaxLen shr 1);
|
||||||
|
|
||||||
|
windowReservSize := (AhistorySize + AkeepAddBufferBefore + AmatchMaxLen + AkeepAddBufferAfter) div 2 + 256;
|
||||||
|
|
||||||
|
inherited _Create(AhistorySize + AkeepAddBufferBefore, AmatchMaxLen + AkeepAddBufferAfter, windowReservSize);
|
||||||
|
|
||||||
|
self.matchMaxLen := AmatchMaxLen;
|
||||||
|
|
||||||
|
_cyclicBufferSize := AhistorySize + 1;
|
||||||
|
if self.cyclicBufferSize <> _cyclicBufferSize then begin
|
||||||
|
self.cyclicBufferSize:=_cyclicBufferSize;
|
||||||
|
son:= AllocMem(_cyclicBufferSize * 2);
|
||||||
|
// GetMem(son,_cyclicBufferSize * 2);
|
||||||
|
// setlength(son,_cyclicBufferSize * 2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
hs := kBT2HashSize;
|
||||||
|
|
||||||
|
if HASH_ARRAY then begin
|
||||||
|
hs := AhistorySize - 1;
|
||||||
|
hs := hs or (hs shr 1);
|
||||||
|
hs := hs or (hs shr 2);
|
||||||
|
hs := hs or (hs shr 4);
|
||||||
|
hs := hs or (hs shr 8);
|
||||||
|
hs := hs shr 1;
|
||||||
|
hs := hs or $FFFF;
|
||||||
|
if (hs > (1 shl 24)) then
|
||||||
|
hs := hs shr 1;
|
||||||
|
hashMask := hs;
|
||||||
|
inc(hs);
|
||||||
|
hs := hs + kFixHashSize;
|
||||||
|
end;
|
||||||
|
if (hs <> hashSizeSum) then begin
|
||||||
|
hashSizeSum := hs;
|
||||||
|
setlength(hash,hashSizeSum);
|
||||||
|
end;
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZBinTree.GetMatches(var Adistances:array of integer):integer;
|
||||||
|
var lenLimit:integer;
|
||||||
|
offset,matchMinPos,cur,maxlen,hashvalue,hash2value,hash3value:integer;
|
||||||
|
temp,curmatch,curmatch2,curmatch3,ptr0,ptr1,len0,len1,count:integer;
|
||||||
|
delta,cyclicpos,pby1,len:integer;
|
||||||
|
begin
|
||||||
|
if pos + matchMaxLen <= streamPos then
|
||||||
|
lenLimit := matchMaxLen
|
||||||
|
else begin
|
||||||
|
lenLimit := streamPos - pos;
|
||||||
|
if lenLimit < kMinMatchCheck then begin
|
||||||
|
MovePos();
|
||||||
|
result:=0;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
offset := 0;
|
||||||
|
if (pos > cyclicBufferSize) then
|
||||||
|
matchMinPos:=(pos - cyclicBufferSize)
|
||||||
|
else matchMinPos:=0;
|
||||||
|
cur := bufferOffset + pos;
|
||||||
|
maxLen := kStartMaxLen; // to avoid items for len < hashSize;
|
||||||
|
hash2Value := 0;
|
||||||
|
hash3Value := 0;
|
||||||
|
|
||||||
|
if HASH_ARRAY then begin
|
||||||
|
temp := CrcTable[bufferBase[cur] and $FF] xor (bufferBase[cur + 1] and $FF);
|
||||||
|
hash2Value := temp and (kHash2Size - 1);
|
||||||
|
temp := temp xor ((bufferBase[cur + 2] and $FF) shl 8);
|
||||||
|
hash3Value := temp and (kHash3Size - 1);
|
||||||
|
hashValue := (temp xor (CrcTable[bufferBase[cur + 3] and $FF] shl 5)) and hashMask;
|
||||||
|
end else
|
||||||
|
hashValue := ((bufferBase[cur] and $FF) xor ((bufferBase[cur + 1] and $FF) shl 8));
|
||||||
|
|
||||||
|
curMatch := hash[kFixHashSize + hashValue];
|
||||||
|
if HASH_ARRAY then begin
|
||||||
|
curMatch2 := hash[hash2Value];
|
||||||
|
curMatch3 := hash[kHash3Offset + hash3Value];
|
||||||
|
hash[hash2Value] := pos;
|
||||||
|
hash[kHash3Offset + hash3Value] := pos;
|
||||||
|
if curMatch2 > matchMinPos then
|
||||||
|
if bufferBase[bufferOffset + curMatch2] = bufferBase[cur] then begin
|
||||||
|
maxLen := 2;
|
||||||
|
Adistances[offset] := maxLen;
|
||||||
|
inc(offset);
|
||||||
|
Adistances[offset] := pos - curMatch2 - 1;
|
||||||
|
inc(offset);
|
||||||
|
end;
|
||||||
|
if curMatch3 > matchMinPos then
|
||||||
|
if bufferBase[bufferOffset + curMatch3] = bufferBase[cur] then begin
|
||||||
|
if curMatch3 = curMatch2 then
|
||||||
|
offset := offset - 2;
|
||||||
|
maxLen := 3;
|
||||||
|
Adistances[offset] := maxlen;
|
||||||
|
inc(offset);
|
||||||
|
Adistances[offset] := pos - curMatch3 - 1;
|
||||||
|
inc(offset);
|
||||||
|
curMatch2 := curMatch3;
|
||||||
|
end;
|
||||||
|
if (offset <> 0) and (curMatch2 = curMatch) then begin
|
||||||
|
offset := offset - 2;
|
||||||
|
maxLen := kStartMaxLen;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
hash[kFixHashSize + hashValue] := pos;
|
||||||
|
|
||||||
|
ptr0 := (cyclicBufferPos shl 1) + 1;
|
||||||
|
ptr1 := (cyclicBufferPos shl 1);
|
||||||
|
|
||||||
|
len0 := kNumHashDirectBytes;
|
||||||
|
len1 := len0;
|
||||||
|
|
||||||
|
if kNumHashDirectBytes <> 0 then begin
|
||||||
|
if (curMatch > matchMinPos) then begin
|
||||||
|
if (bufferBase[bufferOffset + curMatch + kNumHashDirectBytes] <> bufferBase[cur + kNumHashDirectBytes]) then begin
|
||||||
|
maxLen := kNumHashDirectBytes;
|
||||||
|
Adistances[offset] := maxLen;
|
||||||
|
inc(offset);
|
||||||
|
Adistances[offset] := pos - curMatch - 1;
|
||||||
|
inc(offset);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
count := cutValue;
|
||||||
|
|
||||||
|
while (true) do begin
|
||||||
|
if (curMatch <= matchMinPos) or (count = 0) then begin
|
||||||
|
son[ptr1] := kEmptyHashValue;
|
||||||
|
son[ptr0] := son[ptr1];
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
dec(count);
|
||||||
|
delta := pos - curMatch;
|
||||||
|
if delta<=cyclicBufferPos then
|
||||||
|
cyclicpos:=(cyclicBufferPos - delta) shl 1
|
||||||
|
else cyclicpos:=(cyclicBufferPos - delta + cyclicBufferSize) shl 1;
|
||||||
|
|
||||||
|
pby1 := bufferOffset + curMatch;
|
||||||
|
len := min(len0, len1);
|
||||||
|
if bufferBase[pby1 + len] = bufferBase[cur + len] then begin
|
||||||
|
inc(len);
|
||||||
|
while (len <> lenLimit) do begin
|
||||||
|
if (bufferBase[pby1 + len] <> bufferBase[cur + len]) then
|
||||||
|
break;
|
||||||
|
inc(len);
|
||||||
|
end;
|
||||||
|
if maxLen < len then begin
|
||||||
|
maxLen := len;
|
||||||
|
Adistances[offset] := maxlen;
|
||||||
|
inc(offset);
|
||||||
|
Adistances[offset] := delta - 1;
|
||||||
|
inc(offset);
|
||||||
|
if (len = lenLimit) then begin
|
||||||
|
son[ptr1] := son[cyclicPos];
|
||||||
|
son[ptr0] := son[cyclicPos + 1];
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if (bufferBase[pby1 + len] and $FF) < (bufferBase[cur + len] and $FF) then begin
|
||||||
|
son[ptr1] := curMatch;
|
||||||
|
ptr1 := cyclicPos + 1;
|
||||||
|
curMatch := son[ptr1];
|
||||||
|
len1 := len;
|
||||||
|
end else begin
|
||||||
|
son[ptr0] := curMatch;
|
||||||
|
ptr0 := cyclicPos;
|
||||||
|
curMatch := son[ptr0];
|
||||||
|
len0 := len;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
MovePos;
|
||||||
|
result:=offset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.Skip(Anum:integer);
|
||||||
|
var lenLimit,matchminpos,cur,hashvalue,temp,hash2value,hash3value,curMatch:integer;
|
||||||
|
ptr0,ptr1,len,len0,len1,count,delta,cyclicpos,pby1:integer;
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
if pos + matchMaxLen <= streamPos then
|
||||||
|
lenLimit := matchMaxLen
|
||||||
|
else begin
|
||||||
|
lenLimit := streamPos - pos;
|
||||||
|
if lenLimit < kMinMatchCheck then begin
|
||||||
|
MovePos();
|
||||||
|
dec(Anum);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if pos>cyclicBufferSize then
|
||||||
|
matchminpos:=(pos - cyclicBufferSize)
|
||||||
|
else matchminpos:=0;
|
||||||
|
cur := bufferOffset + pos;
|
||||||
|
|
||||||
|
if HASH_ARRAY then begin
|
||||||
|
temp := CrcTable[bufferBase[cur] and $FF] xor (bufferBase[cur + 1] and $FF);
|
||||||
|
hash2Value := temp and (kHash2Size - 1);
|
||||||
|
hash[hash2Value] := pos;
|
||||||
|
temp := temp xor ((bufferBase[cur + 2] and $FF) shl 8);
|
||||||
|
hash3Value := temp and (kHash3Size - 1);
|
||||||
|
hash[kHash3Offset + hash3Value] := pos;
|
||||||
|
hashValue := (temp xor (CrcTable[bufferBase[cur + 3] and $FF] shl 5)) and hashMask;
|
||||||
|
end else
|
||||||
|
hashValue := ((bufferBase[cur] and $FF) xor ((bufferBase[cur + 1] and $FF) shl 8));
|
||||||
|
|
||||||
|
curMatch := hash[kFixHashSize + hashValue];
|
||||||
|
hash[kFixHashSize + hashValue] := pos;
|
||||||
|
|
||||||
|
ptr0 := (cyclicBufferPos shl 1) + 1;
|
||||||
|
ptr1 := (cyclicBufferPos shl 1);
|
||||||
|
|
||||||
|
len0 := kNumHashDirectBytes;
|
||||||
|
len1 := kNumHashDirectBytes;
|
||||||
|
|
||||||
|
count := cutValue;
|
||||||
|
while true do begin
|
||||||
|
if (curMatch <= matchMinPos) or (count = 0) then begin
|
||||||
|
son[ptr1] := kEmptyHashValue;
|
||||||
|
son[ptr0] := son[ptr1];
|
||||||
|
break;
|
||||||
|
end else dec(count);
|
||||||
|
|
||||||
|
delta := pos - curMatch;
|
||||||
|
if (delta <= cyclicBufferPos) then
|
||||||
|
cyclicpos:=(cyclicBufferPos - delta) shl 1
|
||||||
|
else cyclicpos:=(cyclicBufferPos - delta + cyclicBufferSize) shl 1;
|
||||||
|
|
||||||
|
pby1 := bufferOffset + curMatch;
|
||||||
|
len := min(len0, len1);
|
||||||
|
if bufferBase[pby1 + len] = bufferBase[cur + len] then begin
|
||||||
|
inc(len);
|
||||||
|
while (len <> lenLimit) do begin
|
||||||
|
if bufferBase[pby1 + len] <> bufferBase[cur + len] then
|
||||||
|
break;
|
||||||
|
inc(len);
|
||||||
|
end;
|
||||||
|
if len = lenLimit then begin
|
||||||
|
son[ptr1] := son[cyclicPos];
|
||||||
|
son[ptr0] := son[cyclicPos + 1];
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if ((bufferBase[pby1 + len] and $FF) < (bufferBase[cur + len] and $FF)) then begin
|
||||||
|
son[ptr1] := curMatch;
|
||||||
|
ptr1 := cyclicPos + 1;
|
||||||
|
curMatch := son[ptr1];
|
||||||
|
len1 := len;
|
||||||
|
end else begin
|
||||||
|
son[ptr0] := curMatch;
|
||||||
|
ptr0 := cyclicPos;
|
||||||
|
curMatch := son[ptr0];
|
||||||
|
len0 := len;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
MovePos;
|
||||||
|
dec(Anum);
|
||||||
|
until Anum=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.NormalizeLinks(var Aitems:array of integer;const AnumItems,AsubValue:integer);
|
||||||
|
var i,value:integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to AnumItems-1 do begin
|
||||||
|
value := Aitems[i];
|
||||||
|
if value <= AsubValue then
|
||||||
|
value := kEmptyHashValue
|
||||||
|
else value := value - AsubValue;
|
||||||
|
Aitems[i] := value;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.Normalize;
|
||||||
|
var subvalue:integer;
|
||||||
|
begin
|
||||||
|
subValue := pos - cyclicBufferSize;
|
||||||
|
NormalizeLinks(son^, cyclicBufferSize * 2, subValue);
|
||||||
|
NormalizeLinks(hash, hashSizeSum, subValue);
|
||||||
|
ReduceOffsets(subValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZBinTree.SetCutValue(const Acutvalue:integer);
|
||||||
|
begin
|
||||||
|
self.cutValue:=Acutvalue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitCRC;
|
||||||
|
var i,r,j:integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to 255 do begin
|
||||||
|
r := i;
|
||||||
|
for j := 0 to 7 do
|
||||||
|
if ((r and 1) <> 0) then
|
||||||
|
r := (r shr 1) xor integer($EDB88320)
|
||||||
|
else
|
||||||
|
r := r shr 1;
|
||||||
|
CrcTable[i] := r;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
InitCRC;
|
||||||
|
end.
|
170
Addons/ULZInWindow.pas
Normal file
170
Addons/ULZInWindow.pas
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
unit ULZInWindow;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
type TLZInWindow= object(TObj)
|
||||||
|
public
|
||||||
|
bufferBase: array of byte;// pointer to buffer with data
|
||||||
|
stream:PStream;
|
||||||
|
posLimit:integer; // offset (from _buffer) of first byte when new block reading must be done
|
||||||
|
streamEndWasReached:boolean; // if (true) then _streamPos shows real end of stream
|
||||||
|
|
||||||
|
pointerToLastSafePosition:integer;
|
||||||
|
|
||||||
|
bufferOffset:integer;
|
||||||
|
|
||||||
|
blockSize:integer; // Size of Allocated memory block
|
||||||
|
pos:integer; // offset (from _buffer) of curent byte
|
||||||
|
keepSizeBefore:integer; // how many BYTEs must be kept in buffer before _pos
|
||||||
|
keepSizeAfter:integer; // how many BYTEs must be kept buffer after _pos
|
||||||
|
streamPos:integer; // offset (from _buffer) of first not read byte from Stream
|
||||||
|
|
||||||
|
procedure MoveBlock;
|
||||||
|
procedure ReadBlock;
|
||||||
|
procedure _Free;
|
||||||
|
procedure _Create(const AkeepSizeBefore, AkeepSizeAfter, AkeepSizeReserv:integer);
|
||||||
|
procedure SetStream(const Astream:PStream);
|
||||||
|
procedure ReleaseStream;
|
||||||
|
procedure _Init;virtual;
|
||||||
|
procedure MovePos;virtual;
|
||||||
|
function GetIndexByte(const Aindex:integer):byte;
|
||||||
|
// index + limit have not to exceed _keepSizeAfter;
|
||||||
|
function GetMatchLen(const Aindex:integer;Adistance,Alimit:integer):integer;
|
||||||
|
function GetNumAvailableBytes:integer;
|
||||||
|
procedure ReduceOffsets(const AsubValue:integer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure TLZInWindow.MoveBlock;
|
||||||
|
var offset,numbytes,i:integer;
|
||||||
|
begin
|
||||||
|
offset := bufferOffset + pos - keepSizeBefore;
|
||||||
|
// we need one additional byte, since MovePos moves on 1 byte.
|
||||||
|
if (offset > 0) then
|
||||||
|
dec(offset);
|
||||||
|
|
||||||
|
numBytes := bufferOffset + streamPos - offset;
|
||||||
|
|
||||||
|
// check negative offset ????
|
||||||
|
for i := 0 to numBytes -1 do
|
||||||
|
bufferBase[i] := bufferBase[offset + i];
|
||||||
|
bufferOffset := bufferOffset - offset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow.ReadBlock;
|
||||||
|
var size,numreadbytes,pointerToPostion:integer;
|
||||||
|
begin
|
||||||
|
if streamEndWasReached then
|
||||||
|
exit;
|
||||||
|
while (true) do begin
|
||||||
|
size := (0 - bufferOffset) + blockSize - streamPos;
|
||||||
|
if size = 0 then
|
||||||
|
exit;
|
||||||
|
numReadBytes := stream.Read(bufferBase[bufferOffset + streamPos], size);
|
||||||
|
if (numReadBytes = 0) then begin
|
||||||
|
posLimit := streamPos;
|
||||||
|
pointerToPostion := bufferOffset + posLimit;
|
||||||
|
if (pointerToPostion > pointerToLastSafePosition) then
|
||||||
|
posLimit := pointerToLastSafePosition - bufferOffset;
|
||||||
|
streamEndWasReached := true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
streamPos := streamPos + numReadBytes;
|
||||||
|
if (streamPos >= pos + keepSizeAfter) then
|
||||||
|
posLimit := streamPos - keepSizeAfter;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow._Free;
|
||||||
|
begin
|
||||||
|
setlength(bufferBase,0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow._Create(const AkeepSizeBefore, AkeepSizeAfter, AkeepSizeReserv:integer);
|
||||||
|
var _blocksize:integer;
|
||||||
|
begin
|
||||||
|
self.keepSizeBefore := AkeepSizeBefore;
|
||||||
|
self.keepSizeAfter := AkeepSizeAfter;
|
||||||
|
_blocksize := AkeepSizeBefore + AkeepSizeAfter + AkeepSizeReserv;
|
||||||
|
if (length(bufferBase) = 0) or (self.blockSize <> _blocksize) then begin
|
||||||
|
_Free;
|
||||||
|
self.blockSize := _blocksize;
|
||||||
|
setlength(bufferBase,self.blockSize);
|
||||||
|
end;
|
||||||
|
pointerToLastSafePosition := self.blockSize - AkeepSizeAfter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow.SetStream(const Astream:PStream);
|
||||||
|
begin
|
||||||
|
self.stream:=Astream;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow.ReleaseStream;
|
||||||
|
begin
|
||||||
|
stream:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow._Init;
|
||||||
|
begin
|
||||||
|
bufferOffset := 0;
|
||||||
|
pos := 0;
|
||||||
|
streamPos := 0;
|
||||||
|
streamEndWasReached := false;
|
||||||
|
ReadBlock;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow.MovePos;
|
||||||
|
var pointerToPostion:integer;
|
||||||
|
begin
|
||||||
|
inc(pos);
|
||||||
|
if pos > posLimit then begin
|
||||||
|
pointerToPostion := bufferOffset + pos;
|
||||||
|
if pointerToPostion > pointerToLastSafePosition then
|
||||||
|
MoveBlock;
|
||||||
|
ReadBlock;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZInWindow.GetIndexByte(const Aindex:integer):byte;
|
||||||
|
begin
|
||||||
|
result:=bufferBase[bufferOffset + pos + Aindex];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZInWindow.GetMatchLen(const Aindex:integer;Adistance,Alimit:integer):integer;
|
||||||
|
var pby,i:integer;
|
||||||
|
begin
|
||||||
|
if streamEndWasReached then
|
||||||
|
if (pos + Aindex) + Alimit > streamPos then
|
||||||
|
Alimit := streamPos - (pos + Aindex);
|
||||||
|
inc(Adistance);
|
||||||
|
// Byte *pby = _buffer + (size_t)_pos + Aindex;
|
||||||
|
pby := bufferOffset + pos + Aindex;
|
||||||
|
|
||||||
|
i:=0;
|
||||||
|
while (i<Alimit)and(bufferBase[pby + i] = bufferBase[pby + i - Adistance]) do begin
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
result:=i;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZInWindow.GetNumAvailableBytes:integer;
|
||||||
|
begin
|
||||||
|
result:=streamPos - pos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZInWindow.ReduceOffsets(const Asubvalue:integer);
|
||||||
|
begin
|
||||||
|
bufferOffset := bufferOffset + Asubvalue;
|
||||||
|
posLimit := posLimit - Asubvalue;
|
||||||
|
pos := pos - Asubvalue;
|
||||||
|
streamPos := streamPos - Asubvalue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
104
Addons/ULZMABase.pas
Normal file
104
Addons/ULZMABase.pas
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
unit ULZMABase;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
function StateInit:integer;
|
||||||
|
function StateUpdateChar(const index:integer):integer;
|
||||||
|
function StateUpdateMatch(const index:integer):integer;
|
||||||
|
function StateUpdateRep(const index:integer):integer;
|
||||||
|
function StateUpdateShortRep(const index:integer):integer;
|
||||||
|
function StateIsCharState(const index:integer):boolean;
|
||||||
|
function GetLenToPosState(len:integer):integer;
|
||||||
|
|
||||||
|
const kNumRepDistances = 4;
|
||||||
|
kNumStates = 12;
|
||||||
|
kNumPosSlotBits = 6;
|
||||||
|
kDicLogSizeMin = 0;
|
||||||
|
// kDicLogSizeMax = 28;
|
||||||
|
// kDistTableSizeMax = kDicLogSizeMax * 2;
|
||||||
|
|
||||||
|
kNumLenToPosStatesBits = 2; // it's for speed optimization
|
||||||
|
kNumLenToPosStates = 1 shl kNumLenToPosStatesBits;
|
||||||
|
|
||||||
|
kMatchMinLen = 2;
|
||||||
|
|
||||||
|
kNumAlignBits = 4;
|
||||||
|
kAlignTableSize = 1 shl kNumAlignBits;
|
||||||
|
kAlignMask = (kAlignTableSize - 1);
|
||||||
|
|
||||||
|
kStartPosModelIndex = 4;
|
||||||
|
kEndPosModelIndex = 14;
|
||||||
|
kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
|
||||||
|
|
||||||
|
kNumFullDistances = 1 shl (kEndPosModelIndex div 2);
|
||||||
|
|
||||||
|
kNumLitPosStatesBitsEncodingMax = 4;
|
||||||
|
kNumLitContextBitsMax = 8;
|
||||||
|
|
||||||
|
kNumPosStatesBitsMax = 4;
|
||||||
|
kNumPosStatesMax = (1 shl kNumPosStatesBitsMax);
|
||||||
|
kNumPosStatesBitsEncodingMax = 4;
|
||||||
|
kNumPosStatesEncodingMax = (1 shl kNumPosStatesBitsEncodingMax);
|
||||||
|
|
||||||
|
kNumLowLenBits = 3;
|
||||||
|
kNumMidLenBits = 3;
|
||||||
|
kNumHighLenBits = 8;
|
||||||
|
kNumLowLenSymbols = 1 shl kNumLowLenBits;
|
||||||
|
kNumMidLenSymbols = 1 shl kNumMidLenBits;
|
||||||
|
kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 shl kNumHighLenBits);
|
||||||
|
kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function StateInit:integer;
|
||||||
|
begin
|
||||||
|
result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function StateUpdateChar(const index:integer):integer;
|
||||||
|
begin
|
||||||
|
if (index < 4) then
|
||||||
|
result:=0
|
||||||
|
else
|
||||||
|
if (index < 10) then
|
||||||
|
result:=index - 3
|
||||||
|
else
|
||||||
|
result:=index - 6;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function StateUpdateMatch(const index:integer):integer;
|
||||||
|
begin
|
||||||
|
if index<7 then result:=7
|
||||||
|
else result:=10;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function StateUpdateRep(const index:integer):integer;
|
||||||
|
begin
|
||||||
|
if index<7 then result:=8
|
||||||
|
else result:=11;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function StateUpdateShortRep(const index:integer):integer;
|
||||||
|
begin
|
||||||
|
if index<7 then result:=9
|
||||||
|
else result:=11;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function StateIsCharState(const index:integer):boolean;
|
||||||
|
begin
|
||||||
|
result:=index<7;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetLenToPosState(len:integer):integer;
|
||||||
|
begin
|
||||||
|
len := len - kMatchMinLen;
|
||||||
|
if (len < kNumLenToPosStates) then
|
||||||
|
result:=len
|
||||||
|
else result:=(kNumLenToPosStates - 1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
31
Addons/ULZMACommon.pas
Normal file
31
Addons/ULZMACommon.pas
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
unit ULZMACommon;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
type TLZMAProgressAction=(LPAMax,LPAPos);
|
||||||
|
TLZMAProgress=procedure (const Action:TLZMAProgressAction;const Value:int64) of object;
|
||||||
|
|
||||||
|
function ReadByte(const stream:PStream):byte;
|
||||||
|
procedure WriteByte(const stream:PStream;b:byte);
|
||||||
|
|
||||||
|
const CodeProgressInterval = 50;//approx. number of times an OnProgress event will be fired during coding
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function ReadByte(const stream:PStream):byte;
|
||||||
|
begin
|
||||||
|
stream.Read(result,1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure WriteByte(const stream:PStream;b:byte);
|
||||||
|
begin
|
||||||
|
stream.Write(b,1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
428
Addons/ULZMADecoder.pas
Normal file
428
Addons/ULZMADecoder.pas
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
unit ULZMADecoder;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses ULZMABase,UBitTreeDecoder,ULZOutWindow,URangeDecoder,KOL,ULZMACommon;
|
||||||
|
|
||||||
|
type PLZMALenDecoder = ^TLZMALenDecoder;
|
||||||
|
PLZMALiteralDecoder = ^TLZMALiteralDecoder;
|
||||||
|
|
||||||
|
PLZMADecoder = ^TLZMADecoder;
|
||||||
|
TLZMADecoder = object(TObj)
|
||||||
|
private
|
||||||
|
FOnProgress:TLZMAProgress;
|
||||||
|
procedure DoProgress(const Action:TLZMAProgressAction;const Value:integer);
|
||||||
|
public
|
||||||
|
m_OutWindow:PLZOutWindow;
|
||||||
|
m_RangeDecoder:PRangeDecoder;
|
||||||
|
|
||||||
|
m_IsMatchDecoders: array [0..ULZMABase.kNumStates shl ULZMABase.kNumPosStatesBitsMax-1] of smallint;
|
||||||
|
m_IsRepDecoders: array [0..ULZMABase.kNumStates-1] of smallint;
|
||||||
|
m_IsRepG0Decoders: array [0..ULZMABase.kNumStates-1] of smallint;
|
||||||
|
m_IsRepG1Decoders: array [0..ULZMABase.kNumStates-1] of smallint;
|
||||||
|
m_IsRepG2Decoders: array [0..ULZMABase.kNumStates-1] of smallint;
|
||||||
|
m_IsRep0LongDecoders: array [0..ULZMABase.kNumStates shl ULZMABase.kNumPosStatesBitsMax-1] of smallint;
|
||||||
|
|
||||||
|
m_PosSlotDecoder: array [0..ULZMABase.kNumLenToPosStates-1] of PBitTreeDecoder;
|
||||||
|
m_PosDecoders: array [0..ULZMABase.kNumFullDistances - ULZMABase.kEndPosModelIndex-1] of smallint;
|
||||||
|
|
||||||
|
m_PosAlignDecoder:PBitTreeDecoder;
|
||||||
|
|
||||||
|
m_LenDecoder:PLZMALenDecoder;
|
||||||
|
m_RepLenDecoder:PLZMALenDecoder;
|
||||||
|
|
||||||
|
m_LiteralDecoder:PLZMALiteralDecoder;
|
||||||
|
|
||||||
|
m_DictionarySize:integer;
|
||||||
|
m_DictionarySizeCheck:integer;
|
||||||
|
|
||||||
|
m_PosStateMask:integer;
|
||||||
|
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy;virtual;
|
||||||
|
function SetDictionarySize(const dictionarySize:integer):boolean;
|
||||||
|
function SetLcLpPb(const lc,lp,pb:integer):boolean;
|
||||||
|
procedure _Init;
|
||||||
|
function Code(const inStream,outStream:PStream;outSize:int64):boolean;
|
||||||
|
function SetDecoderProperties(const properties:array of byte):boolean;
|
||||||
|
property OnProgress:TLZMAProgress read FOnProgress write FOnProgress;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TLZMALenDecoder = object(TObj)
|
||||||
|
public
|
||||||
|
m_Choice:array [0..1] of smallint;
|
||||||
|
m_LowCoder: array[0..ULZMABase.kNumPosStatesMax-1] of PBitTreeDecoder;
|
||||||
|
m_MidCoder: array[0..ULZMABase.kNumPosStatesMax-1] of PBitTreeDecoder;
|
||||||
|
m_HighCoder: PBitTreeDecoder;
|
||||||
|
m_NumPosStates:integer;
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy;virtual;
|
||||||
|
procedure _Create(const numPosStates:integer);
|
||||||
|
procedure _Init;
|
||||||
|
function Decode(const rangeDecoder:PRangeDecoder;const posState:integer):integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PLZMADecoder2 = ^TLZMADecoder2;
|
||||||
|
TLZMADecoder2 = object(TObj)
|
||||||
|
public
|
||||||
|
m_Decoders: array [0..$300-1] of smallint;
|
||||||
|
procedure _Init;
|
||||||
|
function DecodeNormal(const ArangeDecoder:PRangeDecoder):byte;
|
||||||
|
function DecodeWithMatchByte(const ArangeDecoder:PRangeDecoder;AmatchByte:byte):byte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TLZMALiteralDecoder = object(TObj)
|
||||||
|
public
|
||||||
|
m_Coders: array of PLZMADecoder2;
|
||||||
|
m_NumPrevBits:integer;
|
||||||
|
m_NumPosBits:integer;
|
||||||
|
m_PosMask:integer;
|
||||||
|
procedure _Create(const AnumPosBits, AnumPrevBits:integer);
|
||||||
|
procedure _Init;
|
||||||
|
function GetDecoder(const Apos:integer;const AprevByte:byte):PLZMADecoder2;
|
||||||
|
destructor Destroy;virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
constructor TLZMALenDecoder.Create;
|
||||||
|
begin
|
||||||
|
New(m_HighCoder, Create(ULZMABase.kNumHighLenBits));
|
||||||
|
m_NumPosStates:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TLZMALenDecoder.Destroy;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
m_HighCoder.free;
|
||||||
|
for i:=low(m_LowCoder) to high(m_LowCoder) do begin
|
||||||
|
if m_LowCoder[i]<>nil then m_LowCoder[i].free;
|
||||||
|
if m_MidCoder[i]<>nil then m_MidCoder[i].free;
|
||||||
|
end;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMALenDecoder._Create(const numPosStates:integer);
|
||||||
|
begin
|
||||||
|
while m_NumPosStates < numPosStates do begin
|
||||||
|
New(m_LowCoder[m_NumPosStates], Create(ULZMABase.kNumLowLenBits));
|
||||||
|
New(m_MidCoder[m_NumPosStates], Create(ULZMABase.kNumMidLenBits));
|
||||||
|
inc(m_NumPosStates);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMALenDecoder._Init;
|
||||||
|
var posState:integer;
|
||||||
|
begin
|
||||||
|
URangeDecoder.InitBitModels(m_Choice);
|
||||||
|
for posState := 0 to m_NumPosStates-1 do begin
|
||||||
|
m_LowCoder[posState]._Init;
|
||||||
|
m_MidCoder[posState]._Init;
|
||||||
|
end;
|
||||||
|
m_HighCoder._Init;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMALenDecoder.Decode(const rangeDecoder:PRangeDecoder;const posState:integer):integer;
|
||||||
|
var symbol:integer;
|
||||||
|
begin
|
||||||
|
if (rangeDecoder.DecodeBit(m_Choice, 0) = 0) then begin
|
||||||
|
result:=m_LowCoder[posState].Decode(rangeDecoder);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
symbol := ULZMABase.kNumLowLenSymbols;
|
||||||
|
if (rangeDecoder.DecodeBit(m_Choice, 1) = 0) then
|
||||||
|
symbol := symbol + m_MidCoder[posState].Decode(rangeDecoder)
|
||||||
|
else symbol := symbol + ULZMABase.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder);
|
||||||
|
result:=symbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMADecoder2._Init;
|
||||||
|
begin
|
||||||
|
URangeDecoder.InitBitModels(m_Decoders);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder2.DecodeNormal(const ArangeDecoder:PRangeDecoder):byte;
|
||||||
|
var symbol:integer;
|
||||||
|
begin
|
||||||
|
symbol := 1;
|
||||||
|
repeat
|
||||||
|
symbol := (symbol shl 1) or ArangeDecoder.DecodeBit(m_Decoders, symbol);
|
||||||
|
until not (symbol < $100);
|
||||||
|
result:=symbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder2.DecodeWithMatchByte(const ArangeDecoder:PRangeDecoder;AmatchByte:byte):byte;
|
||||||
|
var symbol:integer;
|
||||||
|
matchbit:integer;
|
||||||
|
bit:integer;
|
||||||
|
begin
|
||||||
|
symbol := 1;
|
||||||
|
repeat
|
||||||
|
matchBit := (AmatchByte shr 7) and 1;
|
||||||
|
AmatchByte := AmatchByte shl 1;
|
||||||
|
bit := ArangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) shl 8) + symbol);
|
||||||
|
symbol := (symbol shl 1) or bit;
|
||||||
|
if (matchBit <> bit) then begin
|
||||||
|
while (symbol < $100) do begin
|
||||||
|
symbol := (symbol shl 1) or ArangeDecoder.DecodeBit(m_Decoders, symbol);
|
||||||
|
end;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
until not (symbol < $100);
|
||||||
|
result:=symbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMALiteralDecoder._Create(const AnumPosBits, AnumPrevBits:integer);
|
||||||
|
var numStates,i:integer;
|
||||||
|
begin
|
||||||
|
if (length(m_Coders) <> 0) and (m_NumPrevBits = AnumPrevBits) and (m_NumPosBits = AnumPosBits) then
|
||||||
|
exit;
|
||||||
|
m_NumPosBits := AnumPosBits;
|
||||||
|
m_PosMask := (1 shl AnumPosBits) - 1;
|
||||||
|
m_NumPrevBits := AnumPrevBits;
|
||||||
|
numStates := 1 shl (m_NumPrevBits + m_NumPosBits);
|
||||||
|
setlength(m_Coders,numStates);
|
||||||
|
for i :=0 to numStates-1 do
|
||||||
|
New(m_Coders[i], Create);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TLZMALiteralDecoder.Destroy;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i :=low(m_Coders) to high(m_Coders) do
|
||||||
|
if m_Coders[i]<>nil then m_Coders[i].Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMALiteralDecoder._Init;
|
||||||
|
var numStates,i:integer;
|
||||||
|
begin
|
||||||
|
numStates := 1 shl (m_NumPrevBits + m_NumPosBits);
|
||||||
|
for i := 0 to numStates -1 do
|
||||||
|
m_Coders[i]._Init;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMALiteralDecoder.GetDecoder(const Apos:integer;const AprevByte:byte):PLZMADecoder2;
|
||||||
|
begin
|
||||||
|
result:=m_Coders[((Apos and m_PosMask) shl m_NumPrevBits) + ((AprevByte and $FF) shr (8 - m_NumPrevBits))];
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TLZMADecoder.Create;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
FOnProgress:=nil;
|
||||||
|
New(m_OutWindow, Create);
|
||||||
|
New(m_RangeDecoder, Create);
|
||||||
|
New(m_PosAlignDecoder, Create(ULZMABase.kNumAlignBits));
|
||||||
|
New(m_LenDecoder, Create);
|
||||||
|
New(m_RepLenDecoder, Create);
|
||||||
|
New(m_LiteralDecoder, Create);
|
||||||
|
m_DictionarySize:= -1;
|
||||||
|
m_DictionarySizeCheck:= -1;
|
||||||
|
for i := 0 to ULZMABase.kNumLenToPosStates -1 do
|
||||||
|
New(m_PosSlotDecoder[i], Create(ULZMABase.kNumPosSlotBits));
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TLZMADecoder.Destroy;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
m_OutWindow.Free;
|
||||||
|
m_RangeDecoder.Free;
|
||||||
|
m_PosAlignDecoder.Free;
|
||||||
|
m_LenDecoder.Free;
|
||||||
|
m_RepLenDecoder.Free;
|
||||||
|
m_LiteralDecoder.Free;
|
||||||
|
for i := 0 to ULZMABase.kNumLenToPosStates -1 do
|
||||||
|
m_PosSlotDecoder[i].Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder.SetDictionarySize(const dictionarySize:integer):boolean;
|
||||||
|
begin
|
||||||
|
if dictionarySize < 0 then
|
||||||
|
result:=false
|
||||||
|
else begin
|
||||||
|
if m_DictionarySize <> dictionarySize then begin
|
||||||
|
m_DictionarySize := dictionarySize;
|
||||||
|
m_DictionarySizeCheck := max(m_DictionarySize, 1);
|
||||||
|
m_OutWindow._Create(max(m_DictionarySizeCheck, (1 shl 12)));
|
||||||
|
end;
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder.SetLcLpPb(const lc,lp,pb:integer):boolean;
|
||||||
|
var numPosStates:integer;
|
||||||
|
begin
|
||||||
|
if (lc > ULZMABase.kNumLitContextBitsMax) or (lp > 4) or (pb > ULZMABase.kNumPosStatesBitsMax) then begin
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
m_LiteralDecoder._Create(lp, lc);
|
||||||
|
numPosStates := 1 shl pb;
|
||||||
|
m_LenDecoder._Create(numPosStates);
|
||||||
|
m_RepLenDecoder._Create(numPosStates);
|
||||||
|
m_PosStateMask := numPosStates - 1;
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMADecoder._Init;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
m_OutWindow._Init(false);
|
||||||
|
|
||||||
|
URangeDecoder.InitBitModels(m_IsMatchDecoders);
|
||||||
|
URangeDecoder.InitBitModels(m_IsRep0LongDecoders);
|
||||||
|
URangeDecoder.InitBitModels(m_IsRepDecoders);
|
||||||
|
URangeDecoder.InitBitModels(m_IsRepG0Decoders);
|
||||||
|
URangeDecoder.InitBitModels(m_IsRepG1Decoders);
|
||||||
|
URangeDecoder.InitBitModels(m_IsRepG2Decoders);
|
||||||
|
URangeDecoder.InitBitModels(m_PosDecoders);
|
||||||
|
|
||||||
|
m_LiteralDecoder._Init();
|
||||||
|
for i := 0 to ULZMABase.kNumLenToPosStates -1 do
|
||||||
|
m_PosSlotDecoder[i]._Init;
|
||||||
|
m_LenDecoder._Init;
|
||||||
|
m_RepLenDecoder._Init;
|
||||||
|
m_PosAlignDecoder._Init;
|
||||||
|
m_RangeDecoder._Init;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder.Code(const inStream,outStream:PStream;outSize:int64):boolean;
|
||||||
|
var state,rep0,rep1,rep2,rep3:integer;
|
||||||
|
nowPos64:int64;
|
||||||
|
prevByte:byte;
|
||||||
|
posState:integer;
|
||||||
|
decoder2:PLZMADecoder2;
|
||||||
|
len,distance,posSlot,numDirectBits:integer;
|
||||||
|
lpos:int64;
|
||||||
|
progint:int64;
|
||||||
|
begin
|
||||||
|
DoProgress(LPAMax,outSize);
|
||||||
|
m_RangeDecoder.SetStream(inStream);
|
||||||
|
m_OutWindow.SetStream(outStream);
|
||||||
|
_Init;
|
||||||
|
|
||||||
|
state := ULZMABase.StateInit;
|
||||||
|
rep0 := 0; rep1 := 0; rep2 := 0; rep3 := 0;
|
||||||
|
|
||||||
|
nowPos64 := 0;
|
||||||
|
prevByte := 0;
|
||||||
|
progint:=outsize div CodeProgressInterval;
|
||||||
|
lpos:=progint;
|
||||||
|
while (outSize < 0) or (nowPos64 < outSize) do begin
|
||||||
|
if (nowPos64 >=lpos) then begin
|
||||||
|
DoProgress(LPAPos,nowPos64);
|
||||||
|
lpos:=lpos+progint;
|
||||||
|
end;
|
||||||
|
posState := nowPos64 and m_PosStateMask;
|
||||||
|
if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state shl ULZMABase.kNumPosStatesBitsMax) + posState) = 0) then begin
|
||||||
|
decoder2 := m_LiteralDecoder.GetDecoder(nowPos64, prevByte);
|
||||||
|
if not ULZMABase.StateIsCharState(state) then
|
||||||
|
prevByte := decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0))
|
||||||
|
else prevByte := decoder2.DecodeNormal(m_RangeDecoder);
|
||||||
|
m_OutWindow.PutByte(prevByte);
|
||||||
|
state := ULZMABase.StateUpdateChar(state);
|
||||||
|
inc(nowPos64);
|
||||||
|
end else begin
|
||||||
|
if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) = 1) then begin
|
||||||
|
len := 0;
|
||||||
|
if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) = 0) then begin
|
||||||
|
if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state shl ULZMABase.kNumPosStatesBitsMax) + posState) = 0) then begin
|
||||||
|
state := ULZMABase.StateUpdateShortRep(state);
|
||||||
|
len := 1;
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
if m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) = 0 then
|
||||||
|
distance := rep1
|
||||||
|
else begin
|
||||||
|
if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) = 0) then
|
||||||
|
distance := rep2
|
||||||
|
else begin
|
||||||
|
distance := rep3;
|
||||||
|
rep3 := rep2;
|
||||||
|
end;
|
||||||
|
rep2 := rep1;
|
||||||
|
end;
|
||||||
|
rep1 := rep0;
|
||||||
|
rep0 := distance;
|
||||||
|
end;
|
||||||
|
if len = 0 then begin
|
||||||
|
len := m_RepLenDecoder.Decode(m_RangeDecoder, posState) + ULZMABase.kMatchMinLen;
|
||||||
|
state := ULZMABase.StateUpdateRep(state);
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
rep3 := rep2;
|
||||||
|
rep2 := rep1;
|
||||||
|
rep1 := rep0;
|
||||||
|
len := ULZMABase.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
|
||||||
|
state := ULZMABase.StateUpdateMatch(state);
|
||||||
|
posSlot := m_PosSlotDecoder[ULZMABase.GetLenToPosState(len)].Decode(m_RangeDecoder);
|
||||||
|
if posSlot >= ULZMABase.kStartPosModelIndex then begin
|
||||||
|
numDirectBits := (posSlot shr 1) - 1;
|
||||||
|
rep0 := ((2 or (posSlot and 1)) shl numDirectBits);
|
||||||
|
if posSlot < ULZMABase.kEndPosModelIndex then
|
||||||
|
rep0 := rep0 + UBitTreeDecoder.ReverseDecode(m_PosDecoders,
|
||||||
|
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits)
|
||||||
|
else begin
|
||||||
|
rep0 := rep0 + (m_RangeDecoder.DecodeDirectBits(
|
||||||
|
numDirectBits - ULZMABase.kNumAlignBits) shl ULZMABase.kNumAlignBits);
|
||||||
|
rep0 := rep0 + m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
|
||||||
|
if rep0 < 0 then begin
|
||||||
|
if rep0 = -1 then
|
||||||
|
break;
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else rep0 := posSlot;
|
||||||
|
end;
|
||||||
|
if (rep0 >= nowPos64) or (rep0 >= m_DictionarySizeCheck) then begin
|
||||||
|
m_OutWindow.Flush();
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
m_OutWindow.CopyBlock(rep0, len);
|
||||||
|
nowPos64 := nowPos64 + len;
|
||||||
|
prevByte := m_OutWindow.GetByte(0);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
m_OutWindow.Flush();
|
||||||
|
m_OutWindow.ReleaseStream();
|
||||||
|
m_RangeDecoder.ReleaseStream();
|
||||||
|
DoProgress(LPAPos,nowPos64);
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZMADecoder.SetDecoderProperties(const properties:array of byte):boolean;
|
||||||
|
var val,lc,remainder,lp,pb,dictionarysize,i:integer;
|
||||||
|
begin
|
||||||
|
if length(properties) < 5 then begin
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
val := properties[0] and $FF;
|
||||||
|
lc := val mod 9;
|
||||||
|
remainder := val div 9;
|
||||||
|
lp := remainder mod 5;
|
||||||
|
pb := remainder div 5;
|
||||||
|
dictionarySize := 0;
|
||||||
|
for i := 0 to 3 do
|
||||||
|
dictionarySize := dictionarysize + ((properties[1 + i]) and $FF) shl (i * 8);
|
||||||
|
if (not SetLcLpPb(lc, lp, pb)) then begin
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result:=SetDictionarySize(dictionarySize);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZMADecoder.DoProgress(const Action:TLZMAProgressAction;const Value:integer);
|
||||||
|
begin
|
||||||
|
if assigned(fonprogress) then
|
||||||
|
fonprogress(action,value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
1518
Addons/ULZMAEncoder.pas
Normal file
1518
Addons/ULZMAEncoder.pas
Normal file
File diff suppressed because it is too large
Load Diff
107
Addons/ULZOutWindow.pas
Normal file
107
Addons/ULZOutWindow.pas
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
unit ULZOutWindow;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL;
|
||||||
|
|
||||||
|
type PLZOutWindow = ^TLZOutWindow;
|
||||||
|
TLZOutWindow=object(TObj)
|
||||||
|
public
|
||||||
|
buffer: array of byte;
|
||||||
|
pos:integer;
|
||||||
|
windowSize:integer;
|
||||||
|
streamPos:integer;
|
||||||
|
stream:PStream;
|
||||||
|
procedure _Create(const AwindowSize:integer);
|
||||||
|
procedure SetStream(const Astream:PStream);
|
||||||
|
procedure ReleaseStream;
|
||||||
|
procedure _Init(const Asolid:boolean);
|
||||||
|
procedure Flush;
|
||||||
|
procedure CopyBlock(const Adistance:integer; Alen:integer);
|
||||||
|
procedure PutByte(const Ab:byte);
|
||||||
|
function GetByte(const Adistance:integer):byte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure TLZOutWindow._Create(const AwindowSize:integer);
|
||||||
|
begin
|
||||||
|
if (length(buffer)=0) or (self.windowSize <> AwindowSize) then
|
||||||
|
setlength(buffer,AwindowSize);
|
||||||
|
self.windowSize := AwindowSize;
|
||||||
|
pos := 0;
|
||||||
|
streamPos := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow.SetStream(const Astream:PStream);
|
||||||
|
begin
|
||||||
|
ReleaseStream;
|
||||||
|
self.stream:=Astream;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow.ReleaseStream;
|
||||||
|
begin
|
||||||
|
flush;
|
||||||
|
self.stream:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow._Init(const Asolid:boolean);
|
||||||
|
begin
|
||||||
|
if not Asolid then begin
|
||||||
|
streamPos:=0;
|
||||||
|
Pos:=0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow.Flush;
|
||||||
|
var size:integer;
|
||||||
|
begin
|
||||||
|
size := pos - streamPos;
|
||||||
|
if (size = 0) then
|
||||||
|
exit;
|
||||||
|
stream.write(buffer[streamPos], size);
|
||||||
|
if (pos >= windowSize) then
|
||||||
|
pos := 0;
|
||||||
|
streamPos := pos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow.CopyBlock(const Adistance:integer;Alen:integer);
|
||||||
|
var _pos:integer;
|
||||||
|
begin
|
||||||
|
_pos := self.pos - Adistance - 1;
|
||||||
|
if _pos < 0 then
|
||||||
|
_pos := _pos + windowSize;
|
||||||
|
while Alen<>0 do begin
|
||||||
|
if _pos >= windowSize then
|
||||||
|
_pos := 0;
|
||||||
|
buffer[self.pos] := buffer[_pos];
|
||||||
|
inc(self.pos);
|
||||||
|
inc(_pos);
|
||||||
|
if self.pos >= windowSize then
|
||||||
|
Flush();
|
||||||
|
dec(Alen);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLZOutWindow.PutByte(const Ab:byte);
|
||||||
|
begin
|
||||||
|
buffer[pos] := Ab;
|
||||||
|
inc(pos);
|
||||||
|
if (pos >= windowSize) then
|
||||||
|
Flush();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLZOutWindow.GetByte(const Adistance:integer):byte;
|
||||||
|
var _pos:integer;
|
||||||
|
begin
|
||||||
|
_pos := self.pos - Adistance - 1;
|
||||||
|
if (_pos < 0) then
|
||||||
|
_pos := _pos + windowSize;
|
||||||
|
result:=buffer[_pos];
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
100
Addons/URangeDecoder.pas
Normal file
100
Addons/URangeDecoder.pas
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
unit URangeDecoder;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL,ULZMACommon;
|
||||||
|
|
||||||
|
type PRangeDecoder = ^TRangeDecoder;
|
||||||
|
TRangeDecoder=object(TObj)
|
||||||
|
public
|
||||||
|
Range,Code:integer;
|
||||||
|
Stream:PStream;
|
||||||
|
procedure SetStream(const AStream:PStream);
|
||||||
|
procedure ReleaseStream;
|
||||||
|
procedure _Init;
|
||||||
|
function DecodeDirectBits(const AnumTotalBits:integer):integer;
|
||||||
|
function DecodeBit(var Aprobs: array of smallint;const Aindex:integer):integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitBitModels(var Aprobs: array of smallint);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const kTopMask = not ((1 shl 24) - 1);
|
||||||
|
kNumBitModelTotalBits = 11;
|
||||||
|
kBitModelTotal = (1 shl kNumBitModelTotalBits);
|
||||||
|
kNumMoveBits = 5;
|
||||||
|
|
||||||
|
procedure TRangeDecoder.SetStream(const AStream:PStream);
|
||||||
|
begin
|
||||||
|
self.Stream:=AStream;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeDecoder.ReleaseStream;
|
||||||
|
begin
|
||||||
|
stream:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeDecoder._Init;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
code:=0;
|
||||||
|
Range:=-1;
|
||||||
|
for i:=0 to 4 do begin
|
||||||
|
code:=(code shl 8) or byte(ReadByte(stream));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeDecoder.DecodeDirectBits(const AnumTotalBits:integer):integer;
|
||||||
|
var i,t:integer;
|
||||||
|
begin
|
||||||
|
result:=0;
|
||||||
|
for i := AnumTotalBits downto 1 do begin
|
||||||
|
range:=range shr 1;
|
||||||
|
t := ((Code - Range) shr 31);
|
||||||
|
Code := Code - Range and (t - 1);
|
||||||
|
result := (result shl 1) or (1 - t);
|
||||||
|
if ((Range and kTopMask) = 0) then begin
|
||||||
|
Code := (Code shl 8) or ReadByte(stream);
|
||||||
|
Range := Range shl 8;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeDecoder.DecodeBit(var Aprobs: array of smallint;const Aindex:integer):integer;
|
||||||
|
var prob,newbound:integer;
|
||||||
|
begin
|
||||||
|
prob:=Aprobs[Aindex];
|
||||||
|
newbound:=(Range shr kNumBitModelTotalBits) * prob;
|
||||||
|
if (integer((integer(Code) xor integer($80000000))) < integer((integer(newBound) xor integer($80000000)))) then begin
|
||||||
|
Range := newBound;
|
||||||
|
Aprobs[Aindex] := (prob + ((kBitModelTotal - prob) shr kNumMoveBits));
|
||||||
|
if ((Range and kTopMask) = 0) then begin
|
||||||
|
Code := (Code shl 8) or ReadByte(stream);
|
||||||
|
Range := Range shl 8;
|
||||||
|
end;
|
||||||
|
result:=0;
|
||||||
|
end else begin
|
||||||
|
Range := Range - newBound;
|
||||||
|
Code := Code - newBound;
|
||||||
|
Aprobs[Aindex] := (prob - ((prob) shr kNumMoveBits));
|
||||||
|
if ((Range and kTopMask) = 0) then begin
|
||||||
|
Code := (Code shl 8) or ReadByte(stream);
|
||||||
|
Range := Range shl 8;
|
||||||
|
end;
|
||||||
|
result:=1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitBitModels(var Aprobs: array of smallint);
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to length(Aprobs)-1 do
|
||||||
|
Aprobs[i] := kBitModelTotal shr 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
175
Addons/URangeEncoder.pas
Normal file
175
Addons/URangeEncoder.pas
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
unit URangeEncoder;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses KOL,ULZMACommon;
|
||||||
|
|
||||||
|
const kNumBitPriceShiftBits = 6;
|
||||||
|
kTopMask = not ((1 shl 24) - 1);
|
||||||
|
kNumBitModelTotalBits = 11;
|
||||||
|
kBitModelTotal = (1 shl kNumBitModelTotalBits);
|
||||||
|
kNumMoveBits = 5;
|
||||||
|
kNumMoveReducingBits = 2;
|
||||||
|
|
||||||
|
type PRangeEncoder = ^TRangeEncoder;
|
||||||
|
TRangeEncoder=object(TObj)
|
||||||
|
private
|
||||||
|
ProbPrices: array [0..kBitModelTotal shr kNumMoveReducingBits-1] of integer;
|
||||||
|
public
|
||||||
|
Stream:PStream;
|
||||||
|
Low,Position:int64;
|
||||||
|
Range,cacheSize,cache:integer;
|
||||||
|
procedure SetStream(const Astream:PStream);
|
||||||
|
procedure ReleaseStream;
|
||||||
|
procedure _Init;
|
||||||
|
procedure FlushData;
|
||||||
|
procedure FlushStream;
|
||||||
|
procedure ShiftLow;
|
||||||
|
procedure EncodeDirectBits(const v,AnumTotalBits:integer);
|
||||||
|
function GetProcessedSizeAdd:int64;
|
||||||
|
procedure Encode(var Aprobs: array of smallint;const Aindex,Asymbol:integer);
|
||||||
|
constructor Create;
|
||||||
|
function GetPrice(const AProb,Asymbol:integer):integer;
|
||||||
|
function GetPrice0(const AProb:integer):integer;
|
||||||
|
function GetPrice1(const AProb:integer):integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var RangeEncoder:PRangeEncoder;
|
||||||
|
|
||||||
|
procedure InitBitModels(var probs:array of smallint);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure TRangeEncoder.SetStream(const Astream:PStream);
|
||||||
|
begin
|
||||||
|
self.Stream:=AStream;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.ReleaseStream;
|
||||||
|
begin
|
||||||
|
stream:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder._Init;
|
||||||
|
begin
|
||||||
|
position := 0;
|
||||||
|
Low := 0;
|
||||||
|
Range := -1;
|
||||||
|
cacheSize := 1;
|
||||||
|
cache := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.FlushData;
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to 4 do
|
||||||
|
ShiftLow();
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.FlushStream;
|
||||||
|
begin
|
||||||
|
//stream.flush;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.ShiftLow;
|
||||||
|
var LowHi:integer;
|
||||||
|
temp:integer;
|
||||||
|
begin
|
||||||
|
LowHi := (Low shr 32);
|
||||||
|
if (LowHi <> 0) or (Low < int64($FF000000)) then begin
|
||||||
|
position := position + cacheSize;
|
||||||
|
temp := cache;
|
||||||
|
repeat
|
||||||
|
WriteByte(stream,temp + LowHi);
|
||||||
|
temp := $FF;
|
||||||
|
dec(cacheSize);
|
||||||
|
until(cacheSize = 0);
|
||||||
|
cache := (Low shr 24);
|
||||||
|
end;
|
||||||
|
inc(cacheSize);
|
||||||
|
Low := (Low and integer($FFFFFF)) shl 8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.EncodeDirectBits(const v,AnumTotalBits:integer);
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i := AnumTotalBits - 1 downto 0 do begin
|
||||||
|
Range := Range shr 1;
|
||||||
|
if (((v shr i) and 1) = 1) then
|
||||||
|
Low := Low + Range;
|
||||||
|
if ((Range and kTopMask) = 0) then begin
|
||||||
|
Range := range shl 8;
|
||||||
|
ShiftLow;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeEncoder.GetProcessedSizeAdd:int64;
|
||||||
|
begin
|
||||||
|
result:=cacheSize + position + 4;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitBitModels(var probs:array of smallint);
|
||||||
|
var i:integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to length(probs) -1 do
|
||||||
|
probs[i] := kBitModelTotal shr 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRangeEncoder.Encode(var Aprobs: array of smallint;const Aindex,Asymbol:integer);
|
||||||
|
var prob,newbound:integer;
|
||||||
|
begin
|
||||||
|
prob := Aprobs[Aindex];
|
||||||
|
newBound := (Range shr kNumBitModelTotalBits) * prob;
|
||||||
|
if (Asymbol = 0) then begin
|
||||||
|
Range := newBound;
|
||||||
|
Aprobs[Aindex] := (prob + ((kBitModelTotal - prob) shr kNumMoveBits));
|
||||||
|
end else begin
|
||||||
|
Low := Low + (newBound and int64($FFFFFFFF));
|
||||||
|
Range := Range - newBound;
|
||||||
|
Aprobs[Aindex] := (prob - ((prob) shr kNumMoveBits));
|
||||||
|
end;
|
||||||
|
if ((Range and kTopMask) = 0) then begin
|
||||||
|
Range := Range shl 8;
|
||||||
|
ShiftLow;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TRangeEncoder.Create;
|
||||||
|
var kNumBits:integer;
|
||||||
|
i,j,start,_end:integer;
|
||||||
|
begin
|
||||||
|
kNumBits := (kNumBitModelTotalBits - kNumMoveReducingBits);
|
||||||
|
for i := kNumBits - 1 downto 0 do begin
|
||||||
|
start := 1 shl (kNumBits - i - 1);
|
||||||
|
_end := 1 shl (kNumBits - i);
|
||||||
|
for j := start to _end -1 do
|
||||||
|
ProbPrices[j] := (i shl kNumBitPriceShiftBits) +
|
||||||
|
(((_end - j) shl kNumBitPriceShiftBits) shr (kNumBits - i - 1));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeEncoder.GetPrice(const AProb,Asymbol:integer):integer;
|
||||||
|
begin
|
||||||
|
result:=ProbPrices[(((AProb - Asymbol) xor ((-Asymbol))) and (kBitModelTotal - 1)) shr kNumMoveReducingBits];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeEncoder.GetPrice0(const AProb:integer):integer;
|
||||||
|
begin
|
||||||
|
result:= ProbPrices[AProb shr kNumMoveReducingBits];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRangeEncoder.GetPrice1(const AProb:integer):integer;
|
||||||
|
begin
|
||||||
|
result:= ProbPrices[(kBitModelTotal - AProb) shr kNumMoveReducingBits];
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
New(RangeEncoder, Create);
|
||||||
|
finalization
|
||||||
|
RangeEncoder.Free;
|
||||||
|
end.
|
1017
Addons/bis.pas
Normal file
1017
Addons/bis.pas
Normal file
File diff suppressed because it is too large
Load Diff
297
Addons/mckWebBrowser.pas
Normal file
297
Addons/mckWebBrowser.pas
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// TKOLWebBrowser v1.0 //
|
||||||
|
// //
|
||||||
|
// Author: Dimaxx (dimaxx@atnet.ru) //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
unit mckWebBrowser;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Classes, Kol, Mirror;
|
||||||
|
|
||||||
|
type
|
||||||
|
TWebBrowserStatusTextChange = procedure(Sender: TObject; const Text: WideString) of object;
|
||||||
|
TWebBrowserProgressChange = procedure(Sender: TObject; Progress: Integer; ProgressMax: Integer) of object;
|
||||||
|
TWebBrowserCommandStateChange = procedure(Sender: TObject; Command: Integer; Enable: WordBool) of object;
|
||||||
|
TWebBrowserTitleChange = procedure(Sender: TObject; const Text: WideString) of object;
|
||||||
|
TWebBrowserPropertyChange = procedure(Sender: TObject; const szProperty: WideString) of object;
|
||||||
|
TWebBrowserBeforeNavigate2 = procedure(Sender: TObject; const pDisp: IDispatch;
|
||||||
|
var URL: OleVariant;
|
||||||
|
var Flags: OleVariant;
|
||||||
|
var TargetFrameName: OleVariant;
|
||||||
|
var PostData: OleVariant;
|
||||||
|
var Headers: OleVariant;
|
||||||
|
var Cancel: WordBool) of object;
|
||||||
|
TWebBrowserNewWindow2 = procedure(Sender: TObject; var ppDisp: IDispatch; var Cancel: WordBool) of object;
|
||||||
|
TWebBrowserNavigateComplete2 = procedure(Sender: TObject; const pDisp: IDispatch;
|
||||||
|
var URL: OleVariant) of object;
|
||||||
|
TWebBrowserDocumentComplete = procedure(Sender: TObject; const pDisp: IDispatch;
|
||||||
|
var URL: OleVariant) of object;
|
||||||
|
TWebBrowserOnVisible = procedure(Sender: TObject; Visible: WordBool) of object;
|
||||||
|
TWebBrowserOnToolBar = procedure(Sender: TObject; ToolBar: WordBool) of object;
|
||||||
|
TWebBrowserOnMenuBar = procedure(Sender: TObject; MenuBar: WordBool) of object;
|
||||||
|
TWebBrowserOnStatusBar = procedure(Sender: TObject; StatusBar: WordBool) of object;
|
||||||
|
TWebBrowserOnFullScreen = procedure(Sender: TObject; FullScreen: WordBool) of object;
|
||||||
|
TWebBrowserOnTheaterMode = procedure(Sender: TObject; TheaterMode: WordBool) of object;
|
||||||
|
|
||||||
|
TKOLWebBrowser = class(TKOLCustomControl)
|
||||||
|
private
|
||||||
|
FOnStatusTextChange: TWebBrowserStatusTextChange;
|
||||||
|
FOnProgressChange: TWebBrowserProgressChange;
|
||||||
|
FOnCommandStateChange: TWebBrowserCommandStateChange;
|
||||||
|
FOnTitleChange: TWebBrowserTitleChange;
|
||||||
|
FOnPropertyChange: TWebBrowserPropertyChange;
|
||||||
|
FOnBeforeNavigate2: TWebBrowserBeforeNavigate2;
|
||||||
|
FOnNewWindow2: TWebBrowserNewWindow2;
|
||||||
|
FOnNavigateComplete2: TWebBrowserNavigateComplete2;
|
||||||
|
FOnDocumentComplete: TWebBrowserDocumentComplete;
|
||||||
|
FOnVisible: TWebBrowserOnVisible;
|
||||||
|
FOnToolBar: TWebBrowserOnToolBar;
|
||||||
|
FOnMenuBar: TWebBrowserOnMenuBar;
|
||||||
|
FOnStatusBar: TWebBrowserOnStatusBar;
|
||||||
|
FOnFullScreen: TWebBrowserOnFullScreen;
|
||||||
|
FOnTheaterMode: TWebBrowserOnTheaterMode;
|
||||||
|
|
||||||
|
FOffline: boolean;
|
||||||
|
FSilent: boolean;
|
||||||
|
FRegisterAsBrowser: boolean;
|
||||||
|
FRegisterAsDropTarget: boolean;
|
||||||
|
protected
|
||||||
|
function AdditionalUnits: string; override;
|
||||||
|
procedure SetupFirst(SL: TStringList; const AName,AParent,Prefix: string); override;
|
||||||
|
procedure AssignEvents(SL: TStringList; const AName: string); override;
|
||||||
|
procedure SetOnStatusTextChange(E: TWebBrowserStatusTextChange);
|
||||||
|
procedure SetOnProgressChange(E: TWebBrowserProgressChange);
|
||||||
|
procedure SetOnCommandStateChange(E: TWebBrowserCommandStateChange);
|
||||||
|
procedure SetOnTitleChange(E: TWebBrowserTitleChange);
|
||||||
|
procedure SetOnPropertyChange(E: TWebBrowserPropertyChange);
|
||||||
|
procedure SetOnBeforeNavigate2(E: TWebBrowserBeforeNavigate2);
|
||||||
|
procedure SetOnNewWindow2(E: TWebBrowserNewWindow2);
|
||||||
|
procedure SetOnNavigateComplete2(E: TWebBrowserNavigateComplete2);
|
||||||
|
procedure SetOnDocumentComplete(E: TWebBrowserDocumentComplete);
|
||||||
|
procedure SetOnVisible(E: TWebBrowserOnVisible);
|
||||||
|
procedure SetOnToolBar(E: TWebBrowserOnToolBar);
|
||||||
|
procedure SetOnMenuBar(E: TWebBrowserOnMenuBar);
|
||||||
|
procedure SetOnStatusBar(E: TWebBrowserOnStatusBar);
|
||||||
|
procedure SetOnFullScreen(E: TWebBrowserOnFullScreen);
|
||||||
|
procedure SetOnTheaterMode(E: TWebBrowserOnTheaterMode);
|
||||||
|
|
||||||
|
procedure SetOffline(V: boolean);
|
||||||
|
procedure SetSilent(V: boolean);
|
||||||
|
procedure SetRegisterAsBrowser(V: boolean);
|
||||||
|
procedure SetRegisterAsDropTarget(V: boolean);
|
||||||
|
public
|
||||||
|
constructor Create(AOwner: TComponent); override;
|
||||||
|
published
|
||||||
|
property Align;
|
||||||
|
property Visible;
|
||||||
|
property TabStop;
|
||||||
|
property TabOrder;
|
||||||
|
property OnEnter;
|
||||||
|
property OnExit;
|
||||||
|
|
||||||
|
property Offline: boolean read FOffline write SetOffline default True;
|
||||||
|
property Silent: boolean read FSilent write SetSilent default False;
|
||||||
|
property RegisterAsBrowser: boolean read FRegisterAsBrowser write SetRegisterAsBrowser default True;
|
||||||
|
property RegisterAsDropTarget: boolean read FRegisterAsDropTarget write SetRegisterAsDropTarget default False;
|
||||||
|
|
||||||
|
property OnStatusTextChange: TWebBrowserStatusTextChange read FOnStatusTextChange write SetOnStatusTextChange;
|
||||||
|
property OnProgressChange: TWebBrowserProgressChange read FOnProgressChange write SetOnProgressChange;
|
||||||
|
property OnCommandStateChange: TWebBrowserCommandStateChange read FOnCommandStateChange write SetOnCommandStateChange;
|
||||||
|
property OnTitleChange: TWebBrowserTitleChange read FOnTitleChange write SetOnTitleChange;
|
||||||
|
property OnPropertyChange: TWebBrowserPropertyChange read FOnPropertyChange write SetOnPropertyChange;
|
||||||
|
property OnBeforeNavigate2: TWebBrowserBeforeNavigate2 read FOnBeforeNavigate2 write SetOnBeforeNavigate2;
|
||||||
|
property OnNewWindow2: TWebBrowserNewWindow2 read FOnNewWindow2 write SetOnNewWindow2;
|
||||||
|
property OnNavigateComplete2: TWebBrowserNavigateComplete2 read FOnNavigateComplete2 write SetOnNavigateComplete2;
|
||||||
|
property OnDocumentComplete: TWebBrowserDocumentComplete read FOnDocumentComplete write SetOnDocumentComplete;
|
||||||
|
property OnVisible: TWebBrowserOnVisible read FOnVisible write SetOnVisible;
|
||||||
|
property OnToolBar: TWebBrowserOnToolBar read FOnToolBar write SetOnToolBar;
|
||||||
|
property OnMenuBar: TWebBrowserOnMenuBar read FOnMenuBar write SetOnMenuBar;
|
||||||
|
property OnStatusBar: TWebBrowserOnStatusBar read FOnStatusBar write SetOnStatusBar;
|
||||||
|
property OnFullScreen: TWebBrowserOnFullScreen read FOnFullScreen write SetOnFullScreen;
|
||||||
|
property OnTheaterMode: TWebBrowserOnTheaterMode read FOnTheaterMode write SetOnTheaterMode;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Register;
|
||||||
|
|
||||||
|
{$R *.dcr}
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
AlignValues: array[TKOLAlign] of string = ('caNone','caLeft','caTop','caRight','caBottom','caClient');
|
||||||
|
Bool2Str: array [Boolean] of string = ('False','True');
|
||||||
|
|
||||||
|
procedure Register;
|
||||||
|
begin
|
||||||
|
RegisterComponents('KOLAddons',[TKOLWebBrowser]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TKOLWebBrowser.Create;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
FOffline:=True;
|
||||||
|
FSilent:=True;
|
||||||
|
FRegisterAsBrowser:=True;
|
||||||
|
FRegisterAsDropTarget:=False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKOLWebBrowser.AdditionalUnits;
|
||||||
|
begin
|
||||||
|
Result:=', KOLWebBrowser';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetupFirst;
|
||||||
|
begin
|
||||||
|
SL.Add(Prefix+AName+' := NewKOLWebBrowser(Result.Form); ');
|
||||||
|
if Align<>caNone then
|
||||||
|
begin
|
||||||
|
SL.Add(Prefix+AName+'.SetAlign( '+AlignValues[Align]+'); ');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
SL.Add(Prefix+AName+'.SetPosition(' +int2str(Left)+', '+int2str(Top)+' );');
|
||||||
|
SL.Add(Prefix+AName+'.SetSize(' +int2str(Width)+', '+int2str(Height)+' );');
|
||||||
|
end;
|
||||||
|
SL.Add(Prefix+AName+'.Offline := '+Bool2Str[FOffline]+';');
|
||||||
|
SL.Add(Prefix+AName+'.Silent := '+Bool2Str[FSilent]+';');
|
||||||
|
SL.Add(Prefix+AName+'.RegisterAsBrowser := '+Bool2Str[FRegisterAsBrowser]+';');
|
||||||
|
SL.Add(Prefix+AName+'.RegisterAsDropTarget := '+Bool2Str[FRegisterAsDropTarget]+';');
|
||||||
|
AssignEvents(SL,AName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.AssignEvents;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
DoAssignEvents(SL,AName,
|
||||||
|
['OnStatusTextChange','OnProgressChange','OnCommandStateChange',
|
||||||
|
'OnTitleChange','OnPropertyChange','OnBeforeNavigate2','OnNewWindow2',
|
||||||
|
'OnNavigateComplete2','OnDocumentComplete','OnVisible','OnToolBar',
|
||||||
|
'OnMenuBar','OnStatusBar','OnFullScreen','OnTheaterMode'],
|
||||||
|
[@OnStatusTextChange,@OnProgressChange,@OnCommandStateChange,
|
||||||
|
@OnTitleChange,@OnPropertyChange,@OnBeforeNavigate2,@OnNewWindow2,
|
||||||
|
@OnNavigateComplete2,@OnDocumentComplete,@OnVisible,@OnToolBar,
|
||||||
|
@OnMenuBar,@OnStatusBar,@OnFullScreen,@OnTheaterMode]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOffline;
|
||||||
|
begin
|
||||||
|
FOffline:=V;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetSilent;
|
||||||
|
begin
|
||||||
|
FSilent:=V;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetRegisterAsBrowser;
|
||||||
|
begin
|
||||||
|
FRegisterAsBrowser:=V;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetRegisterAsDropTarget;
|
||||||
|
begin
|
||||||
|
FRegisterAsDropTarget:=V;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnStatusTextChange;
|
||||||
|
begin
|
||||||
|
FOnStatusTextChange:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnProgressChange;
|
||||||
|
begin
|
||||||
|
FOnProgressChange:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnCommandStateChange;
|
||||||
|
begin
|
||||||
|
FOnCommandStateChange:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnTitleChange;
|
||||||
|
begin
|
||||||
|
FOnTitleChange:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnPropertyChange;
|
||||||
|
begin
|
||||||
|
FOnPropertyChange:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnBeforeNavigate2;
|
||||||
|
begin
|
||||||
|
FOnBeforeNavigate2:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnNewWindow2;
|
||||||
|
begin
|
||||||
|
FOnNewWindow2:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnNavigateComplete2;
|
||||||
|
begin
|
||||||
|
FOnNavigateComplete2:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnDocumentComplete;
|
||||||
|
begin
|
||||||
|
FOnDocumentComplete:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnVisible;
|
||||||
|
begin
|
||||||
|
FOnVisible:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnToolBar;
|
||||||
|
begin
|
||||||
|
FOnToolBar:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnMenuBar;
|
||||||
|
begin
|
||||||
|
FOnMenuBar:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnStatusBar;
|
||||||
|
begin
|
||||||
|
FOnStatusBar:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnFullScreen;
|
||||||
|
begin
|
||||||
|
FOnFullScreen:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TKOLWebBrowser.SetOnTheaterMode;
|
||||||
|
begin
|
||||||
|
FOnTheaterMode:=E;
|
||||||
|
Change;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
Reference in New Issue
Block a user