initial import
authorplugwash <plugwash@p10link.net>
Sun, 13 Apr 2008 19:38:04 +0000 (19:38 +0000)
committerplugwash <plugwash@p10link.net>
Sun, 13 Apr 2008 19:38:04 +0000 (19:38 +0000)
git-svn-id: file:///svnroot/pngwrite/trunk@1 6a9b5287-1b79-473c-b86d-0ef8b3f8a584

27 files changed:
Project1.dof [new file with mode: 0755]
Project1.dpr [new file with mode: 0755]
Project1.res [new file with mode: 0755]
Unit1.dfm [new file with mode: 0644]
Unit1.pas [new file with mode: 0644]
adler.pas [new file with mode: 0755]
drawheart.dof [new file with mode: 0755]
drawheart.dpr [new file with mode: 0755]
drawheart.res [new file with mode: 0755]
graphdraw.dpr [new file with mode: 0644]
graphdraw.res [new file with mode: 0755]
graphdrawu.dfm [new file with mode: 0644]
graphdrawu.pas [new file with mode: 0644]
pgtypes.pas [new file with mode: 0755]
pngwrite.pas [new file with mode: 0755]
pngwritetbitmap.pas [new file with mode: 0644]
readme.paszlib [new file with mode: 0755]
spritepalpng.dof [new file with mode: 0755]
spritepalpng.res [new file with mode: 0755]
svn-commit.tmp [new file with mode: 0644]
trees.pas [new file with mode: 0755]
uint32.inc [new file with mode: 0755]
zconf.inc [new file with mode: 0755]
zdeflate.pas [new file with mode: 0755]
zinflate.pas [new file with mode: 0755]
zlib.pas [new file with mode: 0755]
zutil.pas [new file with mode: 0755]

diff --git a/Project1.dof b/Project1.dof
new file mode 100755 (executable)
index 0000000..7d0efc2
--- /dev/null
@@ -0,0 +1,75 @@
+[Compiler]\r
+A=1\r
+B=0\r
+C=1\r
+D=1\r
+E=0\r
+F=0\r
+G=1\r
+H=1\r
+I=1\r
+J=1\r
+K=0\r
+L=1\r
+M=0\r
+N=1\r
+O=1\r
+P=1\r
+Q=0\r
+R=0\r
+S=0\r
+T=0\r
+U=0\r
+V=1\r
+W=0\r
+X=1\r
+Y=0\r
+Z=1\r
+ShowHints=1\r
+ShowWarnings=1\r
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;\r
+[Linker]\r
+MapFile=0\r
+OutputObjs=0\r
+ConsoleApp=1\r
+DebugInfo=0\r
+MinStackSize=16384\r
+MaxStackSize=1048576\r
+ImageBase=4194304\r
+ExeDescription=\r
+[Directories]\r
+OutputDir=\r
+UnitOutputDir=\r
+SearchPath=\r
+Packages=\r
+Conditionals=\r
+DebugSourceDirs=\r
+UsePackages=0\r
+[Parameters]\r
+RunParams=\r
+HostApplication=\r
+[Version Info]\r
+IncludeVerInfo=0\r
+AutoIncBuild=0\r
+MajorVer=1\r
+MinorVer=0\r
+Release=0\r
+Build=0\r
+Debug=0\r
+PreRelease=0\r
+Special=0\r
+Private=0\r
+DLL=0\r
+Locale=2057\r
+CodePage=1252\r
+[Version Info Keys]\r
+CompanyName=\r
+FileDescription=\r
+FileVersion=1.0.0.0\r
+InternalName=\r
+LegalCopyright=\r
+LegalTrademarks=\r
+OriginalFilename=\r
+ProductName=\r
+ProductVersion=1.0.0.0\r
+Comments=\r
diff --git a/Project1.dpr b/Project1.dpr
new file mode 100755 (executable)
index 0000000..5804582
--- /dev/null
@@ -0,0 +1,14 @@
+program Project1;\r
+\r
+uses\r
+  Forms,\r
+  Unit1 in 'Unit1.pas' {Form1},\r
+  pngwrite in 'pngwrite.pas';\r
+\r
+{$R *.RES}\r
+\r
+begin\r
+  Application.Initialize;\r
+  Application.CreateForm(TForm1, Form1);\r
+  Application.Run;\r
+end.\r
diff --git a/Project1.res b/Project1.res
new file mode 100755 (executable)
index 0000000..35c50c8
Binary files /dev/null and b/Project1.res differ
diff --git a/Unit1.dfm b/Unit1.dfm
new file mode 100644 (file)
index 0000000..bebf29e
Binary files /dev/null and b/Unit1.dfm differ
diff --git a/Unit1.pas b/Unit1.pas
new file mode 100644 (file)
index 0000000..b64e7bd
--- /dev/null
+++ b/Unit1.pas
@@ -0,0 +1,121 @@
+//demo code that lets the user draw an image and then save it to a png file\r
+\r
+{ Copyright (C) 2005 Bas Steendijk and Peter Green\r
+  For conditions of distribution and use, see copyright notice in zlib_license.txt\r
+    which is included in the package\r
+      ----------------------------------------------------------------------------- }\r
+\r
+unit Unit1;\r
+\r
+interface\r
+\r
+uses\r
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,\r
+  ExtCtrls, ColorGrd, StdCtrls;\r
+\r
+type\r
+  TForm1 = class(TForm)\r
+    Shape1: TShape;\r
+    ColorGrid1: TColorGrid;\r
+    Image1: TImage;\r
+    Button1: TButton;\r
+    procedure FormCreate(Sender: TObject);\r
+    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;\r
+      Shift: TShiftState; X, Y: Integer);\r
+    procedure Button1Click(Sender: TObject);\r
+  private\r
+    { Private declarations }\r
+  public\r
+    { Public declarations }\r
+  end;\r
+\r
+var\r
+  Form1: TForm1;\r
+\r
+implementation\r
+uses\r
+  pngwrite;\r
+{$R *.DFM}\r
+type\r
+  tshapesline = array [0..0] of tshape;\r
+  pshapesline = ^tshapesline;\r
+  tshapes = array [0..0] of pshapesline;\r
+  pshapes = ^tshapes;\r
+var\r
+  shapes : pshapes;\r
+  maxline,maxcol : integer;\r
+  procedure TForm1.FormCreate(Sender: TObject);\r
+var\r
+  line,col : integer;\r
+\r
+begin\r
+  maxline := 31;\r
+  maxcol := 63;\r
+  image1.Height := maxline+1;\r
+  image1.Width := maxcol+1;\r
+  Image1.Picture.Bitmap.PixelFormat := pf24bit;\r
+  image1.Picture.Bitmap.Height := maxline+1;\r
+  image1.Picture.Bitmap.Width := maxcol+1;\r
+\r
+\r
+  shapes := allocmem((maxline+1)*sizeof(tshape));\r
+  for line := 0 to maxline do begin\r
+    shapes[line] := allocmem((maxcol+1)*sizeof(pshapesline));\r
+    for col := 0 to maxcol do begin\r
+      if (line=0) and (col=0) then begin\r
+        shapes[0][0] := shape1;\r
+      end else begin\r
+        shapes[line][col] := tshape.create(self);\r
+        shapes[line][col].parent := self;\r
+        shapes[line][col].width := shape1.Width;\r
+        shapes[line][col].height := shape1.Width;\r
+        shapes[line][col].left := shape1.left+(shape1.width-1)*col;\r
+        shapes[line][col].top := shape1.top+(shape1.height-1)*line;\r
+        shapes[line][col].OnMouseDown := shape1.OnMouseDown;\r
+        shapes[line][col].tag := line + (col shl 16);\r
+      end;\r
+    end;\r
+  end;\r
+end;\r
+type\r
+  tlinedata = array[0..0] of byte;\r
+  plinedata = ^tlinedata;\r
+procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;\r
+  Shift: TShiftState; X, Y: Integer);\r
+var\r
+  line : integer;\r
+  col : integer;\r
+  linedata : plinedata;\r
+begin\r
+  tshape(sender).Brush.Color := ColorGrid1.ForegroundColor;\r
+  line := tshape(sender).tag and $FFFF;\r
+  col := tshape(sender).tag shr 16;\r
+  linedata := image1.Picture.Bitmap.scanline[line];\r
+  linedata[(col*3)+2] := tshape(sender).brush.color;\r
+  linedata[(col*3)+1] := tshape(sender).brush.color shr 8;\r
+  linedata[(col*3)  ] := tshape(sender).brush.color shr 16;\r
+  //showmessage(inttostr(linedata[(col*3)  ])); \r
+  image1.invalidate;\r
+end;\r
+\r
+procedure TForm1.Button1Click(Sender: TObject);\r
+var\r
+  stream : tfilestream;\r
+  f      : tpngwrite;\r
+  counter : integer;\r
+begin\r
+  stream := tfilestream.Create('test243.png',fmCreate{fmOpenWrite} or fmShareDenyNone  );\r
+  try\r
+    pngstart(f,stream,24,ctbgr,image1.picture.Bitmap.Height,image1.Picture.Bitmap.Width);\r
+    pngstartdata(f);\r
+    for counter := 0 to image1.picture.Bitmap.Height-1 do begin\r
+      pngwritescanline(f,image1.picture.Bitmap.scanline[counter]);\r
+    end;\r
+    pngfinishdata(f);\r
+    pngfinish(f);\r
+  finally\r
+    stream.Free;\r
+  end;\r
+end;\r
+\r
+end.\r
diff --git a/adler.pas b/adler.pas
new file mode 100755 (executable)
index 0000000..096d191
--- /dev/null
+++ b/adler.pas
@@ -0,0 +1,114 @@
+Unit Adler;\r
+\r
+{\r
+  adler32.c -- compute the Adler-32 checksum of a data stream\r
+  Copyright (C) 1995-1998 Mark Adler\r
+\r
+  Pascal tranlastion\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.paszlib\r
+}\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+uses\r
+  zutil;\r
+\r
+function adler32(adler : uLong; buf : pBytef; len : uInt) : uLong;\r
+\r
+{    Update a running Adler-32 checksum with the bytes buf[0..len-1] and\r
+   return the updated checksum. If buf is NIL, this function returns\r
+   the required initial value for the checksum.\r
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed\r
+   much faster. Usage example:\r
+\r
+   var\r
+     adler : uLong;\r
+   begin\r
+     adler := adler32(0, Z_NULL, 0);\r
+\r
+     while (read_buffer(buffer, length) <> EOF) do\r
+       adler := adler32(adler, buffer, length);\r
+\r
+     if (adler <> original_adler) then\r
+       error();\r
+   end;\r
+}\r
+\r
+implementation\r
+\r
+const\r
+  BASE = uLong(65521); { largest prime smaller than 65536 }\r
+  {NMAX = 5552; original code with unsigned 32 bit integer }\r
+  { NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 }\r
+  NMAX = 3854;        { code with signed 32 bit integer }\r
+  { NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1 }\r
+  { The penalty is the time loss in the extra MOD-calls. }\r
+\r
+\r
+{ ========================================================================= }\r
+\r
+function adler32(adler : uLong; buf : pBytef; len : uInt) : uLong;\r
+var\r
+  s1, s2 : uLong;\r
+  k : int;\r
+begin\r
+  s1 := adler and $ffff;\r
+  s2 := (adler shr 16) and $ffff;\r
+\r
+  if not Assigned(buf) then\r
+  begin\r
+    adler32 := uLong(1);\r
+    exit;\r
+  end;\r
+\r
+  while (len > 0) do\r
+  begin\r
+    if len < NMAX then\r
+      k := len\r
+    else\r
+      k := NMAX;\r
+    Dec(len, k);\r
+    {\r
+    while (k >= 16) do\r
+    begin\r
+      DO16(buf);\r
+      Inc(buf, 16);\r
+      Dec(k, 16);\r
+    end;\r
+    if (k <> 0) then\r
+    repeat\r
+      Inc(s1, buf^);\r
+      Inc(puf);\r
+      Inc(s2, s1);\r
+      Dec(k);\r
+    until (k = 0);\r
+    }\r
+    while (k > 0) do\r
+    begin\r
+      Inc(s1, buf^);\r
+      Inc(s2, s1);\r
+      Inc(buf);\r
+      Dec(k);\r
+    end;\r
+    s1 := s1 mod BASE;\r
+    s2 := s2 mod BASE;\r
+  end;\r
+  adler32 := (s2 shl 16) or s1;\r
+end;\r
+\r
+{\r
+#define DO1(buf,i)\r
+  begin\r
+    Inc(s1, buf[i]);\r
+    Inc(s2, s1);\r
+  end;\r
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);\r
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);\r
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);\r
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);\r
+}\r
+end.\r
+\r
diff --git a/drawheart.dof b/drawheart.dof
new file mode 100755 (executable)
index 0000000..7d0efc2
--- /dev/null
@@ -0,0 +1,75 @@
+[Compiler]\r
+A=1\r
+B=0\r
+C=1\r
+D=1\r
+E=0\r
+F=0\r
+G=1\r
+H=1\r
+I=1\r
+J=1\r
+K=0\r
+L=1\r
+M=0\r
+N=1\r
+O=1\r
+P=1\r
+Q=0\r
+R=0\r
+S=0\r
+T=0\r
+U=0\r
+V=1\r
+W=0\r
+X=1\r
+Y=0\r
+Z=1\r
+ShowHints=1\r
+ShowWarnings=1\r
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;\r
+[Linker]\r
+MapFile=0\r
+OutputObjs=0\r
+ConsoleApp=1\r
+DebugInfo=0\r
+MinStackSize=16384\r
+MaxStackSize=1048576\r
+ImageBase=4194304\r
+ExeDescription=\r
+[Directories]\r
+OutputDir=\r
+UnitOutputDir=\r
+SearchPath=\r
+Packages=\r
+Conditionals=\r
+DebugSourceDirs=\r
+UsePackages=0\r
+[Parameters]\r
+RunParams=\r
+HostApplication=\r
+[Version Info]\r
+IncludeVerInfo=0\r
+AutoIncBuild=0\r
+MajorVer=1\r
+MinorVer=0\r
+Release=0\r
+Build=0\r
+Debug=0\r
+PreRelease=0\r
+Special=0\r
+Private=0\r
+DLL=0\r
+Locale=2057\r
+CodePage=1252\r
+[Version Info Keys]\r
+CompanyName=\r
+FileDescription=\r
+FileVersion=1.0.0.0\r
+InternalName=\r
+LegalCopyright=\r
+LegalTrademarks=\r
+OriginalFilename=\r
+ProductName=\r
+ProductVersion=1.0.0.0\r
+Comments=\r
diff --git a/drawheart.dpr b/drawheart.dpr
new file mode 100755 (executable)
index 0000000..4f01339
--- /dev/null
@@ -0,0 +1,47 @@
+//test program for png code, uses ct8bp mode to draw a red and white heart\r
+//in 1 2 4 and 8 bit per pixel modes.\r
+\r
+program drawheart;\r
+\r
+uses\r
+  pngwrite,classes,sysutils;\r
+\r
+{ $R *.RES}\r
+const\r
+  imagedata : array[0..10] of array [0..10] of byte=(\r
+    (0,0,0,0,0,0,0,0,0,0,0),\r
+    (0,0,1,1,1,0,1,1,1,0,0),\r
+    (0,1,1,1,1,0,1,1,1,1,0),\r
+    (0,1,1,1,1,1,1,1,1,1,0),\r
+    (0,1,1,1,1,1,1,1,1,1,0),\r
+    (0,1,1,1,1,1,1,1,1,1,0),\r
+    (0,0,1,1,1,1,1,1,1,0,0),\r
+    (0,0,0,1,1,1,1,1,0,0,0),\r
+    (0,0,0,0,1,1,1,0,0,0,0),\r
+    (0,0,0,0,0,1,0,0,0,0,0),\r
+    (0,0,0,0,0,0,0,0,0,0,0)\r
+  );\r
+  paldata : array[0..5] of byte=(255,255,255,255,0,0);\r
+var\r
+  outer,counter : integer;\r
+  stream : tfilestream;\r
+  f : tpngwrite;\r
+begin\r
+  for outer := 0 to 3 do begin\r
+\r
+    stream := tfilestream.Create('heart'+inttostr(1 shl outer)+'.png',fmCreate{fmOpenWrite} or fmShareDenyNone );\r
+    try\r
+      pngstart(f,stream,1 shl outer,ct8bp,11,11);\r
+      pngwritepal(f,@paldata,2);\r
+      pngstartdata(f);\r
+\r
+      for counter := 0 to 10 do begin\r
+        pngwritescanline(f,@imagedata[counter]);\r
+      end;\r
+      pngfinishdata(f);\r
+      pngfinish(f);\r
+    finally\r
+      stream.Free;\r
+    end;\r
+  end;\r
+end.\r
diff --git a/drawheart.res b/drawheart.res
new file mode 100755 (executable)
index 0000000..35c50c8
Binary files /dev/null and b/drawheart.res differ
diff --git a/graphdraw.dpr b/graphdraw.dpr
new file mode 100644 (file)
index 0000000..ae19233
--- /dev/null
@@ -0,0 +1,14 @@
+//graph draw test/demo app\r
+program graphdraw;\r
+\r
+uses\r
+  Forms,\r
+  graphdrawu in 'graphdrawu.pas' {Form1};\r
+\r
+{$R *.RES}\r
+\r
+begin\r
+  Application.Initialize;\r
+  Application.CreateForm(TForm1, Form1);\r
+  Application.Run;\r
+end.\r
diff --git a/graphdraw.res b/graphdraw.res
new file mode 100755 (executable)
index 0000000..e1e0839
Binary files /dev/null and b/graphdraw.res differ
diff --git a/graphdrawu.dfm b/graphdrawu.dfm
new file mode 100644 (file)
index 0000000..9825b78
Binary files /dev/null and b/graphdrawu.dfm differ
diff --git a/graphdrawu.pas b/graphdrawu.pas
new file mode 100644 (file)
index 0000000..5ec22ab
--- /dev/null
@@ -0,0 +1,164 @@
+{ Copyright (C) 2005 Bas Steendijk and Peter Green\r
+  For conditions of distribution and use, see copyright notice in zlib_license.txt\r
+    which is included in the package\r
+      ----------------------------------------------------------------------------- }\r
+\r
+//main unit for graph drawing demo\r
+\r
+//draws a sine and cosine graph into a 2 bit per pixel\r
+//array.\r
+//Copies it into a truecolor tbitmap (that is visible on the main form).\r
+//saves the graph from the original buffer to a 2 bit palleted png\r
+//saves the graph from the original buffer to a 2 bit greyscale png\r
+//saves the graph from the tbitmap into a 24 bit truecolor bitmap\r
+\r
+unit graphdrawu;\r
+\r
+interface\r
+\r
+uses\r
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,\r
+  ExtCtrls,pngwrite,pngwritetbitmap;\r
+\r
+type\r
+  TForm1 = class(TForm)\r
+    Image1: TImage;\r
+    procedure FormCreate(Sender: TObject);\r
+  private\r
+    { Private declarations }\r
+  public\r
+    { Public declarations }\r
+  end;\r
+\r
+var\r
+  Form1: TForm1;\r
+  pal : array[0..11] of byte;\r
+implementation\r
+\r
+{$R *.DFM}\r
+\r
+type\r
+  tlinedata = array[word] of byte;\r
+  plinedata = ^tlinedata;\r
+  timagedata = array[word] of plinedata;\r
+  pimagedata = ^timagedata;\r
+var\r
+  imagedata : pimagedata;\r
+procedure TForm1.FormCreate(Sender: TObject);\r
+var\r
+  counter : integer;\r
+  inner : integer;\r
+  y : integer;\r
+  bitmapscanline : plinedata;\r
+  tempfloat : extended;\r
+  currentindex : integer;\r
+  fracpart : integer;\r
+  f : tpngwrite;\r
+  stream : tfilestream;\r
+begin\r
+  //black\r
+  pal[ 0] := 0;\r
+  pal[ 1] := 0;\r
+  pal[ 2] := 0;\r
+\r
+  //blue\r
+  pal[ 3] := 0;\r
+  pal[ 4] := 0;\r
+  pal[ 5] := $FF;\r
+\r
+  //red\r
+  pal[ 6] := $FF;\r
+  pal[ 7] := 0;\r
+  pal[ 8] := 0;\r
+\r
+  //white\r
+  pal[ 9] := $ff;\r
+  pal[10] := $ff;\r
+  pal[11] := $FF;\r
+\r
+  imagedata := allocmem(image1.height*sizeof(plinedata));\r
+  image1.width := (image1.width div 4)*4;\r
+  image1.width := image1.width;\r
+  for counter := 0 to image1.height-1 do begin\r
+\r
+    imagedata[counter] := allocmem(image1.width div 4);\r
+    imagedata[counter][image1.width div 8] := imagedata[counter][image1.width div 8] or $C0;\r
+\r
+  end;\r
+  fillchar(imagedata[image1.height div 2]^,image1.width div 4,#$FF);\r
+  for counter := 0 to image1.width-1 do begin\r
+//    tempfloat := ;\r
+    for fracpart := 0 to 15 do begin\r
+      y := round(  -sin((( (counter+(fracpart/15)) / image1.width){+0.5}) *2*pi  ) *((image1.height-20)div 2) )+((image1.height)div 2);\r
+      //writeln(y);\r
+      imagedata[y][counter div 4] := (imagedata[y][counter div 4]) or  (1 shl (((counter and $3)xor$3)*2)  );\r
+\r
+      y := round(  -cos((( (counter+(fracpart/15)) / image1.width){+0.5}) *2*pi  ) *((image1.height-20)div 2) )+((image1.height)div 2);\r
+      //writeln(y);\r
+      imagedata[y][counter div 4] := (imagedata[y][counter div 4]) or  (2 shl (((counter and $3)xor$3)*2)  );\r
+    end ;\r
+  end;\r
+  image1.Picture.Bitmap.PixelFormat :=pf24bit;\r
+  image1.picture.bitmap.width := image1.width;\r
+  image1.picture.bitmap.height := image1.height;\r
+\r
+\r
+  for counter := 0 to image1.height-1 do begin\r
+    bitmapscanline := image1.picture.bitmap.ScanLine[counter];\r
+    for inner := 0 to image1.width-1 do begin\r
+\r
+      currentindex := (imagedata[counter][inner div 4] shr (((inner and $3)xor$3)*2)   ) and $3;\r
+      //if (counter=0) and (imagedata[counter][inner div 4] <> 0) then begin\r
+      //  writeln(imagedata[counter][inner div 4]);\r
+      //  writeln(currentindex);\r
+      //  writeln;\r
+      //end;\r
+      bitmapscanline[(inner*3)  ] := pal[(currentindex*3)+2];\r
+      bitmapscanline[(inner*3)+1] := pal[(currentindex*3)+1];\r
+      bitmapscanline[(inner*3)+2] := pal[(currentindex*3)  ];\r
+\r
+    end;\r
+  end;\r
+  image1.invalidate;\r
+\r
+  stream := tfilestream.Create('truecolor.png',fmCreate{fmOpenWrite} or fmShareDenyNone        );\r
+  try\r
+    savetbitmaptopng(image1.picture.Bitmap,stream);\r
+  finally\r
+    stream.Free;\r
+  end;\r
+\r
+  stream := tfilestream.Create('4grey.png',fmCreate{fmOpenWrite} or fmShareDenyNone    );\r
+  try\r
+    pngstart(f,stream,2,ctgreyscale ,image1.picture.Bitmap.Height,image1.Picture.Bitmap.Width);\r
+    pngstartdata(f);\r
+\r
+    for counter := 0 to image1.picture.Bitmap.Height-1 do begin\r
+      pngwritescanline(f,imagedata[counter]);\r
+    end;\r
+    pngfinishdata(f);\r
+    pngfinish(f);\r
+  finally\r
+    stream.Free;\r
+  end;\r
+\r
+  stream := tfilestream.Create('4color.png',fmCreate{fmOpenWrite} or fmShareDenyNone   );\r
+  try\r
+    pngstart(f,stream,2,ctpallette ,image1.picture.Bitmap.Height,image1.Picture.Bitmap.Width);\r
+    pngwritepal(f,@pal,4);\r
+    pngstartdata(f);\r
+\r
+    for counter := 0 to image1.picture.Bitmap.Height-1 do begin\r
+      pngwritescanline(f,imagedata[counter]);\r
+    end;\r
+    pngfinishdata(f);\r
+    pngfinish(f);\r
+  finally\r
+    stream.Free;\r
+  end;\r
+\r
+\r
+\r
+end;\r
+\r
+end.\r
diff --git a/pgtypes.pas b/pgtypes.pas
new file mode 100755 (executable)
index 0000000..3c48e26
--- /dev/null
@@ -0,0 +1,20 @@
+{io core originally for linux bworld}\r
+\r
+{ Copyright (C) 2005 Bas Steendijk and Peter Green\r
+  For conditions of distribution and use, see copyright notice in zlib_license.txt\r
+  which is included in the package\r
+  ----------------------------------------------------------------------------- }\r
+\r
+unit pgtypes;\r
+interface\r
+  type\r
+    {$ifdef cpu386}{$define i386}{$endif}\r
+    {$ifdef i386}\r
+      taddrint=longint;\r
+    {$else}\r
+      taddrint=sizeint;\r
+    {$endif}\r
+    paddrint=^taddrint;\r
+\r
+implementation\r
+end.\r
diff --git a/pngwrite.pas b/pngwrite.pas
new file mode 100755 (executable)
index 0000000..8674336
--- /dev/null
@@ -0,0 +1,423 @@
+{pngwrite.pas}\r
+{plugwashes png write code}\r
+\r
+{ Copyright (C) 2005 Bas Steendijk and Peter Green\r
+  For conditions of distribution and use, see copyright notice in zlib_license.txt\r
+    which is included in the package\r
+      ----------------------------------------------------------------------------- }\r
+\r
+unit pngwrite;\r
+\r
+interface\r
+uses\r
+  zlib,zdeflate,zutil,classes,sysutils,pgtypes,\r
+  {$ifdef win32}\r
+    winsock;\r
+  {$else}\r
+    sockets;\r
+  {$endif}\r
+{$i uint32.inc}\r
+\r
+type\r
+\r
+  tcolortype=(ctgreyscale,ctpallette,ctbgr,ctrgb,ct8bp);\r
+\r
+// There are two types of color types\r
+//\r
+// native types result in direct output of the apps data to the png file\r
+// theese are\r
+// ctgreyscale : grey scale data all png supported depths should work\r
+// ctpallette : palletted data all png supported depths should work\r
+// ctrgb : currently 24 bit only\r
+//\r
+// Processed types are processed before data is output to the png file\r
+// ctbgr : truecolor data in bgr order usefull with tbitmap.\r
+// ct8bp : data from app is 8 bits per sample palletted but data is saved as\r
+//         a lower depth palletted format (the app MUST only use the first\r
+//         2^bitdepth pallette entries\r
+\r
+  tpngwrite=record\r
+    destination : tstream;\r
+    lines : integer;\r
+    cols : integer;\r
+    deflatestream : z_stream;\r
+    chunkstart : integer; //used to fill in chunk length later\r
+    chunkbytes : integer;\r
+    chunkcrc   : uint32;\r
+    crc_table : array[byte] of uint32;\r
+    colortype:tcolortype;\r
+    colordepth        : byte;\r
+    bufferingchunkdata : boolean;\r
+    bufferedchunkdata : tstringlist;\r
+  end;\r
+\r
+procedure pngstart(var f : tpngwrite;destination : tstream;colordepth : integer;colortype:tcolortype;lines : integer;cols : integer);\r
+procedure pngwritescanline(var f : tpngwrite;scanline: pointer);\r
+\r
+\r
+procedure pngwritepal(var f : tpngwrite;p:pointer;entrys : integer);\r
+procedure pngstartdata(var f : tpngwrite);\r
+procedure pngfinishdata(var f : tpngwrite);\r
+procedure pngfinish(var f : tpngwrite);\r
+\r
+\r
+\r
+implementation\r
+\r
+\r
+procedure make_crc_table(var f:tpngwrite);\r
+var\r
+  c: uint32;\r
+  n,k : integer;\r
+begin\r
+  with f do begin\r
+\r
+//        unsigned long c;\r
+//        int n, k;\r
+//        for (n = 0; n < 256; n++)\r
+    for n := 0 to 255 do begin\r
+//          c = (unsigned long) n;\r
+      c := n;\r
+//          for (k = 0; k < 8; k++)\r
+      for k := 0 to 7 do begin\r
+//            if (c & 1)\r
+        if (c and 1) <> 0 then begin\r
+//              c = 0xedb88320L ^ (c >> 1);\r
+          c := $edb88320 xor (c shr 1);\r
+//            else\r
+        end else begin\r
+//              c = c >> 1;\r
+          c := c shr 1;\r
+//\r
+        end;\r
+      end;\r
+//          crc_table[n] = c;\r
+      crc_table[n] := c;\r
+//\r
+    end;\r
+//        crc_table_computed = 1;\r
+  end;\r
+end;\r
+(*\r
+   unsigned long update_crc(unsigned long crc, unsigned char *buf,\r
+                               int len)\r
+      {\r
+        unsigned long c = crc;\r
+        int n;\r
+\r
+        if (!crc_table_computed)\r
+          make_crc_table();\r
+        for (n = 0; n < len; n++) {\r
+          c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);\r
+        }\r
+        return c;\r
+      }\r
+*)\r
+procedure update_crc(var f : tpngwrite;buf : string);\r
+\r
+var\r
+  n : integer;\r
+begin\r
+  with f do begin\r
+    for n := 1 to length(buf) do begin\r
+      chunkcrc := crc_table[(chunkcrc xor byte(buf[n])) and $ff] xor (chunkcrc shr 8);\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure writetochunk(var f : tpngwrite;buf : string);\r
+begin\r
+  if length(buf)=0 then raise exception.create('attempt to write zero length block to chunk');\r
+  \r
+  with f do begin\r
+    if bufferingchunkdata then begin\r
+      bufferedchunkdata.Add(buf);\r
+    end else begin\r
+      destination.Write(buf[1],length(buf));\r
+    end;\r
+    update_crc(f,buf);\r
+    inc(chunkbytes,length(buf));\r
+  end;\r
+end;\r
+\r
+\r
+procedure startchunk(var f : tpngwrite;chunktype : string);\r
+var\r
+  outputdata : string;\r
+begin\r
+  with f do begin\r
+    try\r
+      chunkstart := destination.Position;\r
+      // 4 btye dummy for length we will insert this later.\r
+      outputdata := '    ';\r
+      destination.WriteBuffer(pchar(outputdata)^,4);\r
+    except\r
+      bufferingchunkdata := true;\r
+      bufferedchunkdata := tstringlist.create;\r
+    end;\r
+    chunkbytes := -4;\r
+    chunkcrc := $FFFFFFFF;\r
+\r
+    writetochunk(f,chunktype);\r
+\r
+\r
+  end;\r
+end;\r
+\r
+\r
+\r
+\r
+procedure stopchunk(var f:tpngwrite);\r
+var\r
+  currentpos : integer;\r
+  i : integer;\r
+begin\r
+  with f do begin\r
+    if not bufferingchunkdata then begin\r
+\r
+      currentpos := destination.Position;\r
+      destination.position := chunkstart;\r
+    end;\r
+    chunkbytes := htonl(chunkbytes);\r
+    destination.WriteBuffer(chunkbytes,4);\r
+    if bufferingchunkdata then begin\r
+//      writeln('begin write of buffered chunk data');\r
+      for i := 0 to bufferedchunkdata.Count-1 do begin\r
+        destination.Write(bufferedchunkdata[i][1],length(bufferedchunkdata[i]));\r
+      end;\r
+      bufferedchunkdata.Free;\r
+//      writeln('end write of buffered chunk data');\r
+    end else begin\r
+      destination.position := currentpos;\r
+    end;\r
+    chunkcrc := htonl(chunkcrc)     ;\r
+    chunkcrc := chunkcrc xor $FFFFFFFF;\r
+    destination.WriteBuffer(chunkcrc,4);\r
+\r
+  end;\r
+end;\r
+\r
+type\r
+  tihdr=packed record\r
+    width             : uint32;\r
+    height            : uint32;\r
+    Bitdepth          : byte;\r
+    Colortype         : byte;\r
+    Compressionmethod : byte;\r
+    Filtermethod      : byte;\r
+    Interlacemethod   : byte;\r
+  end;\r
+  pihdr=^tihdr;\r
+procedure pngstart(var f : tpngwrite;destination : tstream;colordepth : integer;colortype:tcolortype;lines : integer;cols : integer);\r
+var\r
+  tempstring : string;\r
+  ihdr : pihdr;\r
+begin\r
+  fillchar(f,sizeof(f),#0);\r
+  f.destination := destination;\r
+  f.lines := lines;\r
+  f.cols := cols;\r
+  f.colortype := colortype;\r
+  f.colordepth := colordepth;\r
+  make_crc_table(f);\r
+  with f do begin\r
+    //file header\r
+    destination.Write(pchar(#137'PNG'#13#10#26#10)^,8);\r
+\r
+    startchunk(f,'IHDR');\r
+    setlength(tempstring,sizeof(tihdr));\r
+    ihdr := pihdr(tempstring);\r
+    ihdr.width := htonl(cols);\r
+    ihdr.height := htonl(lines);\r
+    case colortype of\r
+      ctgreyscale : begin\r
+        ihdr.Bitdepth := colordepth;\r
+        ihdr.Colortype := 0;\r
+      end;\r
+      ctpallette,ct8bp : begin\r
+        ihdr.Bitdepth := colordepth;\r
+        ihdr.Colortype := 3;\r
+      end;\r
+\r
+      ctrgb,ctbgr : begin\r
+        ihdr.Bitdepth := 8;\r
+        ihdr.Colortype := 2;\r
+      end;\r
+    end;\r
+\r
+    ihdr.Compressionmethod := 0;\r
+    ihdr.Filtermethod := 0;\r
+    ihdr.Interlacemethod := 0;\r
+    writetochunk(f,tempstring);\r
+    stopchunk(f);\r
+\r
+  end;\r
+end;\r
+\r
+procedure pngwritepal(var f : tpngwrite;p:pointer;entrys : integer);\r
+var\r
+  tempstring : string;\r
+begin\r
+  with f do begin\r
+    startchunk(f,'PLTE');\r
+    setlength(tempstring,entrys*3);\r
+    move(p^,tempstring[1],entrys*3);\r
+    writetochunk(f,tempstring);\r
+    stopchunk(f);\r
+  end;\r
+end;\r
+\r
+procedure pngstartdata(var f : tpngwrite);\r
+begin\r
+  with f do begin\r
+    startchunk(f,'IDAT');\r
+    deflateInit(deflatestream,9);\r
+    //writeln('test');\r
+\r
+  end;\r
+end;\r
+\r
+\r
+\r
+type\r
+  tlinedata = array[0..0] of byte;\r
+  plinedata = ^tlinedata;\r
+function divup(a,b:integer):integer;\r
+begin\r
+  result := (a div b)+ord((a mod b)<>0);\r
+end;\r
+\r
+\r
+procedure pngwritescanline(var f : tpngwrite;scanline: pointer);\r
+var\r
+  outputstr : string;\r
+  nullchar : char;\r
+  scanlineb : plinedata absolute scanline;\r
+  rearrangebuf : plinedata;\r
+  counter : integer;\r
+  pixelsperbyte : integer;\r
+  samplevalue : byte;\r
+begin\r
+  with f do begin\r
+    //writeln('about to write starter byte');\r
+    if cols > 127 then begin\r
+      setlength(outputstr,cols*6);\r
+    end else begin\r
+      setlength(outputstr,768);\r
+    end;\r
+    deflatestream.next_out := pbytef(outputstr);\r
+    deflatestream.avail_out := length(outputstr);\r
+//    writeln(deflatestream.avail_out,' ',deflatestream.avail_in);\r
+    nullchar := #0;\r
+    deflatestream.next_in := @nullchar;\r
+    deflatestream.avail_in :=1;\r
+    //writeln('about to start deflation');\r
+    deflate(deflatestream,0);\r
+    //writeln('deflation complete deflatestream.avail_out=',deflatestream.avail_out);\r
+//    writeln(deflatestream.avail_out,' ',deflatestream.avail_in);\r
+    while deflatestream.avail_out = 0 do begin\r
+      deflatestream.next_out := pbytef(taddrint(deflatestream.next_out) - taddrint(outputstr));\r
+      deflatestream.avail_out := length(outputstr);\r
+      setlength(outputstr,length(outputstr)*2);\r
+      deflatestream.next_out := pbytef(taddrint(deflatestream.next_out) + taddrint(outputstr));\r
+      deflate(deflatestream,0);\r
+    end;\r
+    //writeln('extra deflation done');\r
+    if deflatestream.avail_in <> 0 then raise exception.create('compression problem');\r
+    //writeln('about to write main data');\r
+    case colortype of\r
+\r
+      ctbgr : begin\r
+        getmem(rearrangebuf,cols*3);\r
+\r
+        for counter := 0 to cols-1 do begin\r
+          rearrangebuf[(counter*3)  ] := scanlineb[(counter*3)+2];\r
+          rearrangebuf[(counter*3)+1] := scanlineb[(counter*3)+1];\r
+          rearrangebuf[(counter*3)+2] := scanlineb[(counter*3)  ];\r
+        end;\r
+        deflatestream.next_in := pointer(rearrangebuf);\r
+        deflatestream.avail_in := cols*3;\r
+        deflate(deflatestream,0);\r
+        if deflatestream.avail_in <> 0 then raise exception.create('compression problem');\r
+        freemem(rearrangebuf);\r
+\r
+      end;\r
+      ct8bp : begin\r
+        rearrangebuf := allocmem(divup(cols* colordepth,  8));\r
+        pixelsperbyte := 8 div colordepth;\r
+        for counter := 0 to cols-1 do begin\r
+          //shift sample value into most significant bits (which has the nice side effect of removing any garbage bits)\r
+          samplevalue := scanlineb[counter] shl (8-colordepth);\r
+          //shift sample value into correct place for pixel in question.\r
+          samplevalue := samplevalue shr ((counter mod pixelsperbyte)*colordepth);\r
+          rearrangebuf[counter div pixelsperbyte] := rearrangebuf[counter div pixelsperbyte] or samplevalue;\r
+        end;\r
+        deflatestream.next_in := pointer(rearrangebuf);\r
+        deflatestream.avail_in := divup(cols* colordepth,  8);\r
+        deflate(deflatestream,0);\r
+        if deflatestream.avail_in <> 0 then raise exception.create('compression problem');\r
+        freemem(rearrangebuf);\r
+      end;\r
+\r
+      else begin\r
+        deflatestream.next_in := scanline;\r
+\r
+        deflatestream.avail_in := divup(cols* colordepth,  8);\r
+\r
+        deflate(deflatestream,0);\r
+        while deflatestream.avail_out = 0 do begin\r
+          deflatestream.next_out := pbytef(taddrint(deflatestream.next_out) - taddrint(outputstr));\r
+          deflatestream.avail_out := length(outputstr);\r
+          setlength(outputstr,length(outputstr)*2);\r
+          deflatestream.next_out := pbytef(taddrint(deflatestream.next_out) + taddrint(outputstr));\r
+          deflate(deflatestream,0);\r
+        end;\r
+        if deflatestream.avail_in <> 0 then raise exception.create('compression problem');\r
+      end;\r
+    end;\r
+\r
+    setlength(outputstr,length(outputstr)-deflatestream.avail_out);\r
+    //deflate doesn't always produce output when its given input, if this is the case no point pushing it any further\r
+    if length(outputstr) > 0 then writetochunk(f,outputstr);\r
+//    writeln;\r
+  end;\r
+end;\r
+\r
+procedure pngfinishdata(var f : tpngwrite);\r
+var\r
+  outputstr : string;\r
+  deflateresult : integer;\r
+begin\r
+  with f do begin\r
+    repeat\r
+      setlength(outputstr,512);\r
+      deflatestream.next_out := pbytef(outputstr);\r
+      deflatestream.avail_out := length(outputstr);\r
+      deflateresult := deflate(deflatestream,Z_FINISH);\r
+      setlength(outputstr,length(outputstr)-deflatestream.avail_out);\r
+      writetochunk(f,outputstr);\r
+\r
+    until deflateresult=Z_STREAM_END;\r
+    deflateEnd(deflatestream);\r
+    stopchunk(f);\r
+\r
+  end;\r
+end;\r
+\r
+\r
+procedure pngfinish(var f : tpngwrite);\r
+\r
+begin\r
+  with f do begin\r
+    //setlength(outputstr,512);\r
+    startchunk(f,'IEND');\r
+\r
+    stopchunk(f);\r
+  end;\r
+\r
+end;\r
+\r
+\r
+\r
+\r
+end.\r
diff --git a/pngwritetbitmap.pas b/pngwritetbitmap.pas
new file mode 100644 (file)
index 0000000..f080631
--- /dev/null
@@ -0,0 +1,65 @@
+{unit to write tbitmaps to a png using plugwashes png code}\r
+\r
+unit pngwritetbitmap;\r
+\r
+interface\r
+uses\r
+  pngwrite,\r
+  sysutils,\r
+  classes,\r
+  {$ifdef win32}\r
+    windows,\r
+  {$endif}\r
+  {$ifndef fpc}\r
+\r
+    Graphics;\r
+\r
+  {$else}\r
+    pgtbitmap;\r
+  {$endif}\r
+  \r
+procedure savetbitmaptopng(image:tbitmap;destination : tstream);\r
+implementation\r
+procedure savetbitmaptopng(image:tbitmap;destination : tstream);\r
+var\r
+  paletteentrieswin : array[0..255] of TPaletteEntry;\r
+  paletteentriespng : array[0..768] of byte;\r
+  f:tpngwrite;\r
+  i : integer;\r
+  colortype : tcolortype;\r
+begin\r
+  if (image.PixelFormat <> pf8bit) and (image.pixelformat <> pf24bit) then raise exception.create('unsupported image format, only 8 bit and 24 bit per pixel are currently supported.');\r
+  if image.PixelFormat = pf24bit then begin\r
+    colortype := ctbgr;\r
+  end else begin\r
+    colortype := ctpallette;\r
+  end;\r
+  pngstart(f,destination,8,colortype,image.Height,image.Width);\r
+\r
+  if image.pixelformat = pf8bit then begin\r
+    GetPaletteEntries(image.Palette,0,256,paletteEntrieswin);\r
+\r
+    //writeln('about to start png write');\r
+    //writeln('about to prepare pallette');\r
+    for i := 0 to 255 do begin\r
+      paletteentriespng[(i*3)  ] := paletteEntrieswin[i].pered;\r
+      paletteentriespng[(i*3)+1] := paletteEntrieswin[i].pegreen;\r
+      paletteentriespng[(i*3)+2] := paletteEntrieswin[i].peblue;\r
+    end;\r
+    //writeln('about to write pallette');\r
+    pngwritepal(f,@paletteentriespng,256 );\r
+  end;\r
+\r
+  pngstartdata(f);\r
+  {$O-}\r
+  for i := 0 to Image.Height -1 do begin;\r
+    //writeln('about to write scanline ',i,'image.height=',image.height,'image.ScanLine[i]',longint(image.ScanLine[i]));\r
+    pngwritescanline(f,image.ScanLine[i]);\r
+  end;\r
+  //writeln('about to close main data block');\r
+  pngfinishdata(f);\r
+  //writeln('about to close png');\r
+  pngfinish(f);\r
+\r
+end;\r
+end.\r
diff --git a/readme.paszlib b/readme.paszlib
new file mode 100755 (executable)
index 0000000..887d9ca
--- /dev/null
@@ -0,0 +1,129 @@
+_____________________________________________________________________________\r
+\r
+PASZLIB 1.0                                                   May 11th, 1998\r
+\r
+Based on the zlib 1.1.2, a general purpose data compression library.\r
+\r
+Copyright (C) 1998,1999,2000 by NOMSSI NZALI Jacques H. C. \r
+[kn&n DES]         See "Legal issues" for conditions of distribution and use.\r
+_____________________________________________________________________________\r
+\r
+\r
+Introduction\r
+============\r
+\r
+The 'zlib' compression library provides in-memory compression and\r
+decompression functions, including integrity checks of the uncompressed\r
+data.  This version of the library supports only one compression method\r
+(deflation) but other algorithms will be added later and will have the same\r
+stream interface.\r
+\r
+Compression can be done in a single step if the buffers are large\r
+enough (for example if an input file is mmap'ed), or can be done by\r
+repeated calls of the compression function.  In the latter case, the\r
+application must provide more input and/or consume the output\r
+(providing more output space) before each call.\r
+\r
+The default memory requirements for deflate are 256K plus a few kilobytes\r
+for small objects. The default memory requirements for inflate are 32K\r
+plus a few kilobytes for small objects.\r
+\r
+Change Log\r
+==========\r
+\r
+March 24th 2000 - minizip code by Gilles Vollant ported to Pascal. \r
+                  z_stream.msg defined as string[255] to avoid problems\r
+                  with Delphi 2+ dynamic string handling.\r
+                  changes to silence Delphi 5 compiler warning. If you\r
+                  have Delphi 5, defines Delphi5 in zconf.inc\r
+                              \r
+May 7th 1999    - Some changes for FPC\r
+                  deflateCopy() has new parameters\r
+                  trees.pas - record constant definition\r
+June 17th 1998  - Applied official 1.1.2 patch. \r
+                 Memcheck turned off by default.\r
+                  zutil.pas patch for Delphi 1 memory allocation corrected.\r
+                  dzlib.txt file added.\r
+                  compress2() is now exported\r
+\r
+June 25th 1998 -  fixed a conversion bug: in inftrees.pas, ZFREE(z, v) was\r
+                  missing in line 574;\r
+\r
+File list\r
+=========\r
+\r
+Here is a road map to the files in the Paszlib distribution.\r
+\r
+readme.txt      Introduction, Documentation\r
+dzlib.txt       Changes to Delphi sources for Paszlib stream classes \r
+\r
+include file\r
+\r
+zconf.inc       Configuration declarations.\r
+\r
+Pascal source code files:\r
+\r
+adler.pas      compute the Adler-32 checksum of a data stream\r
+crc.pas        compute the CRC-32 of a data stream\r
+gzio.pas       IO on .gz files\r
+infblock.pas   interpret and process block types to last block\r
+infcodes.pas   process literals and length/distance pairs\r
+inffast.pas    process literals and length/distance pairs fast\r
+inftrees.pas   generate Huffman trees for efficient decoding\r
+infutil.pas    types and macros common to blocks and codes\r
+strutils.pas   string utilities\r
+trees.pas      output deflated data using Huffman coding\r
+zcompres.pas   compress a memory buffer\r
+zdeflate.pas   compress data using the deflation algorithm\r
+zinflate.pas   zlib interface to inflate modules\r
+zlib.pas       zlib data structures. read the comments there!\r
+zuncompr.pas   decompress a memory buffer\r
+zutil.pas\r
+\r
+minizip/ziputils.pas data structure and IO on .zip file \r
+minizip/unzip.pas  \r
+minizip/zip.pas\r
+      \r
+Test applications\r
+\r
+example.pas    usage example of the zlib compression library\r
+minigzip.pas   simulate gzip using the zlib compression library\r
+minizip/miniunz.pas  simulates unzip using the zlib compression library\r
+minizip/minizip.pas  simulates zip using the zlib compression library\r
+\r
+Legal issues\r
+============\r
+\r
+Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali\r
+\r
+  This software is provided 'as-is', without any express or implied\r
+  warranty.  In no event will the author be held liable for any damages\r
+  arising from the use of this software.\r
+\r
+  Permission is granted to anyone to use this software for any purpose,\r
+  including commercial applications, and to alter it and redistribute it\r
+  freely, subject to the following restrictions:\r
+\r
+  1. The origin of this software must not be misrepresented; you must not\r
+     claim that you wrote the original software. If you use this software\r
+     in a product, an acknowledgment in the product documentation would be\r
+     appreciated but is not required.\r
+  2. Altered source versions must be plainly marked as such, and must not be\r
+     misrepresented as being the original software.\r
+  3. This notice may not be removed or altered from any source distribution.\r
+\r
+\r
+Archive Locations:\r
+==================\r
+\r
+Check the Paszlib home page with links\r
+\r
+      http://www.tu-chemnitz.de/~nomssi/paszlib.html\r
+\r
+The data format used by the zlib library is described by RFCs (Request for\r
+Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt\r
+(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).\r
+These documents are also available in other formats from\r
+ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html.\r
+____________________________________________________________________________\r
+Jacques Nomssi Nzali <mailto:nomssi@physik.tu-chemnitz.de> March 24th, 2000
\ No newline at end of file
diff --git a/spritepalpng.dof b/spritepalpng.dof
new file mode 100755 (executable)
index 0000000..7ce4711
--- /dev/null
@@ -0,0 +1,75 @@
+[Compiler]\r
+A=1\r
+B=0\r
+C=1\r
+D=1\r
+E=0\r
+F=0\r
+G=1\r
+H=1\r
+I=1\r
+J=1\r
+K=0\r
+L=1\r
+M=0\r
+N=1\r
+O=1\r
+P=1\r
+Q=0\r
+R=0\r
+S=0\r
+T=0\r
+U=0\r
+V=1\r
+W=0\r
+X=1\r
+Y=0\r
+Z=1\r
+ShowHints=1\r
+ShowWarnings=1\r
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;\r
+[Linker]\r
+MapFile=0\r
+OutputObjs=0\r
+ConsoleApp=1\r
+DebugInfo=0\r
+MinStackSize=16384\r
+MaxStackSize=1048576\r
+ImageBase=4194304\r
+ExeDescription=\r
+[Directories]\r
+OutputDir=\r
+UnitOutputDir=\r
+SearchPath=\r
+Packages=\r
+Conditionals=\r
+DebugSourceDirs=\r
+UsePackages=0\r
+[Parameters]\r
+RunParams=1\r
+HostApplication=\r
+[Version Info]\r
+IncludeVerInfo=0\r
+AutoIncBuild=0\r
+MajorVer=1\r
+MinorVer=0\r
+Release=0\r
+Build=0\r
+Debug=0\r
+PreRelease=0\r
+Special=0\r
+Private=0\r
+DLL=0\r
+Locale=2057\r
+CodePage=1252\r
+[Version Info Keys]\r
+CompanyName=\r
+FileDescription=\r
+FileVersion=1.0.0.0\r
+InternalName=\r
+LegalCopyright=\r
+LegalTrademarks=\r
+OriginalFilename=\r
+ProductName=\r
+ProductVersion=1.0.0.0\r
+Comments=\r
diff --git a/spritepalpng.res b/spritepalpng.res
new file mode 100755 (executable)
index 0000000..35c50c8
Binary files /dev/null and b/spritepalpng.res differ
diff --git a/svn-commit.tmp b/svn-commit.tmp
new file mode 100644 (file)
index 0000000..82b4cd3
--- /dev/null
@@ -0,0 +1,4 @@
+initial import
+--This line, and those below, will be ignored--
+
+A    .
diff --git a/trees.pas b/trees.pas
new file mode 100755 (executable)
index 0000000..dec9326
--- /dev/null
+++ b/trees.pas
@@ -0,0 +1,2249 @@
+Unit trees;\r
+\r
+{$T-}\r
+{$define ORG_DEBUG}\r
+{\r
+  trees.c -- output deflated data using Huffman coding\r
+  Copyright (C) 1995-1998 Jean-loup Gailly\r
+\r
+  Pascal tranlastion\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.paszlib\r
+}\r
+\r
+{\r
+ *  ALGORITHM\r
+ *\r
+ *      The "deflation" process uses several Huffman trees. The more\r
+ *      common source values are represented by shorter bit sequences.\r
+ *\r
+ *      Each code tree is stored in a compressed form which is itself\r
+ * a Huffman encoding of the lengths of all the code strings (in\r
+ * ascending order by source values).  The actual code strings are\r
+ * reconstructed from the lengths in the inflate process, as described\r
+ * in the deflate specification.\r
+ *\r
+ *  REFERENCES\r
+ *\r
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".\r
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc\r
+ *\r
+ *      Storer, James A.\r
+ *          Data Compression:  Methods and Theory, pp. 49-50.\r
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.\r
+ *\r
+ *      Sedgewick, R.\r
+ *          Algorithms, p290.\r
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.\r
+ }\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+uses\r
+  {$ifdef DEBUG}\r
+  strutils,\r
+  {$ENDIF}\r
+  zutil, zlib;\r
+\r
+{ ===========================================================================\r
+  Internal compression state. }\r
+\r
+const\r
+  LENGTH_CODES = 29;\r
+{ number of length codes, not counting the special END_BLOCK code }\r
+\r
+  LITERALS = 256;\r
+{ number of literal bytes 0..255 }\r
+\r
+  L_CODES = (LITERALS+1+LENGTH_CODES);\r
+{ number of Literal or Length codes, including the END_BLOCK code }\r
+\r
+  D_CODES = 30;\r
+{ number of distance codes }\r
+\r
+  BL_CODES = 19;\r
+{ number of codes used to transfer the bit lengths }\r
+\r
+  HEAP_SIZE = (2*L_CODES+1);\r
+{ maximum heap size }\r
+\r
+  MAX_BITS = 15;\r
+{ All codes must not exceed MAX_BITS bits }\r
+\r
+const\r
+  INIT_STATE =  42;\r
+  BUSY_STATE =  113;\r
+  FINISH_STATE = 666;\r
+{ Stream status }\r
+\r
+\r
+{ Data structure describing a single value and its code string. }\r
+type\r
+  ct_data_ptr = ^ct_data;\r
+  ct_data = record\r
+    fc : record\r
+      case byte of\r
+      0:(freq : ush);       { frequency count }\r
+      1:(code : ush);       { bit string }\r
+    end;\r
+    dl : record\r
+      case byte of\r
+      0:(dad : ush);        { father node in Huffman tree }\r
+      1:(len : ush);        { length of bit string }\r
+    end;\r
+  end;\r
+\r
+{ Freq = fc.freq\r
+ Code = fc.code\r
+ Dad = dl.dad\r
+ Len = dl.len }\r
+\r
+type\r
+  ltree_type = array[0..HEAP_SIZE-1] of ct_data;    { literal and length tree }\r
+  dtree_type = array[0..2*D_CODES+1-1] of ct_data;  { distance tree }\r
+  htree_type = array[0..2*BL_CODES+1-1] of ct_data;  { Huffman tree for bit lengths }\r
+  { generic tree type }\r
+  tree_type = array[0..(MaxMemBlock div SizeOf(ct_data))-1] of ct_data;\r
+\r
+  tree_ptr = ^tree_type;\r
+  ltree_ptr = ^ltree_type;\r
+  dtree_ptr = ^dtree_type;\r
+  htree_ptr = ^htree_type;\r
+\r
+\r
+type\r
+  static_tree_desc_ptr = ^static_tree_desc;\r
+  static_tree_desc =\r
+         record\r
+    {const} static_tree : tree_ptr;     { static tree or NIL }\r
+    {const} extra_bits : pzIntfArray;   { extra bits for each code or NIL }\r
+            extra_base : int;           { base index for extra_bits }\r
+            elems : int;                { max number of elements in the tree }\r
+            max_length : int;           { max bit length for the codes }\r
+          end;\r
+\r
+  tree_desc_ptr = ^tree_desc;\r
+  tree_desc = record\r
+    dyn_tree : tree_ptr;    { the dynamic tree }\r
+    max_code : int;            { largest code with non zero frequency }\r
+    stat_desc : static_tree_desc_ptr; { the corresponding static tree }\r
+  end;\r
+\r
+type\r
+  Pos = ush;\r
+  Posf = Pos; {FAR}\r
+  IPos = uInt;\r
+\r
+  pPosf = ^Posf;\r
+\r
+  zPosfArray = array[0..(MaxMemBlock div SizeOf(Posf))-1] of Posf;\r
+  pzPosfArray = ^zPosfArray;\r
+\r
+{ A Pos is an index in the character window. We use short instead of int to\r
+  save space in the various tables. IPos is used only for parameter passing.}\r
+\r
+type\r
+  deflate_state_ptr = ^deflate_state;\r
+  deflate_state = record\r
+    strm : z_streamp;          { pointer back to this zlib stream }\r
+    status : int;              { as the name implies }\r
+    pending_buf : pzByteArray; { output still pending }\r
+    pending_buf_size : ulg;    { size of pending_buf }\r
+    pending_out : pBytef;      { next pending byte to output to the stream }\r
+    pending : int;             { nb of bytes in the pending buffer }\r
+    noheader : int;            { suppress zlib header and adler32 }\r
+    data_type : Byte;          { UNKNOWN, BINARY or ASCII }\r
+    method : Byte;             { STORED (for zip only) or DEFLATED }\r
+    last_flush : int;          { value of flush param for previous deflate call }\r
+\r
+                { used by deflate.pas: }\r
+\r
+    w_size : uInt;             { LZ77 window size (32K by default) }\r
+    w_bits : uInt;             { log2(w_size)  (8..16) }\r
+    w_mask : uInt;             { w_size - 1 }\r
+\r
+    window : pzByteArray;\r
+    { Sliding window. Input bytes are read into the second half of the window,\r
+      and move to the first half later to keep a dictionary of at least wSize\r
+      bytes. With this organization, matches are limited to a distance of\r
+      wSize-MAX_MATCH bytes, but this ensures that IO is always\r
+      performed with a length multiple of the block size. Also, it limits\r
+      the window size to 64K, which is quite useful on MSDOS.\r
+      To do: use the user input buffer as sliding window. }\r
+\r
+    window_size : ulg;\r
+    { Actual size of window: 2*wSize, except when the user input buffer\r
+      is directly used as sliding window. }\r
+\r
+    prev : pzPosfArray;\r
+    { Link to older string with same hash index. To limit the size of this\r
+      array to 64K, this link is maintained only for the last 32K strings.\r
+      An index in this array is thus a window index modulo 32K. }\r
+\r
+    head : pzPosfArray;    { Heads of the hash chains or NIL. }\r
+\r
+    ins_h : uInt;          { hash index of string to be inserted }\r
+    hash_size : uInt;      { number of elements in hash table }\r
+    hash_bits : uInt;      { log2(hash_size) }\r
+    hash_mask : uInt;      { hash_size-1 }\r
+\r
+    hash_shift : uInt;\r
+    { Number of bits by which ins_h must be shifted at each input\r
+      step. It must be such that after MIN_MATCH steps, the oldest\r
+      byte no longer takes part in the hash key, that is:\r
+        hash_shift * MIN_MATCH >= hash_bits     }\r
+\r
+    block_start : long;\r
+    { Window position at the beginning of the current output block. Gets\r
+      negative when the window is moved backwards. }\r
+\r
+    match_length : uInt;           { length of best match }\r
+    prev_match : IPos;             { previous match }\r
+    match_available : boolean;     { set if previous match exists }\r
+    strstart : uInt;               { start of string to insert }\r
+    match_start : uInt;            { start of matching string }\r
+    lookahead : uInt;              { number of valid bytes ahead in window }\r
+\r
+    prev_length : uInt;\r
+    { Length of the best match at previous step. Matches not greater than this\r
+      are discarded. This is used in the lazy match evaluation. }\r
+\r
+    max_chain_length : uInt;\r
+    { To speed up deflation, hash chains are never searched beyond this\r
+      length.  A higher limit improves compression ratio but degrades the\r
+      speed. }\r
+\r
+    { moved to the end because Borland Pascal won't accept the following:\r
+    max_lazy_match : uInt;\r
+    max_insert_length : uInt absolute max_lazy_match;\r
+    }\r
+\r
+    level : int;    { compression level (1..9) }\r
+    strategy : int; { favor or force Huffman coding}\r
+\r
+    good_match : uInt;\r
+    { Use a faster search when the previous match is longer than this }\r
+\r
+    nice_match : int; { Stop searching when current match exceeds this }\r
+\r
+                { used by trees.pas: }\r
+    { Didn't use ct_data typedef below to supress compiler warning }\r
+    dyn_ltree : ltree_type;    { literal and length tree }\r
+    dyn_dtree : dtree_type;  { distance tree }\r
+    bl_tree : htree_type;   { Huffman tree for bit lengths }\r
+\r
+    l_desc : tree_desc;                { desc. for literal tree }\r
+    d_desc : tree_desc;                { desc. for distance tree }\r
+    bl_desc : tree_desc;               { desc. for bit length tree }\r
+\r
+    bl_count : array[0..MAX_BITS+1-1] of ush;\r
+    { number of codes at each bit length for an optimal tree }\r
+\r
+    heap : array[0..2*L_CODES+1-1] of int; { heap used to build the Huffman trees }\r
+    heap_len : int;                   { number of elements in the heap }\r
+    heap_max : int;                   { element of largest frequency }\r
+    { The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\r
+      The same heap array is used to build all trees. }\r
+\r
+    depth : array[0..2*L_CODES+1-1] of uch;\r
+    { Depth of each subtree used as tie breaker for trees of equal frequency }\r
+\r
+\r
+    l_buf : puchfArray;       { buffer for literals or lengths }\r
+\r
+    lit_bufsize : uInt;\r
+    { Size of match buffer for literals/lengths.  There are 4 reasons for\r
+      limiting lit_bufsize to 64K:\r
+        - frequencies can be kept in 16 bit counters\r
+        - if compression is not successful for the first block, all input\r
+          data is still in the window so we can still emit a stored block even\r
+          when input comes from standard input.  (This can also be done for\r
+          all blocks if lit_bufsize is not greater than 32K.)\r
+        - if compression is not successful for a file smaller than 64K, we can\r
+          even emit a stored file instead of a stored block (saving 5 bytes).\r
+          This is applicable only for zip (not gzip or zlib).\r
+        - creating new Huffman trees less frequently may not provide fast\r
+          adaptation to changes in the input data statistics. (Take for\r
+          example a binary file with poorly compressible code followed by\r
+          a highly compressible string table.) Smaller buffer sizes give\r
+          fast adaptation but have of course the overhead of transmitting\r
+          trees more frequently.\r
+        - I can't count above 4 }\r
+\r
+\r
+    last_lit : uInt;      { running index in l_buf }\r
+\r
+    d_buf : pushfArray;\r
+    { Buffer for distances. To simplify the code, d_buf and l_buf have\r
+      the same number of elements. To use different lengths, an extra flag\r
+      array would be necessary. }\r
+\r
+    opt_len : ulg;        { bit length of current block with optimal trees }\r
+    static_len : ulg;     { bit length of current block with static trees }\r
+    compressed_len : ulg; { total bit length of compressed file }\r
+    matches : uInt;       { number of string matches in current block }\r
+    last_eob_len : int;   { bit length of EOB code for last block }\r
+\r
+{$ifdef DEBUG}\r
+    bits_sent : ulg;    { bit length of the compressed data }\r
+{$endif}\r
+\r
+    bi_buf : ush;\r
+    { Output buffer. bits are inserted starting at the bottom (least\r
+      significant bits). }\r
+\r
+    bi_valid : int;\r
+    { Number of valid bits in bi_buf.  All bits above the last valid bit\r
+      are always zero. }\r
+\r
+    case byte of\r
+    0:(max_lazy_match : uInt);\r
+    { Attempt to find a better match only when the current match is strictly\r
+      smaller than this value. This mechanism is used only for compression\r
+      levels >= 4. }\r
+\r
+    1:(max_insert_length : uInt);\r
+    { Insert new strings in the hash table only if the match length is not\r
+      greater than this length. This saves time but degrades compression.\r
+      max_insert_length is used only for compression levels <= 3. }\r
+  end;\r
+\r
+procedure _tr_init (var s : deflate_state);\r
+\r
+function _tr_tally (var s : deflate_state;\r
+                    dist : unsigned;\r
+                    lc : unsigned) : boolean;\r
+\r
+function _tr_flush_block (var s : deflate_state;\r
+                          buf : pcharf;\r
+                          stored_len : ulg;\r
+                         eof : boolean) : ulg;\r
+\r
+procedure _tr_align(var s : deflate_state);\r
+\r
+procedure _tr_stored_block(var s : deflate_state;\r
+                           buf : pcharf;\r
+                           stored_len : ulg;\r
+                           eof : boolean);\r
+\r
+implementation\r
+\r
+{ #define GEN_TREES_H }\r
+\r
+{$ifndef GEN_TREES_H}\r
+{ header created automatically with -DGEN_TREES_H }\r
+\r
+const\r
+  DIST_CODE_LEN = 512; { see definition of array dist_code below }\r
+\r
+{ The static literal tree. Since the bit lengths are imposed, there is no\r
+  need for the L_CODES extra codes used during heap construction. However\r
+  The codes 286 and 287 are needed to build a canonical tree (see _tr_init\r
+  below). }\r
+const\r
+  static_ltree : array[0..L_CODES+2-1] of ct_data = (\r
+{ fc:(freq, code) dl:(dad,len) }\r
+(fc:(freq: 12);dl:(len: 8)), (fc:(freq:140);dl:(len: 8)), (fc:(freq: 76);dl:(len: 8)),\r
+(fc:(freq:204);dl:(len: 8)), (fc:(freq: 44);dl:(len: 8)), (fc:(freq:172);dl:(len: 8)),\r
+(fc:(freq:108);dl:(len: 8)), (fc:(freq:236);dl:(len: 8)), (fc:(freq: 28);dl:(len: 8)),\r
+(fc:(freq:156);dl:(len: 8)), (fc:(freq: 92);dl:(len: 8)), (fc:(freq:220);dl:(len: 8)),\r
+(fc:(freq: 60);dl:(len: 8)), (fc:(freq:188);dl:(len: 8)), (fc:(freq:124);dl:(len: 8)),\r
+(fc:(freq:252);dl:(len: 8)), (fc:(freq:  2);dl:(len: 8)), (fc:(freq:130);dl:(len: 8)),\r
+(fc:(freq: 66);dl:(len: 8)), (fc:(freq:194);dl:(len: 8)), (fc:(freq: 34);dl:(len: 8)),\r
+(fc:(freq:162);dl:(len: 8)), (fc:(freq: 98);dl:(len: 8)), (fc:(freq:226);dl:(len: 8)),\r
+(fc:(freq: 18);dl:(len: 8)), (fc:(freq:146);dl:(len: 8)), (fc:(freq: 82);dl:(len: 8)),\r
+(fc:(freq:210);dl:(len: 8)), (fc:(freq: 50);dl:(len: 8)), (fc:(freq:178);dl:(len: 8)),\r
+(fc:(freq:114);dl:(len: 8)), (fc:(freq:242);dl:(len: 8)), (fc:(freq: 10);dl:(len: 8)),\r
+(fc:(freq:138);dl:(len: 8)), (fc:(freq: 74);dl:(len: 8)), (fc:(freq:202);dl:(len: 8)),\r
+(fc:(freq: 42);dl:(len: 8)), (fc:(freq:170);dl:(len: 8)), (fc:(freq:106);dl:(len: 8)),\r
+(fc:(freq:234);dl:(len: 8)), (fc:(freq: 26);dl:(len: 8)), (fc:(freq:154);dl:(len: 8)),\r
+(fc:(freq: 90);dl:(len: 8)), (fc:(freq:218);dl:(len: 8)), (fc:(freq: 58);dl:(len: 8)),\r
+(fc:(freq:186);dl:(len: 8)), (fc:(freq:122);dl:(len: 8)), (fc:(freq:250);dl:(len: 8)),\r
+(fc:(freq:  6);dl:(len: 8)), (fc:(freq:134);dl:(len: 8)), (fc:(freq: 70);dl:(len: 8)),\r
+(fc:(freq:198);dl:(len: 8)), (fc:(freq: 38);dl:(len: 8)), (fc:(freq:166);dl:(len: 8)),\r
+(fc:(freq:102);dl:(len: 8)), (fc:(freq:230);dl:(len: 8)), (fc:(freq: 22);dl:(len: 8)),\r
+(fc:(freq:150);dl:(len: 8)), (fc:(freq: 86);dl:(len: 8)), (fc:(freq:214);dl:(len: 8)),\r
+(fc:(freq: 54);dl:(len: 8)), (fc:(freq:182);dl:(len: 8)), (fc:(freq:118);dl:(len: 8)),\r
+(fc:(freq:246);dl:(len: 8)), (fc:(freq: 14);dl:(len: 8)), (fc:(freq:142);dl:(len: 8)),\r
+(fc:(freq: 78);dl:(len: 8)), (fc:(freq:206);dl:(len: 8)), (fc:(freq: 46);dl:(len: 8)),\r
+(fc:(freq:174);dl:(len: 8)), (fc:(freq:110);dl:(len: 8)), (fc:(freq:238);dl:(len: 8)),\r
+(fc:(freq: 30);dl:(len: 8)), (fc:(freq:158);dl:(len: 8)), (fc:(freq: 94);dl:(len: 8)),\r
+(fc:(freq:222);dl:(len: 8)), (fc:(freq: 62);dl:(len: 8)), (fc:(freq:190);dl:(len: 8)),\r
+(fc:(freq:126);dl:(len: 8)), (fc:(freq:254);dl:(len: 8)), (fc:(freq:  1);dl:(len: 8)),\r
+(fc:(freq:129);dl:(len: 8)), (fc:(freq: 65);dl:(len: 8)), (fc:(freq:193);dl:(len: 8)),\r
+(fc:(freq: 33);dl:(len: 8)), (fc:(freq:161);dl:(len: 8)), (fc:(freq: 97);dl:(len: 8)),\r
+(fc:(freq:225);dl:(len: 8)), (fc:(freq: 17);dl:(len: 8)), (fc:(freq:145);dl:(len: 8)),\r
+(fc:(freq: 81);dl:(len: 8)), (fc:(freq:209);dl:(len: 8)), (fc:(freq: 49);dl:(len: 8)),\r
+(fc:(freq:177);dl:(len: 8)), (fc:(freq:113);dl:(len: 8)), (fc:(freq:241);dl:(len: 8)),\r
+(fc:(freq:  9);dl:(len: 8)), (fc:(freq:137);dl:(len: 8)), (fc:(freq: 73);dl:(len: 8)),\r
+(fc:(freq:201);dl:(len: 8)), (fc:(freq: 41);dl:(len: 8)), (fc:(freq:169);dl:(len: 8)),\r
+(fc:(freq:105);dl:(len: 8)), (fc:(freq:233);dl:(len: 8)), (fc:(freq: 25);dl:(len: 8)),\r
+(fc:(freq:153);dl:(len: 8)), (fc:(freq: 89);dl:(len: 8)), (fc:(freq:217);dl:(len: 8)),\r
+(fc:(freq: 57);dl:(len: 8)), (fc:(freq:185);dl:(len: 8)), (fc:(freq:121);dl:(len: 8)),\r
+(fc:(freq:249);dl:(len: 8)), (fc:(freq:  5);dl:(len: 8)), (fc:(freq:133);dl:(len: 8)),\r
+(fc:(freq: 69);dl:(len: 8)), (fc:(freq:197);dl:(len: 8)), (fc:(freq: 37);dl:(len: 8)),\r
+(fc:(freq:165);dl:(len: 8)), (fc:(freq:101);dl:(len: 8)), (fc:(freq:229);dl:(len: 8)),\r
+(fc:(freq: 21);dl:(len: 8)), (fc:(freq:149);dl:(len: 8)), (fc:(freq: 85);dl:(len: 8)),\r
+(fc:(freq:213);dl:(len: 8)), (fc:(freq: 53);dl:(len: 8)), (fc:(freq:181);dl:(len: 8)),\r
+(fc:(freq:117);dl:(len: 8)), (fc:(freq:245);dl:(len: 8)), (fc:(freq: 13);dl:(len: 8)),\r
+(fc:(freq:141);dl:(len: 8)), (fc:(freq: 77);dl:(len: 8)), (fc:(freq:205);dl:(len: 8)),\r
+(fc:(freq: 45);dl:(len: 8)), (fc:(freq:173);dl:(len: 8)), (fc:(freq:109);dl:(len: 8)),\r
+(fc:(freq:237);dl:(len: 8)), (fc:(freq: 29);dl:(len: 8)), (fc:(freq:157);dl:(len: 8)),\r
+(fc:(freq: 93);dl:(len: 8)), (fc:(freq:221);dl:(len: 8)), (fc:(freq: 61);dl:(len: 8)),\r
+(fc:(freq:189);dl:(len: 8)), (fc:(freq:125);dl:(len: 8)), (fc:(freq:253);dl:(len: 8)),\r
+(fc:(freq: 19);dl:(len: 9)), (fc:(freq:275);dl:(len: 9)), (fc:(freq:147);dl:(len: 9)),\r
+(fc:(freq:403);dl:(len: 9)), (fc:(freq: 83);dl:(len: 9)), (fc:(freq:339);dl:(len: 9)),\r
+(fc:(freq:211);dl:(len: 9)), (fc:(freq:467);dl:(len: 9)), (fc:(freq: 51);dl:(len: 9)),\r
+(fc:(freq:307);dl:(len: 9)), (fc:(freq:179);dl:(len: 9)), (fc:(freq:435);dl:(len: 9)),\r
+(fc:(freq:115);dl:(len: 9)), (fc:(freq:371);dl:(len: 9)), (fc:(freq:243);dl:(len: 9)),\r
+(fc:(freq:499);dl:(len: 9)), (fc:(freq: 11);dl:(len: 9)), (fc:(freq:267);dl:(len: 9)),\r
+(fc:(freq:139);dl:(len: 9)), (fc:(freq:395);dl:(len: 9)), (fc:(freq: 75);dl:(len: 9)),\r
+(fc:(freq:331);dl:(len: 9)), (fc:(freq:203);dl:(len: 9)), (fc:(freq:459);dl:(len: 9)),\r
+(fc:(freq: 43);dl:(len: 9)), (fc:(freq:299);dl:(len: 9)), (fc:(freq:171);dl:(len: 9)),\r
+(fc:(freq:427);dl:(len: 9)), (fc:(freq:107);dl:(len: 9)), (fc:(freq:363);dl:(len: 9)),\r
+(fc:(freq:235);dl:(len: 9)), (fc:(freq:491);dl:(len: 9)), (fc:(freq: 27);dl:(len: 9)),\r
+(fc:(freq:283);dl:(len: 9)), (fc:(freq:155);dl:(len: 9)), (fc:(freq:411);dl:(len: 9)),\r
+(fc:(freq: 91);dl:(len: 9)), (fc:(freq:347);dl:(len: 9)), (fc:(freq:219);dl:(len: 9)),\r
+(fc:(freq:475);dl:(len: 9)), (fc:(freq: 59);dl:(len: 9)), (fc:(freq:315);dl:(len: 9)),\r
+(fc:(freq:187);dl:(len: 9)), (fc:(freq:443);dl:(len: 9)), (fc:(freq:123);dl:(len: 9)),\r
+(fc:(freq:379);dl:(len: 9)), (fc:(freq:251);dl:(len: 9)), (fc:(freq:507);dl:(len: 9)),\r
+(fc:(freq:  7);dl:(len: 9)), (fc:(freq:263);dl:(len: 9)), (fc:(freq:135);dl:(len: 9)),\r
+(fc:(freq:391);dl:(len: 9)), (fc:(freq: 71);dl:(len: 9)), (fc:(freq:327);dl:(len: 9)),\r
+(fc:(freq:199);dl:(len: 9)), (fc:(freq:455);dl:(len: 9)), (fc:(freq: 39);dl:(len: 9)),\r
+(fc:(freq:295);dl:(len: 9)), (fc:(freq:167);dl:(len: 9)), (fc:(freq:423);dl:(len: 9)),\r
+(fc:(freq:103);dl:(len: 9)), (fc:(freq:359);dl:(len: 9)), (fc:(freq:231);dl:(len: 9)),\r
+(fc:(freq:487);dl:(len: 9)), (fc:(freq: 23);dl:(len: 9)), (fc:(freq:279);dl:(len: 9)),\r
+(fc:(freq:151);dl:(len: 9)), (fc:(freq:407);dl:(len: 9)), (fc:(freq: 87);dl:(len: 9)),\r
+(fc:(freq:343);dl:(len: 9)), (fc:(freq:215);dl:(len: 9)), (fc:(freq:471);dl:(len: 9)),\r
+(fc:(freq: 55);dl:(len: 9)), (fc:(freq:311);dl:(len: 9)), (fc:(freq:183);dl:(len: 9)),\r
+(fc:(freq:439);dl:(len: 9)), (fc:(freq:119);dl:(len: 9)), (fc:(freq:375);dl:(len: 9)),\r
+(fc:(freq:247);dl:(len: 9)), (fc:(freq:503);dl:(len: 9)), (fc:(freq: 15);dl:(len: 9)),\r
+(fc:(freq:271);dl:(len: 9)), (fc:(freq:143);dl:(len: 9)), (fc:(freq:399);dl:(len: 9)),\r
+(fc:(freq: 79);dl:(len: 9)), (fc:(freq:335);dl:(len: 9)), (fc:(freq:207);dl:(len: 9)),\r
+(fc:(freq:463);dl:(len: 9)), (fc:(freq: 47);dl:(len: 9)), (fc:(freq:303);dl:(len: 9)),\r
+(fc:(freq:175);dl:(len: 9)), (fc:(freq:431);dl:(len: 9)), (fc:(freq:111);dl:(len: 9)),\r
+(fc:(freq:367);dl:(len: 9)), (fc:(freq:239);dl:(len: 9)), (fc:(freq:495);dl:(len: 9)),\r
+(fc:(freq: 31);dl:(len: 9)), (fc:(freq:287);dl:(len: 9)), (fc:(freq:159);dl:(len: 9)),\r
+(fc:(freq:415);dl:(len: 9)), (fc:(freq: 95);dl:(len: 9)), (fc:(freq:351);dl:(len: 9)),\r
+(fc:(freq:223);dl:(len: 9)), (fc:(freq:479);dl:(len: 9)), (fc:(freq: 63);dl:(len: 9)),\r
+(fc:(freq:319);dl:(len: 9)), (fc:(freq:191);dl:(len: 9)), (fc:(freq:447);dl:(len: 9)),\r
+(fc:(freq:127);dl:(len: 9)), (fc:(freq:383);dl:(len: 9)), (fc:(freq:255);dl:(len: 9)),\r
+(fc:(freq:511);dl:(len: 9)), (fc:(freq:  0);dl:(len: 7)), (fc:(freq: 64);dl:(len: 7)),\r
+(fc:(freq: 32);dl:(len: 7)), (fc:(freq: 96);dl:(len: 7)), (fc:(freq: 16);dl:(len: 7)),\r
+(fc:(freq: 80);dl:(len: 7)), (fc:(freq: 48);dl:(len: 7)), (fc:(freq:112);dl:(len: 7)),\r
+(fc:(freq:  8);dl:(len: 7)), (fc:(freq: 72);dl:(len: 7)), (fc:(freq: 40);dl:(len: 7)),\r
+(fc:(freq:104);dl:(len: 7)), (fc:(freq: 24);dl:(len: 7)), (fc:(freq: 88);dl:(len: 7)),\r
+(fc:(freq: 56);dl:(len: 7)), (fc:(freq:120);dl:(len: 7)), (fc:(freq:  4);dl:(len: 7)),\r
+(fc:(freq: 68);dl:(len: 7)), (fc:(freq: 36);dl:(len: 7)), (fc:(freq:100);dl:(len: 7)),\r
+(fc:(freq: 20);dl:(len: 7)), (fc:(freq: 84);dl:(len: 7)), (fc:(freq: 52);dl:(len: 7)),\r
+(fc:(freq:116);dl:(len: 7)), (fc:(freq:  3);dl:(len: 8)), (fc:(freq:131);dl:(len: 8)),\r
+(fc:(freq: 67);dl:(len: 8)), (fc:(freq:195);dl:(len: 8)), (fc:(freq: 35);dl:(len: 8)),\r
+(fc:(freq:163);dl:(len: 8)), (fc:(freq: 99);dl:(len: 8)), (fc:(freq:227);dl:(len: 8))\r
+);\r
+\r
+\r
+{ The static distance tree. (Actually a trivial tree since all lens use\r
+  5 bits.) }\r
+  static_dtree : array[0..D_CODES-1] of ct_data = (\r
+(fc:(freq: 0); dl:(len:5)), (fc:(freq:16); dl:(len:5)), (fc:(freq: 8); dl:(len:5)),\r
+(fc:(freq:24); dl:(len:5)), (fc:(freq: 4); dl:(len:5)), (fc:(freq:20); dl:(len:5)),\r
+(fc:(freq:12); dl:(len:5)), (fc:(freq:28); dl:(len:5)), (fc:(freq: 2); dl:(len:5)),\r
+(fc:(freq:18); dl:(len:5)), (fc:(freq:10); dl:(len:5)), (fc:(freq:26); dl:(len:5)),\r
+(fc:(freq: 6); dl:(len:5)), (fc:(freq:22); dl:(len:5)), (fc:(freq:14); dl:(len:5)),\r
+(fc:(freq:30); dl:(len:5)), (fc:(freq: 1); dl:(len:5)), (fc:(freq:17); dl:(len:5)),\r
+(fc:(freq: 9); dl:(len:5)), (fc:(freq:25); dl:(len:5)), (fc:(freq: 5); dl:(len:5)),\r
+(fc:(freq:21); dl:(len:5)), (fc:(freq:13); dl:(len:5)), (fc:(freq:29); dl:(len:5)),\r
+(fc:(freq: 3); dl:(len:5)), (fc:(freq:19); dl:(len:5)), (fc:(freq:11); dl:(len:5)),\r
+(fc:(freq:27); dl:(len:5)), (fc:(freq: 7); dl:(len:5)), (fc:(freq:23); dl:(len:5))\r
+);\r
+\r
+{ Distance codes. The first 256 values correspond to the distances\r
+  3 .. 258, the last 256 values correspond to the top 8 bits of\r
+  the 15 bit distances. }\r
+  _dist_code : array[0..DIST_CODE_LEN-1] of uch = (\r
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,\r
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,\r
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\r
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\r
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,\r
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\r
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\r
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\r
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\r
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,\r
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\r
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\r
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,\r
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\r
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\r
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\r
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\r
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,\r
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\r
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\r
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\r
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\r
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\r
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\r
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\r
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29\r
+);\r
+\r
+{ length code for each normalized match length (0 == MIN_MATCH) }\r
+  _length_code : array[0..MAX_MATCH-MIN_MATCH+1-1] of uch = (\r
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,\r
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\r
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,\r
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\r
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,\r
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,\r
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\r
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\r
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\r
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,\r
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\r
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\r
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28\r
+);\r
+\r
+  \r
+{ First normalized length for each code (0 = MIN_MATCH) }\r
+  base_length : array[0..LENGTH_CODES-1] of int = (\r
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,\r
+64, 80, 96, 112, 128, 160, 192, 224, 0\r
+);\r
+\r
+\r
+{ First normalized distance for each code (0 = distance of 1) }\r
+  base_dist : array[0..D_CODES-1] of int = (\r
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,\r
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,\r
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576\r
+);\r
+{$endif}\r
+\r
+{ Output a byte on the stream.\r
+  IN assertion: there is enough room in pending_buf.\r
+macro put_byte(s, c)\r
+begin\r
+  s^.pending_buf^[s^.pending] := (c);\r
+  Inc(s^.pending);\r
+end\r
+}\r
+\r
+const\r
+  MIN_LOOKAHEAD = (MAX_MATCH+MIN_MATCH+1);\r
+{ Minimum amount of lookahead, except at the end of the input file.\r
+  See deflate.c for comments about the MIN_MATCH+1. }\r
+\r
+{macro d_code(dist)\r
+   if (dist) < 256 then\r
+     := _dist_code[dist]\r
+   else\r
+     := _dist_code[256+((dist) shr 7)]);\r
+  Mapping from a distance to a distance code. dist is the distance - 1 and\r
+  must not have side effects. _dist_code[256] and _dist_code[257] are never\r
+  used. }\r
+\r
+{$ifndef ORG_DEBUG}\r
+{ Inline versions of _tr_tally for speed: }\r
+\r
+#if defined(GEN_TREES_H) || !defined(STDC)\r
+  extern uch _length_code[];\r
+  extern uch _dist_code[];\r
+#else\r
+  extern const uch _length_code[];\r
+  extern const uch _dist_code[];\r
+#endif\r
+\r
+macro _tr_tally_lit(s, c, flush)\r
+var\r
+  cc : uch;\r
+begin\r
+    cc := (c);\r
+    s^.d_buf[s^.last_lit] := 0;\r
+    s^.l_buf[s^.last_lit] := cc;\r
+    Inc(s^.last_lit);\r
+    Inc(s^.dyn_ltree[cc].fc.Freq);\r
+    flush := (s^.last_lit = s^.lit_bufsize-1);\r
+end;\r
+\r
+macro _tr_tally_dist(s, distance, length, flush) \\r
+var\r
+  len : uch;\r
+  dist : ush;\r
+begin\r
+    len := (length);\r
+    dist := (distance);\r
+    s^.d_buf[s^.last_lit] := dist;\r
+    s^.l_buf[s^.last_lit] = len;\r
+    Inc(s^.last_lit);\r
+    Dec(dist);\r
+    Inc(s^.dyn_ltree[_length_code[len]+LITERALS+1].fc.Freq);\r
+    Inc(s^.dyn_dtree[d_code(dist)].Freq);\r
+    flush := (s^.last_lit = s^.lit_bufsize-1);\r
+end;\r
+\r
+{$endif}\r
+\r
+{ ===========================================================================\r
+  Constants }\r
+\r
+const\r
+  MAX_BL_BITS = 7;\r
+{ Bit length codes must not exceed MAX_BL_BITS bits }\r
+\r
+const\r
+  END_BLOCK = 256;\r
+{ end of block literal code }\r
+\r
+const\r
+  REP_3_6 = 16;\r
+{ repeat previous bit length 3-6 times (2 bits of repeat count) }\r
+\r
+const\r
+  REPZ_3_10 = 17;\r
+{ repeat a zero length 3-10 times  (3 bits of repeat count) }\r
+\r
+const\r
+  REPZ_11_138 = 18;\r
+{ repeat a zero length 11-138 times  (7 bits of repeat count) }\r
+\r
+{local}\r
+const\r
+  extra_lbits : array[0..LENGTH_CODES-1] of int\r
+    { extra bits for each length code }\r
+   = (0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0);\r
+\r
+{local}\r
+const\r
+  extra_dbits : array[0..D_CODES-1] of int\r
+    { extra bits for each distance code }\r
+   = (0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13);\r
+\r
+{local}\r
+const\r
+  extra_blbits : array[0..BL_CODES-1] of int { extra bits for each bit length code }\r
+   = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7);\r
+\r
+{local}\r
+const\r
+  bl_order : array[0..BL_CODES-1] of uch\r
+   = (16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15);\r
+{ The lengths of the bit length codes are sent in order of decreasing\r
+  probability, to avoid transmitting the lengths for unused bit length codes.\r
+ }\r
+\r
+const\r
+  Buf_size = (8 * 2*sizeof(char));\r
+{ Number of bits used within bi_buf. (bi_buf might be implemented on\r
+  more than 16 bits on some systems.) }\r
+\r
+{ ===========================================================================\r
+  Local data. These are initialized only once. }\r
+\r
+\r
+{$ifdef GEN_TREES_H)}\r
+{ non ANSI compilers may not accept trees.h }\r
+\r
+const\r
+  DIST_CODE_LEN = 512; { see definition of array dist_code below }\r
+\r
+{local}\r
+var\r
+  static_ltree : array[0..L_CODES+2-1] of ct_data;\r
+{ The static literal tree. Since the bit lengths are imposed, there is no\r
+  need for the L_CODES extra codes used during heap construction. However\r
+  The codes 286 and 287 are needed to build a canonical tree (see _tr_init\r
+  below). }\r
+\r
+{local}\r
+  static_dtree : array[0..D_CODES-1] of ct_data;\r
+{ The static distance tree. (Actually a trivial tree since all codes use\r
+  5 bits.) }\r
+\r
+  _dist_code : array[0..DIST_CODE_LEN-1] of uch;\r
+{ Distance codes. The first 256 values correspond to the distances\r
+  3 .. 258, the last 256 values correspond to the top 8 bits of\r
+  the 15 bit distances. }\r
+\r
+  _length_code : array[0..MAX_MATCH-MIN_MATCH+1-1] of uch;\r
+{ length code for each normalized match length (0 == MIN_MATCH) }\r
+\r
+{local}\r
+  base_length : array[0..LENGTH_CODES-1] of int;\r
+{ First normalized length for each code (0 = MIN_MATCH) }\r
+\r
+{local}\r
+  base_dist : array[0..D_CODES-1] of int;\r
+{ First normalized distance for each code (0 = distance of 1) }\r
+\r
+{$endif} { GEN_TREES_H }\r
+\r
+{local}\r
+const\r
+  static_l_desc :  static_tree_desc  =\r
+      (static_tree: {tree_ptr}(@(static_ltree));  { pointer to array of ct_data }\r
+       extra_bits: {pzIntfArray}(@(extra_lbits)); { pointer to array of int }\r
+       extra_base: LITERALS+1;\r
+       elems: L_CODES;\r
+       max_length: MAX_BITS);\r
+\r
+{local}\r
+const\r
+  static_d_desc : static_tree_desc  =\r
+      (static_tree: {tree_ptr}(@(static_dtree));\r
+       extra_bits: {pzIntfArray}(@(extra_dbits));\r
+       extra_base : 0;\r
+       elems: D_CODES;\r
+       max_length: MAX_BITS);\r
+\r
+{local}\r
+const\r
+  static_bl_desc : static_tree_desc =\r
+      (static_tree: {tree_ptr}(NIL);\r
+       extra_bits: {pzIntfArray}@(extra_blbits);\r
+       extra_base : 0;\r
+       elems: BL_CODES;\r
+       max_length: MAX_BL_BITS);\r
+\r
+(* ===========================================================================\r
+  Local (static) routines in this file. }\r
+\r
+procedure tr_static_init;\r
+procedure init_block(var deflate_state);\r
+procedure pqdownheap(var s : deflate_state;\r
+                     var tree : ct_data;\r
+                     k : int);\r
+procedure gen_bitlen(var s : deflate_state;\r
+                     var desc : tree_desc);\r
+procedure gen_codes(var tree : ct_data;\r
+                    max_code : int;\r
+                    bl_count : pushf);\r
+procedure build_tree(var s : deflate_state;\r
+                     var desc : tree_desc);\r
+procedure scan_tree(var s : deflate_state;\r
+                    var tree : ct_data;\r
+                    max_code : int);\r
+procedure send_tree(var s : deflate_state;\r
+                    var tree : ct_data;\r
+                    max_code : int);\r
+function build_bl_tree(var deflate_state) : int;\r
+procedure send_all_trees(var deflate_state;\r
+                         lcodes : int;\r
+                         dcodes : int;\r
+                         blcodes : int);\r
+procedure compress_block(var s : deflate_state;\r
+                         var ltree : ct_data;\r
+                         var dtree : ct_data);\r
+procedure set_data_type(var s : deflate_state);\r
+function bi_reverse(value : unsigned;\r
+                    length : int) : unsigned;\r
+procedure bi_windup(var deflate_state);\r
+procedure bi_flush(var deflate_state);\r
+procedure copy_block(var deflate_state;\r
+                     buf : pcharf;\r
+                     len : unsigned;\r
+                     header : int);\r
+*)\r
+\r
+{$ifdef GEN_TREES_H}\r
+{local}\r
+procedure gen_trees_header;\r
+{$endif}\r
+\r
+(*\r
+{ ===========================================================================\r
+  Output a short LSB first on the stream.\r
+  IN assertion: there is enough room in pendingBuf. }\r
+\r
+macro put_short(s, w)\r
+begin\r
+    {put_byte(s, (uch)((w) & 0xff));}\r
+    s.pending_buf^[s.pending] := uch((w) and $ff);\r
+    Inc(s.pending);\r
+\r
+    {put_byte(s, (uch)((ush)(w) >> 8));}\r
+    s.pending_buf^[s.pending] := uch(ush(w) shr 8);;\r
+    Inc(s.pending);\r
+end\r
+*)\r
+\r
+{ ===========================================================================\r
+  Send a value on a given number of bits.\r
+  IN assertion: length <= 16 and value fits in length bits. }\r
+\r
+{$ifdef ORG_DEBUG}\r
+\r
+{local}\r
+procedure send_bits(var s : deflate_state;\r
+                    value : int;   { value to send }\r
+                    length : int); { number of bits }\r
+begin\r
+  {$ifdef DEBUG}\r
+  Tracevv(' l '+IntToStr(length)+ ' v '+IntToStr(value));\r
+  Assert((length > 0) and (length <= 15), 'invalid length');\r
+  Inc(s.bits_sent, ulg(length));\r
+  {$ENDIF}\r
+\r
+  { If not enough room in bi_buf, use (valid) bits from bi_buf and\r
+    (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))\r
+    unused bits in value. }\r
+  {$IFOPT Q+} {$Q-} {$DEFINE NoOverflowCheck} {$ENDIF}\r
+  {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}\r
+  if (s.bi_valid > int(Buf_size) - length) then\r
+  begin\r
+    s.bi_buf := s.bi_buf or int(value shl s.bi_valid);\r
+    {put_short(s, s.bi_buf);}\r
+    s.pending_buf^[s.pending] := uch(s.bi_buf and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);;\r
+    Inc(s.pending);\r
+\r
+    s.bi_buf := ush(value) shr (Buf_size - s.bi_valid);\r
+    Inc(s.bi_valid, length - Buf_size);\r
+  end\r
+  else\r
+  begin\r
+    s.bi_buf := s.bi_buf or int(value shl s.bi_valid);\r
+    Inc(s.bi_valid, length);\r
+  end;\r
+  {$IFDEF NoOverflowCheck} {$Q+} {$UNDEF NoOverflowCheck} {$ENDIF}\r
+  {$IFDEF NoRangeCheck} {$Q+} {$UNDEF NoRangeCheck} {$ENDIF}\r
+end;\r
+\r
+{$else} { !DEBUG }\r
+\r
+\r
+macro send_code(s, c, tree)\r
+begin\r
+  send_bits(s, tree[c].Code, tree[c].Len);\r
+  { Send a code of the given tree. c and tree must not have side effects }\r
+end\r
+\r
+macro send_bits(s, value, length) \\r
+begin int len := length;\\r
+  if (s^.bi_valid > (int)Buf_size - len) begin\\r
+    int val := value;\\r
+    s^.bi_buf |= (val << s^.bi_valid);\\r
+    {put_short(s, s.bi_buf);}\r
+    s.pending_buf^[s.pending] := uch(s.bi_buf and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);;\r
+    Inc(s.pending);\r
+\r
+    s^.bi_buf := (ush)val >> (Buf_size - s^.bi_valid);\\r
+    s^.bi_valid += len - Buf_size;\\r
+  end else begin\\r
+    s^.bi_buf |= (value) << s^.bi_valid;\\r
+    s^.bi_valid += len;\\r
+  end\\r
+end;\r
+{$endif} { DEBUG }\r
+\r
+{ ===========================================================================\r
+  Reverse the first len bits of a code, using straightforward code (a faster\r
+  method would use a table)\r
+  IN assertion: 1 <= len <= 15 }\r
+\r
+{local}\r
+function bi_reverse(code : unsigned;         { the value to invert }\r
+                    len : int) : unsigned;   { its bit length }\r
+\r
+var\r
+  res : unsigned; {register}\r
+begin\r
+  res := 0;\r
+  repeat\r
+    res := res or (code and 1);\r
+    code := code shr 1;\r
+    res := res shl 1;\r
+    Dec(len);\r
+  until (len <= 0);\r
+  bi_reverse := res shr 1;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Generate the codes for a given tree and bit counts (which need not be\r
+  optimal).\r
+  IN assertion: the array bl_count contains the bit length statistics for\r
+  the given tree and the field len is set for all tree elements.\r
+  OUT assertion: the field code is set for all tree elements of non\r
+      zero code length. }\r
+\r
+{local}\r
+procedure gen_codes(tree : tree_ptr;  { the tree to decorate }\r
+                    max_code : int;   { largest code with non zero frequency }\r
+                    var bl_count : array of ushf);  { number of codes at each bit length }\r
+\r
+var\r
+  next_code : array[0..MAX_BITS+1-1] of ush; { next code value for each bit length }\r
+  code : ush;              { running code value }\r
+  bits : int;                  { bit index }\r
+  n : int;                     { code index }\r
+var\r
+  len : int;\r
+begin\r
+  code := 0;\r
+\r
+  { The distribution counts are first used to generate the code values\r
+    without bit reversal. }\r
+\r
+  for bits := 1 to MAX_BITS do\r
+  begin\r
+    code := ((code + bl_count[bits-1]) shl 1);\r
+    next_code[bits] := code;\r
+  end;\r
+  { Check that the bit counts in bl_count are consistent. The last code\r
+    must be all ones. }\r
+\r
+  {$IFDEF DEBUG}\r
+  Assert (code + bl_count[MAX_BITS]-1 = (1 shl MAX_BITS)-1,\r
+          'inconsistent bit counts');\r
+  Tracev(#13'gen_codes: max_code '+IntToStr(max_code));\r
+  {$ENDIF}\r
+\r
+  for n := 0 to max_code do\r
+  begin\r
+    len := tree^[n].dl.Len;\r
+    if (len = 0) then\r
+      continue;\r
+    { Now reverse the bits }\r
+    tree^[n].fc.Code := bi_reverse(next_code[len], len);\r
+    Inc(next_code[len]);\r
+    {$ifdef DEBUG}\r
+    if (n>31) and (n<128) then\r
+      Tracecv(tree <> tree_ptr(@static_ltree),\r
+       (^M'n #'+IntToStr(n)+' '+char(n)+' l '+IntToStr(len)+' c '+\r
+         IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')'))\r
+    else\r
+      Tracecv(tree <> tree_ptr(@static_ltree),\r
+      (^M'n #'+IntToStr(n)+'   l '+IntToStr(len)+' c '+\r
+         IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')'));\r
+    {$ENDIF}\r
+  end;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Genererate the file trees.h describing the static trees. }\r
+{$ifdef GEN_TREES_H}\r
+\r
+macro SEPARATOR(i, last, width)\r
+  if (i) = (last) then\r
+    ( ^M');'^M^M\r
+  else    \\r
+    if (i) mod (width) = (width)-1 then\r
+       ','^M\r
+     else\r
+       ', '\r
+\r
+procedure gen_trees_header;\r
+var\r
+  header : system.text;\r
+  i : int;\r
+begin\r
+  system.assign(header, 'trees.inc');\r
+  {$I-}\r
+  ReWrite(header);\r
+  {$I+}\r
+  Assert (IOresult <> 0, 'Can''t open trees.h');\r
+  WriteLn(header,\r
+    '{ header created automatically with -DGEN_TREES_H }'^M);\r
+\r
+  WriteLn(header, 'local const ct_data static_ltree[L_CODES+2] := (');\r
+  for i := 0 to L_CODES+2-1 do\r
+  begin\r
+    WriteLn(header, '((%3u),(%3u))%s', static_ltree[i].Code,\r
+               static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));\r
+  end;\r
+\r
+  WriteLn(header, 'local const ct_data static_dtree[D_CODES] := (');\r
+  for i := 0 to D_CODES-1 do\r
+  begin\r
+    WriteLn(header, '((%2u),(%2u))%s', static_dtree[i].Code,\r
+               static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));\r
+  end;\r
+\r
+  WriteLn(header, 'const uch _dist_code[DIST_CODE_LEN] := (');\r
+  for i := 0 to DIST_CODE_LEN-1 do\r
+  begin\r
+    WriteLn(header, '%2u%s', _dist_code[i],\r
+               SEPARATOR(i, DIST_CODE_LEN-1, 20));\r
+  end;\r
+\r
+  WriteLn(header, 'const uch _length_code[MAX_MATCH-MIN_MATCH+1]= (');\r
+  for i := 0 to MAX_MATCH-MIN_MATCH+1-1 do\r
+  begin\r
+    WriteLn(header, '%2u%s', _length_code[i],\r
+               SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));\r
+  end;\r
+\r
+  WriteLn(header, 'local const int base_length[LENGTH_CODES] := (');\r
+  for i := 0 to LENGTH_CODES-1 do\r
+  begin\r
+    WriteLn(header, '%1u%s', base_length[i],\r
+               SEPARATOR(i, LENGTH_CODES-1, 20));\r
+  end;\r
+\r
+  WriteLn(header, 'local const int base_dist[D_CODES] := (');\r
+  for i := 0 to D_CODES-1 do\r
+  begin\r
+    WriteLn(header, '%5u%s', base_dist[i],\r
+               SEPARATOR(i, D_CODES-1, 10));\r
+  end;\r
+\r
+  close(header);\r
+end;\r
+{$endif} { GEN_TREES_H }\r
+\r
+\r
+{ ===========================================================================\r
+  Initialize the various 'constant' tables. }\r
+\r
+{local}\r
+procedure tr_static_init;\r
+\r
+{$ifdef GEN_TREES_H}\r
+const\r
+  static_init_done : boolean = FALSE;\r
+var\r
+  n : int;        { iterates over tree elements }\r
+  bits : int;     { bit counter }\r
+  length : int;   { length value }\r
+  code : int;     { code value }\r
+  dist : int;     { distance index }\r
+  bl_count : array[0..MAX_BITS+1-1] of ush;\r
+    { number of codes at each bit length for an optimal tree }\r
+begin\r
+    if (static_init_done) then\r
+      exit;\r
+\r
+    { Initialize the mapping length (0..255) -> length code (0..28) }\r
+    length := 0;\r
+    for code := 0 to LENGTH_CODES-1-1 do\r
+    begin\r
+      base_length[code] := length;\r
+      for n := 0 to (1 shl extra_lbits[code])-1 do\r
+      begin\r
+        _length_code[length] := uch(code);\r
+        Inc(length);\r
+      end;\r
+    end;\r
+    Assert (length = 256, 'tr_static_init: length <> 256');\r
+    { Note that the length 255 (match length 258) can be represented\r
+      in two different ways: code 284 + 5 bits or code 285, so we\r
+      overwrite length_code[255] to use the best encoding: }\r
+\r
+    _length_code[length-1] := uch(code);\r
+\r
+    { Initialize the mapping dist (0..32K) -> dist code (0..29) }\r
+    dist := 0;\r
+    for code := 0 to 16-1 do\r
+    begin\r
+      base_dist[code] := dist;\r
+      for n := 0 to (1 shl extra_dbits[code])-1 do\r
+      begin\r
+        _dist_code[dist] := uch(code);\r
+        Inc(dist);\r
+      end;\r
+    end;\r
+    Assert (dist = 256, 'tr_static_init: dist <> 256');\r
+    dist := dist shr 7; { from now on, all distances are divided by 128 }\r
+    for code := 16 to D_CODES-1 do\r
+    begin\r
+      base_dist[code] := dist shl 7;\r
+      for n := 0 to (1 shl (extra_dbits[code]-7))-1 do\r
+      begin\r
+        _dist_code[256 + dist] := uch(code);\r
+        Inc(dist);\r
+      end;\r
+    end;\r
+    Assert (dist = 256, 'tr_static_init: 256+dist <> 512');\r
+\r
+    { Construct the codes of the static literal tree }\r
+    for bits := 0 to MAX_BITS do\r
+      bl_count[bits] := 0;\r
+    n := 0;\r
+    while (n <= 143) do\r
+    begin\r
+      static_ltree[n].dl.Len := 8;\r
+      Inc(n);\r
+      Inc(bl_count[8]);\r
+    end;\r
+    while (n <= 255) do\r
+    begin\r
+      static_ltree[n].dl.Len := 9;\r
+      Inc(n);\r
+      Inc(bl_count[9]);\r
+    end;\r
+    while (n <= 279) do\r
+    begin\r
+      static_ltree[n].dl.Len := 7;\r
+      Inc(n);\r
+      Inc(bl_count[7]);\r
+    end;\r
+    while (n <= 287) do\r
+    begin\r
+      static_ltree[n].dl.Len := 8;\r
+      Inc(n);\r
+      Inc(bl_count[8]);\r
+    end;\r
+\r
+    { Codes 286 and 287 do not exist, but we must include them in the\r
+      tree construction to get a canonical Huffman tree (longest code\r
+      all ones)  }\r
+\r
+    gen_codes(tree_ptr(@static_ltree), L_CODES+1, bl_count);\r
+\r
+    { The static distance tree is trivial: }\r
+    for n := 0 to D_CODES-1 do\r
+    begin\r
+      static_dtree[n].dl.Len := 5;\r
+      static_dtree[n].fc.Code := bi_reverse(unsigned(n), 5);\r
+    end;\r
+    static_init_done := TRUE;\r
+\r
+    gen_trees_header;  { save to include file }\r
+{$else}\r
+begin\r
+{$endif} { GEN_TREES_H) }\r
+end;\r
+\r
+{ ===========================================================================\r
+  Initialize a new block. }\r
+{local}\r
+\r
+procedure init_block(var s : deflate_state);\r
+var\r
+  n : int; { iterates over tree elements }\r
+begin\r
+  { Initialize the trees. }\r
+  for n := 0 to L_CODES-1 do\r
+    s.dyn_ltree[n].fc.Freq := 0;\r
+  for n := 0 to D_CODES-1 do\r
+    s.dyn_dtree[n].fc.Freq := 0;\r
+  for n := 0 to BL_CODES-1 do\r
+    s.bl_tree[n].fc.Freq := 0;\r
+\r
+  s.dyn_ltree[END_BLOCK].fc.Freq := 1;\r
+  s.static_len := Long(0);\r
+  s.opt_len := Long(0);\r
+  s.matches := 0;\r
+  s.last_lit := 0;\r
+end;\r
+\r
+const\r
+  SMALLEST = 1;\r
+{ Index within the heap array of least frequent node in the Huffman tree }\r
+\r
+{ ===========================================================================\r
+  Initialize the tree data structures for a new zlib stream. }\r
+procedure _tr_init(var s : deflate_state);\r
+begin\r
+  tr_static_init;\r
+\r
+  s.compressed_len := Long(0);\r
+\r
+  s.l_desc.dyn_tree := tree_ptr(@s.dyn_ltree);\r
+  s.l_desc.stat_desc := @static_l_desc;\r
+\r
+  s.d_desc.dyn_tree := tree_ptr(@s.dyn_dtree);\r
+  s.d_desc.stat_desc := @static_d_desc;\r
+\r
+  s.bl_desc.dyn_tree := tree_ptr(@s.bl_tree);\r
+  s.bl_desc.stat_desc := @static_bl_desc;\r
+\r
+  s.bi_buf := 0;\r
+  s.bi_valid := 0;\r
+  s.last_eob_len := 8; { enough lookahead for inflate }\r
+{$ifdef DEBUG}\r
+  s.bits_sent := Long(0);\r
+{$endif}\r
+\r
+  { Initialize the first block of the first file: }\r
+  init_block(s);\r
+end;\r
+\r
+{ ===========================================================================\r
+  Remove the smallest element from the heap and recreate the heap with\r
+  one less element. Updates heap and heap_len.\r
+\r
+macro pqremove(s, tree, top)\r
+begin\r
+    top := s.heap[SMALLEST];\r
+    s.heap[SMALLEST] := s.heap[s.heap_len];\r
+    Dec(s.heap_len);\r
+    pqdownheap(s, tree, SMALLEST);\r
+end\r
+}\r
+\r
+{ ===========================================================================\r
+  Compares to subtrees, using the tree depth as tie breaker when\r
+  the subtrees have equal frequency. This minimizes the worst case length.\r
+\r
+macro smaller(tree, n, m, depth)\r
+   ( (tree[n].Freq < tree[m].Freq) or\r
+     ((tree[n].Freq = tree[m].Freq) and (depth[n] <= depth[m])) )\r
+}\r
+\r
+{ ===========================================================================\r
+  Restore the heap property by moving down the tree starting at node k,\r
+  exchanging a node with the smallest of its two sons if necessary, stopping\r
+  when the heap property is re-established (each father smaller than its\r
+  two sons). }\r
+{local}\r
+\r
+procedure pqdownheap(var s : deflate_state;\r
+                     var tree : tree_type;   { the tree to restore }\r
+                     k : int);          { node to move down }\r
+var\r
+  v : int;\r
+  j : int;\r
+begin\r
+  v := s.heap[k];\r
+  j := k shl 1;  { left son of k }\r
+  while (j <= s.heap_len) do\r
+  begin\r
+    { Set j to the smallest of the two sons: }\r
+    if (j < s.heap_len) and\r
+       {smaller(tree, s.heap[j+1], s.heap[j], s.depth)}\r
+      ( (tree[s.heap[j+1]].fc.Freq < tree[s.heap[j]].fc.Freq) or\r
+        ((tree[s.heap[j+1]].fc.Freq = tree[s.heap[j]].fc.Freq) and\r
+         (s.depth[s.heap[j+1]] <= s.depth[s.heap[j]])) ) then\r
+    begin\r
+      Inc(j);\r
+    end;\r
+    { Exit if v is smaller than both sons }\r
+    if {(smaller(tree, v, s.heap[j], s.depth))}\r
+     ( (tree[v].fc.Freq < tree[s.heap[j]].fc.Freq) or\r
+       ((tree[v].fc.Freq = tree[s.heap[j]].fc.Freq) and\r
+        (s.depth[v] <= s.depth[s.heap[j]])) ) then\r
+      break;\r
+    { Exchange v with the smallest son }\r
+    s.heap[k] := s.heap[j];\r
+    k := j;\r
+\r
+    { And continue down the tree, setting j to the left son of k }\r
+    j := j shl 1;\r
+  end;\r
+  s.heap[k] := v;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Compute the optimal bit lengths for a tree and update the total bit length\r
+  for the current block.\r
+  IN assertion: the fields freq and dad are set, heap[heap_max] and\r
+     above are the tree nodes sorted by increasing frequency.\r
+  OUT assertions: the field len is set to the optimal bit length, the\r
+      array bl_count contains the frequencies for each bit length.\r
+      The length opt_len is updated; static_len is also updated if stree is\r
+      not null. }\r
+\r
+{local}\r
+procedure gen_bitlen(var s : deflate_state;\r
+                     var desc : tree_desc);   { the tree descriptor }\r
+var\r
+  tree : tree_ptr;\r
+  max_code : int;\r
+  stree : tree_ptr; {const}\r
+  extra : pzIntfArray; {const}\r
+  base : int;\r
+  max_length : int;\r
+  h : int;              { heap index }\r
+  n, m : int;           { iterate over the tree elements }\r
+  bits : int;           { bit length }\r
+  xbits : int;          { extra bits }\r
+  f : ush;              { frequency }\r
+  overflow : int;   { number of elements with bit length too large }\r
+begin\r
+  tree := desc.dyn_tree;\r
+  max_code := desc.max_code;\r
+  stree := desc.stat_desc^.static_tree;\r
+  extra := desc.stat_desc^.extra_bits;\r
+  base := desc.stat_desc^.extra_base;\r
+  max_length := desc.stat_desc^.max_length;\r
+  overflow := 0;\r
+\r
+  for bits := 0 to MAX_BITS do\r
+    s.bl_count[bits] := 0;\r
+\r
+  { In a first pass, compute the optimal bit lengths (which may\r
+    overflow in the case of the bit length tree). }\r
+\r
+  tree^[s.heap[s.heap_max]].dl.Len := 0; { root of the heap }\r
+\r
+  for h := s.heap_max+1 to HEAP_SIZE-1 do\r
+  begin\r
+    n := s.heap[h];\r
+    bits := tree^[tree^[n].dl.Dad].dl.Len + 1;\r
+    if (bits > max_length) then\r
+    begin\r
+      bits := max_length;\r
+      Inc(overflow);\r
+    end;\r
+    tree^[n].dl.Len := ush(bits);\r
+    { We overwrite tree[n].dl.Dad which is no longer needed }\r
+\r
+    if (n > max_code) then\r
+      continue; { not a leaf node }\r
+\r
+    Inc(s.bl_count[bits]);\r
+    xbits := 0;\r
+    if (n >= base) then\r
+      xbits := extra^[n-base];\r
+    f := tree^[n].fc.Freq;\r
+    Inc(s.opt_len, ulg(f) * (bits + xbits));\r
+    if (stree <> NIL) then\r
+      Inc(s.static_len, ulg(f) * (stree^[n].dl.Len + xbits));\r
+  end;\r
+  if (overflow = 0) then\r
+    exit;\r
+  {$ifdef DEBUG}\r
+  Tracev(^M'bit length overflow');\r
+  {$endif}\r
+  { This happens for example on obj2 and pic of the Calgary corpus }\r
+\r
+  { Find the first bit length which could increase: }\r
+  repeat\r
+    bits := max_length-1;\r
+    while (s.bl_count[bits] = 0) do\r
+      Dec(bits);\r
+    Dec(s.bl_count[bits]);      { move one leaf down the tree }\r
+    Inc(s.bl_count[bits+1], 2); { move one overflow item as its brother }\r
+    Dec(s.bl_count[max_length]);\r
+    { The brother of the overflow item also moves one step up,\r
+      but this does not affect bl_count[max_length] }\r
+\r
+    Dec(overflow, 2);\r
+  until (overflow <= 0);\r
+\r
+  { Now recompute all bit lengths, scanning in increasing frequency.\r
+    h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\r
+    lengths instead of fixing only the wrong ones. This idea is taken\r
+    from 'ar' written by Haruhiko Okumura.) }\r
+  h := HEAP_SIZE;  { Delphi3: compiler warning w/o this }\r
+  for bits := max_length downto 1 do\r
+  begin\r
+    n := s.bl_count[bits];\r
+    while (n <> 0) do\r
+    begin\r
+      Dec(h);\r
+      m := s.heap[h];\r
+      if (m > max_code) then\r
+        continue;\r
+      if (tree^[m].dl.Len <> unsigned(bits)) then\r
+      begin\r
+        {$ifdef DEBUG}\r
+        Trace('code '+IntToStr(m)+' bits '+IntToStr(tree^[m].dl.Len)\r
+              +'.'+IntToStr(bits));\r
+        {$ENDIF}\r
+        Inc(s.opt_len, (long(bits) - long(tree^[m].dl.Len))\r
+                        * long(tree^[m].fc.Freq) );\r
+        tree^[m].dl.Len := ush(bits);\r
+      end;\r
+      Dec(n);\r
+    end;\r
+  end;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Construct one Huffman tree and assigns the code bit strings and lengths.\r
+  Update the total bit length for the current block.\r
+  IN assertion: the field freq is set for all tree elements.\r
+  OUT assertions: the fields len and code are set to the optimal bit length\r
+      and corresponding code. The length opt_len is updated; static_len is\r
+      also updated if stree is not null. The field max_code is set. }\r
+\r
+{local}\r
+procedure build_tree(var s : deflate_state;\r
+                     var desc : tree_desc); { the tree descriptor }\r
+\r
+var\r
+  tree : tree_ptr;\r
+  stree : tree_ptr; {const}\r
+  elems : int;\r
+  n, m : int;          { iterate over heap elements }\r
+  max_code : int;      { largest code with non zero frequency }\r
+  node : int;          { new node being created }\r
+begin\r
+  tree := desc.dyn_tree;\r
+  stree := desc.stat_desc^.static_tree;\r
+  elems := desc.stat_desc^.elems;\r
+  max_code := -1;\r
+\r
+  { Construct the initial heap, with least frequent element in\r
+    heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\r
+    heap[0] is not used. }\r
+  s.heap_len := 0;\r
+  s.heap_max := HEAP_SIZE;\r
+\r
+  for n := 0 to elems-1 do\r
+  begin\r
+    if (tree^[n].fc.Freq <> 0) then\r
+    begin\r
+      max_code := n;\r
+      Inc(s.heap_len);\r
+      s.heap[s.heap_len] := n;\r
+      s.depth[n] := 0;\r
+    end\r
+    else\r
+    begin\r
+      tree^[n].dl.Len := 0;\r
+    end;\r
+  end;\r
+\r
+  { The pkzip format requires that at least one distance code exists,\r
+    and that at least one bit should be sent even if there is only one\r
+    possible code. So to avoid special checks later on we force at least\r
+    two codes of non zero frequency. }\r
+\r
+  while (s.heap_len < 2) do\r
+  begin\r
+    Inc(s.heap_len);\r
+    if (max_code < 2) then\r
+    begin\r
+      Inc(max_code);\r
+      s.heap[s.heap_len] := max_code;\r
+      node := max_code;\r
+    end\r
+    else\r
+    begin\r
+      s.heap[s.heap_len] := 0;\r
+      node := 0;\r
+    end;\r
+    tree^[node].fc.Freq := 1;\r
+    s.depth[node] := 0;\r
+    Dec(s.opt_len);\r
+    if (stree <> NIL) then\r
+      Dec(s.static_len, stree^[node].dl.Len);\r
+    { node is 0 or 1 so it does not have extra bits }\r
+  end;\r
+  desc.max_code := max_code;\r
+\r
+  { The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\r
+    establish sub-heaps of increasing lengths: }\r
+\r
+  for n := s.heap_len div 2 downto 1 do\r
+    pqdownheap(s, tree^, n);\r
+\r
+  { Construct the Huffman tree by repeatedly combining the least two\r
+    frequent nodes. }\r
+\r
+  node := elems;              { next internal node of the tree }\r
+  repeat\r
+    {pqremove(s, tree, n);}  { n := node of least frequency }\r
+    n := s.heap[SMALLEST];\r
+    s.heap[SMALLEST] := s.heap[s.heap_len];\r
+    Dec(s.heap_len);\r
+    pqdownheap(s, tree^, SMALLEST);\r
+\r
+    m := s.heap[SMALLEST]; { m := node of next least frequency }\r
+\r
+    Dec(s.heap_max);\r
+    s.heap[s.heap_max] := n; { keep the nodes sorted by frequency }\r
+    Dec(s.heap_max);\r
+    s.heap[s.heap_max] := m;\r
+\r
+    { Create a new node father of n and m }\r
+    tree^[node].fc.Freq := tree^[n].fc.Freq + tree^[m].fc.Freq;\r
+    { maximum }\r
+    if (s.depth[n] >= s.depth[m]) then\r
+      s.depth[node] := uch (s.depth[n] + 1)\r
+    else\r
+      s.depth[node] := uch (s.depth[m] + 1);\r
+\r
+    tree^[m].dl.Dad := ush(node);\r
+    tree^[n].dl.Dad := ush(node);\r
+{$ifdef DUMP_BL_TREE}\r
+    if (tree = tree_ptr(@s.bl_tree)) then\r
+    begin\r
+      WriteLn(#13'node ',node,'(',tree^[node].fc.Freq,') sons ',n,\r
+              '(',tree^[n].fc.Freq,') ', m, '(',tree^[m].fc.Freq,')');\r
+    end;\r
+{$endif}\r
+    { and insert the new node in the heap }\r
+    s.heap[SMALLEST] := node;\r
+    Inc(node);\r
+    pqdownheap(s, tree^, SMALLEST);\r
+\r
+  until (s.heap_len < 2);\r
+\r
+  Dec(s.heap_max);\r
+  s.heap[s.heap_max] := s.heap[SMALLEST];\r
+\r
+  { At this point, the fields freq and dad are set. We can now\r
+    generate the bit lengths. }\r
+\r
+  gen_bitlen(s, desc);\r
+\r
+  { The field len is now set, we can generate the bit codes }\r
+  gen_codes (tree, max_code, s.bl_count);\r
+end;\r
+\r
+{ ===========================================================================\r
+  Scan a literal or distance tree to determine the frequencies of the codes\r
+  in the bit length tree. }\r
+\r
+{local}\r
+procedure scan_tree(var s : deflate_state;\r
+                    var tree : array of ct_data;    { the tree to be scanned }\r
+                    max_code : int);    { and its largest code of non zero frequency }\r
+var\r
+  n : int;                 { iterates over all tree elements }\r
+  prevlen : int;           { last emitted length }\r
+  curlen : int;            { length of current code }\r
+  nextlen : int;           { length of next code }\r
+  count : int;             { repeat count of the current code }\r
+  max_count : int;         { max repeat count }\r
+  min_count : int;         { min repeat count }\r
+begin\r
+  prevlen := -1;\r
+  nextlen := tree[0].dl.Len;\r
+  count := 0;\r
+  max_count := 7;\r
+  min_count := 4;\r
+\r
+  if (nextlen = 0) then\r
+  begin\r
+    max_count := 138;\r
+    min_count := 3;\r
+  end;\r
+  tree[max_code+1].dl.Len := ush($ffff); { guard }\r
+\r
+  for n := 0 to max_code do\r
+  begin\r
+    curlen := nextlen;\r
+    nextlen := tree[n+1].dl.Len;\r
+    Inc(count);\r
+    if (count < max_count) and (curlen = nextlen) then\r
+      continue\r
+    else\r
+      if (count < min_count) then\r
+        Inc(s.bl_tree[curlen].fc.Freq, count)\r
+      else\r
+        if (curlen <> 0) then\r
+        begin\r
+          if (curlen <> prevlen) then\r
+            Inc(s.bl_tree[curlen].fc.Freq);\r
+          Inc(s.bl_tree[REP_3_6].fc.Freq);\r
+        end\r
+        else\r
+          if (count <= 10) then\r
+            Inc(s.bl_tree[REPZ_3_10].fc.Freq)\r
+          else\r
+            Inc(s.bl_tree[REPZ_11_138].fc.Freq);\r
+\r
+    count := 0;\r
+    prevlen := curlen;\r
+    if (nextlen = 0) then\r
+    begin\r
+      max_count := 138;\r
+      min_count := 3;\r
+    end\r
+    else\r
+      if (curlen = nextlen) then\r
+      begin\r
+        max_count := 6;\r
+        min_count := 3;\r
+      end\r
+      else\r
+      begin\r
+        max_count := 7;\r
+        min_count := 4;\r
+      end;\r
+  end;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Send a literal or distance tree in compressed form, using the codes in\r
+  bl_tree. }\r
+\r
+{local}\r
+procedure send_tree(var s : deflate_state;\r
+                    var tree : array of ct_data;    { the tree to be scanned }\r
+                    max_code : int);    { and its largest code of non zero frequency }\r
+\r
+var\r
+  n : int;                { iterates over all tree elements }\r
+  prevlen : int;          { last emitted length }\r
+  curlen : int;           { length of current code }\r
+  nextlen : int;          { length of next code }\r
+  count : int;            { repeat count of the current code }\r
+  max_count : int;        { max repeat count }\r
+  min_count : int;        { min repeat count }\r
+begin\r
+  prevlen := -1;\r
+  nextlen := tree[0].dl.Len;\r
+  count := 0;\r
+  max_count := 7;\r
+  min_count := 4;\r
+\r
+  { tree[max_code+1].dl.Len := -1; }  { guard already set }\r
+  if (nextlen = 0) then\r
+  begin\r
+    max_count := 138;\r
+    min_count := 3;\r
+  end;\r
+\r
+  for n := 0 to max_code do\r
+  begin\r
+    curlen := nextlen;\r
+    nextlen := tree[n+1].dl.Len;\r
+    Inc(count);\r
+    if (count < max_count) and (curlen = nextlen) then\r
+      continue\r
+    else\r
+      if (count < min_count) then\r
+      begin\r
+        repeat\r
+          {$ifdef DEBUG}\r
+          Tracevvv(#13'cd '+IntToStr(curlen));\r
+          {$ENDIF}\r
+          send_bits(s, s.bl_tree[curlen].fc.Code, s.bl_tree[curlen].dl.Len);\r
+          Dec(count);\r
+        until (count = 0);\r
+      end\r
+      else\r
+        if (curlen <> 0) then\r
+        begin\r
+          if (curlen <> prevlen) then\r
+          begin\r
+            {$ifdef DEBUG}\r
+            Tracevvv(#13'cd '+IntToStr(curlen));\r
+            {$ENDIF}\r
+            send_bits(s, s.bl_tree[curlen].fc.Code, s.bl_tree[curlen].dl.Len);\r
+            Dec(count);\r
+          end;\r
+          {$IFDEF DEBUG}\r
+          Assert((count >= 3) and (count <= 6), ' 3_6?');\r
+          {$ENDIF}\r
+          {$ifdef DEBUG}\r
+          Tracevvv(#13'cd '+IntToStr(REP_3_6));\r
+          {$ENDIF}\r
+          send_bits(s, s.bl_tree[REP_3_6].fc.Code, s.bl_tree[REP_3_6].dl.Len);\r
+          send_bits(s, count-3, 2);\r
+        end\r
+        else\r
+          if (count <= 10) then\r
+          begin\r
+            {$ifdef DEBUG}\r
+            Tracevvv(#13'cd '+IntToStr(REPZ_3_10));\r
+            {$ENDIF}\r
+            send_bits(s, s.bl_tree[REPZ_3_10].fc.Code, s.bl_tree[REPZ_3_10].dl.Len);\r
+            send_bits(s, count-3, 3);\r
+          end\r
+          else\r
+          begin\r
+            {$ifdef DEBUG}\r
+            Tracevvv(#13'cd '+IntToStr(REPZ_11_138));\r
+            {$ENDIF}\r
+            send_bits(s, s.bl_tree[REPZ_11_138].fc.Code, s.bl_tree[REPZ_11_138].dl.Len);\r
+            send_bits(s, count-11, 7);\r
+          end;\r
+    count := 0;\r
+    prevlen := curlen;\r
+    if (nextlen = 0) then\r
+    begin\r
+      max_count := 138;\r
+      min_count := 3;\r
+    end\r
+    else\r
+      if (curlen = nextlen) then\r
+      begin\r
+        max_count := 6;\r
+        min_count := 3;\r
+      end\r
+      else\r
+      begin\r
+        max_count := 7;\r
+        min_count := 4;\r
+      end;\r
+  end;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Construct the Huffman tree for the bit lengths and return the index in\r
+  bl_order of the last bit length code to send. }\r
+\r
+{local}\r
+function build_bl_tree(var s : deflate_state) : int;\r
+var\r
+  max_blindex : int;  { index of last bit length code of non zero freq }\r
+begin\r
+  { Determine the bit length frequencies for literal and distance trees }\r
+  scan_tree(s, s.dyn_ltree, s.l_desc.max_code);\r
+  scan_tree(s, s.dyn_dtree, s.d_desc.max_code);\r
+\r
+  { Build the bit length tree: }\r
+  build_tree(s, s.bl_desc);\r
+  { opt_len now includes the length of the tree representations, except\r
+    the lengths of the bit lengths codes and the 5+5+4 bits for the counts. }\r
+\r
+  { Determine the number of bit length codes to send. The pkzip format\r
+    requires that at least 4 bit length codes be sent. (appnote.txt says\r
+    3 but the actual value used is 4.) }\r
+\r
+  for max_blindex := BL_CODES-1 downto 3 do\r
+  begin\r
+    if (s.bl_tree[bl_order[max_blindex]].dl.Len <> 0) then\r
+      break;\r
+  end;\r
+  { Update opt_len to include the bit length tree and counts }\r
+  Inc(s.opt_len, 3*(max_blindex+1) + 5+5+4);\r
+  {$ifdef DEBUG}\r
+  Tracev(^M'dyn trees: dyn %ld, stat %ld {s.opt_len, s.static_len}');\r
+  {$ENDIF}\r
+\r
+  build_bl_tree := max_blindex;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Send the header for a block using dynamic Huffman trees: the counts, the\r
+  lengths of the bit length codes, the literal tree and the distance tree.\r
+  IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. }\r
+\r
+{local}\r
+procedure send_all_trees(var s : deflate_state;\r
+                         lcodes : int;\r
+                         dcodes : int;\r
+                         blcodes : int); { number of codes for each tree }\r
+var\r
+  rank : int;                    { index in bl_order }\r
+begin\r
+  {$IFDEF DEBUG}\r
+  Assert ((lcodes >= 257) and (dcodes >= 1) and (blcodes >= 4),\r
+          'not enough codes');\r
+  Assert ((lcodes <= L_CODES) and (dcodes <= D_CODES)\r
+          and (blcodes <= BL_CODES), 'too many codes');\r
+  Tracev(^M'bl counts: ');\r
+  {$ENDIF}\r
+  send_bits(s, lcodes-257, 5); { not +255 as stated in appnote.txt }\r
+  send_bits(s, dcodes-1,   5);\r
+  send_bits(s, blcodes-4,  4); { not -3 as stated in appnote.txt }\r
+  for rank := 0 to blcodes-1 do\r
+  begin\r
+    {$ifdef DEBUG}\r
+    Tracev(^M'bl code '+IntToStr(bl_order[rank]));\r
+    {$ENDIF}\r
+    send_bits(s, s.bl_tree[bl_order[rank]].dl.Len, 3);\r
+  end;\r
+  {$ifdef DEBUG}\r
+  Tracev(^M'bl tree: sent '+IntToStr(s.bits_sent));\r
+  {$ENDIF}\r
+\r
+  send_tree(s, s.dyn_ltree, lcodes-1); { literal tree }\r
+  {$ifdef DEBUG}\r
+  Tracev(^M'lit tree: sent '+IntToStr(s.bits_sent));\r
+  {$ENDIF}\r
+\r
+  send_tree(s, s.dyn_dtree, dcodes-1); { distance tree }\r
+  {$ifdef DEBUG}\r
+  Tracev(^M'dist tree: sent '+IntToStr(s.bits_sent));\r
+  {$ENDIF}\r
+end;\r
+\r
+{ ===========================================================================\r
+  Flush the bit buffer and align the output on a byte boundary }\r
+\r
+{local}\r
+procedure bi_windup(var s : deflate_state);\r
+begin\r
+  if (s.bi_valid > 8) then\r
+  begin\r
+    {put_short(s, s.bi_buf);}\r
+    s.pending_buf^[s.pending] := uch(s.bi_buf and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);;\r
+    Inc(s.pending);\r
+  end\r
+  else\r
+    if (s.bi_valid > 0) then\r
+    begin\r
+      {put_byte(s, (Byte)s^.bi_buf);}\r
+      s.pending_buf^[s.pending] := Byte(s.bi_buf);\r
+      Inc(s.pending);\r
+    end;\r
+  s.bi_buf := 0;\r
+  s.bi_valid := 0;\r
+{$ifdef DEBUG}\r
+  s.bits_sent := (s.bits_sent+7) and (not 7);\r
+{$endif}\r
+end;\r
+\r
+{ ===========================================================================\r
+  Copy a stored block, storing first the length and its\r
+  one's complement if requested. }\r
+\r
+{local}\r
+procedure copy_block(var s : deflate_state;\r
+                     buf : pcharf;      { the input data }\r
+                     len : unsigned;    { its length }\r
+                     header : boolean); { true if block header must be written }\r
+begin\r
+  bi_windup(s);        { align on byte boundary }\r
+  s.last_eob_len := 8; { enough lookahead for inflate }\r
+\r
+  if (header) then\r
+  begin\r
+    {put_short(s, (ush)len);}\r
+    s.pending_buf^[s.pending] := uch(ush(len) and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(len) shr 8);;\r
+    Inc(s.pending);\r
+    {put_short(s, (ush)~len);}\r
+    s.pending_buf^[s.pending] := uch(ush(not len) and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(not len) shr 8);;\r
+    Inc(s.pending);\r
+\r
+{$ifdef DEBUG}\r
+    Inc(s.bits_sent, 2*16);\r
+{$endif}\r
+  end;\r
+{$ifdef DEBUG}\r
+  Inc(s.bits_sent, ulg(len shl 3));\r
+{$endif}\r
+  while (len <> 0) do\r
+  begin\r
+    Dec(len);\r
+    {put_byte(s, *buf++);}\r
+    s.pending_buf^[s.pending] := buf^;\r
+    Inc(buf);\r
+    Inc(s.pending);\r
+  end;\r
+end;\r
+\r
+\r
+{ ===========================================================================\r
+  Send a stored block }\r
+\r
+procedure _tr_stored_block(var s : deflate_state;\r
+                           buf : pcharf;     { input block }\r
+                           stored_len : ulg; { length of input block }\r
+                           eof : boolean);   { true if this is the last block for a file }\r
+\r
+begin\r
+  send_bits(s, (STORED_BLOCK shl 1)+ord(eof), 3);  { send block type }\r
+  s.compressed_len := (s.compressed_len + 3 + 7) and ulg(not Long(7));\r
+  Inc(s.compressed_len, (stored_len + 4) shl 3);\r
+\r
+  copy_block(s, buf, unsigned(stored_len), TRUE); { with header }\r
+end;\r
+\r
+{ ===========================================================================\r
+  Flush the bit buffer, keeping at most 7 bits in it. }\r
+\r
+{local}\r
+procedure bi_flush(var s : deflate_state);\r
+begin\r
+  if (s.bi_valid = 16) then\r
+  begin\r
+    {put_short(s, s.bi_buf);}\r
+    s.pending_buf^[s.pending] := uch(s.bi_buf and $ff);\r
+    Inc(s.pending);\r
+    s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);;\r
+    Inc(s.pending);\r
+\r
+    s.bi_buf := 0;\r
+    s.bi_valid := 0;\r
+  end\r
+  else\r
+   if (s.bi_valid >= 8) then\r
+   begin\r
+     {put_byte(s, (Byte)s^.bi_buf);}\r
+     s.pending_buf^[s.pending] := Byte(s.bi_buf);\r
+     Inc(s.pending);\r
+\r
+     s.bi_buf := s.bi_buf shr 8;\r
+     Dec(s.bi_valid, 8);\r
+   end;\r
+end;\r
+\r
+\r
+{ ===========================================================================\r
+  Send one empty static block to give enough lookahead for inflate.\r
+  This takes 10 bits, of which 7 may remain in the bit buffer.\r
+  The current inflate code requires 9 bits of lookahead. If the\r
+  last two codes for the previous block (real code plus EOB) were coded\r
+  on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode\r
+  the last real code. In this case we send two empty static blocks instead\r
+  of one. (There are no problems if the previous block is stored or fixed.)\r
+  To simplify the code, we assume the worst case of last real code encoded\r
+  on one bit only. }\r
+\r
+procedure _tr_align(var s : deflate_state);\r
+begin\r
+  send_bits(s, STATIC_TREES shl 1, 3);\r
+  {$ifdef DEBUG}\r
+  Tracevvv(#13'cd '+IntToStr(END_BLOCK));\r
+  {$ENDIF}\r
+  send_bits(s, static_ltree[END_BLOCK].fc.Code, static_ltree[END_BLOCK].dl.Len);\r
+  Inc(s.compressed_len, Long(10)); { 3 for block type, 7 for EOB }\r
+  bi_flush(s);\r
+  { Of the 10 bits for the empty block, we have already sent\r
+    (10 - bi_valid) bits. The lookahead for the last real code (before\r
+    the EOB of the previous block) was thus at least one plus the length\r
+    of the EOB plus what we have just sent of the empty static block. }\r
+  if (1 + s.last_eob_len + 10 - s.bi_valid < 9) then\r
+  begin\r
+    send_bits(s, STATIC_TREES shl 1, 3);\r
+    {$ifdef DEBUG}\r
+    Tracevvv(#13'cd '+IntToStr(END_BLOCK));\r
+    {$ENDIF}\r
+    send_bits(s, static_ltree[END_BLOCK].fc.Code, static_ltree[END_BLOCK].dl.Len);\r
+    Inc(s.compressed_len, Long(10));\r
+    bi_flush(s);\r
+  end;\r
+  s.last_eob_len := 7;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Set the data type to ASCII or BINARY, using a crude approximation:\r
+  binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.\r
+  IN assertion: the fields freq of dyn_ltree are set and the total of all\r
+  frequencies does not exceed 64K (to fit in an int on 16 bit machines). }\r
+\r
+{local}\r
+procedure set_data_type(var s : deflate_state);\r
+var\r
+  n : int;\r
+  ascii_freq : unsigned;\r
+  bin_freq : unsigned;\r
+begin\r
+  n := 0;\r
+  ascii_freq := 0;\r
+  bin_freq := 0;\r
+\r
+  while (n < 7) do\r
+  begin\r
+    Inc(bin_freq, s.dyn_ltree[n].fc.Freq);\r
+    Inc(n);\r
+  end;\r
+  while (n < 128) do\r
+  begin\r
+    Inc(ascii_freq, s.dyn_ltree[n].fc.Freq);\r
+    Inc(n);\r
+  end;\r
+  while (n < LITERALS) do\r
+  begin\r
+    Inc(bin_freq, s.dyn_ltree[n].fc.Freq);\r
+    Inc(n);\r
+  end;\r
+  if (bin_freq > (ascii_freq shr 2)) then\r
+    s.data_type := Byte(Z_BINARY)\r
+  else\r
+    s.data_type := Byte(Z_ASCII);\r
+end;\r
+\r
+{ ===========================================================================\r
+  Send the block data compressed using the given Huffman trees }\r
+\r
+{local}\r
+procedure compress_block(var s : deflate_state;\r
+                         var ltree : array of ct_data;   { literal tree }\r
+                         var dtree : array of ct_data);  { distance tree }\r
+var\r
+  dist : unsigned;      { distance of matched string }\r
+  lc : int;             { match length or unmatched char (if dist == 0) }\r
+  lx : unsigned;        { running index in l_buf }\r
+  code : unsigned;      { the code to send }\r
+  extra : int;          { number of extra bits to send }\r
+begin\r
+  lx := 0;\r
+  if (s.last_lit <> 0) then\r
+  repeat\r
+    dist := s.d_buf^[lx];\r
+    lc := s.l_buf^[lx];\r
+    Inc(lx);\r
+    if (dist = 0) then\r
+    begin\r
+      { send a literal byte }\r
+      {$ifdef DEBUG}\r
+      Tracevvv(#13'cd '+IntToStr(lc));\r
+      Tracecv((lc > 31) and (lc < 128), ' '+char(lc)+' ');\r
+      {$ENDIF}\r
+      send_bits(s, ltree[lc].fc.Code, ltree[lc].dl.Len);\r
+    end\r
+    else\r
+    begin\r
+      { Here, lc is the match length - MIN_MATCH }\r
+      code := _length_code[lc];\r
+      { send the length code }\r
+      {$ifdef DEBUG}\r
+      Tracevvv(#13'cd '+IntToStr(code+LITERALS+1));\r
+      {$ENDIF}\r
+      send_bits(s, ltree[code+LITERALS+1].fc.Code, ltree[code+LITERALS+1].dl.Len);\r
+      extra := extra_lbits[code];\r
+      if (extra <> 0) then\r
+      begin\r
+        Dec(lc, base_length[code]);\r
+        send_bits(s, lc, extra);       { send the extra length bits }\r
+      end;\r
+      Dec(dist); { dist is now the match distance - 1 }\r
+      {code := d_code(dist);}\r
+      if (dist < 256) then\r
+        code := _dist_code[dist]\r
+      else\r
+        code := _dist_code[256+(dist shr 7)];\r
+\r
+      {$IFDEF DEBUG}\r
+      Assert (code < D_CODES, 'bad d_code');\r
+      {$ENDIF}\r
+\r
+      { send the distance code }\r
+      {$ifdef DEBUG}\r
+      Tracevvv(#13'cd '+IntToStr(code));\r
+      {$ENDIF}\r
+      send_bits(s, dtree[code].fc.Code, dtree[code].dl.Len);\r
+      extra := extra_dbits[code];\r
+      if (extra <> 0) then\r
+      begin\r
+        Dec(dist, base_dist[code]);\r
+        send_bits(s, dist, extra);   { send the extra distance bits }\r
+      end;\r
+    end; { literal or match pair ? }\r
+\r
+    { Check that the overlay between pending_buf and d_buf+l_buf is ok: }\r
+    {$IFDEF DEBUG}\r
+    Assert(s.pending < s.lit_bufsize + 2*lx, 'pendingBuf overflow');\r
+    {$ENDIF}\r
+  until (lx >= s.last_lit);\r
+\r
+  {$ifdef DEBUG}\r
+  Tracevvv(#13'cd '+IntToStr(END_BLOCK));\r
+  {$ENDIF}\r
+  send_bits(s, ltree[END_BLOCK].fc.Code, ltree[END_BLOCK].dl.Len);\r
+  s.last_eob_len := ltree[END_BLOCK].dl.Len;\r
+end;\r
+\r
+\r
+{ ===========================================================================\r
+  Determine the best encoding for the current block: dynamic trees, static\r
+  trees or store, and output the encoded block to the zip file. This function\r
+  returns the total compressed length for the file so far. }\r
+\r
+function _tr_flush_block (var s : deflate_state;\r
+         buf : pcharf;         { input block, or NULL if too old }\r
+         stored_len : ulg;     { length of input block }\r
+         eof : boolean) : ulg; { true if this is the last block for a file }\r
+var\r
+  opt_lenb, static_lenb : ulg; { opt_len and static_len in bytes }\r
+  max_blindex : int;  { index of last bit length code of non zero freq }\r
+begin\r
+  max_blindex := 0;\r
+\r
+  { Build the Huffman trees unless a stored block is forced }\r
+  if (s.level > 0) then\r
+  begin\r
+    { Check if the file is ascii or binary }\r
+    if (s.data_type = Z_UNKNOWN) then\r
+      set_data_type(s);\r
+\r
+    { Construct the literal and distance trees }\r
+    build_tree(s, s.l_desc);\r
+    {$ifdef DEBUG}\r
+    Tracev(^M'lit data: dyn %ld, stat %ld {s.opt_len, s.static_len}');\r
+    {$ENDIF}\r
+\r
+    build_tree(s, s.d_desc);\r
+    {$ifdef DEBUG}\r
+    Tracev(^M'dist data: dyn %ld, stat %ld {s.opt_len, s.static_len}');\r
+    {$ENDIF}\r
+    { At this point, opt_len and static_len are the total bit lengths of\r
+      the compressed block data, excluding the tree representations. }\r
+\r
+    { Build the bit length tree for the above two trees, and get the index\r
+      in bl_order of the last bit length code to send. }\r
+    max_blindex := build_bl_tree(s);\r
+\r
+    { Determine the best encoding. Compute first the block length in bytes}\r
+    opt_lenb := (s.opt_len+3+7) shr 3;\r
+    static_lenb := (s.static_len+3+7) shr 3;\r
+\r
+    {$ifdef DEBUG}\r
+    Tracev(^M'opt %lu(%lu) stat %lu(%lu) stored %lu lit %u '+\r
+           '{opt_lenb, s.opt_len, static_lenb, s.static_len, stored_len,'+\r
+           's.last_lit}');\r
+    {$ENDIF}\r
+\r
+    if (static_lenb <= opt_lenb) then\r
+      opt_lenb := static_lenb;\r
+\r
+  end\r
+  else\r
+  begin\r
+    {$IFDEF DEBUG}\r
+    Assert(buf <> pcharf(NIL), 'lost buf');\r
+    {$ENDIF}\r
+    static_lenb := stored_len + 5;\r
+    opt_lenb := static_lenb;        { force a stored block }\r
+  end;\r
+\r
+  { If compression failed and this is the first and last block,\r
+    and if the .zip file can be seeked (to rewrite the local header),\r
+    the whole file is transformed into a stored file:  }\r
+\r
+{$ifdef STORED_FILE_OK}\r
+{$ifdef FORCE_STORED_FILE}\r
+  if eof and (s.compressed_len = Long(0)) then\r
+  begin { force stored file }\r
+{$else}\r
+  if (stored_len <= opt_lenb) and eof and (s.compressed_len=Long(0))\r
+     and seekable()) do\r
+  begin\r
+{$endif}\r
+    { Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: }\r
+    if (buf = pcharf(0)) then\r
+      error ('block vanished');\r
+\r
+    copy_block(buf, unsigned(stored_len), 0); { without header }\r
+    s.compressed_len := stored_len shl 3;\r
+    s.method := STORED;\r
+  end\r
+  else\r
+{$endif} { STORED_FILE_OK }\r
+\r
+{$ifdef FORCE_STORED}\r
+  if (buf <> pchar(0)) then\r
+  begin { force stored block }\r
+{$else}\r
+  if (stored_len+4 <= opt_lenb) and (buf <> pcharf(0)) then\r
+  begin\r
+                     { 4: two words for the lengths }\r
+{$endif}\r
+    { The test buf <> NULL is only necessary if LIT_BUFSIZE > WSIZE.\r
+      Otherwise we can't have processed more than WSIZE input bytes since\r
+      the last block flush, because compression would have been\r
+      successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\r
+      transform a block into a stored block. }\r
+\r
+    _tr_stored_block(s, buf, stored_len, eof);\r
+\r
+{$ifdef FORCE_STATIC}\r
+  end\r
+  else\r
+    if (static_lenb >= 0) then\r
+    begin { force static trees }\r
+{$else}\r
+  end\r
+  else\r
+    if (static_lenb = opt_lenb) then\r
+    begin\r
+{$endif}\r
+      send_bits(s, (STATIC_TREES shl 1)+ord(eof), 3);\r
+      compress_block(s, static_ltree, static_dtree);\r
+      Inc(s.compressed_len, 3 + s.static_len);\r
+    end\r
+    else\r
+    begin\r
+      send_bits(s, (DYN_TREES shl 1)+ord(eof), 3);\r
+      send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1,\r
+                     max_blindex+1);\r
+      compress_block(s, s.dyn_ltree, s.dyn_dtree);\r
+      Inc(s.compressed_len, 3 + s.opt_len);\r
+    end;\r
+  {$ifdef DEBUG}\r
+  Assert (s.compressed_len = s.bits_sent, 'bad compressed size');\r
+  {$ENDIF}\r
+  init_block(s);\r
+\r
+  if (eof) then\r
+  begin\r
+    bi_windup(s);\r
+    Inc(s.compressed_len, 7);  { align on byte boundary }\r
+  end;\r
+  {$ifdef DEBUG}\r
+  Tracev(#13'comprlen %lu(%lu) {s.compressed_len shr 3,'+\r
+         's.compressed_len-7*ord(eof)}');\r
+  {$ENDIF}\r
+\r
+  _tr_flush_block := s.compressed_len shr 3;\r
+end;\r
+\r
+\r
+{ ===========================================================================\r
+  Save the match info and tally the frequency counts. Return true if\r
+  the current block must be flushed. }\r
+\r
+function _tr_tally (var s : deflate_state;\r
+   dist : unsigned;          { distance of matched string }\r
+   lc : unsigned) : boolean; { match length-MIN_MATCH or unmatched char (if dist=0) }\r
+var\r
+  {$IFDEF DEBUG}\r
+  MAX_DIST : ush;\r
+  {$ENDIF}\r
+  code : ush;\r
+{$ifdef TRUNCATE_BLOCK}\r
+var\r
+  out_length : ulg;\r
+  in_length : ulg;\r
+  dcode : int;\r
+{$endif}\r
+begin\r
+  s.d_buf^[s.last_lit] := ush(dist);\r
+  s.l_buf^[s.last_lit] := uch(lc);\r
+  Inc(s.last_lit);\r
+  if (dist = 0) then\r
+  begin\r
+    { lc is the unmatched char }\r
+    Inc(s.dyn_ltree[lc].fc.Freq);\r
+  end\r
+  else\r
+  begin\r
+    Inc(s.matches);\r
+    { Here, lc is the match length - MIN_MATCH }\r
+    Dec(dist);             { dist := match distance - 1 }\r
+\r
+    {macro d_code(dist)}\r
+    if (dist) < 256 then\r
+      code := _dist_code[dist]\r
+    else\r
+      code := _dist_code[256+(dist shr 7)];\r
+    {$IFDEF DEBUG}\r
+{macro  MAX_DIST(s) <=> ((s)^.w_size-MIN_LOOKAHEAD)\r
+   In order to simplify the code, particularly on 16 bit machines, match\r
+   distances are limited to MAX_DIST instead of WSIZE. }\r
+    MAX_DIST := ush(s.w_size-MIN_LOOKAHEAD);\r
+    Assert((dist < ush(MAX_DIST)) and\r
+           (ush(lc) <= ush(MAX_MATCH-MIN_MATCH)) and\r
+           (ush(code) < ush(D_CODES)),  '_tr_tally: bad match');\r
+    {$ENDIF}\r
+    Inc(s.dyn_ltree[_length_code[lc]+LITERALS+1].fc.Freq);\r
+    {s.dyn_dtree[d_code(dist)].Freq++;}\r
+    Inc(s.dyn_dtree[code].fc.Freq);\r
+  end;\r
+\r
+{$ifdef TRUNCATE_BLOCK}\r
+  { Try to guess if it is profitable to stop the current block here }\r
+  if (s.last_lit and $1fff = 0) and (s.level > 2) then\r
+  begin\r
+    { Compute an upper bound for the compressed length }\r
+    out_length := ulg(s.last_lit)*Long(8);\r
+    in_length := ulg(long(s.strstart) - s.block_start);\r
+    for dcode := 0 to D_CODES-1 do\r
+    begin\r
+      Inc(out_length, ulg(s.dyn_dtree[dcode].fc.Freq *\r
+            (Long(5)+extra_dbits[dcode])) );\r
+    end;\r
+    out_length := out_length shr 3;\r
+    {$ifdef DEBUG}\r
+    Tracev(^M'last_lit %u, in %ld, out ~%ld(%ld%%) ');\r
+          { s.last_lit, in_length, out_length,\r
+           Long(100) - out_length*Long(100) div in_length)); }\r
+    {$ENDIF}\r
+    if (s.matches < s.last_lit div 2) and (out_length < in_length div 2) then\r
+    begin\r
+      _tr_tally := TRUE;\r
+      exit;\r
+    end;\r
+  end;\r
+{$endif}\r
+  _tr_tally := (s.last_lit = s.lit_bufsize-1);\r
+  { We avoid equality with lit_bufsize because of wraparound at 64K\r
+    on 16 bit machines and because stored blocks are restricted to\r
+    64K-1 bytes. }\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/uint32.inc b/uint32.inc
new file mode 100755 (executable)
index 0000000..4abe7f3
--- /dev/null
@@ -0,0 +1,10 @@
+type\r
+  {delphi 3 and before do not have a 32 bits unsigned integer type,\r
+  but longint has the correct behavior - it doesn't on newer delphi versions}\r
+  {$ifndef fpc}\r
+    {$ifdef ver70}{$define pred4}{$endif} {tp7}\r
+    {$ifdef ver80}{$define pred4}{$endif} {delphi 1}\r
+    {$ifdef ver90}{$define pred4}{$endif} {delphi 2}\r
+    {$ifdef ver100}{$define pred4}{$endif} {delphi 3}\r
+  {$endif}\r
+  uint32={$ifdef pred4}longint{$else}longword{$endif};\r
diff --git a/zconf.inc b/zconf.inc
new file mode 100755 (executable)
index 0000000..fbd4f7b
--- /dev/null
+++ b/zconf.inc
@@ -0,0 +1,36 @@
+{ -------------------------------------------------------------------- }\r
+\r
+{$DEFINE MAX_MATCH_IS_258}\r
+\r
+{ Compile with -DMAXSEG_64K if the alloc function cannot allocate more\r
+  than 64k bytes at a time (needed on systems with 16-bit int). }\r
+\r
+{- $DEFINE MAXSEG_64K}\r
+{$IFDEF VER70}\r
+  {$DEFINE MAXSEG_64K}\r
+{$ENDIF}\r
+{$IFNDEF WIN32}\r
+  {$DEFINE UNALIGNED_OK}  { requires SizeOf(ush) = 2 ! }\r
+{$ENDIF}\r
+\r
+{$UNDEF DYNAMIC_CRC_TABLE}\r
+{$UNDEF FASTEST}\r
+{$define patch112}        { apply patch from the zlib home page }\r
+{ -------------------------------------------------------------------- }\r
+{$IFDEF WIN32}\r
+  {$DEFINE Delphi32}\r
+  {- $DEFINE Delphi5}  { keep compiler quiet }\r
+{$ENDIF}\r
+\r
+{$IFDEF DPMI}\r
+  {$DEFINE MSDOS}\r
+{$ENDIF}\r
+\r
+{$IFDEF FPC}\r
+ {$DEFINE Use32}\r
+ {$UNDEF DPMI}\r
+ {$UNDEF MSDOS}\r
+ {$UNDEF UNALIGNED_OK}  { requires SizeOf(ush) = 2 ! }\r
+ {$UNDEF MAXSEG_64K}\r
+ {$UNDEF Delphi32}\r
+{$ENDIF}\r
diff --git a/zdeflate.pas b/zdeflate.pas
new file mode 100755 (executable)
index 0000000..a31940d
--- /dev/null
@@ -0,0 +1,2131 @@
+Unit zDeflate;\r
+\r
+{ Orginal: deflate.h -- internal compression state\r
+           deflate.c -- compress data using the deflation algorithm\r
+  Copyright (C) 1995-1996 Jean-loup Gailly.\r
+\r
+  Pascal tranlastion\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.paszlib\r
+}\r
+\r
+\r
+{  ALGORITHM\r
+\r
+       The "deflation" process depends on being able to identify portions\r
+       of the input text which are identical to earlier input (within a\r
+       sliding window trailing behind the input currently being processed).\r
+\r
+       The most straightforward technique turns out to be the fastest for\r
+       most input files: try all possible matches and select the longest.\r
+       The key feature of this algorithm is that insertions into the string\r
+       dictionary are very simple and thus fast, and deletions are avoided\r
+       completely. Insertions are performed at each input character, whereas\r
+       string matches are performed only when the previous match ends. So it\r
+       is preferable to spend more time in matches to allow very fast string\r
+       insertions and avoid deletions. The matching algorithm for small\r
+       strings is inspired from that of Rabin & Karp. A brute force approach\r
+       is used to find longer strings when a small match has been found.\r
+       A similar algorithm is used in comic (by Jan-Mark Wams) and freeze\r
+       (by Leonid Broukhis).\r
+          A previous version of this file used a more sophisticated algorithm\r
+       (by Fiala and Greene) which is guaranteed to run in linear amortized\r
+       time, but has a larger average cost, uses more memory and is patented.\r
+       However the F&G algorithm may be faster for some highly redundant\r
+       files if the parameter max_chain_length (described below) is too large.\r
+\r
+   ACKNOWLEDGEMENTS\r
+\r
+       The idea of lazy evaluation of matches is due to Jan-Mark Wams, and\r
+       I found it in 'freeze' written by Leonid Broukhis.\r
+       Thanks to many people for bug reports and testing.\r
+\r
+   REFERENCES\r
+\r
+       Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".\r
+       Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc\r
+\r
+       A description of the Rabin and Karp algorithm is given in the book\r
+          "Algorithms" by R. Sedgewick, Addison-Wesley, p252.\r
+\r
+       Fiala,E.R., and Greene,D.H.\r
+          Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595}\r
+\r
+{ $Id: deflate.c,v 1.14 1996/07/02 12:40:55 me Exp $ }\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+uses\r
+  zutil, zlib;\r
+\r
+\r
+function deflateInit_(strm : z_streamp;\r
+                      level : int;\r
+                      const version : string;\r
+                      stream_size : int) : int;\r
+\r
+\r
+function deflateInit (var strm : z_stream; level : int) : int;\r
+\r
+{  Initializes the internal stream state for compression. The fields\r
+   zalloc, zfree and opaque must be initialized before by the caller.\r
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to\r
+   use default allocation functions.\r
+\r
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:\r
+   1 gives best speed, 9 gives best compression, 0 gives no compression at\r
+   all (the input data is simply copied a block at a time).\r
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and\r
+   compression (currently equivalent to level 6).\r
+\r
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not\r
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,\r
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible\r
+   with the version assumed by the caller (ZLIB_VERSION).\r
+   msg is set to null if there is no error message.  deflateInit does not\r
+   perform any compression: this will be done by deflate(). }\r
+\r
+\r
+{EXPORT}\r
+function deflate (var strm : z_stream; flush : int) : int;\r
+\r
+{ Performs one or both of the following actions:\r
+\r
+  - Compress more input starting at next_in and update next_in and avail_in\r
+    accordingly. If not all input can be processed (because there is not\r
+    enough room in the output buffer), next_in and avail_in are updated and\r
+    processing will resume at this point for the next call of deflate().\r
+\r
+  - Provide more output starting at next_out and update next_out and avail_out\r
+    accordingly. This action is forced if the parameter flush is non zero.\r
+    Forcing flush frequently degrades the compression ratio, so this parameter\r
+    should be set only when necessary (in interactive applications).\r
+    Some output may be provided even if flush is not set.\r
+\r
+  Before the call of deflate(), the application should ensure that at least\r
+  one of the actions is possible, by providing more input and/or consuming\r
+  more output, and updating avail_in or avail_out accordingly; avail_out\r
+  should never be zero before the call. The application can consume the\r
+  compressed output when it wants, for example when the output buffer is full\r
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK\r
+  and with zero avail_out, it must be called again after making room in the\r
+  output buffer because there might be more output pending.\r
+\r
+    If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression\r
+  block is terminated and flushed to the output buffer so that the\r
+  decompressor can get all input data available so far. For method 9, a future\r
+  variant on method 8, the current block will be flushed but not terminated.\r
+  Z_SYNC_FLUSH has the same effect as partial flush except that the compressed\r
+  output is byte aligned (the compressor can clear its internal bit buffer)\r
+  and the current block is always terminated; this can be useful if the\r
+  compressor has to be restarted from scratch after an interruption (in which\r
+  case the internal state of the compressor may be lost).\r
+    If flush is set to Z_FULL_FLUSH, the compression block is terminated, a\r
+  special marker is output and the compression dictionary is discarded; this\r
+  is useful to allow the decompressor to synchronize if one compressed block\r
+  has been damaged (see inflateSync below).  Flushing degrades compression and\r
+  so should be used only when necessary.  Using Z_FULL_FLUSH too often can\r
+  seriously degrade the compression. If deflate returns with avail_out == 0,\r
+  this function must be called again with the same value of the flush\r
+  parameter and more output space (updated avail_out), until the flush is\r
+  complete (deflate returns with non-zero avail_out).\r
+\r
+    If the parameter flush is set to Z_FINISH, all pending input is processed,\r
+  all pending output is flushed and deflate returns with Z_STREAM_END if there\r
+  was enough output space; if deflate returns with Z_OK, this function must be\r
+  called again with Z_FINISH and more output space (updated avail_out) but no\r
+  more input data, until it returns with Z_STREAM_END or an error. After\r
+  deflate has returned Z_STREAM_END, the only possible operations on the\r
+  stream are deflateReset or deflateEnd.\r
+\r
+    Z_FINISH can be used immediately after deflateInit if all the compression\r
+  is to be done in a single step. In this case, avail_out must be at least\r
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return\r
+  Z_STREAM_END, then it must be called again as described above.\r
+\r
+    deflate() may update data_type if it can make a good guess about\r
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered\r
+  binary. This field is only for information purposes and does not affect\r
+  the compression algorithm in any manner.\r
+\r
+    deflate() returns Z_OK if some progress has been made (more input\r
+  processed or more output produced), Z_STREAM_END if all input has been\r
+  consumed and all output has been produced (only when flush is set to\r
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example\r
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible. }\r
+\r
+\r
+function deflateEnd (var strm : z_stream) : int;\r
+\r
+{     All dynamically allocated data structures for this stream are freed.\r
+   This function discards any unprocessed input and does not flush any\r
+   pending output.\r
+\r
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the\r
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed\r
+   prematurely (some input or output was discarded). In the error case,\r
+   msg may be set but then points to a static string (which must not be\r
+   deallocated). }\r
+\r
+\r
+\r
+\r
+                        { Advanced functions }\r
+\r
+{ The following functions are needed only in some special applications. }\r
+\r
+\r
+{EXPORT}\r
+function deflateInit2 (var strm : z_stream;\r
+                       level : int;\r
+                       method : int;\r
+                       windowBits : int;\r
+                       memLevel : int;\r
+                       strategy : int) : int;\r
+\r
+{  This is another version of deflateInit with more compression options. The\r
+   fields next_in, zalloc, zfree and opaque must be initialized before by\r
+   the caller.\r
+\r
+     The method parameter is the compression method. It must be Z_DEFLATED in\r
+   this version of the library. (Method 9 will allow a 64K history buffer and\r
+   partial block flushes.)\r
+\r
+     The windowBits parameter is the base two logarithm of the window size\r
+   (the size of the history buffer).  It should be in the range 8..15 for this\r
+   version of the library (the value 16 will be allowed for method 9). Larger\r
+   values of this parameter result in better compression at the expense of\r
+   memory usage. The default value is 15 if deflateInit is used instead.\r
+\r
+     The memLevel parameter specifies how much memory should be allocated\r
+   for the internal compression state. memLevel=1 uses minimum memory but\r
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory\r
+   for optimal speed. The default value is 8. See zconf.h for total memory\r
+   usage as a function of windowBits and memLevel.\r
+\r
+     The strategy parameter is used to tune the compression algorithm. Use the\r
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a\r
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no\r
+   string match).  Filtered data consists mostly of small values with a\r
+   somewhat random distribution. In this case, the compression algorithm is\r
+   tuned to compress them better. The effect of Z_FILTERED is to force more\r
+   Huffman coding and less string matching; it is somewhat intermediate\r
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects\r
+   the compression ratio but not the correctness of the compressed output even\r
+   if it is not set appropriately.\r
+\r
+     If next_in is not null, the library will use this buffer to hold also\r
+   some history information; the buffer must either hold the entire input\r
+   data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in\r
+   is null, the library will allocate its own history buffer (and leave next_in\r
+   null). next_out need not be provided here but must be provided by the\r
+   application for the next call of deflate().\r
+\r
+     If the history buffer is provided by the application, next_in must\r
+   must never be changed by the application since the compressor maintains\r
+   information inside this buffer from call to call; the application\r
+   must provide more input only by increasing avail_in. next_in is always\r
+   reset by the library in this case.\r
+\r
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was\r
+   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as\r
+   an invalid method). msg is set to null if there is no error message.\r
+   deflateInit2 does not perform any compression: this will be done by\r
+   deflate(). }\r
+\r
+\r
+{EXPORT}\r
+function deflateSetDictionary (var strm : z_stream;\r
+                               dictionary : pBytef; {const bytes}\r
+                              dictLength : uint) : int;\r
+\r
+{    Initializes the compression dictionary (history buffer) from the given\r
+   byte sequence without producing any compressed output. This function must\r
+   be called immediately after deflateInit or deflateInit2, before any call\r
+   of deflate. The compressor and decompressor must use exactly the same\r
+   dictionary (see inflateSetDictionary).\r
+     The dictionary should consist of strings (byte sequences) that are likely\r
+   to be encountered later in the data to be compressed, with the most commonly\r
+   used strings preferably put towards the end of the dictionary. Using a\r
+   dictionary is most useful when the data to be compressed is short and\r
+   can be predicted with good accuracy; the data can then be compressed better\r
+   than with the default empty dictionary. In this version of the library,\r
+   only the last 32K bytes of the dictionary are used.\r
+     Upon return of this function, strm->adler is set to the Adler32 value\r
+   of the dictionary; the decompressor may later use this value to determine\r
+   which dictionary has been used by the compressor. (The Adler32 value\r
+   applies to the whole dictionary even if only a subset of the dictionary is\r
+   actually used by the compressor.)\r
+\r
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a\r
+   parameter is invalid (such as NULL dictionary) or the stream state\r
+   is inconsistent (for example if deflate has already been called for this\r
+   stream). deflateSetDictionary does not perform any compression: this will\r
+   be done by deflate(). }\r
+\r
+{EXPORT}\r
+function deflateCopy (dest : z_streamp;\r
+                      source : z_streamp) : int;\r
+\r
+{  Sets the destination stream as a complete copy of the source stream.  If\r
+   the source stream is using an application-supplied history buffer, a new\r
+   buffer is allocated for the destination stream.  The compressed output\r
+   buffer is always application-supplied. It's the responsibility of the\r
+   application to provide the correct values of next_out and avail_out for the\r
+   next call of deflate.\r
+\r
+     This function can be useful when several compression strategies will be\r
+   tried, for example when there are several ways of pre-processing the input\r
+   data with a filter. The streams that will be discarded should then be freed\r
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal\r
+   compression state which can be quite large, so this strategy is slow and\r
+   can consume lots of memory.\r
+\r
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\r
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\r
+   (such as zalloc being NULL). msg is left unchanged in both source and\r
+   destination. }\r
+\r
+{EXPORT}\r
+function deflateReset (var strm : z_stream) : int;\r
+\r
+{   This function is equivalent to deflateEnd followed by deflateInit,\r
+   but does not free and reallocate all the internal compression state.\r
+   The stream will keep the same compression level and any other attributes\r
+   that may have been set by deflateInit2.\r
+\r
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\r
+   stream state was inconsistent (such as zalloc or state being NIL). }\r
+\r
+\r
+{EXPORT}\r
+function deflateParams (var strm : z_stream; level : int; strategy : int) : int;\r
+\r
+{    Dynamically update the compression level and compression strategy.\r
+   This can be used to switch between compression and straight copy of\r
+   the input data, or to switch to a different kind of input data requiring\r
+   a different strategy. If the compression level is changed, the input\r
+   available so far is compressed with the old level (and may be flushed);\r
+   the new level will take effect only at the next call of deflate().\r
+\r
+     Before the call of deflateParams, the stream state must be set as for\r
+   a call of deflate(), since the currently available input may have to\r
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.\r
+\r
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source\r
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR\r
+   if strm->avail_out was zero. }\r
+\r
+\r
+const\r
+   deflate_copyright : string = ' deflate 1.1.2 Copyright 1995-1998 Jean-loup Gailly ';\r
+\r
+{ If you use the zlib library in a product, an acknowledgment is welcome\r
+  in the documentation of your product. If for some reason you cannot\r
+  include such an acknowledgment, I would appreciate that you keep this\r
+  copyright string in the executable of your product. }\r
+\r
+implementation\r
+\r
+uses\r
+  trees, adler;\r
+\r
+{  ===========================================================================\r
+   Function prototypes. }\r
+\r
+type\r
+   block_state = (\r
+    need_more,      { block not completed, need more input or more output }\r
+    block_done,     { block flush performed }\r
+    finish_started, { finish started, need only more output at next deflate }\r
+    finish_done);   { finish done, accept no more input or output }\r
+\r
+{ Compression function. Returns the block state after the call. }\r
+type\r
+  compress_func = function(var s : deflate_state; flush : int) : block_state;\r
+\r
+{local}\r
+procedure fill_window(var s : deflate_state); forward;\r
+{local}\r
+function deflate_stored(var s : deflate_state; flush : int) : block_state; far; forward;\r
+{local}\r
+function deflate_fast(var s : deflate_state; flush : int) : block_state; far; forward;\r
+{local}\r
+function deflate_slow(var s : deflate_state; flush : int) : block_state; far; forward;\r
+{local}\r
+procedure lm_init(var s : deflate_state); forward;\r
+\r
+{local}\r
+procedure putShortMSB(var s : deflate_state; b : uInt); forward;\r
+{local}\r
+procedure  flush_pending (var strm : z_stream); forward;\r
+{local}\r
+function read_buf(strm : z_streamp;\r
+                  buf : pBytef;\r
+                  size : unsigned) : int; forward;\r
+{$ifdef ASMV}\r
+procedure match_init; { asm code initialization }\r
+function longest_match(var deflate_state; cur_match : IPos) : uInt; forward;\r
+{$else}\r
+{local}\r
+function longest_match(var s : deflate_state; cur_match : IPos) : uInt;\r
+  forward;\r
+{$endif}\r
+\r
+{$ifdef DEBUG}\r
+{local}\r
+procedure check_match(var s : deflate_state;\r
+                      start, match : IPos;\r
+                      length : int); forward;\r
+{$endif}\r
+\r
+{  ==========================================================================\r
+  local data }\r
+\r
+const\r
+  ZNIL = 0;\r
+{ Tail of hash chains }\r
+\r
+const\r
+  TOO_FAR = 4096;\r
+{ Matches of length 3 are discarded if their distance exceeds TOO_FAR }\r
+\r
+const\r
+  MIN_LOOKAHEAD = (MAX_MATCH+MIN_MATCH+1);\r
+{ Minimum amount of lookahead, except at the end of the input file.\r
+  See deflate.c for comments about the MIN_MATCH+1. }\r
+\r
+{macro MAX_DIST(var s : deflate_state) : uInt;\r
+begin\r
+  MAX_DIST := (s.w_size - MIN_LOOKAHEAD);\r
+end;\r
+  In order to simplify the code, particularly on 16 bit machines, match\r
+  distances are limited to MAX_DIST instead of WSIZE. }\r
+\r
+\r
+{ Values for max_lazy_match, good_match and max_chain_length, depending on\r
+  the desired pack level (0..9). The values given below have been tuned to\r
+  exclude worst case performance for pathological files. Better values may be\r
+  found for specific files. }\r
+\r
+type\r
+  config = record\r
+   good_length : ush; { reduce lazy search above this match length }\r
+   max_lazy : ush;    { do not perform lazy search above this match length }\r
+   nice_length : ush; { quit search above this match length }\r
+   max_chain : ush;\r
+   func : compress_func;\r
+  end;\r
+\r
+{local}\r
+const\r
+  configuration_table : array[0..10-1] of config = (\r
+{      good lazy nice chain }\r
+{0} (good_length:0;  max_lazy:0;   nice_length:0;   max_chain:0;    func:deflate_stored),  { store only }\r
+{1} (good_length:4;  max_lazy:4;   nice_length:8;   max_chain:4;    func:deflate_fast), { maximum speed, no lazy matches }\r
+{2} (good_length:4;  max_lazy:5;   nice_length:16;  max_chain:8;    func:deflate_fast),\r
+{3} (good_length:4;  max_lazy:6;   nice_length:32;  max_chain:32;   func:deflate_fast),\r
+\r
+{4} (good_length:4;  max_lazy:4;   nice_length:16;  max_chain:16;   func:deflate_slow),  { lazy matches }\r
+{5} (good_length:8;  max_lazy:16;  nice_length:32;  max_chain:32;   func:deflate_slow),\r
+{6} (good_length:8;  max_lazy:16;  nice_length:128; max_chain:128;  func:deflate_slow),\r
+{7} (good_length:8;  max_lazy:32;  nice_length:128; max_chain:256;  func:deflate_slow),\r
+{8} (good_length:32; max_lazy:128; nice_length:258; max_chain:1024; func:deflate_slow),\r
+{9} (good_length:32; max_lazy:258; nice_length:258; max_chain:4096; func:deflate_slow)); { maximum compression }\r
+\r
+{ Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4\r
+  For deflate_fast() (levels <= 3) good is ignored and lazy has a different\r
+  meaning. }\r
+\r
+const\r
+  EQUAL = 0;\r
+{ result of memcmp for equal strings }\r
+\r
+{ ==========================================================================\r
+  Update a hash value with the given input byte\r
+  IN  assertion: all calls to to UPDATE_HASH are made with consecutive\r
+     input characters, so that a running hash key can be computed from the\r
+     previous key instead of complete recalculation each time.\r
+\r
+macro UPDATE_HASH(s,h,c)\r
+   h := (( (h) shl s^.hash_shift) xor (c)) and s^.hash_mask;\r
+}\r
+\r
+{ ===========================================================================\r
+  Insert string str in the dictionary and set match_head to the previous head\r
+  of the hash chain (the most recent string with same hash key). Return\r
+  the previous length of the hash chain.\r
+  If this file is compiled with -DFASTEST, the compression level is forced\r
+  to 1, and no hash chains are maintained.\r
+  IN  assertion: all calls to to INSERT_STRING are made with consecutive\r
+     input characters and the first MIN_MATCH bytes of str are valid\r
+     (except for the last MIN_MATCH-1 bytes of the input file). }\r
+\r
+procedure INSERT_STRING(var s : deflate_state;\r
+                        str : uInt;\r
+                        var match_head : IPos);\r
+begin\r
+{$ifdef FASTEST}\r
+   {UPDATE_HASH(s, s.ins_h, s.window[(str) + (MIN_MATCH-1)])}\r
+    s.ins_h := ((s.ins_h shl s.hash_shift) xor\r
+                 (s.window^[(str) + (MIN_MATCH-1)])) and s.hash_mask;\r
+    match_head := s.head[s.ins_h]\r
+    s.head[s.ins_h] := Pos(str);\r
+{$else}\r
+   {UPDATE_HASH(s, s.ins_h, s.window[(str) + (MIN_MATCH-1)])}\r
+    s.ins_h := ((s.ins_h shl s.hash_shift) xor\r
+                 (s.window^[(str) + (MIN_MATCH-1)])) and s.hash_mask;\r
+\r
+    match_head := s.head^[s.ins_h];\r
+    s.prev^[(str) and s.w_mask] := match_head;\r
+    s.head^[s.ins_h] := Pos(str);\r
+{$endif}\r
+end;\r
+\r
+{  =========================================================================\r
+  Initialize the hash table (avoiding 64K overflow for 16 bit systems).\r
+  prev[] will be initialized on the fly.\r
+\r
+macro CLEAR_HASH(s)\r
+    s^.head[s^.hash_size-1] := ZNIL;\r
+    zmemzero(pBytef(s^.head), unsigned(s^.hash_size-1)*sizeof(s^.head^[0]));\r
+}\r
+\r
+{  ======================================================================== }\r
+\r
+function deflateInit2_(var strm : z_stream;\r
+                       level : int;\r
+                       method : int;\r
+                       windowBits : int;\r
+                       memLevel : int;\r
+                       strategy : int;\r
+                       const version : string;\r
+                       stream_size : int) : int;\r
+var\r
+  s : deflate_state_ptr;\r
+  noheader : int;\r
+\r
+  overlay : pushfArray;\r
+  { We overlay pending_buf and d_buf+l_buf. This works since the average\r
+    output size for (length,distance) codes is <= 24 bits. }\r
+begin\r
+  noheader := 0;\r
+  if (version  =  '') or (version[1] <> ZLIB_VERSION[1]) or\r
+     (stream_size <> sizeof(z_stream)) then\r
+  begin\r
+    deflateInit2_ := Z_VERSION_ERROR;\r
+    exit;\r
+  end;\r
+  {\r
+  if (strm = Z_NULL) then\r
+  begin\r
+    deflateInit2_ := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  }\r
+  { SetLength(strm.msg, 255); }\r
+  strm.msg := '';\r
+  if not Assigned(strm.zalloc) then\r
+  begin\r
+    {$IFDEF FPC}  strm.zalloc := @zcalloc;  {$ELSE}\r
+    strm.zalloc := zcalloc;\r
+    {$ENDIF}\r
+    strm.opaque := voidpf(0);\r
+  end;\r
+  if not Assigned(strm.zfree) then\r
+    {$IFDEF FPC}  strm.zfree := @zcfree;  {$ELSE}\r
+    strm.zfree := zcfree;\r
+    {$ENDIF}\r
+\r
+  if (level  =  Z_DEFAULT_COMPRESSION) then\r
+    level := 6;\r
+{$ifdef FASTEST}\r
+    level := 1;\r
+{$endif}\r
+\r
+  if (windowBits < 0) then { undocumented feature: suppress zlib header }\r
+  begin\r
+    noheader := 1;\r
+    windowBits := -windowBits;\r
+  end;\r
+  if (memLevel < 1) or (memLevel > MAX_MEM_LEVEL) or (method <> Z_DEFLATED)\r
+    or (windowBits < 8) or (windowBits > 15) or (level < 0)\r
+    or (level > 9) or (strategy < 0) or (strategy > Z_HUFFMAN_ONLY) then\r
+  begin\r
+    deflateInit2_ := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  s := deflate_state_ptr (ZALLOC(strm, 1, sizeof(deflate_state)));\r
+  if (s = Z_NULL) then\r
+  begin\r
+    deflateInit2_ := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+  strm.state := pInternal_state(s);\r
+  s^.strm := @strm;\r
+\r
+  s^.noheader := noheader;\r
+  s^.w_bits := windowBits;\r
+  s^.w_size := 1 shl s^.w_bits;\r
+  s^.w_mask := s^.w_size - 1;\r
+\r
+  s^.hash_bits := memLevel + 7;\r
+  s^.hash_size := 1 shl s^.hash_bits;\r
+  s^.hash_mask := s^.hash_size - 1;\r
+  s^.hash_shift :=  ((s^.hash_bits+MIN_MATCH-1) div MIN_MATCH);\r
+\r
+  s^.window := pzByteArray (ZALLOC(strm, s^.w_size, 2*sizeof(Byte)));\r
+  s^.prev   := pzPosfArray (ZALLOC(strm, s^.w_size, sizeof(Pos)));\r
+  s^.head   := pzPosfArray (ZALLOC(strm, s^.hash_size, sizeof(Pos)));\r
+\r
+  s^.lit_bufsize := 1 shl (memLevel + 6); { 16K elements by default }\r
+\r
+  overlay := pushfArray (ZALLOC(strm, s^.lit_bufsize, sizeof(ush)+2));\r
+  s^.pending_buf := pzByteArray (overlay);\r
+  s^.pending_buf_size := ulg(s^.lit_bufsize) * (sizeof(ush)+Long(2));\r
+\r
+  if (s^.window = Z_NULL) or (s^.prev = Z_NULL) or (s^.head = Z_NULL)\r
+   or (s^.pending_buf = Z_NULL) then\r
+  begin\r
+    {ERR_MSG(Z_MEM_ERROR);}\r
+    strm.msg := z_errmsg[z_errbase-Z_MEM_ERROR];\r
+    deflateEnd (strm);\r
+    deflateInit2_ := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+  s^.d_buf := pushfArray( @overlay^[s^.lit_bufsize div sizeof(ush)] );\r
+  s^.l_buf := puchfArray( @s^.pending_buf^[(1+sizeof(ush))*s^.lit_bufsize] );\r
+\r
+  s^.level := level;\r
+  s^.strategy := strategy;\r
+  s^.method := Byte(method);\r
+\r
+  deflateInit2_ := deflateReset(strm);\r
+end;\r
+\r
+{  ========================================================================= }\r
+\r
+function deflateInit2(var strm : z_stream;\r
+                      level : int;\r
+                      method : int;\r
+                      windowBits : int;\r
+                      memLevel : int;\r
+                      strategy : int) : int;\r
+{ a macro }\r
+begin\r
+  deflateInit2 := deflateInit2_(strm, level, method, windowBits,\r
+                   memLevel, strategy, ZLIB_VERSION, sizeof(z_stream));\r
+end;\r
+\r
+{  ========================================================================= }\r
+\r
+function deflateInit_(strm : z_streamp;\r
+                      level : int;\r
+                      const version : string;\r
+                      stream_size : int) : int;\r
+begin\r
+  if (strm = Z_NULL) then\r
+    deflateInit_ := Z_STREAM_ERROR\r
+  else\r
+    deflateInit_ := deflateInit2_(strm^, level, Z_DEFLATED, MAX_WBITS,\r
+                   DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size);\r
+  { To do: ignore strm^.next_in if we use it as window }\r
+end;\r
+\r
+{  ========================================================================= }\r
+\r
+function deflateInit(var strm : z_stream; level : int) : int;\r
+{ deflateInit is a macro to allow checking the zlib version\r
+  and the compiler's view of z_stream: }\r
+begin\r
+  deflateInit := deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS,\r
+         DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof(z_stream));\r
+end;\r
+\r
+{  ======================================================================== }\r
+function deflateSetDictionary (var strm : z_stream;\r
+                               dictionary : pBytef;\r
+                               dictLength : uInt) : int;\r
+var\r
+  s : deflate_state_ptr;\r
+  length : uInt;\r
+  n : uInt;\r
+  hash_head : IPos;\r
+var\r
+  MAX_DIST : uInt;  {macro}\r
+begin\r
+  length := dictLength;\r
+  hash_head := 0;\r
+\r
+  if {(@strm  =  Z_NULL) or}\r
+     (strm.state  =  Z_NULL) or (dictionary  =  Z_NULL)\r
+    or (deflate_state_ptr(strm.state)^.status <> INIT_STATE) then\r
+  begin\r
+    deflateSetDictionary := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  s := deflate_state_ptr(strm.state);\r
+  strm.adler := adler32(strm.adler, dictionary, dictLength);\r
+\r
+  if (length < MIN_MATCH) then\r
+  begin\r
+    deflateSetDictionary := Z_OK;\r
+    exit;\r
+  end;\r
+  MAX_DIST := (s^.w_size - MIN_LOOKAHEAD);\r
+  if (length > MAX_DIST) then\r
+  begin\r
+    length := MAX_DIST;\r
+{$ifndef USE_DICT_HEAD}\r
+    Inc(dictionary, dictLength - length);  { use the tail of the dictionary }\r
+{$endif}\r
+  end;\r
+\r
+  zmemcpy( pBytef(s^.window), dictionary, length);\r
+  s^.strstart := length;\r
+  s^.block_start := long(length);\r
+\r
+  { Insert all strings in the hash table (except for the last two bytes).\r
+    s^.lookahead stays null, so s^.ins_h will be recomputed at the next\r
+    call of fill_window. }\r
+\r
+  s^.ins_h := s^.window^[0];\r
+  {UPDATE_HASH(s, s^.ins_h, s^.window[1]);}\r
+  s^.ins_h := ((s^.ins_h shl s^.hash_shift) xor (s^.window^[1]))\r
+              and s^.hash_mask;\r
+\r
+  for n := 0 to length - MIN_MATCH do\r
+  begin\r
+    INSERT_STRING(s^, n, hash_head);\r
+  end;\r
+  {if (hash_head <> 0) then\r
+    hash_head := 0;  - to make compiler happy }\r
+  deflateSetDictionary := Z_OK;\r
+end;\r
+\r
+{  ======================================================================== }\r
+function deflateReset (var strm : z_stream) : int;\r
+var\r
+  s : deflate_state_ptr;\r
+begin\r
+  if {(@strm = Z_NULL) or}\r
+   (strm.state = Z_NULL)\r
+   or (not Assigned(strm.zalloc)) or (not Assigned(strm.zfree)) then\r
+  begin\r
+    deflateReset := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  strm.total_out := 0;\r
+  strm.total_in := 0;\r
+  strm.msg := '';      { use zfree if we ever allocate msg dynamically }\r
+  strm.data_type := Z_UNKNOWN;\r
+\r
+  s := deflate_state_ptr(strm.state);\r
+  s^.pending := 0;\r
+  s^.pending_out := pBytef(s^.pending_buf);\r
+\r
+  if (s^.noheader < 0) then\r
+  begin\r
+    s^.noheader := 0; { was set to -1 by deflate(..., Z_FINISH); }\r
+  end;\r
+  if s^.noheader <> 0 then\r
+    s^.status := BUSY_STATE\r
+  else\r
+    s^.status := INIT_STATE;\r
+  strm.adler := 1;\r
+  s^.last_flush := Z_NO_FLUSH;\r
+\r
+  _tr_init(s^);\r
+  lm_init(s^);\r
+\r
+  deflateReset := Z_OK;\r
+end;\r
+\r
+{  ======================================================================== }\r
+function deflateParams(var strm : z_stream;\r
+                       level : int;\r
+                       strategy : int) : int;\r
+var\r
+  s : deflate_state_ptr;\r
+  func : compress_func;\r
+  err : int;\r
+begin\r
+  err := Z_OK;\r
+  if {(@strm  =  Z_NULL) or} (strm.state  =  Z_NULL) then\r
+  begin\r
+    deflateParams := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  s := deflate_state_ptr(strm.state);\r
+\r
+  if (level = Z_DEFAULT_COMPRESSION) then\r
+  begin\r
+    level := 6;\r
+  end;\r
+  if (level < 0) or (level > 9) or (strategy < 0)\r
+  or (strategy > Z_HUFFMAN_ONLY) then\r
+  begin\r
+    deflateParams := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  func := configuration_table[s^.level].func;\r
+\r
+  if (@func <> @configuration_table[level].func)\r
+    and (strm.total_in <> 0) then\r
+  begin\r
+      { Flush the last buffer: }\r
+      err := deflate(strm, Z_PARTIAL_FLUSH);\r
+  end;\r
+  if (s^.level <> level) then\r
+  begin\r
+    s^.level := level;\r
+    s^.max_lazy_match   := configuration_table[level].max_lazy;\r
+    s^.good_match       := configuration_table[level].good_length;\r
+    s^.nice_match       := configuration_table[level].nice_length;\r
+    s^.max_chain_length := configuration_table[level].max_chain;\r
+  end;\r
+  s^.strategy := strategy;\r
+  deflateParams := err;\r
+end;\r
+\r
+{ =========================================================================\r
+  Put a short in the pending buffer. The 16-bit value is put in MSB order.\r
+  IN assertion: the stream state is correct and there is enough room in\r
+  pending_buf. }\r
+\r
+{local}\r
+procedure putShortMSB (var s : deflate_state; b : uInt);\r
+begin\r
+  s.pending_buf^[s.pending] := Byte(b shr 8);\r
+  Inc(s.pending);\r
+  s.pending_buf^[s.pending] := Byte(b and $ff);\r
+  Inc(s.pending);\r
+end;\r
+\r
+{ =========================================================================\r
+  Flush as much pending output as possible. All deflate() output goes\r
+  through this function so some applications may wish to modify it\r
+  to avoid allocating a large strm^.next_out buffer and copying into it.\r
+  (See also read_buf()). }\r
+\r
+{local}\r
+procedure flush_pending(var strm : z_stream);\r
+var\r
+  len : unsigned;\r
+  s : deflate_state_ptr;\r
+begin\r
+  s := deflate_state_ptr(strm.state);\r
+  len := s^.pending;\r
+\r
+  if (len > strm.avail_out) then\r
+    len := strm.avail_out;\r
+  if (len = 0) then\r
+    exit;\r
+\r
+  zmemcpy(strm.next_out, s^.pending_out, len);\r
+  Inc(strm.next_out, len);\r
+  Inc(s^.pending_out, len);\r
+  Inc(strm.total_out, len);\r
+  Dec(strm.avail_out, len);\r
+  Dec(s^.pending, len);\r
+  if (s^.pending = 0) then\r
+  begin\r
+    s^.pending_out := pBytef(s^.pending_buf);\r
+  end;\r
+end;\r
+\r
+{ ========================================================================= }\r
+function deflate (var strm : z_stream; flush : int) : int;\r
+var\r
+  old_flush : int; { value of flush param for previous deflate call }\r
+  s : deflate_state_ptr;\r
+var\r
+  header : uInt;\r
+  level_flags : uInt;\r
+var\r
+  bstate : block_state;\r
+begin\r
+  if {(@strm = Z_NULL) or} (strm.state = Z_NULL)\r
+    or (flush > Z_FINISH) or (flush < 0) then\r
+  begin\r
+    deflate := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  s := deflate_state_ptr(strm.state);\r
+\r
+  if (strm.next_out = Z_NULL) or\r
+     ((strm.next_in = Z_NULL) and (strm.avail_in <> 0)) or\r
+     ((s^.status = FINISH_STATE) and (flush <> Z_FINISH)) then\r
+  begin\r
+    {ERR_RETURN(strm^, Z_STREAM_ERROR);}\r
+    strm.msg := z_errmsg[z_errbase - Z_STREAM_ERROR];\r
+    deflate := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  if (strm.avail_out = 0) then\r
+  begin\r
+    {ERR_RETURN(strm^, Z_BUF_ERROR);}\r
+    strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];\r
+    deflate := Z_BUF_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  s^.strm := @strm; { just in case }\r
+  old_flush := s^.last_flush;\r
+  s^.last_flush := flush;\r
+\r
+  { Write the zlib header }\r
+  if (s^.status = INIT_STATE) then\r
+  begin\r
+\r
+    header := (Z_DEFLATED + ((s^.w_bits-8) shl 4)) shl 8;\r
+    level_flags := (s^.level-1) shr 1;\r
+\r
+    if (level_flags > 3) then\r
+      level_flags := 3;\r
+    header := header or (level_flags shl 6);\r
+    if (s^.strstart <> 0) then\r
+      header := header or PRESET_DICT;\r
+    Inc(header, 31 - (header mod 31));\r
+\r
+    s^.status := BUSY_STATE;\r
+    putShortMSB(s^, header);\r
+\r
+    { Save the adler32 of the preset dictionary: }\r
+    if (s^.strstart <> 0) then\r
+    begin\r
+      putShortMSB(s^, uInt(strm.adler shr 16));\r
+      putShortMSB(s^, uInt(strm.adler and $ffff));\r
+    end;\r
+    strm.adler := long(1);\r
+  end;\r
+\r
+  { Flush as much pending output as possible }\r
+  if (s^.pending <> 0) then\r
+  begin\r
+    flush_pending(strm);\r
+    if (strm.avail_out = 0) then\r
+    begin\r
+      { Since avail_out is 0, deflate will be called again with\r
+       more output space, but possibly with both pending and\r
+       avail_in equal to zero. There won't be anything to do,\r
+       but this is not an error situation so make sure we\r
+       return OK instead of BUF_ERROR at next call of deflate: }\r
+\r
+      s^.last_flush := -1;\r
+      deflate := Z_OK;\r
+      exit;\r
+    end;\r
+\r
+  { Make sure there is something to do and avoid duplicate consecutive\r
+    flushes. For repeated and useless calls with Z_FINISH, we keep\r
+    returning Z_STREAM_END instead of Z_BUFF_ERROR. }\r
+\r
+  end\r
+  else\r
+    if (strm.avail_in = 0) and (flush <= old_flush)\r
+      and (flush <> Z_FINISH) then\r
+    begin\r
+      {ERR_RETURN(strm^, Z_BUF_ERROR);}\r
+      strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];\r
+      deflate := Z_BUF_ERROR;\r
+      exit;\r
+    end;\r
+\r
+  { User must not provide more input after the first FINISH: }\r
+  if (s^.status = FINISH_STATE) and (strm.avail_in <> 0) then\r
+  begin\r
+    {ERR_RETURN(strm^, Z_BUF_ERROR);}\r
+    strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];\r
+    deflate := Z_BUF_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  { Start a new block or continue the current one. }\r
+  if (strm.avail_in <> 0) or (s^.lookahead <> 0)\r
+    or ((flush <> Z_NO_FLUSH) and (s^.status <> FINISH_STATE)) then\r
+  begin\r
+    bstate := configuration_table[s^.level].func(s^, flush);\r
+\r
+    if (bstate = finish_started) or (bstate = finish_done) then\r
+      s^.status := FINISH_STATE;\r
+\r
+    if (bstate = need_more) or (bstate = finish_started) then\r
+    begin\r
+      if (strm.avail_out = 0) then\r
+        s^.last_flush := -1; { avoid BUF_ERROR next call, see above }\r
+\r
+      deflate := Z_OK;\r
+      exit;\r
+      { If flush != Z_NO_FLUSH && avail_out == 0, the next call\r
+       of deflate should use the same flush parameter to make sure\r
+       that the flush is complete. So we don't have to output an\r
+       empty block here, this will be done at next call. This also\r
+       ensures that for a very small output buffer, we emit at most\r
+        one empty block. }\r
+    end;\r
+    if (bstate = block_done) then\r
+    begin\r
+      if (flush = Z_PARTIAL_FLUSH) then\r
+        _tr_align(s^)\r
+      else\r
+      begin  { FULL_FLUSH or SYNC_FLUSH }\r
+        _tr_stored_block(s^, pcharf(NIL), Long(0), FALSE);\r
+        { For a full flush, this empty block will be recognized\r
+          as a special marker by inflate_sync(). }\r
+\r
+        if (flush = Z_FULL_FLUSH) then\r
+        begin\r
+          {macro CLEAR_HASH(s);}             { forget history }\r
+          s^.head^[s^.hash_size-1] := ZNIL;\r
+          zmemzero(pBytef(s^.head), unsigned(s^.hash_size-1)*sizeof(s^.head^[0]));\r
+        end;\r
+      end;\r
+\r
+      flush_pending(strm);\r
+      if (strm.avail_out = 0) then\r
+      begin\r
+        s^.last_flush := -1; { avoid BUF_ERROR at next call, see above }\r
+       deflate := Z_OK;\r
+        exit;\r
+      end;\r
+\r
+    end;\r
+  end;\r
+  {$IFDEF DEBUG}\r
+  Assert(strm.avail_out > 0, 'bug2');\r
+  {$ENDIF}\r
+  if (flush <> Z_FINISH) then\r
+  begin\r
+    deflate := Z_OK;\r
+    exit;\r
+  end;\r
+\r
+  if (s^.noheader <> 0) then\r
+  begin\r
+    deflate := Z_STREAM_END;\r
+    exit;\r
+  end;\r
+\r
+  { Write the zlib trailer (adler32) }\r
+  putShortMSB(s^, uInt(strm.adler shr 16));\r
+  putShortMSB(s^, uInt(strm.adler and $ffff));\r
+  flush_pending(strm);\r
+  { If avail_out is zero, the application will call deflate again\r
+    to flush the rest. }\r
+\r
+  s^.noheader := -1; { write the trailer only once! }\r
+  if s^.pending <> 0 then\r
+    deflate := Z_OK\r
+  else\r
+    deflate := Z_STREAM_END;\r
+end;\r
+\r
+{ ========================================================================= }\r
+function deflateEnd (var strm : z_stream) : int;\r
+var\r
+  status : int;\r
+  s : deflate_state_ptr;\r
+begin\r
+  if {(@strm = Z_NULL) or} (strm.state = Z_NULL) then\r
+  begin\r
+    deflateEnd := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  s := deflate_state_ptr(strm.state);\r
+  status := s^.status;\r
+  if (status <> INIT_STATE) and (status <> BUSY_STATE) and\r
+     (status <> FINISH_STATE) then\r
+  begin\r
+    deflateEnd := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  { Deallocate in reverse order of allocations: }\r
+  TRY_FREE(strm, s^.pending_buf);\r
+  TRY_FREE(strm, s^.head);\r
+  TRY_FREE(strm, s^.prev);\r
+  TRY_FREE(strm, s^.window);\r
+\r
+  ZFREE(strm, s);\r
+  strm.state := Z_NULL;\r
+\r
+  if status = BUSY_STATE then\r
+    deflateEnd := Z_DATA_ERROR\r
+  else\r
+    deflateEnd := Z_OK;\r
+end;\r
+\r
+{ =========================================================================\r
+  Copy the source state to the destination state.\r
+  To simplify the source, this is not supported for 16-bit MSDOS (which\r
+  doesn't have enough memory anyway to duplicate compression states). }\r
+\r
+\r
+{ ========================================================================= }\r
+function deflateCopy (dest, source : z_streamp) : int;\r
+{$ifndef MAXSEG_64K}\r
+var\r
+  ds : deflate_state_ptr;\r
+  ss : deflate_state_ptr;\r
+  overlay : pushfArray;\r
+{$endif}\r
+begin\r
+{$ifdef MAXSEG_64K}\r
+  deflateCopy := Z_STREAM_ERROR;\r
+  exit;\r
+{$else}\r
+\r
+  if (source = Z_NULL) or (dest = Z_NULL) or (source^.state = Z_NULL) then\r
+  begin\r
+    deflateCopy := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  ss := deflate_state_ptr(source^.state);\r
+  dest^ := source^;\r
+\r
+  ds := deflate_state_ptr( ZALLOC(dest^, 1, sizeof(deflate_state)) );\r
+  if (ds = Z_NULL) then\r
+  begin\r
+    deflateCopy := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+  dest^.state := pInternal_state(ds);\r
+  ds^ := ss^;\r
+  ds^.strm := dest;\r
+\r
+  ds^.window := pzByteArray ( ZALLOC(dest^, ds^.w_size, 2*sizeof(Byte)) );\r
+  ds^.prev   := pzPosfArray ( ZALLOC(dest^, ds^.w_size, sizeof(Pos)) );\r
+  ds^.head   := pzPosfArray ( ZALLOC(dest^, ds^.hash_size, sizeof(Pos)) );\r
+  overlay := pushfArray ( ZALLOC(dest^, ds^.lit_bufsize, sizeof(ush)+2) );\r
+  ds^.pending_buf := pzByteArray ( overlay );\r
+\r
+  if (ds^.window = Z_NULL) or (ds^.prev = Z_NULL) or (ds^.head = Z_NULL)\r
+     or (ds^.pending_buf = Z_NULL) then\r
+  begin\r
+    deflateEnd (dest^);\r
+    deflateCopy := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+  { following zmemcpy do not work for 16-bit MSDOS }\r
+  zmemcpy(pBytef(ds^.window), pBytef(ss^.window), ds^.w_size * 2 * sizeof(Byte));\r
+  zmemcpy(pBytef(ds^.prev), pBytef(ss^.prev), ds^.w_size * sizeof(Pos));\r
+  zmemcpy(pBytef(ds^.head), pBytef(ss^.head), ds^.hash_size * sizeof(Pos));\r
+  zmemcpy(pBytef(ds^.pending_buf), pBytef(ss^.pending_buf), uInt(ds^.pending_buf_size));\r
+\r
+  ds^.pending_out := @ds^.pending_buf^[ptr2int(ss^.pending_out) - ptr2int(ss^.pending_buf)];\r
+  ds^.d_buf := pushfArray (@overlay^[ds^.lit_bufsize div sizeof(ush)] );\r
+  ds^.l_buf := puchfArray (@ds^.pending_buf^[(1+sizeof(ush))*ds^.lit_bufsize]);\r
+\r
+  ds^.l_desc.dyn_tree := tree_ptr(@ds^.dyn_ltree);\r
+  ds^.d_desc.dyn_tree := tree_ptr(@ds^.dyn_dtree);\r
+  ds^.bl_desc.dyn_tree := tree_ptr(@ds^.bl_tree);\r
+\r
+  deflateCopy := Z_OK;\r
+{$endif}\r
+end;\r
+\r
+\r
+{ ===========================================================================\r
+  Read a new buffer from the current input stream, update the adler32\r
+  and total number of bytes read.  All deflate() input goes through\r
+  this function so some applications may wish to modify it to avoid\r
+  allocating a large strm^.next_in buffer and copying from it.\r
+  (See also flush_pending()). }\r
+\r
+{local}\r
+function read_buf(strm : z_streamp; buf : pBytef; size : unsigned) : int;\r
+var\r
+  len : unsigned;\r
+begin\r
+  len := strm^.avail_in;\r
+\r
+  if (len > size) then\r
+    len := size;\r
+  if (len = 0) then\r
+  begin\r
+    read_buf := 0;\r
+    exit;\r
+  end;\r
+\r
+  Dec(strm^.avail_in, len);\r
+\r
+  if deflate_state_ptr(strm^.state)^.noheader = 0 then\r
+  begin\r
+    strm^.adler := adler32(strm^.adler, strm^.next_in, len);\r
+  end;\r
+  zmemcpy(buf, strm^.next_in, len);\r
+  Inc(strm^.next_in, len);\r
+  Inc(strm^.total_in, len);\r
+\r
+  read_buf := int(len);\r
+end;\r
+\r
+{ ===========================================================================\r
+  Initialize the "longest match" routines for a new zlib stream }\r
+\r
+{local}\r
+procedure lm_init (var s : deflate_state);\r
+begin\r
+  s.window_size := ulg( uLong(2)*s.w_size);\r
+\r
+  {macro CLEAR_HASH(s);}\r
+  s.head^[s.hash_size-1] := ZNIL;\r
+  zmemzero(pBytef(s.head), unsigned(s.hash_size-1)*sizeof(s.head^[0]));\r
+\r
+  { Set the default configuration parameters: }\r
+\r
+  s.max_lazy_match   := configuration_table[s.level].max_lazy;\r
+  s.good_match       := configuration_table[s.level].good_length;\r
+  s.nice_match       := configuration_table[s.level].nice_length;\r
+  s.max_chain_length := configuration_table[s.level].max_chain;\r
+\r
+  s.strstart := 0;\r
+  s.block_start := long(0);\r
+  s.lookahead := 0;\r
+  s.prev_length := MIN_MATCH-1;\r
+  s.match_length := MIN_MATCH-1;\r
+  s.match_available := FALSE;\r
+  s.ins_h := 0;\r
+{$ifdef ASMV}\r
+  match_init; { initialize the asm code }\r
+{$endif}\r
+end;\r
+\r
+{ ===========================================================================\r
+  Set match_start to the longest match starting at the given string and\r
+  return its length. Matches shorter or equal to prev_length are discarded,\r
+  in which case the result is equal to prev_length and match_start is\r
+  garbage.\r
+  IN assertions: cur_match is the head of the hash chain for the current\r
+    string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\r
+  OUT assertion: the match length is not greater than s^.lookahead. }\r
+\r
+\r
+{$ifndef ASMV}\r
+{ For 80x86 and 680x0, an optimized version will be provided in match.asm or\r
+  match.S. The code will be functionally equivalent. }\r
+\r
+{$ifndef FASTEST}\r
+\r
+{local}\r
+function longest_match(var s : deflate_state;\r
+                       cur_match : IPos  { current match }\r
+                       ) : uInt;\r
+label\r
+  nextstep;\r
+var\r
+  chain_length : unsigned;    { max hash chain length }\r
+  {register} scan : pBytef;   { current string }\r
+  {register} match : pBytef;  { matched string }\r
+  {register} len : int;       { length of current match }\r
+  best_len : int;             { best match length so far }\r
+  nice_match : int;           { stop if match long enough }\r
+  limit : IPos;\r
+\r
+  prev : pzPosfArray;\r
+  wmask : uInt;\r
+{$ifdef UNALIGNED_OK}\r
+  {register} strend : pBytef;\r
+  {register} scan_start : ush;\r
+  {register} scan_end : ush;\r
+{$else}\r
+  {register} strend : pBytef;\r
+  {register} scan_end1 : Byte;\r
+  {register} scan_end : Byte;\r
+{$endif}\r
+var\r
+  MAX_DIST : uInt;\r
+begin\r
+  chain_length := s.max_chain_length; { max hash chain length }\r
+  scan := @(s.window^[s.strstart]);\r
+  best_len := s.prev_length;              { best match length so far }\r
+  nice_match := s.nice_match;             { stop if match long enough }\r
+\r
+\r
+  MAX_DIST := s.w_size - MIN_LOOKAHEAD;\r
+{In order to simplify the code, particularly on 16 bit machines, match\r
+distances are limited to MAX_DIST instead of WSIZE. }\r
+\r
+  if s.strstart > IPos(MAX_DIST) then\r
+    limit := s.strstart - IPos(MAX_DIST)\r
+  else\r
+    limit := ZNIL;\r
+  { Stop when cur_match becomes <= limit. To simplify the code,\r
+    we prevent matches with the string of window index 0. }\r
+\r
+  prev := s.prev;\r
+  wmask := s.w_mask;\r
+\r
+{$ifdef UNALIGNED_OK}\r
+  { Compare two bytes at a time. Note: this is not always beneficial.\r
+    Try with and without -DUNALIGNED_OK to check. }\r
+\r
+  strend := pBytef(@(s.window^[s.strstart + MAX_MATCH - 1]));\r
+  scan_start := pushf(scan)^;\r
+  scan_end   := pushfArray(scan)^[best_len-1];   { fix }\r
+{$else}\r
+  strend := pBytef(@(s.window^[s.strstart + MAX_MATCH]));\r
+  {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}\r
+  scan_end1  := pzByteArray(scan)^[best_len-1];\r
+  {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF}\r
+  scan_end   := pzByteArray(scan)^[best_len];\r
+{$endif}\r
+\r
+    { The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\r
+      It is easy to get rid of this optimization if necessary. }\r
+    {$IFDEF DEBUG}\r
+    Assert((s.hash_bits >= 8) and (MAX_MATCH = 258), 'Code too clever');\r
+    {$ENDIF}\r
+    { Do not waste too much time if we already have a good match: }\r
+    if (s.prev_length >= s.good_match) then\r
+    begin\r
+      chain_length := chain_length shr 2;\r
+    end;\r
+\r
+    { Do not look for matches beyond the end of the input. This is necessary\r
+      to make deflate deterministic. }\r
+\r
+    if (uInt(nice_match) > s.lookahead) then\r
+      nice_match := s.lookahead;\r
+    {$IFDEF DEBUG}\r
+    Assert(ulg(s.strstart) <= s.window_size-MIN_LOOKAHEAD, 'need lookahead');\r
+    {$ENDIF}\r
+    repeat\r
+        {$IFDEF DEBUG}\r
+        Assert(cur_match < s.strstart, 'no future');\r
+        {$ENDIF}\r
+        match := @(s.window^[cur_match]);\r
+\r
+        { Skip to next match if the match length cannot increase\r
+          or if the match length is less than 2: }\r
+\r
+{$undef DO_UNALIGNED_OK}\r
+{$ifdef UNALIGNED_OK}\r
+  {$ifdef MAX_MATCH_IS_258}\r
+    {$define DO_UNALIGNED_OK}\r
+  {$endif}\r
+{$endif}\r
+\r
+{$ifdef DO_UNALIGNED_OK}\r
+        { This code assumes sizeof(unsigned short) = 2. Do not use\r
+          UNALIGNED_OK if your compiler uses a different size. }\r
+  {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}\r
+        if (pushfArray(match)^[best_len-1] <> scan_end) or\r
+           (pushf(match)^ <> scan_start) then\r
+          goto nextstep; {continue;}\r
+  {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF}\r
+\r
+        { It is not necessary to compare scan[2] and match[2] since they are\r
+          always equal when the other bytes match, given that the hash keys\r
+          are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at\r
+          strstart+3, +5, ... up to strstart+257. We check for insufficient\r
+          lookahead only every 4th comparison; the 128th check will be made\r
+          at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is\r
+          necessary to put more guard bytes at the end of the window, or\r
+          to check more often for insufficient lookahead. }\r
+        {$IFDEF DEBUG}\r
+        Assert(pzByteArray(scan)^[2] = pzByteArray(match)^[2], 'scan[2]?');\r
+        {$ENDIF}\r
+        Inc(scan);\r
+        Inc(match);\r
+\r
+        repeat\r
+          Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break;\r
+          Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break;\r
+          Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break;\r
+          Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break;\r
+        until (ptr2int(scan) >= ptr2int(strend));\r
+        { The funny "do while" generates better code on most compilers }\r
+\r
+        { Here, scan <= window+strstart+257 }\r
+        {$IFDEF DEBUG}\r
+        {$ifopt R+} {$define RangeCheck} {$endif} {$R-}\r
+        Assert(ptr2int(scan) <=\r
+               ptr2int(@(s.window^[unsigned(s.window_size-1)])),\r
+               'wild scan');\r
+        {$ifdef RangeCheck} {$R+} {$undef RangeCheck} {$endif}\r
+        {$ENDIF}\r
+        if (scan^ = match^) then\r
+          Inc(scan);\r
+\r
+        len := (MAX_MATCH - 1) - int(ptr2int(strend)) + int(ptr2int(scan));\r
+        scan := strend;\r
+        Dec(scan, (MAX_MATCH-1));\r
+\r
+{$else} { UNALIGNED_OK }\r
+\r
+  {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}\r
+        if (pzByteArray(match)^[best_len]   <> scan_end) or\r
+           (pzByteArray(match)^[best_len-1] <> scan_end1) or\r
+           (match^ <> scan^) then\r
+          goto nextstep; {continue;}\r
+  {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF}\r
+        Inc(match);\r
+        if (match^ <> pzByteArray(scan)^[1]) then\r
+          goto nextstep; {continue;}\r
+\r
+        { The check at best_len-1 can be removed because it will be made\r
+          again later. (This heuristic is not always a win.)\r
+          It is not necessary to compare scan[2] and match[2] since they\r
+          are always equal when the other bytes match, given that\r
+          the hash keys are equal and that HASH_BITS >= 8. }\r
+\r
+        Inc(scan, 2);\r
+        Inc(match);\r
+        {$IFDEF DEBUG}\r
+        Assert( scan^ = match^, 'match[2]?');\r
+        {$ENDIF}\r
+        { We check for insufficient lookahead only every 8th comparison;\r
+          the 256th check will be made at strstart+258. }\r
+\r
+        repeat\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+          Inc(scan); Inc(match); if (scan^ <> match^) then break;\r
+        until (ptr2int(scan) >= ptr2int(strend));\r
+\r
+        {$IFDEF DEBUG}\r
+        Assert(ptr2int(scan) <=\r
+               ptr2int(@(s.window^[unsigned(s.window_size-1)])),\r
+               'wild scan');\r
+        {$ENDIF}\r
+\r
+        len := MAX_MATCH - int(ptr2int(strend) - ptr2int(scan));\r
+        scan := strend;\r
+        Dec(scan, MAX_MATCH);\r
+\r
+{$endif} { UNALIGNED_OK }\r
+\r
+        if (len > best_len) then\r
+        begin\r
+            s.match_start := cur_match;\r
+            best_len := len;\r
+            if (len >= nice_match) then\r
+              break;\r
+  {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}\r
+{$ifdef UNALIGNED_OK}\r
+            scan_end   := pzByteArray(scan)^[best_len-1];\r
+{$else}\r
+            scan_end1  := pzByteArray(scan)^[best_len-1];\r
+            scan_end   := pzByteArray(scan)^[best_len];\r
+{$endif}\r
+  {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF}\r
+        end;\r
+    nextstep:\r
+      cur_match := prev^[cur_match and wmask];\r
+      Dec(chain_length);\r
+    until (cur_match <= limit) or (chain_length = 0);\r
+\r
+    if (uInt(best_len) <= s.lookahead) then\r
+      longest_match := uInt(best_len)\r
+    else\r
+      longest_match := s.lookahead;\r
+end;\r
+{$endif} { ASMV }\r
+\r
+{$else} { FASTEST }\r
+{ ---------------------------------------------------------------------------\r
+  Optimized version for level = 1 only }\r
+\r
+{local}\r
+function longest_match(var s : deflate_state;\r
+                       cur_match : IPos  { current match }\r
+                       ) : uInt;\r
+var\r
+  {register} scan : pBytef;   { current string }\r
+  {register} match : pBytef;  { matched string }\r
+  {register} len : int;       { length of current match }\r
+  {register} strend : pBytef;\r
+begin\r
+  scan := @s.window^[s.strstart];\r
+  strend := @s.window^[s.strstart + MAX_MATCH];\r
+\r
+\r
+    { The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\r
+      It is easy to get rid of this optimization if necessary. }\r
+    {$IFDEF DEBUG}\r
+    Assert((s.hash_bits >= 8) and (MAX_MATCH = 258), 'Code too clever');\r
+\r
+    Assert(ulg(s.strstart) <= s.window_size-MIN_LOOKAHEAD, 'need lookahead');\r
+\r
+    Assert(cur_match < s.strstart, 'no future');\r
+    {$ENDIF}\r
+    match := s.window + cur_match;\r
+\r
+    { Return failure if the match length is less than 2: }\r
+\r
+    if (match[0] <> scan[0]) or (match[1] <> scan[1]) then\r
+    begin\r
+      longest_match := MIN_MATCH-1;\r
+      exit;\r
+    end;\r
+\r
+    { The check at best_len-1 can be removed because it will be made\r
+      again later. (This heuristic is not always a win.)\r
+      It is not necessary to compare scan[2] and match[2] since they\r
+      are always equal when the other bytes match, given that\r
+      the hash keys are equal and that HASH_BITS >= 8. }\r
+\r
+    scan += 2, match += 2;\r
+    Assert(scan^ = match^, 'match[2]?');\r
+\r
+    { We check for insufficient lookahead only every 8th comparison;\r
+      the 256th check will be made at strstart+258. }\r
+\r
+    repeat\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+      Inc(scan); Inc(match); if scan^<>match^ then break;\r
+    until (ptr2int(scan) >= ptr2int(strend));\r
+\r
+    Assert(scan <= s.window+unsigned(s.window_size-1), 'wild scan');\r
+\r
+    len := MAX_MATCH - int(strend - scan);\r
+\r
+    if (len < MIN_MATCH) then\r
+    begin\r
+      return := MIN_MATCH - 1;\r
+      exit;\r
+    end;\r
+\r
+    s.match_start := cur_match;\r
+    if len <= s.lookahead then\r
+      longest_match := len\r
+    else\r
+      longest_match := s.lookahead;\r
+end;\r
+{$endif} { FASTEST }\r
+\r
+{$ifdef DEBUG}\r
+{ ===========================================================================\r
+  Check that the match at match_start is indeed a match. }\r
+\r
+{local}\r
+procedure check_match(var s : deflate_state;\r
+                      start, match : IPos;\r
+                      length : int);\r
+begin\r
+  exit;\r
+  { check that the match is indeed a match }\r
+  if (zmemcmp(pBytef(@s.window^[match]),\r
+              pBytef(@s.window^[start]), length) <> EQUAL) then\r
+  begin\r
+    WriteLn(' start ',start,', match ',match ,' length ', length);\r
+    repeat\r
+      Write(char(s.window^[match]), char(s.window^[start]));\r
+      Inc(match);\r
+      Inc(start);\r
+      Dec(length);\r
+    Until (length = 0);\r
+    z_error('invalid match');\r
+  end;\r
+  if (z_verbose > 1) then\r
+  begin\r
+    Write('\\[',start-match,',',length,']');\r
+    repeat\r
+       Write(char(s.window^[start]));\r
+       Inc(start);\r
+       Dec(length);\r
+    Until (length = 0);\r
+  end;\r
+end;\r
+{$endif}\r
+\r
+{ ===========================================================================\r
+  Fill the window when the lookahead becomes insufficient.\r
+  Updates strstart and lookahead.\r
+\r
+  IN assertion: lookahead < MIN_LOOKAHEAD\r
+  OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\r
+     At least one byte has been read, or avail_in = 0; reads are\r
+     performed for at least two bytes (required for the zip translate_eol\r
+     option -- not supported here). }\r
+\r
+{local}\r
+procedure fill_window(var s : deflate_state);\r
+var\r
+  {register} n, m : unsigned;\r
+  {register} p : pPosf;\r
+  more : unsigned;    { Amount of free space at the end of the window. }\r
+  wsize : uInt;\r
+begin\r
+   wsize := s.w_size;\r
+   repeat\r
+     more := unsigned(s.window_size -ulg(s.lookahead) -ulg(s.strstart));\r
+\r
+     { Deal with !@#$% 64K limit: }\r
+     if (more = 0) and (s.strstart = 0) and (s.lookahead = 0) then\r
+       more := wsize\r
+     else\r
+     if (more = unsigned(-1)) then\r
+     begin\r
+       { Very unlikely, but possible on 16 bit machine if strstart = 0\r
+         and lookahead = 1 (input done one byte at time) }\r
+       Dec(more);\r
+\r
+       { If the window is almost full and there is insufficient lookahead,\r
+         move the upper half to the lower one to make room in the upper half.}\r
+     end\r
+     else\r
+       if (s.strstart >= wsize+ {MAX_DIST}(wsize-MIN_LOOKAHEAD)) then\r
+       begin\r
+         zmemcpy( pBytef(s.window), pBytef(@(s.window^[wsize])),\r
+                 unsigned(wsize));\r
+         Dec(s.match_start, wsize);\r
+         Dec(s.strstart, wsize); { we now have strstart >= MAX_DIST }\r
+         Dec(s.block_start, long(wsize));\r
+\r
+         { Slide the hash table (could be avoided with 32 bit values\r
+           at the expense of memory usage). We slide even when level = 0\r
+           to keep the hash table consistent if we switch back to level > 0\r
+           later. (Using level 0 permanently is not an optimal usage of\r
+           zlib, so we don't care about this pathological case.) }\r
+\r
+         n := s.hash_size;\r
+         p := @s.head^[n];\r
+         repeat\r
+           Dec(p);\r
+           m := p^;\r
+           if (m >= wsize) then\r
+             p^ := Pos(m-wsize)\r
+           else\r
+             p^ := Pos(ZNIL);\r
+           Dec(n);\r
+         Until (n=0);\r
+\r
+         n := wsize;\r
+{$ifndef FASTEST}\r
+         p := @s.prev^[n];\r
+         repeat\r
+           Dec(p);\r
+           m := p^;\r
+           if (m >= wsize) then\r
+             p^ := Pos(m-wsize)\r
+           else\r
+             p^:= Pos(ZNIL);\r
+             { If n is not on any hash chain, prev^[n] is garbage but\r
+               its value will never be used. }\r
+           Dec(n);\r
+         Until (n=0);\r
+{$endif}\r
+         Inc(more, wsize);\r
+     end;\r
+     if (s.strm^.avail_in = 0) then\r
+       exit;\r
+\r
+     {* If there was no sliding:\r
+      *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\r
+      *    more == window_size - lookahead - strstart\r
+      * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\r
+      * => more >= window_size - 2*WSIZE + 2\r
+      * In the BIG_MEM or MMAP case (not yet supported),\r
+      *   window_size == input_size + MIN_LOOKAHEAD  &&\r
+      *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\r
+      * Otherwise, window_size == 2*WSIZE so more >= 2.\r
+      * If there was sliding, more >= WSIZE. So in all cases, more >= 2. }\r
+\r
+     {$IFDEF DEBUG}\r
+     Assert(more >= 2, 'more < 2');\r
+     {$ENDIF}\r
+\r
+     n := read_buf(s.strm, pBytef(@(s.window^[s.strstart + s.lookahead])),\r
+                  more);\r
+     Inc(s.lookahead, n);\r
+\r
+     { Initialize the hash value now that we have some input: }\r
+     if (s.lookahead >= MIN_MATCH) then\r
+     begin\r
+       s.ins_h := s.window^[s.strstart];\r
+       {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);}\r
+       s.ins_h := ((s.ins_h shl s.hash_shift) xor s.window^[s.strstart+1])\r
+                     and s.hash_mask;\r
+{$ifdef MIN_MATCH <> 3}\r
+       Call UPDATE_HASH() MIN_MATCH-3 more times\r
+{$endif}\r
+     end;\r
+     { If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\r
+       but this is not important since only literal bytes will be emitted. }\r
+\r
+   until (s.lookahead >= MIN_LOOKAHEAD) or (s.strm^.avail_in = 0);\r
+end;\r
+\r
+{ ===========================================================================\r
+  Flush the current block, with given end-of-file flag.\r
+  IN assertion: strstart is set to the end of the current match. }\r
+\r
+procedure FLUSH_BLOCK_ONLY(var s : deflate_state; eof : boolean); {macro}\r
+begin\r
+  if (s.block_start >= Long(0)) then\r
+    _tr_flush_block(s, pcharf(@s.window^[unsigned(s.block_start)]),\r
+                    ulg(long(s.strstart) - s.block_start), eof)\r
+  else\r
+    _tr_flush_block(s, pcharf(Z_NULL),\r
+                    ulg(long(s.strstart) - s.block_start), eof);\r
+\r
+  s.block_start := s.strstart;\r
+  flush_pending(s.strm^);\r
+  {$IFDEF DEBUG}\r
+  Tracev('[FLUSH]');\r
+  {$ENDIF}\r
+end;\r
+\r
+{ Same but force premature exit if necessary.\r
+macro FLUSH_BLOCK(var s : deflate_state; eof : boolean) : boolean;\r
+var\r
+  result : block_state;\r
+begin\r
+ FLUSH_BLOCK_ONLY(s, eof);\r
+ if (s.strm^.avail_out = 0) then\r
+ begin\r
+   if eof then\r
+     result := finish_started\r
+   else\r
+     result := need_more;\r
+   exit;\r
+ end;\r
+end;\r
+}\r
+\r
+{ ===========================================================================\r
+  Copy without compression as much as possible from the input stream, return\r
+  the current block state.\r
+  This function does not insert new strings in the dictionary since\r
+  uncompressible data is probably not useful. This function is used\r
+  only for the level=0 compression option.\r
+  NOTE: this function should be optimized to avoid extra copying from\r
+  window to pending_buf. }\r
+\r
+\r
+{local}\r
+function deflate_stored(var s : deflate_state; flush : int) : block_state;\r
+{ Stored blocks are limited to 0xffff bytes, pending_buf is limited\r
+  to pending_buf_size, and each stored block has a 5 byte header: }\r
+var\r
+  max_block_size : ulg;\r
+  max_start : ulg;\r
+begin\r
+  max_block_size := $ffff;\r
+  if (max_block_size > s.pending_buf_size - 5) then\r
+    max_block_size := s.pending_buf_size - 5;\r
+\r
+  { Copy as much as possible from input to output: }\r
+  while TRUE do\r
+  begin\r
+    { Fill the window as much as possible: }\r
+    if (s.lookahead <= 1) then\r
+    begin\r
+      {$IFDEF DEBUG}\r
+      Assert( (s.strstart < s.w_size + {MAX_DIST}s.w_size-MIN_LOOKAHEAD) or\r
+              (s.block_start >= long(s.w_size)), 'slide too late');\r
+      {$ENDIF}\r
+      fill_window(s);\r
+      if (s.lookahead = 0) and (flush = Z_NO_FLUSH) then\r
+      begin\r
+        deflate_stored := need_more;\r
+        exit;\r
+      end;\r
+\r
+      if (s.lookahead = 0) then\r
+        break; { flush the current block }\r
+    end;\r
+    {$IFDEF DEBUG}\r
+    Assert(s.block_start >= long(0), 'block gone');\r
+    {$ENDIF}\r
+    Inc(s.strstart, s.lookahead);\r
+    s.lookahead := 0;\r
+\r
+    { Emit a stored block if pending_buf will be full: }\r
+    max_start := s.block_start + max_block_size;\r
+    if (s.strstart = 0) or (ulg(s.strstart) >= max_start) then\r
+    begin\r
+      { strstart = 0 is possible when wraparound on 16-bit machine }\r
+      s.lookahead := uInt(s.strstart - max_start);\r
+      s.strstart := uInt(max_start);\r
+      {FLUSH_BLOCK(s, FALSE);}\r
+      FLUSH_BLOCK_ONLY(s, FALSE);\r
+      if (s.strm^.avail_out = 0) then\r
+      begin\r
+        deflate_stored := need_more;\r
+        exit;\r
+      end;\r
+    end;\r
+\r
+    { Flush if we may have to slide, otherwise block_start may become\r
+      negative and the data will be gone: }\r
+\r
+    if (s.strstart - uInt(s.block_start) >= {MAX_DIST}\r
+        s.w_size-MIN_LOOKAHEAD) then\r
+    begin\r
+      {FLUSH_BLOCK(s, FALSE);}\r
+      FLUSH_BLOCK_ONLY(s, FALSE);\r
+      if (s.strm^.avail_out = 0) then\r
+      begin\r
+        deflate_stored := need_more;\r
+        exit;\r
+      end;\r
+    end;\r
+  end;\r
+\r
+  {FLUSH_BLOCK(s, flush = Z_FINISH);}\r
+  FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);\r
+  if (s.strm^.avail_out = 0) then\r
+  begin\r
+    if flush = Z_FINISH then\r
+      deflate_stored := finish_started\r
+    else\r
+      deflate_stored := need_more;\r
+    exit;\r
+  end;\r
+\r
+  if flush = Z_FINISH then\r
+    deflate_stored := finish_done\r
+  else\r
+    deflate_stored := block_done;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Compress as much as possible from the input stream, return the current\r
+  block state.\r
+  This function does not perform lazy evaluation of matches and inserts\r
+  new strings in the dictionary only for unmatched strings or for short\r
+  matches. It is used only for the fast compression options. }\r
+\r
+{local}\r
+function deflate_fast(var s : deflate_state; flush : int) : block_state;\r
+var\r
+  hash_head : IPos;     { head of the hash chain }\r
+  bflush : boolean;     { set if current block must be flushed }\r
+begin\r
+  hash_head := ZNIL;\r
+  while TRUE do\r
+  begin\r
+  { Make sure that we always have enough lookahead, except\r
+    at the end of the input file. We need MAX_MATCH bytes\r
+    for the next match, plus MIN_MATCH bytes to insert the\r
+    string following the next match. }\r
+\r
+    if (s.lookahead < MIN_LOOKAHEAD) then\r
+    begin\r
+      fill_window(s);\r
+      if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then\r
+      begin\r
+        deflate_fast := need_more;\r
+        exit;\r
+      end;\r
+\r
+      if (s.lookahead = 0) then\r
+        break; { flush the current block }\r
+    end;\r
+\r
+\r
+    { Insert the string window[strstart .. strstart+2] in the\r
+      dictionary, and set hash_head to the head of the hash chain: }\r
+\r
+    if (s.lookahead >= MIN_MATCH) then\r
+    begin\r
+      INSERT_STRING(s, s.strstart, hash_head);\r
+    end;\r
+\r
+    { Find the longest match, discarding those <= prev_length.\r
+      At this point we have always match_length < MIN_MATCH }\r
+    if (hash_head <> ZNIL) and\r
+       (s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD){MAX_DIST}) then\r
+    begin\r
+      { To simplify the code, we prevent matches with the string\r
+        of window index 0 (in particular we have to avoid a match\r
+        of the string with itself at the start of the input file). }\r
+      if (s.strategy <> Z_HUFFMAN_ONLY) then\r
+      begin\r
+        s.match_length := longest_match (s, hash_head);\r
+      end;\r
+      { longest_match() sets match_start }\r
+    end;\r
+    if (s.match_length >= MIN_MATCH) then\r
+    begin\r
+      {$IFDEF DEBUG}\r
+      check_match(s, s.strstart, s.match_start, s.match_length);\r
+      {$ENDIF}\r
+\r
+      {_tr_tally_dist(s, s.strstart - s.match_start,\r
+                        s.match_length - MIN_MATCH, bflush);}\r
+      bflush := _tr_tally(s, s.strstart - s.match_start,\r
+                        s.match_length - MIN_MATCH);\r
+\r
+      Dec(s.lookahead, s.match_length);\r
+\r
+      { Insert new strings in the hash table only if the match length\r
+        is not too large. This saves time but degrades compression. }\r
+\r
+{$ifndef FASTEST}\r
+      if (s.match_length <= s.max_insert_length)\r
+       and (s.lookahead >= MIN_MATCH) then\r
+      begin\r
+        Dec(s.match_length); { string at strstart already in hash table }\r
+        repeat\r
+          Inc(s.strstart);\r
+          INSERT_STRING(s, s.strstart, hash_head);\r
+          { strstart never exceeds WSIZE-MAX_MATCH, so there are\r
+            always MIN_MATCH bytes ahead. }\r
+          Dec(s.match_length);\r
+        until (s.match_length = 0);\r
+        Inc(s.strstart);\r
+      end\r
+      else\r
+{$endif}\r
+\r
+      begin\r
+        Inc(s.strstart, s.match_length);\r
+        s.match_length := 0;\r
+        s.ins_h := s.window^[s.strstart];\r
+        {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);}\r
+        s.ins_h := (( s.ins_h shl s.hash_shift) xor\r
+                     s.window^[s.strstart+1]) and s.hash_mask;\r
+if MIN_MATCH <> 3 then   { the linker removes this }\r
+begin\r
+          {Call UPDATE_HASH() MIN_MATCH-3 more times}\r
+end;\r
+\r
+        { If lookahead < MIN_MATCH, ins_h is garbage, but it does not\r
+          matter since it will be recomputed at next deflate call. }\r
+\r
+      end;\r
+    end\r
+    else\r
+    begin\r
+      { No match, output a literal byte }\r
+      {$IFDEF DEBUG}\r
+      Tracevv(char(s.window^[s.strstart]));\r
+      {$ENDIF}\r
+      {_tr_tally_lit (s, 0, s.window^[s.strstart], bflush);}\r
+      bflush := _tr_tally (s, 0, s.window^[s.strstart]);\r
+\r
+      Dec(s.lookahead);\r
+      Inc(s.strstart);\r
+    end;\r
+    if bflush then\r
+    begin  {FLUSH_BLOCK(s, FALSE);}\r
+      FLUSH_BLOCK_ONLY(s, FALSE);\r
+      if (s.strm^.avail_out = 0) then\r
+      begin\r
+        deflate_fast := need_more;\r
+        exit;\r
+      end;\r
+    end;\r
+  end;\r
+  {FLUSH_BLOCK(s, flush = Z_FINISH);}\r
+  FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);\r
+  if (s.strm^.avail_out = 0) then\r
+  begin\r
+    if flush = Z_FINISH then\r
+      deflate_fast := finish_started\r
+    else\r
+      deflate_fast := need_more;\r
+    exit;\r
+  end;\r
+\r
+  if flush = Z_FINISH then\r
+    deflate_fast := finish_done\r
+  else\r
+    deflate_fast := block_done;\r
+end;\r
+\r
+{ ===========================================================================\r
+  Same as above, but achieves better compression. We use a lazy\r
+  evaluation for matches: a match is finally adopted only if there is\r
+  no better match at the next window position. }\r
+\r
+{local}\r
+function deflate_slow(var s : deflate_state; flush : int) : block_state;\r
+var\r
+  hash_head : IPos;       { head of hash chain }\r
+  bflush : boolean;       { set if current block must be flushed }\r
+var\r
+  max_insert : uInt;\r
+begin\r
+  hash_head := ZNIL;\r
+\r
+  { Process the input block. }\r
+  while TRUE do\r
+  begin\r
+    { Make sure that we always have enough lookahead, except\r
+      at the end of the input file. We need MAX_MATCH bytes\r
+      for the next match, plus MIN_MATCH bytes to insert the\r
+      string following the next match. }\r
+\r
+    if (s.lookahead < MIN_LOOKAHEAD) then\r
+    begin\r
+      fill_window(s);\r
+      if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then\r
+      begin\r
+        deflate_slow := need_more;\r
+        exit;\r
+      end;\r
+\r
+      if (s.lookahead = 0) then\r
+        break; { flush the current block }\r
+    end;\r
+\r
+    { Insert the string window[strstart .. strstart+2] in the\r
+      dictionary, and set hash_head to the head of the hash chain: }\r
+\r
+    if (s.lookahead >= MIN_MATCH) then\r
+    begin\r
+      INSERT_STRING(s, s.strstart, hash_head);\r
+    end;\r
+\r
+    { Find the longest match, discarding those <= prev_length. }\r
+\r
+    s.prev_length := s.match_length;\r
+    s.prev_match := s.match_start;\r
+    s.match_length := MIN_MATCH-1;\r
+\r
+    if (hash_head <> ZNIL) and (s.prev_length < s.max_lazy_match) and\r
+       (s.strstart - hash_head <= {MAX_DIST}(s.w_size-MIN_LOOKAHEAD)) then\r
+    begin\r
+        { To simplify the code, we prevent matches with the string\r
+          of window index 0 (in particular we have to avoid a match\r
+          of the string with itself at the start of the input file). }\r
+\r
+        if (s.strategy <> Z_HUFFMAN_ONLY) then\r
+        begin\r
+          s.match_length := longest_match (s, hash_head);\r
+        end;\r
+        { longest_match() sets match_start }\r
+\r
+        if (s.match_length <= 5) and ((s.strategy = Z_FILTERED) or\r
+             ((s.match_length = MIN_MATCH) and\r
+              (s.strstart - s.match_start > TOO_FAR))) then\r
+        begin\r
+            { If prev_match is also MIN_MATCH, match_start is garbage\r
+              but we will ignore the current match anyway. }\r
+\r
+            s.match_length := MIN_MATCH-1;\r
+        end;\r
+    end;\r
+    { If there was a match at the previous step and the current\r
+      match is not better, output the previous match: }\r
+\r
+    if (s.prev_length >= MIN_MATCH)\r
+      and (s.match_length <= s.prev_length) then\r
+    begin\r
+      max_insert := s.strstart + s.lookahead - MIN_MATCH;\r
+      { Do not insert strings in hash table beyond this. }\r
+      {$ifdef DEBUG}\r
+      check_match(s, s.strstart-1, s.prev_match, s.prev_length);\r
+      {$endif}\r
+\r
+      {_tr_tally_dist(s, s->strstart -1 - s->prev_match,\r
+                       s->prev_length - MIN_MATCH, bflush);}\r
+      bflush := _tr_tally(s, s.strstart -1 - s.prev_match,\r
+                           s.prev_length - MIN_MATCH);\r
+\r
+      { Insert in hash table all strings up to the end of the match.\r
+        strstart-1 and strstart are already inserted. If there is not\r
+        enough lookahead, the last two strings are not inserted in\r
+        the hash table. }\r
+\r
+      Dec(s.lookahead, s.prev_length-1);\r
+      Dec(s.prev_length, 2);\r
+      repeat\r
+        Inc(s.strstart);\r
+        if (s.strstart <= max_insert) then\r
+        begin\r
+          INSERT_STRING(s, s.strstart, hash_head);\r
+        end;\r
+        Dec(s.prev_length);\r
+      until (s.prev_length = 0);\r
+      s.match_available := FALSE;\r
+      s.match_length := MIN_MATCH-1;\r
+      Inc(s.strstart);\r
+\r
+      if (bflush) then  {FLUSH_BLOCK(s, FALSE);}\r
+      begin\r
+        FLUSH_BLOCK_ONLY(s, FALSE);\r
+        if (s.strm^.avail_out = 0) then\r
+        begin\r
+          deflate_slow := need_more;\r
+          exit;\r
+        end;\r
+      end;\r
+    end\r
+    else\r
+      if (s.match_available) then\r
+      begin\r
+        { If there was no match at the previous position, output a\r
+          single literal. If there was a match but the current match\r
+          is longer, truncate the previous match to a single literal. }\r
+        {$IFDEF DEBUG}\r
+        Tracevv(char(s.window^[s.strstart-1]));\r
+        {$ENDIF}\r
+        bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);\r
+\r
+        if bflush then\r
+        begin\r
+          FLUSH_BLOCK_ONLY(s, FALSE);\r
+        end;\r
+        Inc(s.strstart);\r
+        Dec(s.lookahead);\r
+        if (s.strm^.avail_out = 0) then\r
+        begin\r
+          deflate_slow := need_more;\r
+          exit;\r
+        end;\r
+      end\r
+      else\r
+      begin\r
+        { There is no previous match to compare with, wait for\r
+          the next step to decide. }\r
+\r
+        s.match_available := TRUE;\r
+        Inc(s.strstart);\r
+        Dec(s.lookahead);\r
+      end;\r
+  end;\r
+\r
+  {$IFDEF DEBUG}\r
+  Assert (flush <> Z_NO_FLUSH, 'no flush?');\r
+  {$ENDIF}\r
+  if (s.match_available) then\r
+  begin\r
+    {$IFDEF DEBUG}\r
+    Tracevv(char(s.window^[s.strstart-1]));\r
+    bflush :=\r
+    {$ENDIF}\r
+      _tr_tally (s, 0, s.window^[s.strstart-1]);\r
+    s.match_available := FALSE;\r
+  end;\r
+  {FLUSH_BLOCK(s, flush = Z_FINISH);}\r
+  FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);\r
+  if (s.strm^.avail_out = 0) then\r
+  begin\r
+    if flush = Z_FINISH then\r
+      deflate_slow := finish_started\r
+    else\r
+      deflate_slow := need_more;\r
+    exit;\r
+  end;\r
+  if flush = Z_FINISH then\r
+    deflate_slow := finish_done\r
+  else\r
+    deflate_slow := block_done;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/zinflate.pas b/zinflate.pas
new file mode 100755 (executable)
index 0000000..2d48883
--- /dev/null
@@ -0,0 +1,750 @@
+Unit  zInflate;\r
+\r
+{  inflate.c -- zlib interface to inflate modules\r
+   Copyright (C) 1995-1998 Mark Adler\r
+\r
+  Pascal tranlastion\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.paszlib\r
+}\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+uses\r
+  zutil, zlib, infblock, infutil;\r
+\r
+function inflateInit(var z : z_stream) : int;\r
+\r
+{    Initializes the internal stream state for decompression. The fields\r
+   zalloc, zfree and opaque must be initialized before by the caller.  If\r
+   zalloc and zfree are set to Z_NULL, inflateInit updates them to use default\r
+   allocation functions.\r
+\r
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not\r
+   enough memory, Z_VERSION_ERROR if the zlib library version is incompatible\r
+   with the version assumed by the caller.  msg is set to null if there is no\r
+   error message. inflateInit does not perform any decompression: this will be\r
+   done by inflate(). }\r
+\r
+\r
+\r
+function inflateInit_(z : z_streamp;\r
+                      const version : string;\r
+                      stream_size : int) : int;\r
+\r
+\r
+function inflateInit2_(var z: z_stream;\r
+                       w : int;\r
+                       const version : string;\r
+                       stream_size : int) : int;\r
+\r
+function inflateInit2(var z: z_stream;\r
+                       windowBits : int) : int;\r
+\r
+{\r
+     This is another version of inflateInit with an extra parameter. The\r
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized\r
+   before by the caller.\r
+\r
+     The windowBits parameter is the base two logarithm of the maximum window\r
+   size (the size of the history buffer).  It should be in the range 8..15 for\r
+   this version of the library. The default value is 15 if inflateInit is used\r
+   instead. If a compressed stream with a larger window size is given as\r
+   input, inflate() will return with the error code Z_DATA_ERROR instead of\r
+   trying to allocate a larger window.\r
+\r
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\r
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative\r
+   memLevel). msg is set to null if there is no error message.  inflateInit2\r
+   does not perform any decompression apart from reading the zlib header if\r
+   present: this will be done by inflate(). (So next_in and avail_in may be\r
+   modified, but next_out and avail_out are unchanged.)\r
+}\r
+\r
+\r
+\r
+function inflateEnd(var z : z_stream) : int;\r
+\r
+{\r
+   All dynamically allocated data structures for this stream are freed.\r
+   This function discards any unprocessed input and does not flush any\r
+   pending output.\r
+\r
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state\r
+   was inconsistent. In the error case, msg may be set but then points to a\r
+   static string (which must not be deallocated).\r
+}\r
+\r
+function inflateReset(var z : z_stream) : int;\r
+\r
+{\r
+   This function is equivalent to inflateEnd followed by inflateInit,\r
+   but does not free and reallocate all the internal decompression state.\r
+   The stream will keep attributes that may have been set by inflateInit2.\r
+\r
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\r
+   stream state was inconsistent (such as zalloc or state being NULL).\r
+}\r
+\r
+\r
+function inflate(var z : z_stream;\r
+                 f : int) : int;\r
+{\r
+  inflate decompresses as much data as possible, and stops when the input\r
+  buffer becomes empty or the output buffer becomes full. It may introduce\r
+  some output latency (reading input without producing any output)\r
+  except when forced to flush.\r
+\r
+  The detailed semantics are as follows. inflate performs one or both of the\r
+  following actions:\r
+\r
+  - Decompress more input starting at next_in and update next_in and avail_in\r
+    accordingly. If not all input can be processed (because there is not\r
+    enough room in the output buffer), next_in is updated and processing\r
+    will resume at this point for the next call of inflate().\r
+\r
+  - Provide more output starting at next_out and update next_out and avail_out\r
+    accordingly.  inflate() provides as much output as possible, until there\r
+    is no more input data or no more space in the output buffer (see below\r
+    about the flush parameter).\r
+\r
+  Before the call of inflate(), the application should ensure that at least\r
+  one of the actions is possible, by providing more input and/or consuming\r
+  more output, and updating the next_* and avail_* values accordingly.\r
+  The application can consume the uncompressed output when it wants, for\r
+  example when the output buffer is full (avail_out == 0), or after each\r
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it\r
+  must be called again after making room in the output buffer because there\r
+  might be more output pending.\r
+\r
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much\r
+  output as possible to the output buffer. The flushing behavior of inflate is\r
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH\r
+  and Z_FINISH, but the current implementation actually flushes as much output\r
+  as possible anyway.\r
+\r
+    inflate() should normally be called until it returns Z_STREAM_END or an\r
+  error. However if all decompression is to be performed in a single step\r
+  (a single call of inflate), the parameter flush should be set to\r
+  Z_FINISH. In this case all pending input is processed and all pending\r
+  output is flushed; avail_out must be large enough to hold all the\r
+  uncompressed data. (The size of the uncompressed data may have been saved\r
+  by the compressor for this purpose.) The next operation on this stream must\r
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH\r
+  is never required, but can be used to inform inflate that a faster routine\r
+  may be used for the single inflate() call.\r
+\r
+     If a preset dictionary is needed at this point (see inflateSetDictionary\r
+  below), inflate sets strm-adler to the adler32 checksum of the\r
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise \r
+  it sets strm->adler to the adler32 checksum of all output produced\r
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or\r
+  an error code as described below. At the end of the stream, inflate()\r
+  checks that its computed adler32 checksum is equal to that saved by the\r
+  compressor and returns Z_STREAM_END only if the checksum is correct.\r
+\r
+    inflate() returns Z_OK if some progress has been made (more input processed\r
+  or more output produced), Z_STREAM_END if the end of the compressed data has\r
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a\r
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\r
+  corrupted (input stream not conforming to the zlib format or incorrect\r
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent\r
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not\r
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not\r
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR\r
+  case, the application may then call inflateSync to look for a good\r
+  compression block.\r
+}\r
+\r
+\r
+function inflateSetDictionary(var z : z_stream;\r
+                              dictionary : pBytef; {const array of byte}\r
+                              dictLength : uInt) : int;\r
+\r
+{\r
+     Initializes the decompression dictionary from the given uncompressed byte\r
+   sequence. This function must be called immediately after a call of inflate\r
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor\r
+   can be determined from the Adler32 value returned by this call of\r
+   inflate. The compressor and decompressor must use exactly the same\r
+   dictionary (see deflateSetDictionary).\r
+\r
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\r
+   parameter is invalid (such as NULL dictionary) or the stream state is\r
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\r
+   expected one (incorrect Adler32 value). inflateSetDictionary does not\r
+   perform any decompression: this will be done by subsequent calls of\r
+   inflate().\r
+}\r
+\r
+function inflateSync(var z : z_stream) : int;\r
+\r
+{\r
+  Skips invalid compressed data until a full flush point (see above the\r
+  description of deflate with Z_FULL_FLUSH) can be found, or until all\r
+  available input is skipped. No output is provided.\r
+\r
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR\r
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,\r
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success\r
+  case, the application may save the current current value of total_in which\r
+  indicates where valid compressed data was found. In the error case, the\r
+  application may repeatedly call inflateSync, providing more input each time,\r
+  until success or end of the input data.\r
+}\r
+\r
+\r
+function inflateSyncPoint(var z : z_stream) : int;\r
+\r
+\r
+implementation\r
+\r
+uses\r
+  adler;\r
+\r
+function inflateReset(var z : z_stream) : int;\r
+begin\r
+  if (z.state = Z_NULL) then\r
+  begin\r
+    inflateReset :=  Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  z.total_out := 0;\r
+  z.total_in := 0;\r
+  z.msg := '';\r
+  if z.state^.nowrap then\r
+    z.state^.mode := BLOCKS\r
+  else\r
+    z.state^.mode := METHOD;\r
+  inflate_blocks_reset(z.state^.blocks^, z, Z_NULL);\r
+  {$IFDEF DEBUG}\r
+  Tracev('inflate: reset');\r
+  {$ENDIF}\r
+  inflateReset :=  Z_OK;\r
+end;\r
+\r
+\r
+function inflateEnd(var z : z_stream) : int;\r
+begin\r
+  if (z.state = Z_NULL) or not Assigned(z.zfree) then\r
+  begin\r
+    inflateEnd :=  Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  if (z.state^.blocks <> Z_NULL) then\r
+    inflate_blocks_free(z.state^.blocks, z);\r
+  ZFREE(z, z.state);\r
+  z.state := Z_NULL;\r
+  {$IFDEF DEBUG}\r
+  Tracev('inflate: end');\r
+  {$ENDIF}\r
+  inflateEnd :=  Z_OK;\r
+end;\r
+\r
+\r
+function inflateInit2_(var z: z_stream;\r
+                       w : int;\r
+                       const version : string;\r
+                       stream_size : int) : int;\r
+begin\r
+  if (version = '') or (version[1] <> ZLIB_VERSION[1]) or\r
+      (stream_size <> sizeof(z_stream)) then\r
+  begin\r
+    inflateInit2_ := Z_VERSION_ERROR;\r
+    exit;\r
+  end;\r
+  { initialize state }\r
+  { SetLength(strm.msg, 255); }\r
+  z.msg := '';\r
+  if not Assigned(z.zalloc) then\r
+  begin\r
+    {$IFDEF FPC}  z.zalloc := @zcalloc;  {$ELSE}\r
+    z.zalloc := zcalloc;\r
+    {$endif}\r
+    z.opaque := voidpf(0);\r
+  end;\r
+  if not Assigned(z.zfree) then\r
+    {$IFDEF FPC}  z.zfree := @zcfree;  {$ELSE}\r
+    z.zfree := zcfree;\r
+    {$ENDIF}\r
+\r
+  z.state := pInternal_state( ZALLOC(z,1,sizeof(internal_state)) );\r
+  if (z.state = Z_NULL) then\r
+  begin\r
+    inflateInit2_ := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+\r
+  z.state^.blocks := Z_NULL;\r
+\r
+  { handle undocumented nowrap option (no zlib header or check) }\r
+  z.state^.nowrap := FALSE;\r
+  if (w < 0) then\r
+  begin\r
+    w := - w;\r
+    z.state^.nowrap := TRUE;\r
+  end;\r
+\r
+  { set window size }\r
+  if (w < 8) or (w > 15) then\r
+  begin\r
+    inflateEnd(z);\r
+    inflateInit2_ := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  z.state^.wbits := uInt(w);\r
+\r
+  { create inflate_blocks state }\r
+  if z.state^.nowrap then\r
+    z.state^.blocks := inflate_blocks_new(z, NIL, uInt(1) shl w)\r
+  else\r
+  {$IFDEF FPC}\r
+    z.state^.blocks := inflate_blocks_new(z, @adler32, uInt(1) shl w);\r
+  {$ELSE}\r
+    z.state^.blocks := inflate_blocks_new(z, adler32, uInt(1) shl w);\r
+  {$ENDIF}\r
+  if (z.state^.blocks = Z_NULL) then\r
+  begin\r
+    inflateEnd(z);\r
+    inflateInit2_ := Z_MEM_ERROR;\r
+    exit;\r
+  end;\r
+  {$IFDEF DEBUG}\r
+  Tracev('inflate: allocated');\r
+  {$ENDIF}\r
+  { reset state }\r
+  inflateReset(z);\r
+  inflateInit2_ :=  Z_OK;\r
+end;\r
+\r
+function inflateInit2(var z: z_stream; windowBits : int) : int;\r
+begin\r
+  inflateInit2 := inflateInit2_(z, windowBits, ZLIB_VERSION, sizeof(z_stream));\r
+end;\r
+\r
+\r
+function inflateInit(var z : z_stream) : int;\r
+{ inflateInit is a macro to allow checking the zlib version\r
+  and the compiler's view of z_stream:  }\r
+begin\r
+  inflateInit := inflateInit2_(z, DEF_WBITS, ZLIB_VERSION, sizeof(z_stream));\r
+end;\r
+\r
+function inflateInit_(z : z_streamp;\r
+                      const version : string;\r
+                      stream_size : int) : int;\r
+begin\r
+  { initialize state }\r
+  if (z = Z_NULL) then\r
+    inflateInit_ := Z_STREAM_ERROR\r
+  else\r
+    inflateInit_ := inflateInit2_(z^, DEF_WBITS, version, stream_size);\r
+end;\r
+\r
+function inflate(var z : z_stream;\r
+                 f : int) : int;\r
+var\r
+  r : int;\r
+  b : uInt;\r
+begin\r
+  if (z.state = Z_NULL) or (z.next_in = Z_NULL) then\r
+  begin\r
+    inflate := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  if f = Z_FINISH then\r
+    f := Z_BUF_ERROR\r
+  else\r
+    f := Z_OK;\r
+  r := Z_BUF_ERROR;\r
+  while True do\r
+  case (z.state^.mode) of\r
+    BLOCKS:\r
+      begin\r
+        r := inflate_blocks(z.state^.blocks^, z, r);\r
+        if (r = Z_DATA_ERROR) then\r
+        begin\r
+          z.state^.mode := BAD;\r
+          z.state^.sub.marker := 0;       { can try inflateSync }\r
+          continue;            { break C-switch }\r
+        end;\r
+        if (r = Z_OK) then\r
+          r := f;\r
+        if (r <> Z_STREAM_END) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+        inflate_blocks_reset(z.state^.blocks^, z, @z.state^.sub.check.was);\r
+        if (z.state^.nowrap) then\r
+        begin\r
+          z.state^.mode := DONE;\r
+          continue;            { break C-switch }\r
+        end;\r
+        z.state^.mode := CHECK4;  { falltrough }\r
+      end;\r
+    CHECK4:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+\r
+        {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        z.state^.sub.check.need := uLong(z.next_in^) shl 24;\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := CHECK3;   { falltrough }\r
+      end;\r
+    CHECK3:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+        {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := CHECK2;   { falltrough }\r
+      end;\r
+    CHECK2:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+\r
+        {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := CHECK1;   { falltrough }\r
+      end;\r
+    CHECK1:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+        {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) );\r
+        Inc(z.next_in);\r
+\r
+\r
+        if (z.state^.sub.check.was <> z.state^.sub.check.need) then\r
+        begin\r
+          z.state^.mode := BAD;\r
+          z.msg := 'incorrect data check';\r
+          z.state^.sub.marker := 5;       { can't try inflateSync }\r
+          continue;           { break C-switch }\r
+        end;\r
+        {$IFDEF DEBUG}\r
+        Tracev('inflate: zlib check ok');\r
+        {$ENDIF}\r
+        z.state^.mode := DONE; { falltrough }\r
+      end;\r
+    DONE:\r
+      begin\r
+        inflate := Z_STREAM_END;\r
+        exit;\r
+      end;\r
+    METHOD:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f; {}\r
+\r
+        {z.state^.sub.method := NEXTBYTE(z);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        z.state^.sub.method := z.next_in^;\r
+        Inc(z.next_in);\r
+\r
+        if ((z.state^.sub.method and $0f) <> Z_DEFLATED) then\r
+        begin\r
+          z.state^.mode := BAD;\r
+          z.msg := 'unknown compression method';\r
+          z.state^.sub.marker := 5;       { can't try inflateSync }\r
+          continue;  { break C-switch }\r
+        end;\r
+        if ((z.state^.sub.method shr 4) + 8 > z.state^.wbits) then\r
+        begin\r
+          z.state^.mode := BAD;\r
+          z.msg := 'invalid window size';\r
+          z.state^.sub.marker := 5;       { can't try inflateSync }\r
+          continue; { break C-switch }\r
+        end;\r
+        z.state^.mode := FLAG;\r
+        { fall trough }\r
+      end;\r
+    FLAG:\r
+      begin\r
+        {NEEDBYTE}\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f; {}\r
+        {b := NEXTBYTE(z);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        b := z.next_in^;\r
+        Inc(z.next_in);\r
+\r
+        if (((z.state^.sub.method shl 8) + b) mod 31) <> 0 then {% mod ?}\r
+        begin\r
+          z.state^.mode := BAD;\r
+          z.msg := 'incorrect header check';\r
+          z.state^.sub.marker := 5;       { can't try inflateSync }\r
+          continue;      { break C-switch }\r
+        end;\r
+        {$IFDEF DEBUG}\r
+        Tracev('inflate: zlib header ok');\r
+        {$ENDIF}\r
+        if ((b and PRESET_DICT) = 0) then\r
+        begin\r
+          z.state^.mode := BLOCKS;\r
+         continue;      { break C-switch }\r
+        end;\r
+        z.state^.mode := DICT4;\r
+        { falltrough }\r
+      end;\r
+    DICT4:\r
+      begin\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+\r
+        {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        z.state^.sub.check.need :=  uLong(z.next_in^) shl 24;\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := DICT3;        { falltrough }\r
+      end;\r
+    DICT3:\r
+      begin\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+        {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := DICT2;        { falltrough }\r
+      end;\r
+    DICT2:\r
+      begin\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        r := f;\r
+\r
+        {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);\r
+        Inc(z.next_in);\r
+\r
+        z.state^.mode := DICT1;        { falltrough }\r
+      end;\r
+    DICT1:\r
+      begin\r
+        if (z.avail_in = 0) then\r
+        begin\r
+          inflate := r;\r
+          exit;\r
+        end;\r
+        { r := f;    ---  wird niemals benutzt }\r
+        {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}\r
+        Dec(z.avail_in);\r
+        Inc(z.total_in);\r
+        Inc(z.state^.sub.check.need, uLong(z.next_in^) );\r
+        Inc(z.next_in);\r
+\r
+        z.adler := z.state^.sub.check.need;\r
+        z.state^.mode := DICT0;\r
+        inflate := Z_NEED_DICT;\r
+        exit;\r
+      end;\r
+    DICT0:\r
+      begin\r
+        z.state^.mode := BAD;\r
+        z.msg := 'need dictionary';\r
+        z.state^.sub.marker := 0;         { can try inflateSync }\r
+        inflate := Z_STREAM_ERROR;\r
+        exit;\r
+      end;\r
+    BAD:\r
+      begin\r
+        inflate := Z_DATA_ERROR;\r
+        exit;\r
+      end;\r
+    else\r
+      begin\r
+        inflate := Z_STREAM_ERROR;\r
+        exit;\r
+      end;\r
+  end;\r
+{$ifdef NEED_DUMMY_result}\r
+  result := Z_STREAM_ERROR;  { Some dumb compilers complain without this }\r
+{$endif}\r
+end;\r
+\r
+function inflateSetDictionary(var z : z_stream;\r
+                              dictionary : pBytef; {const array of byte}\r
+                              dictLength : uInt) : int;\r
+var\r
+  length : uInt;\r
+begin\r
+  length := dictLength;\r
+\r
+  if (z.state = Z_NULL) or (z.state^.mode <> DICT0) then\r
+  begin\r
+    inflateSetDictionary := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  if (adler32(Long(1), dictionary, dictLength) <> z.adler) then\r
+  begin\r
+    inflateSetDictionary := Z_DATA_ERROR;\r
+    exit;\r
+  end;\r
+  z.adler := Long(1);\r
+\r
+  if (length >= (uInt(1) shl z.state^.wbits)) then\r
+  begin\r
+    length := (1 shl z.state^.wbits)-1;\r
+    Inc( dictionary, dictLength - length);\r
+  end;\r
+  inflate_set_dictionary(z.state^.blocks^, dictionary^, length);\r
+  z.state^.mode := BLOCKS;\r
+  inflateSetDictionary := Z_OK;\r
+end;\r
+\r
+\r
+function inflateSync(var z : z_stream) : int;\r
+const\r
+  mark : packed array[0..3] of byte = (0, 0, $ff, $ff);\r
+var\r
+  n : uInt;       { number of bytes to look at }\r
+  p : pBytef;     { pointer to bytes }\r
+  m : uInt;       { number of marker bytes found in a row }\r
+  r, w : uLong;   { temporaries to save total_in and total_out }\r
+begin\r
+  { set up }\r
+  if (z.state = Z_NULL) then\r
+  begin\r
+    inflateSync := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  if (z.state^.mode <> BAD) then\r
+  begin\r
+    z.state^.mode := BAD;\r
+    z.state^.sub.marker := 0;\r
+  end;\r
+  n := z.avail_in;\r
+  if (n = 0) then\r
+  begin\r
+    inflateSync := Z_BUF_ERROR;\r
+    exit;\r
+  end;\r
+  p := z.next_in;\r
+  m := z.state^.sub.marker;\r
+\r
+  { search }\r
+  while (n <> 0) and (m < 4) do\r
+  begin\r
+    if (p^ = mark[m]) then\r
+      Inc(m)\r
+    else\r
+      if (p^ <> 0) then\r
+        m := 0\r
+      else\r
+        m := 4 - m;\r
+    Inc(p);\r
+    Dec(n);\r
+  end;\r
+\r
+  { restore }\r
+  Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in));\r
+  z.next_in := p;\r
+  z.avail_in := n;\r
+  z.state^.sub.marker := m;\r
+\r
+\r
+  { return no joy or set up to restart on a new block }\r
+  if (m <> 4) then\r
+  begin\r
+    inflateSync := Z_DATA_ERROR;\r
+    exit;\r
+  end;\r
+  r := z.total_in;\r
+  w := z.total_out;\r
+  inflateReset(z);\r
+  z.total_in := r;\r
+  z.total_out := w;\r
+  z.state^.mode := BLOCKS;\r
+  inflateSync := Z_OK;\r
+end;\r
+\r
+\r
+{\r
+  returns true if inflate is currently at the end of a block generated\r
+  by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\r
+  implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH\r
+  but removes the length bytes of the resulting empty stored block. When\r
+  decompressing, PPP checks that at the end of input packet, inflate is\r
+  waiting for these length bytes.\r
+}\r
+\r
+function inflateSyncPoint(var z : z_stream) : int;\r
+begin\r
+  if (z.state = Z_NULL) or (z.state^.blocks = Z_NULL) then\r
+  begin\r
+    inflateSyncPoint := Z_STREAM_ERROR;\r
+    exit;\r
+  end;\r
+  inflateSyncPoint := inflate_blocks_sync_point(z.state^.blocks^);\r
+end;\r
+\r
+end.\r
diff --git a/zlib.pas b/zlib.pas
new file mode 100755 (executable)
index 0000000..a8042c3
--- /dev/null
+++ b/zlib.pas
@@ -0,0 +1,523 @@
+Unit Zlib;\r
+\r
+\r
+{ Original:\r
+   zlib.h -- interface of the 'zlib' general purpose compression library\r
+  version 1.1.0, Feb 24th, 1998\r
+\r
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler\r
+\r
+  This software is provided 'as-is', without any express or implied\r
+  warranty.  In no event will the authors be held liable for any damages\r
+  arising from the use of this software.\r
+\r
+  Permission is granted to anyone to use this software for any purpose,\r
+  including commercial applications, and to alter it and redistribute it\r
+  freely, subject to the following restrictions:\r
+\r
+  1. The origin of this software must not be misrepresented; you must not\r
+     claim that you wrote the original software. If you use this software\r
+     in a product, an acknowledgment in the product documentation would be\r
+     appreciated but is not required.\r
+  2. Altered source versions must be plainly marked as such, and must not be\r
+     misrepresented as being the original software.\r
+  3. This notice may not be removed or altered from any source distribution.\r
+\r
+  Jean-loup Gailly        Mark Adler\r
+  jloup@gzip.org          madler@alumni.caltech.edu\r
+\r
+\r
+  The data format used by the zlib library is described by RFCs (Request for\r
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt\r
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).\r
+\r
+\r
+  Pascal tranlastion\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.txt\r
+}\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+uses\r
+  zutil;\r
+\r
+{ zconf.h -- configuration of the zlib compression library }\r
+{ zutil.c -- target dependent utility functions for the compression library }\r
+\r
+{ The 'zlib' compression library provides in-memory compression and\r
+  decompression functions, including integrity checks of the uncompressed\r
+  data.  This version of the library supports only one compression method\r
+  (deflation) but other algorithms will be added later and will have the same\r
+  stream interface.\r
+\r
+     Compression can be done in a single step if the buffers are large\r
+  enough (for example if an input file is mmap'ed), or can be done by\r
+  repeated calls of the compression function.  In the latter case, the\r
+  application must provide more input and/or consume the output\r
+  (providing more output space) before each call.\r
+\r
+     The library also supports reading and writing files in gzip (.gz) format\r
+  with an interface similar to that of stdio.\r
+\r
+     The library does not install any signal handler. The decoder checks\r
+  the consistency of the compressed data, so the library should never\r
+  crash even in case of corrupted input. }\r
+\r
+\r
+\r
+{ Compile with -DMAXSEG_64K if the alloc function cannot allocate more\r
+  than 64k bytes at a time (needed on systems with 16-bit int). }\r
+\r
+{ Maximum value for memLevel in deflateInit2 }\r
+{$ifdef MAXSEG_64K}\r
+  {$IFDEF VER70}\r
+  const\r
+    MAX_MEM_LEVEL = 7;\r
+    DEF_MEM_LEVEL = MAX_MEM_LEVEL;  { default memLevel }\r
+  {$ELSE}\r
+  const\r
+    MAX_MEM_LEVEL = 8;\r
+    DEF_MEM_LEVEL = MAX_MEM_LEVEL;  { default memLevel }\r
+  {$ENDIF}\r
+{$else}\r
+const\r
+  MAX_MEM_LEVEL = 9;\r
+  DEF_MEM_LEVEL = 8; { if MAX_MEM_LEVEL > 8 }\r
+{$endif}\r
+\r
+{ Maximum value for windowBits in deflateInit2 and inflateInit2 }\r
+const\r
+{$IFDEF VER70}\r
+  MAX_WBITS = 14; { 32K LZ77 window }\r
+{$ELSE}\r
+  MAX_WBITS = 15; { 32K LZ77 window }\r
+{$ENDIF}\r
+\r
+{ default windowBits for decompression. MAX_WBITS is for compression only }\r
+const\r
+  DEF_WBITS = MAX_WBITS;\r
+\r
+{ The memory requirements for deflate are (in bytes):\r
+            1 shl (windowBits+2)   +  1 shl (memLevel+9)\r
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)\r
+ plus a few kilobytes for small objects. For example, if you want to reduce\r
+ the default memory requirements from 256K to 128K, compile with\r
+     DMAX_WBITS=14 DMAX_MEM_LEVEL=7\r
+ Of course this will generally degrade compression (there's no free lunch).\r
+\r
+ The memory requirements for inflate are (in bytes) 1 shl windowBits\r
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes\r
+ for small objects. }\r
+\r
+\r
+{ Huffman code lookup table entry--this entry is four bytes for machines\r
+  that have 16-bit pointers (e.g. PC's in the small or medium model). }\r
+\r
+type\r
+  pInflate_huft = ^inflate_huft;\r
+  inflate_huft = Record\r
+    Exop,             { number of extra bits or operation }\r
+    bits : Byte;      { number of bits in this code or subcode }\r
+    {pad : uInt;}       { pad structure to a power of 2 (4 bytes for }\r
+                      {  16-bit, 8 bytes for 32-bit int's) }\r
+    base : uInt;      { literal, length base, or distance base }\r
+                      { or table offset }\r
+  End;\r
+\r
+type\r
+  huft_field = Array[0..(MaxMemBlock div SizeOf(inflate_huft))-1] of inflate_huft;\r
+  huft_ptr = ^huft_field;\r
+type\r
+  ppInflate_huft = ^pInflate_huft;\r
+\r
+type\r
+  inflate_codes_mode = ( { waiting for "i:"=input, "o:"=output, "x:"=nothing }\r
+        START,    { x: set up for LEN }\r
+        LEN,      { i: get length/literal/eob next }\r
+        LENEXT,   { i: getting length extra (have base) }\r
+        DIST,     { i: get distance next }\r
+        DISTEXT,  { i: getting distance extra }\r
+        COPY,     { o: copying bytes in window, waiting for space }\r
+        LIT,      { o: got literal, waiting for output space }\r
+        WASH,     { o: got eob, possibly still output waiting }\r
+        ZEND,     { x: got eob and all data flushed }\r
+        BADCODE); { x: got error }\r
+\r
+{ inflate codes private state }\r
+type\r
+  pInflate_codes_state = ^inflate_codes_state;\r
+  inflate_codes_state = record\r
+\r
+    mode : inflate_codes_mode;        { current inflate_codes mode }\r
+\r
+    { mode dependent information }\r
+    len : uInt;\r
+    sub : record                      { submode }\r
+      Case Byte of\r
+      0:(code : record                { if LEN or DIST, where in tree }\r
+          tree : pInflate_huft;       { pointer into tree }\r
+          need : uInt;                { bits needed }\r
+         end);\r
+      1:(lit : uInt);                 { if LIT, literal }\r
+      2:(copy: record                 { if EXT or COPY, where and how much }\r
+           get : uInt;                { bits to get for extra }\r
+           dist : uInt;               { distance back to copy from }\r
+         end);\r
+    end;\r
+\r
+    { mode independent information }\r
+    lbits : Byte;                     { ltree bits decoded per branch }\r
+    dbits : Byte;                     { dtree bits decoder per branch }\r
+    ltree : pInflate_huft;            { literal/length/eob tree }\r
+    dtree : pInflate_huft;            { distance tree }\r
+  end;\r
+\r
+type\r
+  check_func = function(check : uLong;\r
+                        buf : pBytef;\r
+                        {const buf : array of byte;}\r
+                       len : uInt) : uLong;\r
+type\r
+  inflate_block_mode =\r
+     (ZTYPE,    { get type bits (3, including end bit) }\r
+      LENS,     { get lengths for stored }\r
+      STORED,   { processing stored block }\r
+      TABLE,    { get table lengths }\r
+      BTREE,    { get bit lengths tree for a dynamic block }\r
+      DTREE,    { get length, distance trees for a dynamic block }\r
+      CODES,    { processing fixed or dynamic block }\r
+      DRY,      { output remaining window bytes }\r
+      BLKDONE,  { finished last block, done }\r
+      BLKBAD);  { got a data error--stuck here }\r
+\r
+type\r
+  pInflate_blocks_state = ^inflate_blocks_state;\r
+\r
+{ inflate blocks semi-private state }\r
+  inflate_blocks_state = record\r
+\r
+    mode : inflate_block_mode;     { current inflate_block mode }\r
+\r
+    { mode dependent information }\r
+    sub : record                  { submode }\r
+    case Byte of\r
+    0:(left : uInt);              { if STORED, bytes left to copy }\r
+    1:(trees : record             { if DTREE, decoding info for trees }\r
+        table : uInt;               { table lengths (14 bits) }\r
+        index : uInt;               { index into blens (or border) }\r
+        blens : PuIntArray;         { bit lengths of codes }\r
+        bb : uInt;                  { bit length tree depth }\r
+        tb : pInflate_huft;         { bit length decoding tree }\r
+      end);\r
+    2:(decode : record            { if CODES, current state }\r
+        tl : pInflate_huft;\r
+        td : pInflate_huft;         { trees to free }\r
+        codes : pInflate_codes_state;\r
+      end);\r
+    end;\r
+    last : boolean;               { true if this block is the last block }\r
+\r
+    { mode independent information }\r
+    bitk : uInt;            { bits in bit buffer }\r
+    bitb : uLong;           { bit buffer }\r
+    hufts : huft_ptr; {pInflate_huft;}  { single malloc for tree space }\r
+    window : pBytef;        { sliding window }\r
+    zend : pBytef;          { one byte after sliding window }\r
+    read : pBytef;          { window read pointer }\r
+    write : pBytef;         { window write pointer }\r
+    checkfn : check_func;   { check function }\r
+    check : uLong;          { check on output }\r
+  end;\r
+\r
+type\r
+  inflate_mode = (\r
+      METHOD,   { waiting for method byte }\r
+      FLAG,     { waiting for flag byte }\r
+      DICT4,    { four dictionary check bytes to go }\r
+      DICT3,    { three dictionary check bytes to go }\r
+      DICT2,    { two dictionary check bytes to go }\r
+      DICT1,    { one dictionary check byte to go }\r
+      DICT0,    { waiting for inflateSetDictionary }\r
+      BLOCKS,   { decompressing blocks }\r
+      CHECK4,   { four check bytes to go }\r
+      CHECK3,   { three check bytes to go }\r
+      CHECK2,   { two check bytes to go }\r
+      CHECK1,   { one check byte to go }\r
+      DONE,     { finished check, done }\r
+      BAD);     { got an error--stay here }\r
+\r
+{ inflate private state }\r
+type\r
+  pInternal_state = ^internal_state; { or point to a deflate_state record }\r
+  internal_state = record\r
+\r
+     mode : inflate_mode;  { current inflate mode }\r
+\r
+     { mode dependent information }\r
+     sub : record          { submode }\r
+       case byte of\r
+       0:(method : uInt);  { if FLAGS, method byte }\r
+       1:(check : record   { if CHECK, check values to compare }\r
+           was : uLong;        { computed check value }\r
+           need : uLong;       { stream check value }\r
+          end);\r
+       2:(marker : uInt);  { if BAD, inflateSync's marker bytes count }\r
+     end;\r
+\r
+     { mode independent information }\r
+     nowrap : boolean;      { flag for no wrapper }\r
+     wbits : uInt;          { log2(window size)  (8..15, defaults to 15) }\r
+     blocks : pInflate_blocks_state;    { current inflate_blocks state }\r
+   end;\r
+\r
+type\r
+  alloc_func = function(opaque : voidpf; items : uInt; size : uInt) : voidpf;\r
+  free_func = procedure(opaque : voidpf; address : voidpf);\r
+\r
+type\r
+  z_streamp = ^z_stream;\r
+  z_stream = record\r
+    next_in : pBytef;     { next input byte }\r
+    avail_in : uInt;      { number of bytes available at next_in }\r
+    total_in : uLong;     { total nb of input bytes read so far }\r
+\r
+    next_out : pBytef;    { next output byte should be put there }\r
+    avail_out : uInt;     { remaining free space at next_out }\r
+    total_out : uLong;    { total nb of bytes output so far }\r
+\r
+    msg : string[255];         { last error message, '' if no error }\r
+    state : pInternal_state; { not visible by applications }\r
+\r
+    zalloc : alloc_func;  { used to allocate the internal state }\r
+    zfree : free_func;    { used to free the internal state }\r
+    opaque : voidpf;      { private data object passed to zalloc and zfree }\r
+\r
+    data_type : int;      { best guess about the data type: ascii or binary }\r
+    adler : uLong;        { adler32 value of the uncompressed data }\r
+    reserved : uLong;     { reserved for future use }\r
+  end;\r
+\r
+\r
+{  The application must update next_in and avail_in when avail_in has\r
+   dropped to zero. It must update next_out and avail_out when avail_out\r
+   has dropped to zero. The application must initialize zalloc, zfree and\r
+   opaque before calling the init function. All other fields are set by the\r
+   compression library and must not be updated by the application.\r
+\r
+   The opaque value provided by the application will be passed as the first\r
+   parameter for calls of zalloc and zfree. This can be useful for custom\r
+   memory management. The compression library attaches no meaning to the\r
+   opaque value.\r
+\r
+   zalloc must return Z_NULL if there is not enough memory for the object.\r
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate\r
+   exactly 65536 bytes, but will not be required to allocate more than this\r
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,\r
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*\r
+   have their offset normalized to zero. The default allocation function\r
+   provided by this library ensures this (see zutil.c). To reduce memory\r
+   requirements and avoid any allocation of 64K objects, at the expense of\r
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).\r
+\r
+   The fields total_in and total_out can be used for statistics or\r
+   progress reports. After compression, total_in holds the total size of\r
+   the uncompressed data and may be saved for use in the decompressor\r
+   (particularly if the decompressor wants to decompress everything in\r
+   a single step). }\r
+\r
+const  { constants }\r
+   Z_NO_FLUSH      = 0;\r
+   Z_PARTIAL_FLUSH = 1;\r
+   Z_SYNC_FLUSH    = 2;\r
+   Z_FULL_FLUSH    = 3;\r
+   Z_FINISH        = 4;\r
+{ Allowed flush values; see deflate() below for details }\r
+\r
+   Z_OK            = 0;\r
+   Z_STREAM_END    = 1;\r
+   Z_NEED_DICT     = 2;\r
+   Z_ERRNO         = (-1);\r
+   Z_STREAM_ERROR  = (-2);\r
+   Z_DATA_ERROR    = (-3);\r
+   Z_MEM_ERROR     = (-4);\r
+   Z_BUF_ERROR     = (-5);\r
+   Z_VERSION_ERROR = (-6);\r
+{ Return codes for the compression/decompression functions. Negative\r
+  values are errors, positive values are used for special but normal events.}\r
+\r
+   Z_NO_COMPRESSION         = 0;\r
+   Z_BEST_SPEED             = 1;\r
+   Z_BEST_COMPRESSION       = 9;\r
+   Z_DEFAULT_COMPRESSION    = (-1);\r
+{ compression levels }\r
+\r
+   Z_FILTERED            = 1;\r
+   Z_HUFFMAN_ONLY        = 2;\r
+   Z_DEFAULT_STRATEGY    = 0;\r
+{ compression strategy; see deflateInit2() below for details }\r
+\r
+   Z_BINARY   = 0;\r
+   Z_ASCII    = 1;\r
+   Z_UNKNOWN  = 2;\r
+{ Possible values of the data_type field }\r
+\r
+   Z_DEFLATED   = 8;\r
+{ The deflate compression method (the only one supported in this version) }\r
+\r
+   Z_NULL  = NIL;  { for initializing zalloc, zfree, opaque }\r
+\r
+  {$IFDEF GZIO}\r
+var\r
+  errno : int;\r
+  {$ENDIF}\r
+\r
+        { common constants }\r
+\r
+\r
+{ The three kinds of block type }\r
+const\r
+  STORED_BLOCK = 0;\r
+  STATIC_TREES = 1;\r
+  DYN_TREES = 2;\r
+{ The minimum and maximum match lengths }\r
+const\r
+  MIN_MATCH = 3;\r
+{$ifdef MAX_MATCH_IS_258}\r
+  MAX_MATCH = 258;\r
+{$else}\r
+  MAX_MATCH = ??;    { deliberate syntax error }\r
+{$endif}\r
+\r
+const\r
+  PRESET_DICT = $20; { preset dictionary flag in zlib header }\r
+\r
+\r
+  {$IFDEF DEBUG}\r
+  procedure Assert(cond : boolean; msg : string);\r
+  {$ENDIF}\r
+\r
+  procedure Trace(x : string);\r
+  procedure Tracev(x : string);\r
+  procedure Tracevv(x : string);\r
+  procedure Tracevvv(x : string);\r
+  procedure Tracec(c : boolean; x : string);\r
+  procedure Tracecv(c : boolean; x : string);\r
+\r
+function zlibVersion : string;\r
+{ The application can compare zlibVersion and ZLIB_VERSION for consistency.\r
+  If the first character differs, the library code actually used is\r
+  not compatible with the zlib.h header file used by the application.\r
+  This check is automatically made by deflateInit and inflateInit. }\r
+\r
+function zError(err : int) : string;\r
+\r
+function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf;\r
+\r
+procedure ZFREE (var strm : z_stream; ptr : voidpf);\r
+\r
+procedure TRY_FREE (var strm : z_stream; ptr : voidpf);\r
+\r
+const\r
+  ZLIB_VERSION : string[10] = '1.1.2';\r
+\r
+const\r
+  z_errbase = Z_NEED_DICT;\r
+  z_errmsg : Array[0..9] of string[21] = { indexed by 2-zlib_error }\r
+           ('need dictionary',     { Z_NEED_DICT       2  }\r
+            'stream end',          { Z_STREAM_END      1  }\r
+            '',                    { Z_OK              0  }\r
+            'file error',          { Z_ERRNO         (-1) }\r
+            'stream error',        { Z_STREAM_ERROR  (-2) }\r
+            'data error',          { Z_DATA_ERROR    (-3) }\r
+            'insufficient memory', { Z_MEM_ERROR     (-4) }\r
+            'buffer error',        { Z_BUF_ERROR     (-5) }\r
+            'incompatible version',{ Z_VERSION_ERROR (-6) }\r
+            '');\r
+const\r
+  z_verbose : int = 1;\r
+\r
+{$IFDEF DEBUG}\r
+procedure z_error (m : string);\r
+{$ENDIF}\r
+\r
+implementation\r
+\r
+function zError(err : int) : string;\r
+begin\r
+  zError := z_errmsg[Z_NEED_DICT-err];\r
+end;\r
+\r
+function zlibVersion : string;\r
+begin\r
+  zlibVersion := ZLIB_VERSION;\r
+end;\r
+\r
+procedure z_error (m : string);\r
+begin\r
+  WriteLn(output, m);\r
+  Write('Zlib - Halt...');\r
+  ReadLn;\r
+  Halt(1);\r
+end;\r
+\r
+procedure Assert(cond : boolean; msg : string);\r
+begin\r
+  if not cond then\r
+    z_error(msg);\r
+end;\r
+\r
+procedure Trace(x : string);\r
+begin\r
+  WriteLn(x);\r
+end;\r
+\r
+procedure Tracev(x : string);\r
+begin\r
+ if (z_verbose>0) then\r
+   WriteLn(x);\r
+end;\r
+\r
+procedure Tracevv(x : string);\r
+begin\r
+  if (z_verbose>1) then\r
+    WriteLn(x);\r
+end;\r
+\r
+procedure Tracevvv(x : string);\r
+begin\r
+  if (z_verbose>2) then\r
+    WriteLn(x);\r
+end;\r
+\r
+procedure Tracec(c : boolean; x : string);\r
+begin\r
+  if (z_verbose>0) and (c) then\r
+    WriteLn(x);\r
+end;\r
+\r
+procedure Tracecv(c : boolean; x : string);\r
+begin\r
+  if (z_verbose>1) and c then\r
+    WriteLn(x);\r
+end;\r
+\r
+function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf;\r
+begin\r
+  ZALLOC := strm.zalloc(strm.opaque, items, size);\r
+end;\r
+\r
+procedure ZFREE (var strm : z_stream; ptr : voidpf);\r
+begin\r
+  strm.zfree(strm.opaque, ptr);\r
+end;\r
+\r
+procedure TRY_FREE (var strm : z_stream; ptr : voidpf);\r
+begin\r
+  {if @strm <> Z_NULL then}\r
+    strm.zfree(strm.opaque, ptr);\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/zutil.pas b/zutil.pas
new file mode 100755 (executable)
index 0000000..d37a948
--- /dev/null
+++ b/zutil.pas
@@ -0,0 +1,548 @@
+//Modified by plugwash for 64 bit support\r
+Unit ZUtil;\r
+\r
+{\r
+  Copyright (C) 1998 by Jacques Nomssi Nzali\r
+  For conditions of distribution and use, see copyright notice in readme.paszlib\r
+}\r
+\r
+interface\r
+\r
+{$I zconf.inc}\r
+\r
+{ Type declarations }\r
+\r
+type\r
+  {Byte   = usigned char;  8 bits}\r
+  Bytef  = byte;\r
+  charf  = byte;\r
+\r
+{$IFDEF FPC}\r
+  int    = longint;\r
+{$ELSE}\r
+  int    = integer;\r
+{$ENDIF}\r
+\r
+  intf   = int;\r
+{$IFDEF MSDOS}\r
+  uInt   = Word;\r
+{$ELSE}\r
+  {$IFDEF FPC}\r
+    uInt   = longint;     { 16 bits or more }\r
+    {$INFO Cardinal}\r
+  {$ELSE}\r
+    uInt   = cardinal;     { 16 bits or more }\r
+  {$ENDIF}\r
+{$ENDIF}\r
+  uIntf  = uInt;\r
+\r
+  Long   = longint;\r
+{$ifdef Delphi5}  \r
+  uLong  = Cardinal;\r
+{$else}\r
+  uLong  = LongInt;      { 32 bits or more }\r
+{$endif}\r
+  uLongf = uLong;\r
+\r
+  voidp  = pointer;\r
+  voidpf = voidp;\r
+  pBytef = ^Bytef;\r
+  pIntf  = ^intf;\r
+  puIntf = ^uIntf;\r
+  puLong = ^uLongf;\r
+  {$ifdef fpc}\r
+    ptr2int = sizeint;\r
+  {$else}\r
+    ptr2int = uInt;\r
+  {$endif}\r
+{ a pointer to integer casting is used to do pointer arithmetic.\r
+  ptr2int must be an integer type and sizeof(ptr2int) must be less\r
+  than sizeof(pointer) - Nomssi }\r
+\r
+const\r
+  {$IFDEF MAXSEG_64K}\r
+  MaxMemBlock = $FFFF;\r
+  {$ELSE}\r
+  MaxMemBlock = MaxInt;\r
+  {$ENDIF}\r
+\r
+type\r
+  zByteArray = array[0..(MaxMemBlock div SizeOf(Bytef))-1] of Bytef;\r
+  pzByteArray = ^zByteArray;\r
+type\r
+  zIntfArray = array[0..(MaxMemBlock div SizeOf(Intf))-1] of Intf;\r
+  pzIntfArray = ^zIntfArray;\r
+type\r
+  zuIntArray = array[0..(MaxMemBlock div SizeOf(uInt))-1] of uInt;\r
+  PuIntArray = ^zuIntArray;\r
+\r
+{ Type declarations - only for deflate }\r
+\r
+type\r
+  uch  = Byte;\r
+  uchf = uch; { FAR }\r
+  ush  = Word;\r
+  ushf = ush;\r
+  ulg  = LongInt;\r
+\r
+  unsigned = uInt;\r
+\r
+  pcharf = ^charf;\r
+  puchf = ^uchf;\r
+  pushf = ^ushf;\r
+\r
+type\r
+  zuchfArray = zByteArray;\r
+  puchfArray = ^zuchfArray;\r
+type\r
+  zushfArray = array[0..(MaxMemBlock div SizeOf(ushf))-1] of ushf;\r
+  pushfArray = ^zushfArray;\r
+\r
+procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);\r
+function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;\r
+procedure zmemzero(destp : pBytef; len : uInt);\r
+procedure zcfree(opaque : voidpf; ptr : voidpf);\r
+function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;\r
+\r
+implementation\r
+\r
+{$ifdef ver80}\r
+  {$define Delphi16}\r
+{$endif}\r
+{$ifdef ver70}\r
+  {$define HugeMem}\r
+{$endif}\r
+{$ifdef ver60}\r
+  {$define HugeMem}\r
+{$endif}\r
+\r
+{$IFDEF CALLDOS}\r
+uses\r
+  WinDos;\r
+{$ENDIF}\r
+{$IFDEF Delphi16}\r
+uses\r
+  WinTypes,\r
+  WinProcs;\r
+{$ENDIF}\r
+{$IFNDEF FPC}\r
+  {$IFDEF DPMI}\r
+  uses\r
+    WinAPI;\r
+  {$ENDIF}\r
+{$ENDIF}\r
+\r
+{$IFDEF CALLDOS}\r
+{ reduce your application memory footprint with $M before using this }\r
+function dosAlloc (Size : Longint) : Pointer;\r
+var\r
+  regs: TRegisters;\r
+begin\r
+  regs.bx := (Size + 15) div 16; { number of 16-bytes-paragraphs }\r
+  regs.ah := $48;                { Allocate memory block }\r
+  msdos(regs);\r
+  if regs.Flags and FCarry <> 0 then\r
+    DosAlloc := NIL\r
+  else\r
+    DosAlloc := Ptr(regs.ax, 0);\r
+end;\r
+\r
+\r
+function dosFree(P : pointer) : boolean;\r
+var\r
+  regs: TRegisters;\r
+begin\r
+  dosFree := FALSE;\r
+  regs.bx := Seg(P^);             { segment }\r
+  if Ofs(P) <> 0 then\r
+    exit;\r
+  regs.ah := $49;                { Free memory block }\r
+  msdos(regs);\r
+  dosFree := (regs.Flags and FCarry = 0);\r
+end;\r
+{$ENDIF}\r
+\r
+type\r
+  LH = record\r
+    L, H : word;\r
+  end;\r
+\r
+{$IFDEF HugeMem}\r
+  {$define HEAP_LIST}\r
+{$endif}\r
+\r
+{$IFDEF HEAP_LIST} {--- to avoid Mark and Release --- }\r
+const\r
+  MaxAllocEntries = 50;\r
+type\r
+  TMemRec = record\r
+    orgvalue,\r
+    value : pointer;\r
+    size: longint;\r
+  end;\r
+const\r
+  allocatedCount : 0..MaxAllocEntries = 0;\r
+var\r
+  allocatedList : array[0..MaxAllocEntries-1] of TMemRec;\r
+\r
+ function NewAllocation(ptr0, ptr : pointer; memsize : longint) : boolean;\r
+ begin\r
+   if (allocatedCount < MaxAllocEntries) and (ptr0 <> NIL) then\r
+   begin\r
+     with allocatedList[allocatedCount] do\r
+     begin\r
+       orgvalue := ptr0;\r
+       value := ptr;\r
+       size := memsize;\r
+     end;\r
+     Inc(allocatedCount);  { we don't check for duplicate }\r
+     NewAllocation := TRUE;\r
+   end\r
+   else\r
+     NewAllocation := FALSE;\r
+ end;\r
+{$ENDIF}\r
+\r
+{$IFDEF HugeMem}\r
+\r
+{ The code below is extremely version specific to the TP 6/7 heap manager!!}\r
+type\r
+  PFreeRec = ^TFreeRec;\r
+  TFreeRec = record\r
+    next: PFreeRec;\r
+    size: Pointer;\r
+  end;\r
+type\r
+  HugePtr = voidpf;\r
+\r
+\r
+ procedure IncPtr(var p:pointer;count:word);\r
+ { Increments pointer }\r
+ begin\r
+   inc(LH(p).L,count);\r
+   if LH(p).L < count then\r
+     inc(LH(p).H,SelectorInc);  { $1000 }\r
+ end;\r
+\r
+ procedure DecPtr(var p:pointer;count:word);\r
+ { decrements pointer }\r
+ begin\r
+   if count > LH(p).L then\r
+     dec(LH(p).H,SelectorInc);\r
+   dec(LH(p).L,Count);\r
+ end;\r
+\r
+ procedure IncPtrLong(var p:pointer;count:longint);\r
+ { Increments pointer; assumes count > 0 }\r
+ begin\r
+   inc(LH(p).H,SelectorInc*LH(count).H);\r
+   inc(LH(p).L,LH(Count).L);\r
+   if LH(p).L < LH(count).L then\r
+     inc(LH(p).H,SelectorInc);\r
+ end;\r
+\r
+ procedure DecPtrLong(var p:pointer;count:longint);\r
+ { Decrements pointer; assumes count > 0 }\r
+ begin\r
+   if LH(count).L > LH(p).L then\r
+     dec(LH(p).H,SelectorInc);\r
+   dec(LH(p).L,LH(Count).L);\r
+   dec(LH(p).H,SelectorInc*LH(Count).H);\r
+ end;\r
+ { The next section is for real mode only }\r
+\r
+function Normalized(p : pointer)  : pointer;\r
+var\r
+  count : word;\r
+begin\r
+  count := LH(p).L and $FFF0;\r
+  Normalized := Ptr(LH(p).H + (count shr 4), LH(p).L and $F);\r
+end;\r
+\r
+procedure FreeHuge(var p:HugePtr; size : longint);\r
+const\r
+  blocksize = $FFF0;\r
+var\r
+  block : word;\r
+begin\r
+  while size > 0 do\r
+  begin\r
+    { block := minimum(size, blocksize); }\r
+    if size > blocksize then\r
+      block := blocksize\r
+    else\r
+      block := size;\r
+\r
+    dec(size,block);\r
+    freemem(p,block);\r
+    IncPtr(p,block);    { we may get ptr($xxxx, $fff8) and 31 bytes left }\r
+    p := Normalized(p); { to free, so we must normalize }\r
+  end;\r
+end;\r
+\r
+function FreeMemHuge(ptr : pointer) : boolean;\r
+var\r
+  i : integer; { -1..MaxAllocEntries }\r
+begin\r
+  FreeMemHuge := FALSE;\r
+  i := allocatedCount - 1;\r
+  while (i >= 0) do\r
+  begin\r
+    if (ptr = allocatedList[i].value) then\r
+    begin\r
+      with allocatedList[i] do\r
+        FreeHuge(orgvalue, size);\r
+\r
+      Move(allocatedList[i+1], allocatedList[i],\r
+           SizeOf(TMemRec)*(allocatedCount - 1 - i));\r
+      Dec(allocatedCount);\r
+      FreeMemHuge := TRUE;\r
+      break;\r
+    end;\r
+    Dec(i);\r
+  end;\r
+end;\r
+\r
+procedure GetMemHuge(var p:HugePtr;memsize:Longint);\r
+const\r
+  blocksize = $FFF0;\r
+var\r
+  size : longint;\r
+  prev,free : PFreeRec;\r
+  save,temp : pointer;\r
+  block : word;\r
+begin\r
+  p := NIL;\r
+  { Handle the easy cases first }\r
+  if memsize > maxavail then\r
+    exit\r
+  else\r
+    if memsize <= blocksize then\r
+    begin\r
+      getmem(p, memsize);\r
+      if not NewAllocation(p, p, memsize) then\r
+      begin\r
+        FreeMem(p, memsize);\r
+        p := NIL;\r
+      end;\r
+    end\r
+    else\r
+    begin\r
+      size := memsize + 15;\r
+\r
+      { Find the block that has enough space }\r
+      prev := PFreeRec(@freeList);\r
+      free := prev^.next;\r
+      while (free <> heapptr) and (ptr2int(free^.size) < size) do\r
+      begin\r
+        prev := free;\r
+        free := prev^.next;\r
+      end;\r
+\r
+      { Now free points to a region with enough space; make it the first one and\r
+        multiple allocations will be contiguous. }\r
+\r
+      save := freelist;\r
+      freelist := free;\r
+      { In TP 6, this works; check against other heap managers }\r
+      while size > 0 do\r
+      begin\r
+        { block := minimum(size, blocksize); }\r
+        if size > blocksize then\r
+          block := blocksize\r
+        else\r
+          block := size;\r
+        dec(size,block);\r
+        getmem(temp,block);\r
+      end;\r
+\r
+      { We've got what we want now; just sort things out and restore the\r
+        free list to normal }\r
+\r
+      p := free;\r
+      if prev^.next <> freelist then\r
+      begin\r
+        prev^.next := freelist;\r
+        freelist := save;\r
+      end;\r
+\r
+      if (p <> NIL) then\r
+      begin\r
+        { return pointer with 0 offset }\r
+        temp := p;\r
+        if Ofs(p^)<>0 Then\r
+          p := Ptr(Seg(p^)+1,0);  { hack }\r
+        if not NewAllocation(temp, p, memsize + 15) then\r
+        begin\r
+          FreeHuge(temp, size);\r
+          p := NIL;\r
+        end;\r
+      end;\r
+\r
+    end;\r
+end;\r
+\r
+{$ENDIF}\r
+\r
+procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);\r
+begin\r
+  Move(sourcep^, destp^, len);\r
+end;\r
+\r
+function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;\r
+var\r
+  j : uInt;\r
+  source,\r
+  dest : pBytef;\r
+begin\r
+  source := s1p;\r
+  dest := s2p;\r
+  for j := 0 to pred(len) do\r
+  begin\r
+    if (source^ <> dest^) then\r
+    begin\r
+      zmemcmp := 2*Ord(source^ > dest^)-1;\r
+      exit;\r
+    end;\r
+    Inc(source);\r
+    Inc(dest);\r
+  end;\r
+  zmemcmp := 0;\r
+end;\r
+\r
+procedure zmemzero(destp : pBytef; len : uInt);\r
+begin\r
+  FillChar(destp^, len, 0);\r
+end;\r
+\r
+procedure zcfree(opaque : voidpf; ptr : voidpf);\r
+{$ifdef Delphi16}\r
+var\r
+  Handle : THandle;\r
+{$endif}\r
+{$IFDEF FPC}\r
+var\r
+  memsize : uint;\r
+{$ENDIF}\r
+begin\r
+  {$IFDEF DPMI}\r
+  {h :=} GlobalFreePtr(ptr);\r
+  {$ELSE}\r
+    {$IFDEF CALL_DOS}\r
+    dosFree(ptr);\r
+    {$ELSE}\r
+      {$ifdef HugeMem}\r
+      FreeMemHuge(ptr);\r
+      {$else}\r
+        {$ifdef Delphi16}\r
+        Handle := GlobalHandle(LH(ptr).H); { HiWord(LongInt(ptr)) }\r
+        GlobalUnLock(Handle);\r
+        GlobalFree(Handle);\r
+        {$else}\r
+          {$IFDEF FPC}\r
+          Dec(puIntf(ptr));\r
+          memsize := puIntf(ptr)^;\r
+          FreeMem(ptr, memsize+SizeOf(uInt));\r
+          {$ELSE}\r
+          FreeMem(ptr);  { Delphi 2,3,4 }\r
+          {$ENDIF}\r
+        {$endif}\r
+      {$endif}\r
+    {$ENDIF}\r
+  {$ENDIF}\r
+end;\r
+\r
+function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;\r
+var\r
+  p : voidpf;\r
+  memsize : uLong;\r
+{$ifdef Delphi16}\r
+  handle : THandle;\r
+{$endif}\r
+begin\r
+  memsize := uLong(items) * size;\r
+  {$IFDEF DPMI}\r
+  p := GlobalAllocPtr(gmem_moveable, memsize);\r
+  {$ELSE}\r
+    {$IFDEF CALLDOS}\r
+    p := dosAlloc(memsize);\r
+    {$ELSE}\r
+      {$ifdef HugeMem}\r
+      GetMemHuge(p, memsize);\r
+      {$else}\r
+        {$ifdef Delphi16}\r
+        Handle := GlobalAlloc(HeapAllocFlags, memsize);\r
+        p := GlobalLock(Handle);\r
+        {$else}\r
+          {$IFDEF FPC}\r
+          GetMem(p, memsize+SizeOf(uInt));\r
+          puIntf(p)^:= memsize;\r
+          Inc(puIntf(p));\r
+          {$ELSE}\r
+          GetMem(p, memsize);  { Delphi: p := AllocMem(memsize); }\r
+          {$ENDIF}\r
+        {$endif}\r
+      {$endif}\r
+    {$ENDIF}\r
+  {$ENDIF}\r
+  zcalloc := p;\r
+end;\r
+\r
+end.\r
+\r
+\r
+{ edited from a SWAG posting:\r
+\r
+In Turbo Pascal 6, the heap is the memory allocated when using the Procedures 'New' and\r
+'GetMem'. The heap starts at the address location pointed to by 'Heaporg' and\r
+grows to higher addresses as more memory is allocated. The top of the heap,\r
+the first address of allocatable memory space above the allocated memory\r
+space, is pointed to by 'HeapPtr'.\r
+\r
+Memory is deallocated by the Procedures 'Dispose' and 'FreeMem'. As memory\r
+blocks are deallocated more memory becomes available, but..... When a block\r
+of memory, which is not the top-most block in the heap is deallocated, a gap\r
+in the heap will appear. to keep track of these gaps Turbo Pascal maintains\r
+a so called free list.\r
+\r
+The Function 'MaxAvail' holds the size of the largest contiguous free block\r
+_in_ the heap. The Function 'MemAvail' holds the sum of all free blocks in\r
+the heap.\r
+\r
+TP6.0 keeps track of the free blocks by writing a 'free list Record' to the\r
+first eight Bytes of the freed memory block! A (TP6.0) free-list Record\r
+contains two four Byte Pointers of which the first one points to the next\r
+free memory block, the second Pointer is not a Real Pointer but contains the\r
+size of the memory block.\r
+\r
+Summary\r
+\r
+TP6.0 maintains a linked list with block sizes and Pointers to the _next_\r
+free block. An extra heap Variable 'Heapend' designate the end of the heap.\r
+When 'HeapPtr' and 'FreeList' have the same value, the free list is empty.\r
+\r
+\r
+                     TP6.0     Heapend\r
+                ÚÄÄÄÄÄÄÄÄÄ¿ <ÄÄÄÄ\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³\r
+                ³         ³  HeapPtr\r
+             ÚÄ>ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ\r
+             ³  ³         ³\r
+             ³  ÃÄÄÄÄÄÄÄÄÄ´\r
+             ÀÄij  Free   ³\r
+             ÚÄ>ÃÄÄÄÄÄÄÄÄÄ´\r
+             ³  ³         ³\r
+             ³  ÃÄÄÄÄÄÄÄÄÄ´\r
+             ÀÄij  Free   ³  FreeList\r
+                ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ\r
+                ³         ³  Heaporg\r
+                ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ\r
+\r
+\r
+}\r